我最近在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);
}
片段着色器:
#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));
}
所以我做的方法是计算光矢量和相机矢量之间的半矢量,然后用法线点。这一切都很好。但是,我做了两件很奇怪的事情。
通常,一切都在眼睛坐标中完成。但是,我从顶点着色器传递到片段着色器的位置在本地坐标中。
这是困扰我的部分。在vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
行上我用相对于局部坐标中的顶点位置减去相机坐标中的光矢量。这似乎完全错了。
简而言之,我理解这段代码应该做什么,以及phong着色的半矢量方法是如何工作的。
但为什么这段代码有用呢?
编辑:我们提供的入门代码是开源的,因此如果您愿意,可以download the completed project直接查看。该项目适用于Windows上的VS 2012(您需要设置GLEW,GLM和freeGLUT),并且应该在GCC上工作而不需要更改代码(可能是对makefile库路径的更改或两次)。
请注意,在源文件中," light_pos"被称为" gem_pos",因为我们的光源是你用WSADXC移动的小宝石。按M键以获得多个灯光的Phong。
答案 0 :(得分:8)
这种作用的原因是偶然的,但看看为什么它仍然有效是很有趣的。
Phong着色是一种
中的三种技巧使用phong着色,我们有三个术语:高光,漫反射和环境;这三个术语代表了phong着色中使用的三种技术。
这些术语都不严格要求矢量空间;只要你是一致的,你就可以在世界,地方或相机空间中进行phong着色。眼睛空间通常用于照明,因为它更容易使用,转换也很简单。
但如果你在原点怎么办?现在你乘以零;很容易看出原点上的任何向量空间之间没有区别。巧合的是,在起源时,你所处的向量空间并不重要;它会工作。
vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
请注意,它基本上减去了0;这是本地使用的唯一时间,并且它在一个地方使用它可以造成最小的伤害。由于物体位于原点,因此它的所有顶点也应该在原点处或非常接近原点。在原点,近似是精确的;所有向量空间汇合。非常接近原点,它非常接近精确;即使我们使用了精确的实数,它也只是一个非常小的分歧,但我们并没有使用精确的实数,我们使用浮点数,使问题复杂化。
基本上,你很幸运;如果对象不在原点,这将无法工作。尝试移动它,看看!
此外,您还没有使用Phong shading;您正在使用Blinn-Phong shading(这是用半矢量替换reflect()的名称,仅供参考)。