目前,我正在实施好的老Phong阴影。总的来说,它看起来很正确,但正常情况出现了一种模式,我无法解释。
我认为,如果不仔细看,Stanford Bunny看起来非常正确。
这是我的顶点着色器:
#version 330 core
layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec3 vNormal;
out vec4 fWorldPosition;
smooth out vec3 fWorldNormalSmooth;
...
void main() {
fWorldNormalSmooth = normalize(NormalMatrix*vNormal);
fWorldPosition = WorldMatrix*vPosition;
gl_Position = ProjectionMatrix*ViewMatrix*WorldMatrix*vPosition;
}
这是我的片段着色器:
#version 330 core
smooth in vec3 fWorldNormalSmooth;
in vec4 fWorldPosition;
out vec4 color;
...
vec4 shadePointLight(Material material, PointLight pointLight, vec3 worldPosition, vec3 worldNormal) {
vec3 cameraPosition = wdiv(inverse(ViewMatrix)*vec4(0, 0, 0, 1));
vec3 cameraDirection = normalize(cameraPosition - worldPosition);
vec3 lightDirection = normalize(pointLight.position - worldPosition);
vec3 reflectionDirection = reflect(-lightDirection, worldNormal);
vec4 i_amb = material.ambientReflection*pointLight.ambientColor;
vec4 i_diff = max(0, dot(worldNormal, lightDirection))*material.diffuseReflection*pointLight.diffuseColor;
vec4 i_spec = pow(max(0, dot(reflectionDirection, cameraDirection)), material.shininess)*material.specularReflection*pointLight.specularColor;
float distance = length(pointLight.position - worldPosition);
float d = 1.0 / (pointLight.falloff.constant + pointLight.falloff.linear*distance + pointLight.falloff.quadratic*distance*distance);
return i_amb + d*(i_diff + i_spec);
}
void main() {
...
color = shadePointLight(material, pointLight, wdiv(fWorldPosition), normalize(fWorldNormalSmooth));
}
有人可以解释这种行为吗?
答案 0 :(得分:2)
当在两个相同长度的矢量之间线性插值时,如在顶点和片段阶段之间发生的那样,所得矢量的长度将在两者之间变短。在两个法线之间进行内插的数学上正确的方法是执行spherical linear interpolation(SLERP),但是对于角度的微小变化,您可以简单地将片段着色器中的内插法线向量归一化(这是因为小sin(x) ≈ x
)的小角度近似值x
。 编辑:对于较大的角度,需要通过适当的SLERP插值。