最简单光照模型中的光照方向及其变换

Posted

技术标签:

【中文标题】最简单光照模型中的光照方向及其变换【英文标题】:Light Direction and its Transformation in the Simplest Lighting Model 【发布时间】:2011-09-05 12:33:55 【问题描述】:

所以,我已经在我的 OpenGL 学习任务中了解了基本照明。

想象一下这个最简单的照明模型。每个顶点都有一个位置、颜色和法线。着色器获取模型视图投影矩阵(MVP)、模型视图矩阵(MV)和法线矩阵(N),计算为( MV-1)T,以及作为制服的LightColorLightDirection。顶点着色器执行光照计算——片段着色器只输出插值后的颜色。

现在,在我遇到的关于这个主题的每个教程中,我看到了两件让我感到困惑的事情。首先,LightDirection 已经被假定在眼睛坐标中。二、输出颜色计算为

max(0, dot(LightDirection, N * normal))*LightColor*Color;

我希望 LightDirection 应该首先反转,也就是说,我认为正确的公式是

max(0, dot(-LightDirection, N * normal))*LightColor*Color;

似乎假设LightDirection实际上是实际光流的向量的反向。

Q1:这是某种既定约定,即此模型中的 LightDirection 被假定为无限远光源的矢量而不是光方向的矢量,还是这不是主要问题,只是碰巧在我遇到的教程中如此假设?

Q2:如果 LightDirection 是在世界坐标而不是眼睛坐标,应该用法线矩阵还是模型视图矩阵转换成眼睛坐标?

感谢您澄清这些事情!

【问题讨论】:

【参考方案1】:

Q1:这是某种既定的约定,即该模型中的 LightDirection 被假定为无限远光源的矢量,而不是光方向的矢量,或者这不是主要问题,它就这样发生了在我遇到的教程中是这么假设的吗?

在固定函数 OpenGL 中,当提供光的位置时,第 4 个参数确定光是定向的还是位置的。在定向光的情况下,提供的矢量指向(无限远)光源。

在位置光源的情况下,每个顶点的 LightDirection 计算为LightDirection = LightPosition - VertexPosition——为了简单起见这个计算是在眼睛坐标中完成的

Q2:如果LightDirection是世界坐标而不是眼睛坐标,应该用法线矩阵还是模型视图矩阵转换成眼睛坐标?

在固定函数 OpenGL 中,通过glLighti 提供的光照位置由调用时当前模型视图矩阵转换。如果光是位置的,它会被通常的模型视图矩阵转换。在定向光的情况下,使用法线矩阵。

【讨论】:

非常感谢,datenwolf。关于您对 Q2 的回答:定向光与法线矩阵相乘是因为没有需要与模型视图相乘还是因为与模型视图相乘会产生不正确的结果?跨度> “正规矩阵”这个名称有点误导。我最好称之为“方向变换矩阵”。这就是 (M^-1)^T 的特别之处:适用于方向,而不是位置。 Lighthouse3D 有一篇关于它的优秀文章lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix @datenwolf 在实现光线追踪器时,我记得使用光线-球体相交来实现光线-椭球相交。如果球体sM 转换为椭球体e,而不是进行r-e 交集,我转换了射线r' = rM⁻¹ 并进行了r'-s 交集。但是只有当我将M⁻¹ 应用于ray.originray.direction 而不是M⁻¹ 应用于原点,((M⁻¹)⁻¹)ᵀ = Mᵀ 应用于方向时,transformRay 函数才给出正确的输出。为什么? (M⁻¹)ᵀ 是否仅适用于法线向量而不适用于您评论中所述的所有方向向量? 可能我也完全误解了一些东西,因此评论正确地了解了这件事。但是,my prof's lecture 也表示相同。我们在哪些情况下应用反转置?我不能盲目地这样做,即对所有方向向量应用反转置吗? @legends2k:当您想知道切线空间如何相对于常规变换进行变换时,您可以应用逆转置。切线空间是相对于表面(空间)的方向空间。所以它并不立即适用于任何一种空间矢量,而是适用于某一类矢量。所以当我提到“方向”向量时,我实际上是指这些方向。【参考方案2】:

这是某种既定的约定,即该模型中的 LightDirection 被假定为指向无限远光源的矢量,而不是光方向的矢量,或者这不是主要问题,只是碰巧在我遇到的教程是这么假设的?

两者都没有。光有很多种。

定向光表示从场景的角度来看无限远的光源。它由一个矢量方向表示。

位置光表示在场景空间中具有位置的光源。它由一个向量位置表示。

这取决于你的着色器的光照模型,它使用什么。事实上,你可以有一个定向光源和几个点光源,它们都会影响同一个模型。这取决于你。

您看到的教程只是使用了定向灯。尽管他们可能至少应该提到定向光近似。

如果 LightDirection 是在世界坐标而不是眼睛坐标中,应该用法线矩阵还是模型视图矩阵将其转换为眼睛坐标?

两者都没有。如果光的方向在世界坐标中,那么您也需要将法线放入世界坐标中。在什么空间进行照明并不重要(尽管在剪辑空间或其他非线性后投影空间中进行照明相当困难);重要的是一切都在同一个空间中。

默认的 OpenGL 模型视图矩阵按照它所说的进行:它从模型空间到 视图 空间(眼睛空间)。它穿过世界空间,但并不止于此。而默认的 OpenGL 法线矩阵只是模型视图矩阵的反转置。所以他们都不会把你带到世界空间。

一般来说,出于best explained elsewhere 的原因,您不应该在世界空间中进行光照(或 GPU 上的任何其他操作)。为了在世界空间中进行光照,您需要有转换为世界空间的矩阵。我的建议是做正确的事:将光线方向放在眼睛空间,将世界空间留给 CPU 代码。

【讨论】:

以上是关于最简单光照模型中的光照方向及其变换的主要内容,如果未能解决你的问题,请参考以下文章

Phong和Blinn-Phong光照模型

OpenGL:光照模型视图投影变换

光照模型

Unity Shaders学习笔记之为创建自定义慢反射光照模型

第五章 Unity中的基础光照

通过使用Unity Shader实现基础光照效果