GPUImage for Android 如何使用这个 glsl文件

发布于:2024-12-18 ⋅ 阅读:(42) ⋅ 点赞:(0)

使用 GPUImage for Android 加载和应用自定义 GLSL 文件(例如你的 transition 文件)的方法如下:


1. 准备 GLSL 文件

确保你的 GLSL 文件已经调整为 GPUImage 的格式。对于你的自定义 GLSL 文件,GPUImage 期望包含以下结构:

  • 顶点着色器:
    GPUImage 默认使用标准顶点着色器,你无需更改。内容如下:

    attribute vec4 position;
    attribute vec4 inputTextureCoordinate;
    
    varying vec2 textureCoordinate;
    
    void main() {
        gl_Position = position;
        textureCoordinate = inputTextureCoordinate.xy;
    }
    
  • 片段着色器:
    调整你的 GLSL 文件以适配 GPUImage 的 getFromColorgetToColor 的实现。

    precision mediump float;
    
    varying vec2 textureCoordinate;
    
    uniform sampler2D inputImageTexture;   // 当前纹理
    uniform sampler2D inputImageTexture2; // 下一个纹理
    
    uniform float progress;   // 过渡进度
    uniform float dots;       // 参数 dots
    uniform vec2 center;      // 参数中心点
    
    const float SQRT_2 = 1.414213562373;
    
    vec4 getFromColor(vec2 uv) {
        return texture2D(inputImageTexture, uv);
    }
    
    vec4 getToColor(vec2 uv) {
        return texture2D(inputImageTexture2, uv);
    }
    
    vec4 transition(vec2 uv) {
        bool nextImage = distance(fract(uv * dots), vec2(0.5, 0.5)) < (progress / distance(uv, center));
        return nextImage ? getToColor(uv) : getFromColor(uv);
    }
    
    void main() {
        gl_FragColor = transition(textureCoordinate);
    }
    

将片段着色器保存为一个 .glsl 文件,例如:assets/shaders/transition.glsl


2. 在 GPUImage 中使用自定义着色器

2.1 添加 GPUImage 库

在项目的 build.gradle 文件中添加 GPUImage 的依赖:

implementation 'jp.co.cyberagent.android:gpuimage:2.1.0'
2.2 创建自定义滤镜

创建一个类来加载自定义片段着色器:

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

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

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

    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.3 应用滤镜并显示效果

将滤镜应用到 GPUImageViewGPUImage 上:

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

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

// 加载两张图片作为纹理
gpuImage.setImage(BitmapFactory.decodeResource(resources, R.drawable.image1))
customFilter.setProgress(0f)  // 起始过渡进度

// 应用自定义滤镜
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. 完整布局文件

确保你在 XML 文件中定义了 GPUImageView

<com.example.gpuimage.GPUImageView
    android:id="@+id/gpuImageView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

4. 动态参数设置

  • 如果需要动态调整 dotscenter 参数,可以通过暴露方法 setDots()setCenter() 实现。
  • 例如:
    customFilter.setDots(30f)
    customFilter.setCenter(floatArrayOf(0.3f, 0.7f))
    

总结

以上步骤说明了如何在 GPUImage 中加载并使用你的自定义 GLSL 文件。核心流程包括:

  1. 准备兼容的 GLSL 文件。
  2. 使用 GPUImage 创建自定义滤镜。
  3. 通过动画动态调整 progress 等 Uniform 参数,完成过渡效果。

如果需要进一步扩展或调试代码,请随时告诉我!


网站公告

今日签到

点亮在社区的每一天
去签到