使用 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 的getFromColor
和getToColor
的实现。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 应用滤镜并显示效果
将滤镜应用到 GPUImageView
或 GPUImage
上:
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. 动态参数设置
- 如果需要动态调整
dots
和center
参数,可以通过暴露方法setDots()
和setCenter()
实现。 - 例如:
customFilter.setDots(30f) customFilter.setCenter(floatArrayOf(0.3f, 0.7f))
总结
以上步骤说明了如何在 GPUImage 中加载并使用你的自定义 GLSL 文件。核心流程包括:
- 准备兼容的 GLSL 文件。
- 使用 GPUImage 创建自定义滤镜。
- 通过动画动态调整
progress
等 Uniform 参数,完成过渡效果。
如果需要进一步扩展或调试代码,请随时告诉我!