0

我正在尝试在 OpenGL 中实现 HDR。

这是我制作 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); )

4

1 回答 1

4

您的代码是有限浮点精度的牺牲品。许多可以在十进制系统中精确表示的值,例如您示例中的 1.1,无法以 CPU/GPU 使用的基于二进制的浮点格式精确表示。

这意味着当您将 1.1 写入输出时,实际值会略多或略少。然后,当您在第二遍中将该值与 1.1 进行比较时,结果将或多或少是任意的,具体取决于该值的四舍五入方式。

如果您将值存储为 R32F,这可能会起作用,因为存储格式的精度将与比较期间使用的算术精度相同。但即使在那种情况下,我也会感到紧张。使用浮点值做几乎任何事情,并希望最终结果与预期值相同,这是危险的,除非您确切了解对值做了什么。

在这种情况下,由于该值存储为 R16F(半浮点),然后以 32 位浮点精度与原始值进行比较,几乎可以肯定不会相同。

于 2014-12-18T06:33:30.847 回答