#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 внутри цикла - это вообще ничего не поменяет... Я просто в смятении, дамы и господа, и запрашиваю помощи.