在 GLSL 中让相机正常
Posted
技术标签:
【中文标题】在 GLSL 中让相机正常【英文标题】:Get the camera normal in GLSL 【发布时间】:2015-11-08 10:13:41 【问题描述】:我有一个 OpenGL 场景,我在其中查看这样的对象:
gluLookAt(10, 10, -10, -10, -10, 10, 0, 1, 0);
所以我知道如果我想在着色器中使用我的相机的 z 轴,它看起来就像这个的归一化向量:
vec3(1.0, 1.0, -1,0);
有没有办法在顶点着色器中计算这个向量?
我想计算近/远裁剪平面的法线,但在顶点(或片段)着色器中找不到方法。
我正在使用旧管道(OpenGL v2.0/ GLSL v. 1.10)并且不想将矢量传递给着色器(尽管我知道这是执行此操作的常用且高效的方法)。
【问题讨论】:
欢迎来到 SO!请将 OpenGL 版本(和 GLSL 版本,如果相关)添加到 OpenGL/GLSL 问题中。gluLookAt
已弃用,但在讨论 OpenGL 时仍将其用作短语,因此我不知道您是在技术上使用它还是仅用于说明。
OpenGL 1.1 没有 GLSL。从 OpenGL 2.0 开始
对不起,这是 OpenGL v2.0 / GLSL v1.10
现在更有意义了。 ;)
【参考方案1】:
固定函数顶点变换通过应用两个矩阵来工作:
-
从对象空间到眼睛空间的“ModelView”矩阵
从眼睛空间到剪辑空间的“投影”矩阵
gluLookAt()
所做的是通过在世界空间中定义一些相机来指定视图矩阵。而你似乎想要重构的是这个世界空间中的观察方向。
但是,对于固定功能 GL,这是不可能的。您所拥有的只是产品 view * model
。如果没有更多信息,您无法将其分解为 view
和 model
部分。并且这些信息都不存在于固定函数 GL 中——它从来没有拥有一个世界空间,或者关心一个单独的视图矩阵。这种区别确实发生了——如果有的话——在应用程序逻辑中。
有趣的问题是:你甚至需要世界空间的观察方向来做什么?固定函数 GL 在眼睛空间中进行此类计算,其中观察方向只是 (0,0,-1,0)。
所以我看到了两种选择:
-
使用统一(或将数据传输到着色器的其他方式)指定一些附加信息,就像其他答案已经建议的那样
直接在眼睛空间中进行计算
【讨论】:
第 2 点。成功了。我想计算相机观察方向和顶点法线的点积。所以诀窍不仅在于尝试转换相机的法线,还在于转换顶点: 最后我用了这个:vertexNormal = gl_NormalMatrix*gl_Normal;
vertexViewDirection = -normalize(gl_ModelViewMatrix*gl_Vertex).xyz;
【参考方案2】:
将其作为制服传递给您的着色器。请参阅glUniform3f 的文档。
在客户端代码中,执行如下操作:
auto cameraUp = camera.getUp();
glUniform3f(uniformLocationInShader, cameraUp.x, cameraUp.y, cameraUp.z)
在顶点着色器中,为相机向上矢量添加一个制服,然后按预期使用它。
uniform vec3 cameraUp;
void main()
// do stuff with cameraUp
【讨论】:
我知道这很聪明,但这正是我不想做的事情;-) 嗯,您需要将某种制服传递给着色器以获取此信息...如果您将视图矩阵作为制服,您应该能够从这些列之一。 所以我想这是唯一的方法吗?我不能使用眼睛平面或类似的东西吗? 是的,这正是制服的目的:将信息传递给着色器...顺便说一句,近和远剪辑平面是您的 投影 矩阵的一部分。这与您的相机的向上矢量无关。 好吧,我只需要 z 向量。我可以从投影矩阵中提取它吗?【参考方案3】:(已弃用)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 的长度为 sqrt(3),因此没有标准化。
编辑
在了解 OpenGL 和 GLSL 版本后,您可以从中获取
legacy GLSL 1.10.59 doc
GLSL 1.10.59 已经有了自定义制服(我记不清了,2.0/1.10 太早了);因此,您只需将该向量作为制服传递,就是这样。
因为它用于每个顶点,所以计算一次比在着色器中对每个顶点再次计算效率更高(当然,鉴于渲染的顶点块相当大)。
【讨论】:
感谢您的回答,但我正在寻找一种方法来计算此法线在顶点着色器中。有没有办法做到这一点? @Corbie 当然,但请发布您的 GL 和 GLSL 版本! @Corbie 和你在着色器中填充的制服,如果有的话。 我已经添加了版本。没有相关的制服。以上是关于在 GLSL 中让相机正常的主要内容,如果未能解决你的问题,请参考以下文章
glsl 着色器 - 颜色混合,正常模式(如在 Photoshop 中)
我的 GLSL 着色器程序链接正常,但是当我尝试使用它时出错——我该如何调试它?
如何在 Android 中保存相机拍摄的图片(应用 glsl 效果)?