GLSL着色器优化:用数学方法替代UV翻转中的if语句
无分支实现UV轴翻转的GLSL优化方案
原着色器通过rot向量控制UV的X/Y轴翻转,但使用if分支会引发GPU线程发散,影响渲染性能;同时当rot.x或rot.y为0时,直接执行rot.x - p.x会得到负UV值,导致纹理采样错误。可以利用GLSL的线性插值特性或直接数学运算实现无分支的翻转逻辑,完全替代条件判断。
核心逻辑说明
我们的需求是:
- 当
rot.x = 1时,翻转X轴UV:p.x = 1.0 - p.x - 当
rot.x = 0时,保持原UV值:p.x = p.x
GLSL内置的mix(a, b, t)函数本质是线性插值,计算逻辑为a*(1-t) + b*t,正好匹配上述需求:当t=1时取b值(翻转后的UV),当t=0时取a值(原UV)。同理可应用到Y轴。
优化后完整代码
// 优化后无分支版本,已适配AGK classic #ifdef GL_ES precision mediump float; precision mediump int; #endif #define PROCESSING_TEXTURE_SHADER varying mediump vec2 uvVarying; uniform sampler2D texture0; uniform vec2 rot; // 从AGK程序传入的控制向量,x/y取值仅为0或1 void main(void) { // 无分支实现UV翻转:rot.x=1时翻转X轴,rot.y=1时翻转Y轴 vec2 p = vec2( mix(uvVarying.x, 1.0 - uvVarying.x, rot.x), mix(uvVarying.y, 1.0 - uvVarying.y, rot.y) ); vec3 col = texture2D(texture0, p).rgb; gl_FragColor = vec4(col, 1.0); }
等效的纯数学运算实现
如果不想使用mix函数,也可以直接展开线性插值的计算逻辑,效果完全一致:
vec2 p = uvVarying; p.x = rot.x * (1.0 - p.x) + (1.0 - rot.x) * p.x; p.y = rot.y * (1.0 - p.y) + (1.0 - rot.y) * p.y;
两种实现都完全避免了条件分支,GPU可以高效执行SIMD指令,同时确保rot为0时UV值保持不变,不会出现负数值的采样错误。
内容的提问来源于stack exchange,提问作者Peter Kennedy
相关产品推荐
相关产品推荐

