在 GLSL 中使相机正常
Get the camera normal in GLSL
我有一个 OpenGL 场景,我在其中查看这样的对象:
gluLookAt(10, 10, -10, -10, -10, 10, 0, 1, 0);
所以我知道如果我想在着色器中使用相机的 z 轴,它看起来会像这个的归一化向量:
vec3(1.0, 1.0, -1,0);
有没有办法在顶点着色器中计算这个向量?
我想计算 near/far 裁剪平面的法线,但无法在顶点(或片段)着色器中找到执行此操作的方法。
我使用的是旧管道 (OpenGL v2.0/ GLSL v. 1.10),不想将矢量传递给着色器(尽管我知道这是执行此操作的常用且高效的方法).
(已弃用)gluLookAt 的参数是 (vec3) eye_、center_ 和 up_ 的分量(x_ 表示向量值数据 x_)
f: ℝ^3 x ℝ^3 x ℝ^3 -> ℝ4xℝ4
eye_, center_, up_ -> ViewMatrix
因此您可能寻找的是
dir_ = normalize(center_ - eye_),
在着色器中获取它们的最佳方式和位置取决于您使用的 GL 和 GLSL 版本。
这个向量
vec3(1.0, 1.0, -1,0);
btw has length sqrt(3), thus it's not normalized.
编辑
了解 OpenGL 和 GLSL 版本后,可以从
GLSL 1.10.59 已经有了自定义制服(我记不清了,2.0/1.10 太久远了);因此,您只需将该向量作为制服传入即可,仅此而已。
因为它用于每个顶点,所以计算一次比在着色器中再次为每个顶点计算一次更有效(当然,假设渲染的顶点块相当大)。
将其作为制服传递给您的着色器。请参阅 glUniform3f.
的文档
在客户端代码中,执行如下操作:
auto cameraUp = camera.getUp();
glUniform3f(uniformLocationInShader, cameraUp.x, cameraUp.y, cameraUp.z)
在顶点着色器中,为相机向上矢量添加统一,然后按预期使用它。
uniform vec3 cameraUp;
void main()
{
// do stuff with cameraUp
}
固定函数顶点变换通过应用两个矩阵来工作:
- 从对象 space 到眼睛 space
的 "ModelView" 矩阵变换
- 从眼睛 space 到剪辑 space
的 "Projection" 矩阵
gluLookAt()
所做的是通过在 world space 中定义一些相机来指定视图矩阵。而你似乎要重构的是这个世界的视线方向space.
但是,对于固定功能 GL,不可能。您所拥有的只是 产品 view * model
。如果没有更多信息,您无法将其分解为 view
和 model
部分。 none 这些信息存在于固定函数 GL 中——它从来没有 有 一个世界 space,或者关心一个单独的视图矩阵。这种区别确实发生在应用程序逻辑中 - 如果有的话。
有趣的问题是:你甚至需要世界 space 的观察方向做什么?固定函数 GL 在眼睛 space 中进行此类计算,其中观察方向只是 (0,0,-1,0)。
所以我看到两个选项供您选择:
- 使用统一(或其他将数据传输到着色器的方法)来指定一些附加信息,就像其他答案已经建议的那样
- 直接用眼睛进行计算space
我有一个 OpenGL 场景,我在其中查看这样的对象:
gluLookAt(10, 10, -10, -10, -10, 10, 0, 1, 0);
所以我知道如果我想在着色器中使用相机的 z 轴,它看起来会像这个的归一化向量:
vec3(1.0, 1.0, -1,0);
有没有办法在顶点着色器中计算这个向量?
我想计算 near/far 裁剪平面的法线,但无法在顶点(或片段)着色器中找到执行此操作的方法。
我使用的是旧管道 (OpenGL v2.0/ GLSL v. 1.10),不想将矢量传递给着色器(尽管我知道这是执行此操作的常用且高效的方法).
(已弃用)gluLookAt 的参数是 (vec3) eye_、center_ 和 up_ 的分量(x_ 表示向量值数据 x_)
f: ℝ^3 x ℝ^3 x ℝ^3 -> ℝ4xℝ4
eye_, center_, up_ -> ViewMatrix
因此您可能寻找的是
dir_ = normalize(center_ - eye_),
在着色器中获取它们的最佳方式和位置取决于您使用的 GL 和 GLSL 版本。
这个向量
vec3(1.0, 1.0, -1,0);
btw has length sqrt(3), thus it's not normalized.
编辑
了解 OpenGL 和 GLSL 版本后,可以从
GLSL 1.10.59 已经有了自定义制服(我记不清了,2.0/1.10 太久远了);因此,您只需将该向量作为制服传入即可,仅此而已。
因为它用于每个顶点,所以计算一次比在着色器中再次为每个顶点计算一次更有效(当然,假设渲染的顶点块相当大)。
将其作为制服传递给您的着色器。请参阅 glUniform3f.
的文档在客户端代码中,执行如下操作:
auto cameraUp = camera.getUp();
glUniform3f(uniformLocationInShader, cameraUp.x, cameraUp.y, cameraUp.z)
在顶点着色器中,为相机向上矢量添加统一,然后按预期使用它。
uniform vec3 cameraUp;
void main()
{
// do stuff with cameraUp
}
固定函数顶点变换通过应用两个矩阵来工作:
- 从对象 space 到眼睛 space 的 "ModelView" 矩阵变换
- 从眼睛 space 到剪辑 space 的 "Projection" 矩阵
gluLookAt()
所做的是通过在 world space 中定义一些相机来指定视图矩阵。而你似乎要重构的是这个世界的视线方向space.
但是,对于固定功能 GL,不可能。您所拥有的只是 产品 view * model
。如果没有更多信息,您无法将其分解为 view
和 model
部分。 none 这些信息存在于固定函数 GL 中——它从来没有 有 一个世界 space,或者关心一个单独的视图矩阵。这种区别确实发生在应用程序逻辑中 - 如果有的话。
有趣的问题是:你甚至需要世界 space 的观察方向做什么?固定函数 GL 在眼睛 space 中进行此类计算,其中观察方向只是 (0,0,-1,0)。
所以我看到两个选项供您选择:
- 使用统一(或其他将数据传输到着色器的方法)来指定一些附加信息,就像其他答案已经建议的那样
- 直接用眼睛进行计算space