Более плавные градиентные переходы с OpenGL?

Я использую следующий шейдер для рендеринга купола неба для имитации ночного неба. Моя проблема - четко видимые переходы между цветами.

Что вызывает эти резкие градиентные переходы?

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

Фрагментный шейдер:

#version 330
in vec3 worldPosition;
layout(location = 0) out vec4 outputColor;

void main()
{
    float height = 0.007*(abs(worldPosition.y)-200);    
    vec4 apexColor = vec4(0,0,0,1);
    vec4 centerColor = vec4(0.159, 0.132, 0.1, 1);

    outputColor = mix(centerColor, apexColor, height);
}

Пиксельный формат FBO:

GL.TexImage2D(
    TextureTarget.Texture2D,
    0,
    PixelInternalFormat.Rgb32f,
    WindowWidth,
    WindowHeight,
    0,
    PixelFormat.Rgb,
    PixelType.Float,
    IntPtr.Zero )

person livin_amuk    schedule 17.07.2018    source источник
comment
Как ко всему этому относится формат RGB32F? Я бы сказал, что вы не видите полосы в этой текстуре, вы просто видите ее, когда вы, наконец, визуализируете (или переносите) ее в окончательный буфер кадра, который обычно имеет только 8-битную точность.   -  person derhass    schedule 17.07.2018
comment
@derhass Я включил информацию о формате пикселей, если это было связано с проблемой, это казалось правдоподобным, учитывая то, что я знал в то время.   -  person livin_amuk    schedule 18.07.2018


Ответы (2)


Как объяснил Ripi2, 24-битный цвет не может точно представить градиент, и разрывы между представляемыми цветами становятся резко заметными на градиентах одного цвета.

Чтобы скрыть цветовые полосы, я реализовал простую форму упорядоченного сглаживания с текстурой 8x8, сгенерированной с использованием этого алгоритма матрицы Байера.

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

vec4 dither = vec4(texture2D(MyTexture0, gl_FragCoord.xy / 8.0).r / 32.0 - (1.0 / 128.0));
colourOut += dither;

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

person livin_amuk    schedule 18.07.2018
comment
Будет намного лучше, если вы отредактируете вопрос и ответ и используете какое-то изображение, которое не почти черное, что, пожалуй, наиболее трудно увидеть сбои. - person Ripi2; 18.07.2018

Обычно мониторы имеют разрешение 8 бит на канал. Например, интенсивность красного цвета варьируется от 0 до 255.

Если размер вашего окна по горизонтали составляет 768 пикселей, и вы хотите полный градиент на красном канале, то каждый шаг цвета занимает 768/256 = 3 пикселя. В зависимости от вашего здоровья глаз вы можете увидеть полосы.

Как сделать плавный градиент на этих 3 пикселях? Используйте субпиксельный рендеринг.
По сути, вы «расширяете» цветовой шаг между соседними пикселями: добавляете небольшое количество других каналов к соседям и немного уменьшаете количество центрального пикселя.

person Ripi2    schedule 17.07.2018
comment
Субпиксельный рендеринг предназначен для сглаживания. Я думаю, вы имеете в виду дизеринг. - person derhass; 17.07.2018
comment
@derhass Ну, здесь будет использоваться дизеринг Флойда-Стейнберга. Суть в использовании соседних пикселей для сглаживания градиента. - person Ripi2; 17.07.2018
comment
Флойда-Стейнберга сложно реализовать параллельно. простой упорядоченный дизеринг (байер) очень хорошо работает на графических процессорах, и его легко реализовать. - person derhass; 17.07.2018