У меня есть карта окружения HDR radiance в виде изображения текстуры LatLong 2D, которое я хочу преобразовать в файл cubemap. Я делаю это, загружая карту HDR в виде 2D-флоат-текстуры, проецируя ее на куб, а затем визуализирую сцену внутри этого куба с 6 разных направлений, непосредственно заполняя карту cubemap glFramebufferTexture2D
с соответствующими гранику куба, как цель текстурной функции.Render from HDRi Карта LatLong непосредственно с плавающей точкой cubemap - не HDR
Сформированный cubemap точка cubemap плавающей генерироваться следующим образом:
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) и выходной файл cubemap (как плавающий). Я ожидаю, что лица cubemap получат должным образом обработку текстур с плавающей запятой и напрямую скопируют значения HDR , Тем не менее, куб-карта появляется LDR в момент добавления tonemapping (с переменной экспозицией). Я получаю довольно много полос, и я явно пропускаю точность HDR, как показано на следующем изображении (с экспозицией ~ 7.5)
Я не уверен, есть ли что-то я пропускаю, и я не мог найти много на документы OpenGL в отношении рендеринга непосредственно с плавающей запятой буфера кадров; Я предполагаю, что это возможно, поскольку это не имело бы смысла, если бы это было не так.
Для полноты, здесь соответствующий код, который генерирует cubemap из 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 2D изображение -> куб:
#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 в cubemap преобразование идет хорошо, как окружающая среда 2D правильно визуализации на cubemap, а просто прижат к [0,1] в диапазоне момент это визуализируется как skybox, как будто где-то в течение долгого времени он потерял свои данные с плавающей запятой.
Я застрял в этой проблеме какое-то время и надеялся, что кто-нибудь из вас может пролить некоторое понимание (можно ли даже рисовать кубики таким образом?). Спасибо.
EDIT: Вот та же картина с высокой экспозицией, установленной с Photoshop, как вы можете увидеть много деталей, которые возникают, я потерял в визуализаторе.
Вы пытались нажать экспозицию в исходном файле .hdr. (в фотошопе или что-то еще). Вы видели те же артефакты. Файлы Radiance закодированы в RGBE. Поскольку RGB имеет один и тот же показатель, вы можете получить плохое качество цветности с помощью ярких или темных пикселей. Кроме того, фотографии HDR, как правило, создаются на одной фотографии, сделанной с различными экспозициями. В зависимости от качества камеры версии с низкой экспозицией также могут иметь плохое качество цвета. – pleup
Первое изображение из самого средства рендеринга, из значений плавающей запятой, поэтому 'stb_image.h' уже расшифровал формат RGBE в float. Я также добавил изображение, как видно из Photoshop, с высокой экспозицией, где вы действительно можете увидеть детали, которые ранее не могли видеть с экспозицией по умолчанию. – Djemon
Хорошо. Если это не исходное изображение, оно может появиться из шейдера. Вы указываете точность float в своем шейдере фрагмента. Вы можете попытаться добавить «точность highp float»; в начале фразового шейдера. – pleup