OpenGL ES片段着色器双条件判断时的异常行为排查
OpenGL ES片段着色器同时绘制横竖线时出现错位异常
我正在开发一款基于OpenGL-ES的Android应用,近期编写片段着色器时遭遇怪异问题。尝试通过如下代码在纹理上绘制像素网格:
#type fragment #version 300 es precision mediump float; uniform sampler2D uTexture; in vec4 fColor; in vec2 fTexCoordinate; out vec4 color; void main() { if (fColor.xyzw == vec4(0, 0, 0, 0)) { float x = fTexCoordinate.x; float y = fTexCoordinate.y; float targetX = round(x * 1000.0) / 1000.0; float targetY = round(y * 1000.0) / 1000.0; bool paintVertical = abs(x - targetX + 0.0001) < 0.0001; bool paintHorizontal = abs(y - targetY + 0.0001) < 0.0001; if (paintHorizontal) { color = vec4(1.0, 0.0, 0.0, 1.0); return; } color = texture(uTexture, fTexCoordinate); } else { color = fColor; } }
单独使用if (paintHorizontal)判断时,水平线绘制正常;替换为if (paintVertical)时,垂直线绘制也正常;但改用if (paintHorizontal || paintVertical)同时判断时,出现了线条错位的异常结果。
问题原因及解决方案
核心问题出在你判断线条的逻辑上:
- 你写的
abs(x - targetX + 0.0001) < 0.0001并不是计算x与targetX的绝对误差,而是把x - targetX的结果偏移了0.0001再判断绝对值。这个表达式等价于x - targetX处于[-0.0001, 0]区间,也就是只检测x小于等于targetX且差值在0.0001内的像素。 - 单独判断水平线或垂直线时,这个单向偏移只会让线条往一个方向轻微偏移,视觉上不容易察觉异常;但同时判断横竖线时,两个轴的单向偏移逻辑叠加,导致线条的交叉位置、整体走向出现错位。
修正方法很简单,把判断逻辑改成直接计算x和targetX的绝对差值是否小于阈值:
bool paintVertical = abs(x - targetX) < 0.0001; bool paintHorizontal = abs(y - targetY) < 0.0001;
这样就能正确检测到目标坐标附近的像素,同时绘制横竖线时就不会出现错位问题了。
内容的提问来源于stack exchange,提问作者CLR 123
相关产品推荐
相关产品推荐

