在屏幕上使用模数 Space GLSL 中的坐标未产生预期结果

Using Modulo on Screen Space Coordinates in GLSL Not Producing Expected Result

我想这更像是一道数学题。

这是一个基本的着色器:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
    
    if(uv.x < .5) col = vec3(0.0,0.0,0.0);

    // Output to screen
    fragColor = vec4(col,1.0);
}

首先,我们在 (0.0,0.1) 之间标准化 X 坐标,其中 0.0 是屏幕最左侧,1.0 是最右侧。通过将 x 坐标 < .5 的所有像素变为黑色,我只是将一半的屏幕遮盖成黑色。结果如下:

如果我用屏幕space坐标也能达到类似的效果,实际屏幕的宽度是800像素。所以我可以通过执行以下操作将 x < 400 的每个像素用黑色遮盖:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
    
    if(fragCoord.x < 400.) col = vec3(0.0,0.0,0.0);

    // Output to screen
    fragColor = vec4(col,1.0);
}

结果相同:

那么从逻辑上讲,我应该可以在屏幕 space 坐标上使用 Modulo 来创建条纹。通过获取 mod(fragCoord.x,10.0) 并检查结果为 0.0 的位置,我应该禁用其 x 值为 10 的任何像素行。

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
    
    if(mod(fragCoord.x, 10.0) == 0.0) col = vec3(0.0,0.0,0.0);

    // Output to screen
    fragColor = vec4(col,1.0);
}

然而,我所期望的并没有发生:

有人可以解释为什么我在 x%10 == 0 的地方看不到黑色像素行吗?

我假设 fragCoord 是由 gl_FragCoord 设置的。

mod is a floating point operation and the values of gl_FragCoord 不是整数。请参阅 Khronos OpenGL 参考资料:

By default, gl_FragCoord assumes a lower-left origin for window coordinates and assumes pixel centers are located at half-pixel centers. For example, the (x, y) location (0.5, 0.5) is returned for the lower-left-most pixel in a window.

因此模运算的结果永远不会是0.0。将 fragCoord.x 转换为整数值并使用 % 运算符:

if(mod(fragCoord.x, 10.0) == 0.0) col = vec3(0.0,0.0,0.0);

if (int(fragCoord.x) % 10 == 0) col = vec3(0.0);

以防有人想看Rabbid76的回答结果

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
    
    if (int(fragCoord.x) % 10 == 0) col = vec3(0.0);
    // Output to screen
    fragColor = vec4(col,1.0);
}