我正在编写一个 Phong 着色的小测试,并且正在将我的头撞在砖墙上,试图让镜面反射组件工作。它似乎可以正常工作,除了镜面光同时应用于对象的前部和后部。(对象本身是透明的,面在 CPU 端手动排序。)
请注意,漫反射组件工作得很好(仅显示在面向光源的一侧)——我认为这似乎排除了法线到达片段着色器的问题。
据我了解,镜面反射分量与眼睛矢量和反射光矢量之间的角度的余弦成正比。
为了让事情变得超级简单,我的测试代码尝试在世界空间中执行此操作。相机位置和光矢量分别被硬编码(对不起(0,0,4)
)(-0.707, 0, -0.707)
。因此,眼向量为(0,0,4) - fragPosition
。
由于模型矩阵只执行旋转,顶点着色器只是简单地通过模型矩阵变换顶点法线。(注意:这不是很好的做法,因为许多类型的变换不保留法线正交性。通常对于法线矩阵,您应该使用模型矩阵左上角 3x3 的逆转置。)为了简单起见,片段着色器在单个浮点颜色通道上运行,并跳过镜面反射指数(/使用指数 1)。
顶点着色器:
#version 140
uniform mat4 mvpMtx;
uniform mat4 modelMtx;
in vec3 inVPos;
in vec3 inVNormal;
out vec3 normal_world;
out vec3 fragpos_world;
void main(void) {
gl_Position = mvpMtx * vec4(inVPos, 1.0);
normal_world = vec3(modelMtx * vec4(inVNormal, 0.0));
fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0));
}
片段着色器:
#version 140
uniform float
uLightS,
uLightD,
uLightA;
uniform float uObjOpacity;
in vec3 normal_world, fragpos_world;
out vec4 fragOutColour;
void main(void) {
vec3 vN = normalize(normal_world);
vec3 vL = vec3(-0.707, 0, -0.707);
// Diffuse:
// refl in all directions is proportional to cos(angle between -light vector & normal)
// i.e. proportional to -l.n
float df = max(dot(-vL, vN), 0.0);
// Specular:
// refl toward eye is proportional to cos(angle between eye & reflected light vectors)
// i.e. proportional to r.e
vec3 vE = normalize(vec3(0, 0, 4) - fragpos_world);
vec3 vR = reflect(vL, vN);
float sf = max(dot(vR, vE), 0.0);
float col = uLightA + df*uLightD + sf*uLightS;
fragOutColour = vec4(col, col, col, uObjOpacity);
}
我在这里找不到错误;谁能解释为什么镜面反射分量出现在物体的背面和面向光的一侧?
非常感谢。