我有一個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)
我不知道是否有什麼我失蹤,我找不到太多關於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文件上推送曝光。 (在Photoshop或其他)。你有沒有看到相同的人造物品? Radiance文件以RGBE編碼。由於RGB共享相同的指數,因此可能會導致色彩質量差,亮度或暗色像素較多。另外,HDR照片通常是從不同曝光拍攝的相同照片創建的。根據相機質量的不同,低曝光版本也可能具有較差的色彩質量。 – pleup
第一個圖像來自渲染器本身,來自浮點值,所以'stb_image.h'已經將RGBE格式解碼爲浮點。我還從Photoshop中添加了高曝光度的圖像,您可以確實看到以前用默認曝光度看不到的細節。 – Djemon
好的。如果它不是源圖像,它可能來自着色器。你是否在片段着色器中指定浮點精度?您可能會嘗試添加「精度最高的浮點數」;在碎片着色器的開始處。 – pleup