为什么这个Phong着色器有效?

Lew*_*wis 9 opengl shader glsl

我最近在GLSL中写了一个Phong着色器作为学校作业的一部分.我从教程开始,然后使用代码,直到我开始工作.据我所知,它的工作完全正常,但我特别写了一行,我不明白它为什么起作用.

顶点着色器:

#version 330

layout (location = 0) in vec3 Position;    // Vertex position
layout (location = 1) in vec3 Normal;      // Vertex normal

out vec3 Norm;
out vec3 Pos;
out vec3 LightDir;

uniform mat3 NormalMatrix;      // ModelView matrix without the translation component, and inverted
uniform mat4 MVP;               // ModelViewProjection Matrix
uniform mat4 ModelView;         // ModelView matrix
uniform vec3 light_pos;         // Position of the light

void main()
{
    Norm = normalize(NormalMatrix * Normal);
    Pos = Position;
    LightDir = NormalMatrix * (light_pos - Position);

    gl_Position = MVP * vec4(Position, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

片段着色器:

#version 330

in vec3 Norm;
in vec3 Pos;
in vec3 LightDir;

layout (location = 0) out vec4 FragColor;

uniform mat3 NormalMatrix;
uniform mat4 ModelView;

void main()
{
    vec3 normalDirCameraCoords = normalize(Norm);
    vec3 vertexPosLocalCoords = normalize(Pos);
    vec3 lightDirCameraCoords = normalize(LightDir);

    float dist = max(length(LightDir), 1.0);

    float intensity = max(dot(normalDirCameraCoords, lightDirCameraCoords), 0.0) / pow(dist, 1.001);

    vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
    float intSpec = max(dot(h, normalDirCameraCoords), 0.0);
    vec4 spec = vec4(0.9, 0.9, 0.9, 1.0) * (pow(intSpec, 100) / pow(dist, 1.2));

    FragColor = max((intensity * vec4(0.7, 0.7, 0.7, 1.0)) + spec, vec4(0.07, 0.07, 0.07, 1.0));
}
Run Code Online (Sandbox Code Playgroud)

所以我正在做的方法是计算光矢量和相机矢量之间的半矢量,然后用法线点.这一切都很好.但是,我做了两件很奇怪的事情.

  1. 通常,一切都在眼睛坐标中完成.但是,我从顶点着色器传递到片段着色器的位置在本地坐标中.

  2. 这是困扰我的部分.就行了vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);,我减去光矢量相机在顶点位置坐标的本地坐标.这似乎是完全错误的.

简而言之,我理解这段代码应该做什么,以及phong着色的半矢量方法是如何工作的.

但为什么这段代码有效呢?

编辑:我们提供的入门代码是开源的,因此您可以下载已完成的项目,如果您愿意,可以直接查看.该项目适用于Windows上的VS 2012(您需要设置GLEW,GLM和freeGLUT),并且应该在GCC上工作而不需要更改代码(可能是makefile库路径的一两个更改).

请注意,在源文件中,"light_pos"被称为"gem_pos",因为我们的光源是您使用WSADXC移动的小宝石.按M键以获得多个灯光的Phong.

Ali*_*ice 8

这种作用的原因是偶然的,但有趣的是看它为何仍然有效.

Phong着色是三种技术于一体

使用phong着色,我们有三个术语:镜面反射,漫反射环境 ; 这三个术语代表了phong着色中使用的三种技术.

这些术语都不严格要求向量空间; 只要你是一致的,你就可以在世界,地方或相机空间中进行phong着色.眼睛空间通常用于照明,因为它更容易使用,转换也很简单.

但是如果你在原点呢?现在你乘以零; 很容易看出原点上任何向量空间之间没有区别.巧合的是,在起源时,你所处的向量空间并不重要; 它会工作的.

vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
Run Code Online (Sandbox Code Playgroud)

请注意,它基本上减去0; 这是本地唯一使用的时间,并且它在一个地方使用它可以造成最小的伤害.由于物体位于原点,因此它的所有顶点也应该位于原点或非常接近原点.在原点,近似是精确的; 所有向量空间汇合.非常接近原点,它非常接近精确; 即使我们使用精确的实数,它也是一个非常小的分歧,但我们不使用精确的实数,我们使用浮点数,使问题复杂化.

基本上,你很幸运; 如果对象不在原点,这将不起作用.尝试移动它,看看!

另外,你没有使用Phong着色 ; 你正在使用Blinn-Phong着色(这是用半向量替换reflect()的名称,仅供参考).