首页 > 解决方案 > 看不懂learnopengl.com漫射辐照度教程中的captureViews

问题描述

我在https://learnopengl.com/PBR/IBL/Diffuse-irradiance学习 IBL 。

本教程通过创建 6 个视图将 equirectangular 转换为立方体贴图。

视图是以下代码:

glm::mat4 captureViews[] = 
{
   glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 1.0f,  0.0f,  0.0f), glm::vec3(0.0f, -1.0f,  0.0f)),
   glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f,  0.0f,  0.0f), glm::vec3(0.0f, -1.0f,  0.0f)),
   glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f,  1.0f,  0.0f), glm::vec3(0.0f,  0.0f,  1.0f)),
   glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, -1.0f,  0.0f), glm::vec3(0.0f,  0.0f, -1.0f)),
   glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f,  0.0f,  1.0f), glm::vec3(0.0f, -1.0f,  0.0f)),
   glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f,  0.0f, -1.0f), glm::vec3(0.0f, -1.0f,  0.0f))
};

我不明白 的第三个参数glm::lookAt

glm::lookAt的第三个参数是up向量。我认为captureViews应该是:

// zero is    [0, 0, 0]
// right is   [1, 0, 0]
// left is    [-1, 0, 0]
// up is      [0, 1, 0]
// down is    [0, -1, 0]
// back is    [0, 0, 1]
// forward is [0, 0, -1]
glm::mat4 captureViews[] = 
{
   glm::lookAt(zero, right, up),
   glm::lookAt(zero, left, up),
   glm::lookAt(zero, up, back),
   glm::lookAt(zero, down, forward),
   glm::lookAt(zero, back, up),
   glm::lookAt(zero, forward, up)
};

但我完全错了。我不明白教程up向量中的魔力。

谁能为我解释一下?

标签: c++openglglm-math

解决方案


当使用立方体贴图纹理时,必须将 3 维方向矢量转换为相对于贴图一侧的 2 维纹理坐标。

此转换规范的相关部分是OpenGL 4.6 API Core Profile Specification,8.13 Cube Map Texture Selection,第 253 页:

当对立方体贴图纹理进行采样时,(s t r)纹理坐标被视为(rx ry rz)从立方体中心发出的方向矢量。q坐标被忽略。在纹理应用时,插值的每片段方向向量根据最大幅度坐标方向(长轴方向)选择立方体贴图面的二维图像之一。如果两个或多个坐标具有相同的量级,则实现可以定义规则以消除这种情况的歧义。该规则必须是确定性的并且仅取决于(rx ry rz). 表 8.19 中的目标列解释了主轴方向如何映射到特定立方体贴图目标的二维图像。使用sc,tcma由表 8.19 中规定的长轴方向确定,更新后(s t) 的计算如下:

s = 1/2 * (s_c / |m_a| + 1)
t = 1/2 * (t_c / |m_a| + 1)


Major Axis Direction|        Target             |sc |tc |ma |
--------------------+---------------------------+---+---+---+
       +rx          |TEXTURE_CUBE_MAP_POSITIVE_X|−rz|−ry| rx|
       −rx          |TEXTURE_CUBE_MAP_NEGATIVE_X| rz|−ry| rx|
       +ry          |TEXTURE_CUBE_MAP_POSITIVE_Y| rx| rz| ry|
       −ry          |TEXTURE_CUBE_MAP_NEGATIVE_Y| rx|−rz| ry|
       +rz          |TEXTURE_CUBE_MAP_POSITIVE_Z| rx|−ry| rz|
       −rz          |TEXTURE_CUBE_MAP_NEGATIVE_Z|−rx|−ry| rz|
--------------------+---------------------------+---+---+---+

sccooresponds u coordiante 和tccooridnate v。所以tc必须在视图空间向上向量的方向


查看表格的第一行:

+rx | TEXTURE_CUBE_MAP_POSITIVE_X | −rz | −ry | rx

这意味着,对于立方体贴图的 X+ 侧(右侧),对应于切线和副法线的方向是

sc = (0, 0, -1)
tc = (0, -1, 0)

这与表格的第一行完美匹配glm::mat4 captureViews[]

glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f))

因为主要方向是由视线给出的,它是从眼睛位置到目标 ( los = target - eye) 的方向,因此 (1, 0, 0)。
上向量 (or ts) 是 (0, -1, 0)。
sc由视线和向上向量 (0, 0, -1) 的叉积给出。


推荐阅读