2016-10-10 2 views
0

У меня есть карта окружения 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)

LDR image of what should be HDR

Я не уверен, есть ли что-то я пропускаю, и я не мог найти много на документы 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 image from Photoshop with high exposure

+0

Вы пытались нажать экспозицию в исходном файле .hdr. (в фотошопе или что-то еще). Вы видели те же артефакты. Файлы Radiance закодированы в RGBE. Поскольку RGB имеет один и тот же показатель, вы можете получить плохое качество цветности с помощью ярких или темных пикселей. Кроме того, фотографии HDR, как правило, создаются на одной фотографии, сделанной с различными экспозициями. В зависимости от качества камеры версии с низкой экспозицией также могут иметь плохое качество цвета. – pleup

+0

Первое изображение из самого средства рендеринга, из значений плавающей запятой, поэтому 'stb_image.h' уже расшифровал формат RGBE в float. Я также добавил изображение, как видно из Photoshop, с высокой экспозицией, где вы действительно можете увидеть детали, которые ранее не могли видеть с экспозицией по умолчанию. – Djemon

+0

Хорошо. Если это не исходное изображение, оно может появиться из шейдера. Вы указываете точность float в своем шейдере фрагмента. Вы можете попытаться добавить «точность highp float»; в начале фразового шейдера. – pleup

ответ

1

Третий параметр вашего glTexImage2D вызова должен быть GL_RGB16F или GL_RGB32F. Указывает внутренний формат.

Два параметра GL_RGB и GL_FLOAT в конце используются только для указания макета памяти необязательного указателя данных. Они не влияют на внутренний формат.

+0

Вот и все! Спасибо огромное! – Djemon

Смежные вопросы