View 为什么不在卡通着色(Lighthouse 3D教程)中的法向量上应用模型视图矩阵?

View 为什么不在卡通着色(Lighthouse 3D教程)中的法向量上应用模型视图矩阵?,view,model,matrix,glsl,shader,View,Model,Matrix,Glsl,Shader,我正在通过实践学习GLSL 本教程有一个称为卡通着色的示例 在本例中,顶点着色器编写如下: uniform vec3 lightDir; varying float intensity; void main() { intensity = dot(lightDir,gl_Normal); gl_Position = ftransform(); } 据我所知,如果曲面旋转,则该曲面顶点的法向量也应旋转相同的量,以便法向量反映曲面的新方向。但是,在上面的代码中,

我正在通过实践学习GLSL

本教程有一个称为卡通着色的示例

在本例中,顶点着色器编写如下:

 uniform vec3 lightDir;
 varying float intensity;

 void main()
 {
      intensity = dot(lightDir,gl_Normal);
      gl_Position = ftransform();
 }
据我所知,如果曲面旋转,则该曲面顶点的法向量也应旋转相同的量,以便法向量反映曲面的新方向。但是,在上面的代码中,模型视图矩阵未应用于法向量。法向量直接用于计算光强度

关于我的担忧,以下是教程所说的:

“假设灯光的方向是在世界空间中定义的。”

如果在OpenGL应用程序中未对模型执行旋转或缩放,则在世界空间中定义的法线(作为gl_法线提供给顶点着色器)与在局部空间中定义的法线一致

这些解释给了我几个问题:

1. What are world space and local space? How are they different? (This question
   seems a little bit elementary, but I need to understand...)

2. I figure the fact that "the light’s direction is defined in world space"
   has something to do with not applying the Model View Matrix on to the
   normal vector of a vertex. But, what is that?

3. Finally, If we don't apply the Model View Matrix on the normal vector then
   wouldn't the normal be pointing to a direction different from the actual
   direction of the surface? How do we solve this problem?
我希望我把问题说清楚


谢谢

世界空间是,听起来像是:世界的空间。它是虚拟世界中存在的所有对象所在的公共空间。世界空间的主要目的是定义一个公共空间,相机(或眼睛)也可以在其中定位

局部空间(有些人也称为“模型空间”)是顶点属性数据所在的空间。如果网格来自使用3DS Max、Blender等工具的用户,则这些位置和法线的空间不一定与世界空间相同

简单地说,眼睛空间(也称为相机空间或视图空间)本质上是世界空间,除了一切都与相机的位置和方向有关。在世界空间中移动摄影机时,实际上只是将世界更改为眼睛空间变换。眼睛空间中的摄影机始终位于原点

就我个人而言,我的印象是Lighthouse 3D教程的人变得有点懒了。很少出现顶点法线位于世界空间的情况,因此不显示必须变换法线和位置(这就是
fttransform()
所做的)会产生误导

本教程是正确的,因为如果您在世界空间中有法线,在世界空间中有灯光方向(并且您正在进行定向照明,而不是点照明),那么您不需要变换任何东西。变换法线的目的是将其从局部空间变换到与灯光方向相同的空间。在这里,它们只是定义它们在同一个空间中

遗憾的是,实际用户通常不会有机会定义他们的顶点法线位于本地以外的任何空间。因此,他们必须对其进行改造

最后,如果我们不在法向量上应用模型视图矩阵,那么法向量不是指向与曲面实际方向不同的方向吗

谁在乎呢?重要的是两个方向在同一个空间。该空间是否与顶点位置的空间相同并不重要。随着对图形的深入了解,您会发现便于照明的空间可能不是您将位置变换为的空间

没关系。因为光照方程只取朝向灯光和曲面法线的方向。它不需要一个位置,除非你在做点光源,即使这样,这个位置也只在它允许你计算光的方向和衰减因子的情况下才有用。您可以选择灯光方向,并将其转换为您想要的任何空间

有些人在局部空间照明。如果要进行凹凸贴图,通常需要在与纹理平面相切的空间中进行照明


增编:

处理法线的标准方法(假设您的矩阵仍然通过OpenGL的标准矩阵命令)是假设法线与位置数据位于同一空间。因此,它们也需要转变

然而,出于以下原因(注意:为了充分披露,我写了这一页),你不能仅仅用你将用于位置的矩阵变换法线。幸运的是,OpenGL的编写是为了实现这一点,因此如果您使用标准OpenGL矩阵堆栈,它们会为您提供一个预定义的矩阵来处理此问题:
gl\u NormalMatrix

GLSL中的典型照明场景如下所示:

uniform vec3 eyeSpaceLightDir;
varying float intensity;

void main()
{
    vec3 eyeSpaceNormal = gl_NormalMatrix * gl_Normal;
    intensity = dot(eyeSpaceLightDir, eyeSpaceNormal);
    gl_Position = ftransform;
}

我倾向于在变量名之前说明它们所在的空间,这样就可以清楚地知道发生了什么。

谢谢您的回答。但是,我仍然不清楚您对最后一个问题的答案。假设您通过指定三个顶点来绘制平面。对于每个顶点,指定法线。然后,在该平面上执行旋转。编写顶点着色器时,为了在顶点上应用旋转,请使用函数ftTransform()。同时,还必须旋转法线,对吗?这样它们就能指向正确的方向。那你是怎么做到的?(即,在法线上应用模型视图矩阵)@Einiosaurus:应用于平面的旋转将是局部到世界变换的一部分(技术上是局部到眼睛)。Lighthouse 3D教程预计法线已经在世界空间中。因此,不允许在不破坏着色器假设的情况下对平面应用旋转。简而言之,本教程的着色器不允许您的建议。他们只是简单地定义了这个问题,这就是为什么我说他们懒惰的原因。是的!我明白你的意思。然而,我要问的是本教程定义的问题的解决方案。假设法线不在世界空间中,我们必须变换它,你知道吗