不应该使用环境照明和漫射照明,使用碎片照明效果与顶点照明效果相同吗?

无限光源,只有环境光和漫射光 – 没有镜面光,顶点照明和碎片照明的渲染结果似乎应该是相同的,因为所有的照明计算都是线性的,这意味着计算 – 插值和插值 – 然后计算应该是一样的。 然而,实际的结果仍然不完全相同,碎片照明仍然平稳。 我误解了什么? 还是仅仅是因为在计算 – 然后插值时计算精度的损失?

碎片照明代码:

// Vertex shader attribute vec4 Position; attribute vec3 Normal; uniform mat4 Projection; uniform mat4 Modelview; uniform mat3 NormalMatrix; varying vec3 EyespaceNormal; void main(void) { EyespaceNormal = NormalMatrix * Normal; gl_Position = Projection * Modelview * Position; } // Fragment shader varying mediump vec3 EyespaceNormal; uniform highp vec3 LightPosition; uniform highp vec3 DiffuseMaterial; uniform highp vec3 AmbientMaterial; void main(void) { highp vec3 N = normalize(EyespaceNormal); highp vec3 L = normalize(LightPosition); highp float df = max(0.0, dot(N, L)); lowp vec3 color = AmbientMaterial + df * DiffuseMaterial; gl_FragColor = vec4(color, 1); } 

顶点照明代码:

 // Vertex shader attribute vec4 Position; attribute vec3 Normal; uniform mat4 Projection; uniform mat4 Modelview; uniform mat3 NormalMatrix; uniform highp vec3 LightPosition; uniform highp vec3 DiffuseMaterial; uniform highp vec3 AmbientMaterial; varying lowp vec3 Color; void main(void) { highp vec3 EyespaceNormal = NormalMatrix * Normal; highp vec3 N = normalize(EyespaceNormal); highp vec3 L = normalize(LightPosition); highp float df = max(0.0, dot(N, L)); Color = AmbientMaterial + df * DiffuseMaterial; gl_Position = Projection * Modelview * Position; } // Fragment shader varying lowp vec3 Color; void main(void) { gl_FragColor = vec4(Color, 1); } 

向量归一化不是线性的,这足以产生差异。

将法线想象成单位球体上的点; 那么线性内插会穿过内部,而不是沿着表面移动,这意味着内插法线不会对应于任何可能的表面方向(其大小将小于1)。 对插值后的法线进行标准化恢复合理的结果。

Nathan Reed首先得到了这个链接,但Math.SE这个问题正是我想到的关于这个主题的更正式的信息。