Использование координат по модулю в пространстве экрана в GLSL не дает ожидаемого результата

#c #glsl #shader

#c #glsl #шейдер

Вопрос:

Я полагаю, что это скорее математический вопрос, чем что-либо еще.

Вот базовый шейдер:

 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);
}
 

Сначала мы нормализуем наши координаты X между (0.0,0.1), где 0.0 — крайний левый угол экрана, а 1.0 — крайний правый. Превращая все пиксели с координатами x <.5 в черные, я просто маскирую половину экрана черным. Это приводит к следующему:

введите описание изображения здесь

Если я использую координаты пространства экрана, я могу добиться аналогичного результата, ширина фактического экрана составляет 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);
}
 

Что приводит к тому же:
введите описание изображения здесь

Логически тогда я должен иметь возможность использовать координаты по модулю в пространстве экрана для создания полос. Взяв 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 == 0?

Ответ №1:

Я предполагаю fragCoord , что задано gl_FragCoord .

mod это операция с плавающей запятой, и значения gl_FragCoord не являются целыми. См. Ссылку на Khronos OpenGL:

По умолчанию gl_FragCoord принимает начало координат окна в нижнем левом углу и предполагает, что центры пикселей расположены в центрах полупикселей. Например, местоположение (x, y) (0,5, 0,5) возвращается для самого нижнего левого пикселя в окне.

Поэтому результат операции по модулю никогда не будет равен 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);
 

Комментарии:

1. Вау! Большое вам спасибо! Это помогло мне лучше понять, что происходит!

Ответ №2:

На случай, если кто-нибудь захочет увидеть результат ответа 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);
}
 

введите описание изображения здесь