GPUImage 中,如果你需要加载两张图片作为输入纹理用于过渡效果

在 GPUImage 中,如果你需要加载两张图片作为输入纹理用于过渡效果,你需要自定义处理多个纹理。以下是解决方法:


步骤

1. 修改自定义滤镜类支持两张纹理

GPUImage 的默认实现只支持一张图片。你需要扩展 GPUImageFilter,为第二张图片添加纹理支持。

更新你的 CustomTransitionFilter 类:

class CustomTransitionFilter(context: Context) : GPUImageFilter(NO_FILTER_VERTEX_SHADER, loadShaderFromAssets(context)) {

    private var progressLocation: Int = 0
    private var dotsLocation: Int = 0
    private var centerLocation: Int = 0
    private var secondTextureHandle: Int = -1
    private var secondTextureLocation: Int = 0

    override fun onInit() {
        super.onInit()
        // 获取 Uniform 参数的位置
        progressLocation = GLES20.glGetUniformLocation(program, "progress")
        dotsLocation = GLES20.glGetUniformLocation(program, "dots")
        centerLocation = GLES20.glGetUniformLocation(program, "center")
        secondTextureLocation = GLES20.glGetUniformLocation(program, "inputImageTexture2")
    }

    override fun onInitialized() {
        super.onInitialized()
        // 初始化 Uniform 参数
        setProgress(0f)
        setDots(20f)
        setCenter(floatArrayOf(0.5f, 0.5f))
    }

    override fun onDrawFrame(textureId: Int, cubeBuffer: FloatBuffer, textureBuffer: FloatBuffer) {
        // 激活并绑定第一个纹理
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
        GLES20.glUniform1i(getTextureUniformLocation(), 0)

        // 激活并绑定第二个纹理
        if (secondTextureHandle != -1) {
            GLES20.glActiveTexture(GLES20.GL_TEXTURE1)
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, secondTextureHandle)
            GLES20.glUniform1i(secondTextureLocation, 1)
        }

        super.onDrawFrame(textureId, cubeBuffer, textureBuffer)
    }

    fun setSecondTexture(secondBitmap: Bitmap) {
        // 加载第二张纹理
        val textures = IntArray(1)
        GLES20.glGenTextures(1, textures, 0)
        secondTextureHandle = textures[0]

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, secondTextureHandle)
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, secondBitmap, 0)

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR.toFloat())
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat())
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat())
    }

    fun setProgress(progress: Float) {
        setFloat(progressLocation, progress)
    }

    fun setDots(dots: Float) {
        setFloat(dotsLocation, dots)
    }

    fun setCenter(center: FloatArray) {
        setFloatVec2(centerLocation, center)
    }

    private fun loadShaderFromAssets(context: Context): String {
        return context.assets.open("shaders/transition.glsl").bufferedReader().use { it.readText() }
    }
}

2. 加载两张图片作为纹理

你可以在初始化时加载两张图片,并将第二张图片设置为自定义滤镜的第二纹理。

val gpuImageView = findViewById<GPUImageView>(R.id.gpuImageView)

// 初始化 GPUImage 和自定义滤镜
val gpuImage = GPUImage(this)
val customFilter = CustomTransitionFilter(this)

// 加载第一张图片
val bitmap1 = BitmapFactory.decodeResource(resources, R.drawable.image1)
gpuImage.setImage(bitmap1)

// 加载第二张图片作为纹理
val bitmap2 = BitmapFactory.decodeResource(resources, R.drawable.image2)
customFilter.setSecondTexture(bitmap2)

// 应用自定义滤镜
gpuImage.setFilter(customFilter)

// 动态更新过渡进度
val animator = ValueAnimator.ofFloat(0f, 1f).apply {
    duration = 2000
    addUpdateListener { animation ->
        val progress = animation.animatedValue as Float
        customFilter.setProgress(progress)
        gpuImageView.requestRender() // 通知视图刷新
    }
}
animator.start()

3. 动态过渡效果

如上代码,通过动画设置 progress 的值,完成从 bitmap1bitmap2 的过渡效果。


总结

  1. 自定义 CustomTransitionFilter 类,添加对第二张图片纹理的支持。
  2. 使用 setSecondTexture() 方法加载第二张图片。
  3. 动态更新 progress 参数,实现过渡效果。

这种方式利用 GPUImage 的底层 OpenGL 渲染能力,同时支持自定义 GLSL 文件的动态过渡逻辑。如果有其他问题,随时告诉我!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值