我最近在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一起移动的小 gem 。按M键可让Phong带有多个指示灯。
最佳答案
起作用的原因是偶然的,但是有趣的是为什么它仍然起作用。
Phong着色是中的三种技术
使用phong阴影时,我们有三个术语:“镜面反射”,“漫反射”和“环境”;这三个术语代表在phong着色中使用的三种技术。
这些术语都不严格要求向量空间。只要您保持一致,就可以在世界,本地或摄影机空间中使用phong着色。眼部空间通常用于照明,因为它更易于使用且转换也很简单。
但是,如果您是原籍怎么办?现在您乘以零;很容易看出,原点的任何向量空间之间都没有差异。碰巧的是,从根本上讲,您位于哪个向量空间都无关紧要;会的。
vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
请注意,它基本上是减去0。这是唯一一次使用本地方法,并且在可能造成最小损害的地方使用它。由于对象位于原点,因此其所有顶点也应位于原点或非常接近原点。在原点,近似值是精确的;所有向量空间都收敛。非常接近原点,非常接近精确;即使我们使用精确实数,也会有很小的差异,但是我们不使用精确实数,而是使用浮点数,这使问题更加复杂。
基本上,您很幸运;如果对象不是原点,这将不起作用。尝试移动它看看!
另外,您没有使用Phong shading;您正在使用Blinn-Phong shading(这是用半个向量替换reflect()的名称,仅供引用)。
关于opengl - 为什么此Phong着色器起作用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22411998/