gpt4 book ai didi

c++ - 从 HDRi LatLong 贴图直接渲染到浮点立方体贴图 - 而不是 HDR

转载 作者:行者123 更新时间:2023-11-28 01:59:53 24 4
gpt4 key购买 nike

我有一个 HDR 辐射环境贴图作为 LatLong 2D 纹理图像,我想将其转换为立方体贴图。为此,我将 HDR 贴图加载为 2D 浮点纹理,将其投影到一个立方体上,然后从 6 个不同方向渲染该立方体内部的场景,直接使用具有相应立方体贴图面的 glFramebufferTexture2D 填充立方体贴图作为函数的纹理目标。

生成的立方体贴图是一个浮点立方体贴图,生成方式如下:

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 值。使用 stb_image.h 加载 HDR 图像,如下所示:

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 浮点贴图)和输出立方体贴图(作为 float )我希望立方体贴图面被正确地视为浮点纹理并直接复制 HDR 值。然而,当我添加色调映射(使用可变曝光)时,立方体贴图出现 LDR,我得到了很多 strip ,并且我明显缺少 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] 范围内,就好像过程中的某个地方一样丢失了它的 float 据。

我已经在这个问题上纠结了一段时间,希望你们中的任何人都能给出一些见解(甚至可以像这样直接渲染到 float 立方体贴图吗?)。谢谢。


编辑:这是从 Photoshop 设置高曝光度的同一张图片,您可以看到很多我在渲染器中丢失的细节。

HDR image from Photoshop with high exposure

最佳答案

glTexImage2D 调用的第三个参数需要是 GL_RGB16F 或 GL_RGB32F。它指定了内部格式。

最后的两个参数GL_RGB和GL_FLOAT只是用来指定可选数据指针的内存布局。它们不会影响内部格式。

关于c++ - 从 HDRi LatLong 贴图直接渲染到浮点立方体贴图 - 而不是 HDR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39965899/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com