opengl GLSL代码的奇怪行为(变量、条件运算符)

yvfmudvl  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(128)

我尝试用一个简单的片段着色器在OpenGL 3D项目中实现一个360°纹理,我从摄像头的位置向每个像素的方向发送一个单位向量,然后使用一些三角函数得到像素的纹理坐标。但是在一个方向(负x)上有一些像素的颜色错误(它们的颜色来自纹理的底部,这是它们通常不应该有的)。
在这段代码中,像素问题就出现了:

vec2 textureCoords = vec2(
        ((unitV.x < 0.0 ? 0.0 : 0.5) + (atan(unitV.z / unitV.x) / TWOPI)),
        (0.5 - (asin(unitV.y) / PI))
out_Color = texture(skyTexture, textureCoords);

但使用下面的代码,它运行得很好:

if(unitV.x < 0.0)
        out_Color = texture(skyTexture, vec2(0.0 + (atan(unitV.z / unitV.x) / TWOPI), (0.5 - (asin(unitV.y) / PI))));
  else
        out_Color = texture(skyTexture, vec2(0.5 + (atan(unitV.z / unitV.x) / TWOPI), (0.5 - (asin(unitV.y) / PI))));

(vec3 unitVi是来自摄像机位置的像素的归一化方向向量,它是作为来自均匀性的局部变量针对每个像素计算的。)
“如果我没有忽略一个非常基本的东西,这两个版本应该是完全一样的,但结果却不一样......”
注意:我的主要问题不是像素有时是错误的事实,它只是这两个事实,在我看来,确切的代码位导致不同的结果一致。

wlzqhblo

wlzqhblo1#

如果我没有忽略一些非常基本的东西,这两个版本应该是完全相同的,但结果是不同的。
不,它们不一定会产生相同的结果,只有当uintV是动态一致的时,它们才会产生相同的结果。
对纹理进行采样时,GL将计算纹理坐标梯度,以确定纹理是缩小还是放大,并且在使用mip贴图时,还将计算要使用的细节级别。
通常情况下,GPU会通过与2x2像素块中相邻像素的值进行有限差分来 * 近似 * 导数。因此,如果您碰巧有一个2x2像素块,其中,假设左侧像素为uintV.x < 0,右侧像素为uintV.x >= 0,则纹理坐标将出现0.5的巨大跳跃。这意味着GL将假定一半纹理被Map到单个像素,这需要非常高的小中见大贴图级别。
当你写:

if(unitV.x < 0.0)
        out_Color = texture(skyTexture, vec2(0.0 + (atan(unitV.z / unitV.x) / TOWPI), (0.5 - (asin(unitV.y) / PI))));
  else
        out_Color = texture(skyTexture, vec2(0.5 + (atan(unitV.z / unitV.x) / TOWPI), (0.5 - (asin(unitV.y) / PI))));

如果uintV不是动态一致的,纹理采样的效果仍然是不确定的,正如@BDL在注解中提到的。这里的问题是,如果你在同一个调用组中有两个调用采用不同的分支,它们将对从未计算过的值进行有限差分,因为相邻像素甚至没有执行该分支。它可能会给予你一些“更好”的结果,但只是偶然。
使用隐式渐变的正确方法是:

vec4 out_ColorA = texture(skyTexture, vec2(0.0 + ...));    
vec4 out_ColorB = texture(skyTexture, vec2(0.5 + ...));
out_Color = (unitV.x < 0.0) ? outCOlorA : out_ColorB;

但是,在您的用例中,使用 * 显式 * 渐变可能会更好:

vec2 texcoords = vec2((atan(unitV.z / unitV.x) / TOWPI), (0.5 - (asin(unitV.y) / PI)));
vec2 gradX = dFdx(texcoords);
vec2 gradY = dFdy(texcoords);
out_Color = textureGrad(skyTexture, vec2(((unitV.x<0.0)?0.0:0.5)+texcoords.x,texcoords.y), gradX, gradY);

相关问题