Значения OpenGL HDR ограничены

Я пытаюсь реализовать HDR в OpenGL.

Вот как я делаю кадровый буфер HDR:

glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

glGenTextures(1, &fboTex);
glBindTexture(GL_TEXTURE_2D, fboTex);
glTexImage2D( GL_TEXTURE_2D, 0,GL_RGBA16F,screen->w, screen->h,0,GL_RGBA,GL_FLOAT,NULL);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);

glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screen->w, screen->h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers);

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
std::cout<<"Error loading the Framebuffer"<<std::endl;
return;
}

Первый шаг, я использую этот пиксельный шейдер для рендеринга моей сцены и тестирования кадрового буфера HDR:

void main (void)
{

gl_FragColor = vec4(1.1,1.1,1.1,0.0);//1.1 just for test

}

И, наконец, я рендеринг на экран с этим пиксельным шейдером:

uniform sampler2D tex;

void main(void)
{

float color = texture2D(tex, gl_TexCoord[0].st).x;

if(color<1.1)gl_FragColor = vec4(1.0,0.0,0.0,0.0); //bad

else gl_FragColor = vec4(0.0,1.0,0.0,0.0);//yes what we want

}

Согласно моему второму шейдеру, я должен получить зеленый полноэкранный режим, если HDR работает. Но, кажется, мои значения фиксируются на первом этапе, и я получаю красный экран (если (цвет<1.1) gl_FragColor = vec4 (1.0,0.0,0.0,0.0); )

0

Решение

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

Это означает, что когда вы записываете 1.1 в ваш вывод, фактическое значение будет немного больше или чуть меньше. Когда вы затем сравните значение с 1,1 во втором проходе, результат будет более или менее произвольным, в зависимости от того, как значение было округлено.

Это могло бы сработать, если вы сохранили значения как R32F, поскольку точность сохраненного формата будет такой же, как точность арифметики, использованной во время сравнения. Но я бы нервничал даже в этом случае. Делать практически все с плавающими значениями и надеяться, что конечный результат будет идентичен ожидаемому значению, опасно, если вы не понимаете именно так что сделано с ценностью.

В этом случае, поскольку значение сохраняется как R16F (half-float), а затем сравнивается с исходным значением с 32-разрядной точностью с плавающей точкой, оно почти наверняка не будет таким же.

4

Другие решения


По вопросам рекламы [email protected]