@meta941

Как вычисляется цвет пикселя во фрагментном шейдере?

#version 330


out vec4 fragColor;

uniform vec2 resolution = vec2(1280, 720);
uniform float time;

vec2 rotate2D(vec2 uv, float a)
{
    float s = sin(a);
    float c = cos(a);
    return mat2(c, -s, s, c) * uv;
}

void main()
{
    vec2 uv = (gl_FragCoord.xy - 0.5 * resolution.xy) / resolution.y;
    vec3 col = vec3(0.0);

    uv = rotate2D(uv, time);

    float r = 0.17;
    for (float i = 0.0; i < 60.0; i += 1)
    {
        float a = i / 10;
        float dx = 2 * r * cos(a) - r * cos(2 * a);
        float dy = 2 * r * sin(a) - r * sin(2 * a);

        col += 0.001 / length(uv - vec2(dx + 0.1, dy));
    }

    fragColor = vec4(col, 1.0);
}


Это фрагментный шейдер для рисования кардиоиды.
И меня смущает конкретно цикл for

На сколько сейчас хватает моего понимания: функция main выполняется циклично для каждого отдельного фрагмента.
Тогда вопрос: почему значение col, куда вычисляется цвет пикселя, не имеет одно и то же значение на выходе, если fragColor присваивается только после завершения цикла?

Я попросил сделать ChatGPT эмуляцию такого кода на C#
col внутри main

static void Main()
{
    // Инициализация переменных
    float r = 0.17f;
    

    // Примерные значения для `uv`
    Tuple<float, float> uv = Tuple.Create(0.5f, 0.5f);

    for (int j = 0; j < 1280; j++) // эмуляция main
    {
        float col = 0.0f; // еслии сделать так, то значение всегда будет 0,10195324
        for (float i = 0.0f; i < 60.0f; i += 1.0f)
        {
            float a = i / 10.0f;
            float dx = 2 * r * (float)Math.Cos(a) - r * (float)Math.Cos(2 * a);
            float dy = 2 * r * (float)Math.Sin(a) - r * (float)Math.Sin(2 * a);

            // Вычисляем расстояние между `uv` и `(dx + 0.1, dy)`
            float distance = Length(uv, Tuple.Create(dx + 0.1f, dy));
            col += 0.001f / distance;
        }

        Console.WriteLine("Final col value: " + col);
    }
}

// Функция для вычисления длины (расстояния) между двумя точками
static float Length(Tuple<float, float> p1, Tuple<float, float> p2)
{
    float dx = p1.Item1 - p2.Item1;
    float dy = p1.Item2 - p2.Item2;
    return (float)Math.Sqrt(dx * dx + dy * dy);
}


col вне main

static void Main()
{
    // Инициализация переменных
    float r = 0.17f;
    

    // Примерные значения для `uv`
    Tuple<float, float> uv = Tuple.Create(0.5f, 0.5f);
    float col = 0.0f; // еслии сделать так, то col будет постепенно накапливаться

    for (int j = 0; j < 1280; j++) // эмуляция main
    {
        for (float i = 0.0f; i < 60.0f; i += 1.0f)
        {
            float a = i / 10.0f;
            float dx = 2 * r * (float)Math.Cos(a) - r * (float)Math.Cos(2 * a);
            float dy = 2 * r * (float)Math.Sin(a) - r * (float)Math.Sin(2 * a);

            // Вычисляем расстояние между `uv` и `(dx + 0.1, dy)`
            float distance = Length(uv, Tuple.Create(dx + 0.1f, dy));
            col += 0.001f / distance;
        }

        Console.WriteLine("Final col value: " + col);
    }
}

// Функция для вычисления длины (расстояния) между двумя точками
static float Length(Tuple<float, float> p1, Tuple<float, float> p2)
{
    float dx = p1.Item1 - p2.Item1;
    float dy = p1.Item2 - p2.Item2;
    return (float)Math.Sqrt(dx * dx + dy * dy);
}



Впрочем, даже если я поставлю fragColor внутри цикла - это вообще ничего не поменяет... Я просто в смятении, дамы и господа, и запрашиваю помощи.
  • Вопрос задан
  • 36 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы