Всегда ли сэмплеры OpenGL GLSL возвращают значения с плавающей точкой от 0,0 до 1,0? - PullRequest
6 голосов
/ 22 февраля 2012

Я создал пару текстур RGBA с плавающей точкой ...

glBindTexture( GL_TEXTURE_2D, texid[k] );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA,
             GL_FLOAT, data);

, а затем я поочередно буферизирую рендеринг / сэмплирование их в шейдерной программе

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                       GL_TEXTURE_2D, texid[i], 0)

...

    state_tex_loc = glGetUniformLocation( program, "state_tex" )
    glUniform1i( state_tex_loc, 0 )
    glActiveTexture( GL_TEXTURE0 )
    glBindTexture( GL_TEXTURE_2D, texid[1-i] )

...

    void main( void )
    {
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        vec2 sample_pos = gl_Vertex.xy / vec2( xscale, yscale );
        vec4 sample = texture2D( state_tex, sample_pos.xy );
        sample.rgb = sample.rgb + vec3( 0.5, 0.5, 0.5 );
        if ( sample.r > 1.1 )
            sample.rgb = vec3( 0.0, 0.0, 0.0 );
        gl_FrontColor = sample;
    }

...

    void main( void )
    {
        gl_FragColor = gl_Color;
    }

Обратите внимание на то, что sample.r больше 1,1.Такого никогда не бывает.Кажется, что либо вызов texture2D, либо вывод шейдерного фрагмента ограничивает значение sample.rgb значением [0.0..1.0].И все же, я понимаю, что сами текстуры имеют полные типы с плавающей точкой.

Есть ли способ избежать этого зажима?

ОБНОВЛЕНИЕ:

В соответствии с инструкциями ниже, я исправил мой glTexImage2D() вызов для использования GL_RGBA32F_ARB, но я все ещене получайте значение больше 1,0 из сэмплера.

ОБНОВЛЕНИЕ 2:

Я только что попытался инициализировать текстуры со значениями больше 1,0, и это работает!texture2d() возвращает исходные значения> 1,0.Возможно, это означает, что проблема в фрагментном шейдере, пишущем в текстуру?

ОБНОВЛЕНИЕ 3:

Я пытался изменить шейдеры, и это работает:

    varying vec4 out_color;
    void main( void )
    {
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        vec2 sample_pos = gl_Vertex.xy / vec2( xscale, yscale );
        vec4 sample = texture2D( state_tex, sample_pos.xy );
        sample.rgb = sample.rgb + vec3( 0.5, 0.5, 0.5 );
        if ( sample.r > 1.1 )
            sample.rgb = vec3( 0.0, 0.0, 0.0 );
        out_color = sample;
    }

...

    varying vec4 out_color;
    void main( void )
    {
        gl_FragColor = out_color;
    }

Почему использование настраиваемой переменной работы, но использование встроенной переменной gl_FrontColor / gl_Color не работает?

1 Ответ

7 голосов
/ 22 февраля 2012

Я создал пару RGBA-текстур с плавающей точкой ...

Нет, вы этого не сделали.

glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_FLOAT, data);

Этот оператор не создаеттекстура с плавающей точкой.Ну, может быть, так и есть, если вы используете OpenGL ES, но это определенно не в настольном GL.Хотя я почти уверен, что OpenGL ES не позволяет использовать «4» в качестве внутреннего формата.

В настольном GL третий параметр для glTexImage2D определяет формат изображения .Это этот параметр, который сообщает OpenGL, являются ли данные с плавающей точкой, целыми числами или чем-то еще.Когда вы используете «4» (что вы должны никогда делать, потому что это ужасный способ указать внутренний формат. Всегда используйте реальный внутренний формат), вы сообщаете OpenGL, что вы хотите 4 беззнакового нормализованного целого числакомпоненты.

Последние три параметра определяют местоположение, формат и тип данных пикселей данных, которые вы хотите загрузить в текстуру .В настольных GL это не влияет на то, как хранятся данные.Вы просто сообщаете OpenGL, как выглядят ваши входные пиксели.Спецификация OpenGL ES неразумно меняет это.Последние три параметра имеют некоторое влияние на внутренний формат данных.

В любом случае, если вам нужны 32-битные числа с плавающей запятой, вы должны запросить их:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data);

Почему использование нестандартной переменной работы, но использование встроенной переменной gl_FrontColor / gl_Color не работает?

Потому что она встроенная.Я годами не использовал встроенный GLSL, поэтому я даже не заметил этого.

Спецификация совместимости 3.3 имеет функцию glClampColor, которая определяет поведение цветового ограничения вершин (и фрагментов).Это влияет только на встроенные модули.Лично?Я бы избегал этого и просто не использовал встроенный материал вообще.

...