关于Phong着色和Goraud着色的唯一实际区别是,如果片段颜色的计算是在顶点着色器中完成的,那么它就是Goraud,否则就是phong。我在下面有一些顶点着色器和片段着色器代码:
//vertexShader.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
gl_Position = projection * view * vec4(FragPos, 1.0);
}
//FragmentShader.fs
#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec3 FragPos;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
void main()
{
// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// specular
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0),32);
vec3 specular = specularStrength * spec * lightColor;
vec3 result = (ambient + diffuse + specular) * objectColor;
FragColor = vec4(result, 1.0);
}
事实证明,在低聚对象上,Phong看起来更加平滑。因此,知识障碍基本上在于片段如何获取着色器。首先让我们看一下wonderful resource learnopenGL已经提供了什么。
总而言之,它告诉我们在顶点处提供的颜色值被内插在顶点所形成的片段的边界内。因此,这非常有意义,就像对形成顶点的颜色进行加权平均一样。
但是,就像Phong阴影模型一样,在片段着色器中直接进行计算,会发生什么?片段像素如何着色?假设存在三个顶点,那么该片段是用第一种颜色完全着色的,是用第二种颜色完整着色的,然后是第三种颜色着色的?所取颜色的总中位数是多少?在片段着色器中进行计算时,片段如何着色?
Phong an Gouraud底纹之间的区别在于:
在高多边形网格上,由于每个三角形的色散变小,两者都给出非常接近的结果。
在低多边形网格上,对Gouraud
中的阴影颜色求平均会带来较差的视觉效果,因为对颜色求平均几乎没有物理意义。在特殊情况下,这意味着每个片段的Normal
和FragPos
不同。每个三角形都有3个角。在顶点着色器中为三角形的每个角计算Normal
和FragPos
。对于每个由三角形覆盖的片段,将对角的属性进行插值,并且插值矢量是片段着色器的输入。由于每个片段具有不同的输入(Normal
和FragPos
),因此每个片段的计算输出(FragColor
)都不同。相邻片段的输出仅略有不同,因为输入也仅略有不同。这将导致平滑的照明。请注意,即使法线向量(Normal
)是面法线(三个顶点的法线相同),但FragPos
仍然是不同的。