Использование по модулю координат экранного пространства в 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 < 0,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);
}

Что приводит к тому же:

По логике, я должен иметь возможность использовать 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?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
227
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я предполагаю, что 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);

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

Alex 20.12.2020 02:00

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

Другие вопросы по теме