2016-10-10 115 views
0

我有一个HDR辐射环境地图作为我想要转换为立方体贴图的LatLong 2D纹理图像。我通过将HDR贴图加载为2D浮动纹理,将其投影到立方体上,然后从6个不同方向渲染该立方体内的场景,直接填充具有各自立方体贴图面的glFramebufferTexture2D的立方体贴图作为函数的纹理目标。从HDRi LatLong地图直接渲染到浮点立方图 - 不是HDR

生成立方体贴图是产生如下浮点立方体贴图:

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 

for (unsigned int i = 0; i < 6; ++i) 
{ 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, NULL); 
} 
if (mipmap) 
    glGenerateMipmap(GL_TEXTURE_CUBE_MAP); 

注意,类型参数是GL_FLOAT所以应适当接受HDR值。 HDR图像是使用stb_image.h如下加载:

if (stbi_is_hdr(path.c_str())) 
{ 
    stbi_set_flip_vertically_on_load(true); 

    int width, height, nrComponents; 
    float *data = stbi_loadf(path.c_str(), &width, &height, &nrComponents, 0); 
    if (data) 
    { 
     GLenum format; 
     if (nrComponents == 3) 
      format = GL_RGB; 
     else if (nrComponents == 4) 
      format = GL_RGBA; 

     Bind(); 
      glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_FLOAT, data); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
      if (Mipmapping) 
       glGenerateMipmap(GL_TEXTURE_2D); 
     Unbind(); 
     stbi_image_free(data); 
    } 
} 

我也试过遍历数组和获取最大浮点值,看看是否HDR正确地加载和我目前的HDR地图的最高浮点值是288这远远高于我期望的1.0

基于输入纹理(HDR浮点图)和输出立方体贴图(作为浮点数),我认为事情会变得棘手,我期望立方体贴图的面部可以正确对待为浮点纹理并直接复制HDR值。然而,当我添加色调映射(具有可变曝光)时,立方体贴图出现LDR。我得到了相当多的条带,并且我明显缺少HDR的精度,如下图所示(曝光为〜7.5)

LDR image of what should be HDR

我不知道是否有什么我失踪,我找不到太多关于OpenGL的有关直接渲染到浮点帧缓冲的文档;我认为这是可能的,因为如果不是这样,它是没有意义的。

为了完整起见,这里是产生距离的LatLong图像的立方体贴图(与renderCustomCommand渲染适当采样立方体设置)的相关代码:

glGenFramebuffers(1, &m_FramebufferCubemap); 
glGenRenderbuffers(1, &m_CubemapDepthRBO); 

Camera faceCameras[6] = { 
    Camera(position, vec3(1.0f, 0.0f, 0.0f), vec3(0.0f, -1.0f, 0.0f)), 
    Camera(position, vec3(-1.0f, 0.0f, 0.0f), vec3(0.0f, -1.0f, 0.0f)), 
    Camera(position, vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f)), 
    Camera(position, vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f,- 1.0f)), 
    Camera(position, vec3(0.0f, 0.0f, 1.0f), vec3(0.0f, -1.0f, 0.0f)), 
    Camera(position, vec3(0.0f, 0.0f, -1.0f), vec3(0.0f, -1.0f, 0.0f)) 
}; 

glBindFramebuffer(GL_FRAMEBUFFER, m_FramebufferCubemap); 
glBindRenderbuffer(GL_RENDERBUFFER, m_CubemapDepthRBO); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_CubemapDepthRBO); 

glViewport(0, 0, width, height); 
glBindFramebuffer(GL_FRAMEBUFFER, m_FramebufferCubemap); 

for (unsigned int i = 0; i < 6; ++i) 
{ 
    Camera *camera = &faceCameras[i]; 
    camera->SetPerspective(90.0f, width/height, 0.1f, 100.0f); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubeTarget->ID, 0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    for (unsigned int i = 0; i < renderCommands.size(); ++i) 
    { 
     renderCustomCommand(&renderCommands[i], camera); 
    } 
} 

glBindFramebuffer(GL_FRAMEBUFFER, 0); 
glViewport(0, 0, m_RenderSize.x, m_RenderSize.y); 

下面是用于采样的LatLong二维码图片 - >立方体:

#version 330 core 
out vec4 FragColor; 
in vec3 wPos; 

#include sample.glsl 

uniform sampler2D environment; 

void main() 
{ 
    vec2 uv = SampleLatLong(normalize(wPos)); 
    vec3 color = texture(environment, uv).rgb; 
    FragColor = vec4(color, 1.0); 
} 

注意,LatLong网到立方体贴图转换顺利,作为2D环境上正常渲染一个立方体贴图,而是简单地夹到[0,1]区间上它呈现为一个瞬间天空盒,就好像某个地方一样很长的过程中,它失去了它的浮点数据。

我一直在这个问题上停留了一段时间,并希望你们中的任何一个人都能够发现一些见解(甚至有可能直接渲染浮动立方体像这样?)。谢谢。


编辑:这里是相同的图像具有高曝光从Photoshop设置,你可以看到很多细节浮现,我在渲染器已经失去了。

HDR image from Photoshop with high exposure

+0

您是否尝试在原始.hdr文件上推送曝光。 (在Photoshop或其他)。你有没有看到相同的人造物品? Radiance文件以RGBE编码。由于RGB共享相同的指数,因此可能会导致色彩质量差,亮度或暗色像素较多。另外,HDR照片通常是从不同曝光拍摄的相同照片创建的。根据相机质量的不同,低曝光版本也可能具有较差的色彩质量。 – pleup

+0

第一个图像来自渲染器本身,来自浮点值,所以'stb_image.h'已经将RGBE格式解码为浮点。我还从Photoshop中添加了高曝光度的图像,您可以确实看到以前用默认曝光度看不到的细节。 – Djemon

+0

好的。如果它不是源图像,它可能来自着色器。你是否在片段着色器中指定浮点精度?您可能会尝试添加“精度最高的浮点数”;在碎片着色器的开始处。 – pleup

回答

1

您的通话glTexImage2D的第三个参数需要GL_RGB16F或GL_RGB32F。 它指定了内部格式。

最后两个参数GL_RGB和GL_FLOAT仅用于指定可选数据指针的内存布局。他们不影响内部格式。

+0

就是这样!非常感谢! – Djemon