Значения 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 работает. Но кажется, что мои значения зажаты на первом шаге, и я получаю красный экран ( if(color‹1.1)gl_FragColor = vec4(1.0,0.0,0.0,0.0); )


person CLOYZ    schedule 18.12.2014    source источник
comment
1.1 не может быть точно представлено числом с плавающей запятой. Может попробовать сравнить с 1.05? Или установить значение 1,2?   -  person Reto Koradi    schedule 18.12.2014


Ответы (1)


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

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

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

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

person Reto Koradi    schedule 18.12.2014