0

キューブマップに変換したい LatLong 2D テクスチャ イメージとして HDR 放射輝度環境マップがあります。これを行うには、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);

type パラメータはGL_FLOATHDR 値を適切に受け入れる必要があるため、注意してください。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 float マップ) と出力キューブマップ (float として) に基づいて、物事がトリッキーになるところです。キューブマップの面が浮動小数点テクスチャとして適切に処理され、HDR 値が直接コピーされることを期待します。ただし、キューブマップは、トーンマッピング (可変露出) を追加した瞬間に LDR に見えます。非常に多くのバンディングが発生し、次の画像が示すように HDR の精度が明らかに欠けています (露出が ~7.5 の場合)。

HDR であるべきものの LDR 画像

不足しているものがあるかどうかはわかりません。また、浮動小数点フレームバッファへの直接レンダリングに関する 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 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 環境はキューブマップ上で適切にレンダリングされますが、プロセスのどこかでフローティングが失われたかのように、スカイボックスとしてレンダリングされた瞬間に [0,1] の範囲にクランプされるだけです。ポイントデータ。

私はしばらくの間この問題に悩まされていましたが、あなたの誰かが何らかの洞察を得ることができることを望んでいました (このようなフロート キューブマップに直接レンダリングすることさえ可能ですか?)。ありがとうございました。


編集:レンダラーで失った多くの詳細が浮かび上がるのを見ることができるので、これは Photoshop から設定された高露出の同じ写真です。

高露出の Photoshop からの HDR 画像

4

1 に答える 1