OpenGL 渲染到立方体贴图

OpenGL rendering to cubemap

我正在尝试渲染到立方体贴图。正在渲染的场景是地形。 我使用经纬度调试显示来查看某个立方体贴图中的内容。 左下方的两个调试视图是仅显示方向的虚拟立方体贴图和一个带有真实图片的立方体贴图。

右下半部分的调试视图显示了我在立方体贴图中渲染的内容。

我尝试了很多不同的组合来设置相机,但其中 none 给出了合乎逻辑的结果。我还将代码与几个实施动态立方体贴图的示例进行了比较,但我仍然无法发现问题所在。我不知道下一步该尝试什么,所以欢迎任何帮助或建议。

绘制到立方体贴图函数:

void Draw(GLuint cubemap, glm::ivec2 res, glm::vec3 position)
{

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glBindRenderbuffer(GL_RENDERBUFFER, rb);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, res.x, res.y);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);

    // camera
    glm::mat4 p = glm::perspective(90.0f, 1.0f, 0.01f, 10.0f);
    glm::mat4 v;

    glm::vec3 targets[6] = {
        glm::vec3(+1.0f, 0.0f, 0.0f),
        glm::vec3(-1.0f, 0.0f, 0.0f),
        glm::vec3(0.0f, +1.0f, 0.0f),
        glm::vec3(0.0f, -1.0f, 0.0f),
        glm::vec3(0.0f, 0.0f, +1.0f),
        glm::vec3(0.0f, 0.0f, -1.0f)
    };
    glm::vec3 ups[6] = {
        glm::vec3(0.0f, 1.0f, 0.0f),
        glm::vec3(0.0f, 1.0f, 0.0f),
        glm::vec3(0.0f, 0.0f, 1.0f),
        glm::vec3(0.0f, 0.0f, -1.0f),
        glm::vec3(0.0f, 1.0f, 0.0f),
        glm::vec3(0.0f, 1.0f, 0.0f)
    };

    // render
    for (int i = 0; i < 6; i++)
    {
        glViewport(0, 0, res.x, res.y);
        // setup target face
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap, 0);
        // setup camera
        v = glm::lookAt(position, position + targets[i], ups[i]);
        // draw
        DrawTerrain(terrain.heightmap, terrain.m, v, p);    // model, view, projection matrices
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

矩阵错了。在对值进行非常彻底的检查后,glm 返回的值对于投影和视图矩阵都不正确。我会看看是否会报告错误修复请求,但现在,这里是实际修复矩阵的代码。

// projection matrix (fov = 90 degrees, aspect = 1.0)
glm::mat4 p;
float n = 0.1f, f = 2.0f; // near and far
p[0][0] = 1.0f;
p[1][1] = 1.0f;
p[2][2] = -f / (f - n);
p[2][3] = -1.0f;
p[3][2] = -(f*n) / (f - n);

glm::vec3 targets[6] = {
    glm::vec3(+1.0f, 0.0f, 0.0f),
    glm::vec3(-1.0f, 0.0f, 0.0f),
    glm::vec3(0.0f, +1.0f, 0.0f),
    glm::vec3(0.0f, -1.0f, 0.0f),
    glm::vec3(0.0f, 0.0f, +1.0f),
    glm::vec3(0.0f, 0.0f, -1.0f)
};
glm::vec3 ups[6] = {
    glm::vec3(0.0f, 1.0f, 0.0f),
    glm::vec3(0.0f, 1.0f, 0.0f),
    glm::vec3(0.0f, 0.0f, -1.0f),
    glm::vec3(0.0f, 0.0f, 1.0f),
    glm::vec3(0.0f, 1.0f, 0.0f),
    glm::vec3(0.0f, 1.0f, 0.0f)
};
for(int i=0; i<6; ++i)
{
    // view matrix
    v = glm::lookAt(position, position + targets[i], ups[i]);
    v[0][2] *= -1.0f;
    v[1][2] *= -1.0f;
    v[2][2] *= -1.0f;
    v[3][2] *= -1.0f;   
    // render...
}

编辑:

根据 Andreas 的评论,我进行了更多调查。

glm::perspective 需要以弧度为单位的 FOV,但由于使用该函数的每个示例都以度数调用它,所以我从未真正怀疑过它。在 scrathapixel 检查后,我确定透视矩阵是正确的(即使行列式为负)。所以,FOV 是弧度的,那是我的错误。

然而,lookAt 是错误的。我比较了多个资源中的该函数,并且肯定与 bgfx's lookAt 进行了比较,实际上,整个第三列的符号应该颠倒了。因此,我将视图矩阵的该列与 -1 相乘的变化仍然存在。