Android OpenGL ES 2.0场景下如何快速翻转FBO解决纹理倒置问题
你遇到的翻转问题本质是OpenGL纹理坐标默认左下角为(0,0),每次FBO离屏渲染会默认沿Y轴翻转一次内容,所以每多一级滤镜输出,纹理朝向就会反转一次,和固定方向的蒙版纹理自然就出现偶数级错位的问题。
方案1:着色器动态调整采样坐标(推荐,零额外开销)
这是成本最低的修改方式,不需要额外的渲染流程,仅需调整采样逻辑即可:
- 新增uniform变量控制是否翻转Y轴,根据当前滤镜是奇数/偶数级传入对应值
- 仅对来自上一级FBO的
uTexture做坐标翻转,固定蒙版uMaskTexture保持原始坐标采样
修改后的着色器代码:
#version 100 precision mediump float; uniform sampler2D uTexture; uniform sampler2D uMaskTexture; // 新增控制变量,需要翻转时传1.0,不需要时传0.0 uniform float uFlipY; varying vec2 vTexCoord; void main(){ // 调整uTexture的采样坐标 vec2 texCoord = vTexCoord; texCoord.y = mix(texCoord.y, 1.0 - texCoord.y, uFlipY); // 修复原代码逻辑错误:不能对采样器直接做乘法,需先采样再计算 vec4 srcColor = texture2D(uTexture, texCoord); float mask = texture2D(uMaskTexture, vTexCoord).r; gl_FragColor = srcColor * mask; }
使用逻辑:第N个滤镜(从0开始计数)渲染时,uFlipY传入N % 2的值即可,刚好抵消每一级FBO带来的自动翻转,无需额外处理FBO本身。
方案2:CPU侧修改顶点纹理坐标
如果不想修改着色器代码,可以在绑定顶点缓冲前动态修改纹理坐标的Y值:
- 不需要翻转时,纹理坐标保持原
(0,0), (1,0), (0,1), (1,1) - 需要翻转时,将纹理坐标Y值替换为
1-Y,即变为(0,1), (1,1), (0,0), (1,0)
该方案同样无额外渲染开销,适合着色器统一封装不便修改的场景。
方案3:单独翻转FBO纹理(不推荐,仅作补充)
如果必须得到正向的FBO纹理供其他逻辑使用,可以增加一个极简的翻转渲染Pass:
- 准备一个全屏Quad和专用翻转着色器,仅做
gl_FragColor = texture2D(inputTex, vec2(vTexCoord.x, 1.0 - vTexCoord.y))逻辑 - 每级滤镜渲染完成后,将FBO输出过一遍翻转Pass再传入下一级
该方案会增加额外的draw call和显存读写开销,非必要不建议使用。
内容的提问来源于stack exchange,提问作者oHuflying
相关产品推荐
相关产品推荐

