计算机图形学 – Flat Shading、Gouraud Shading、Phong Shading的区别
1 Flat Shading、Gouraud Shading、Phong Shading的区别
从下图可以看出Flat Shading、Gouraud Shading、Phong Shading三种着色模型的区别,其中a为Flat Shading,b为Gouraud Shading,c为Phong Shading。
1.1 三种Shading Model的比较
1.1.1 算法的提出
Flat Shading >> Gouraud Shading >> Phong Shading
1.1.2 从简单到复杂
Flat Shading >> Gouraud Shading >> Phong Shading
1.1.3 原理上
- Flat Shading:constant surface shading,三角形的顶点没有法向量,三角形的整个面才有法向量,打光时整个三角形只呈现一种颜色;
- Gouraud Shading:color interpolation shading,三角形的各个顶点都有法向量,打光时三个顶点都有各自的颜色,然后通过双线性内插(bilinear interpolation)插值整个三角面片的颜色,这导致整个三角形会存在渐变的颜色效果;
- Phong Shading:vertex normal interpolation shading,三角形的各个顶点都有各自的法向量,先对三角形整个面做法向量的双线性内插,然后打光求整个三角形的颜色;
1.1.4 复杂度
假设三角形面积为A,三角形个数为N,打一次光需要6次乘法和2次加法和1次查表的计算量(疑惑),将打一次光的运算量设定为L,做一次双线性内插的运算设定为B,则
- Flat Shading:N * L
- Gouraud Shading:N * (3 * L+ b * A)
- Phong Shading:(B + L) * N * A
所以计算复杂度是:Flading Shading < Gouraud Shading < Phong Shading
1.1.5 三者的着色示意图如下
1.1.6 三者的GLSL shader
1.1.6.1 Gouraud Shader
vertex shader
<code class="language-cpp line-numbers">#version 420 core // Per-vertex inputs layout (location = 0) in vec4 position; layout (location = 1) in vec3 normal; // Matrices we'll need layout (std140) uniform constants { mat4 mv_matrix; mat4 view_matrix; mat4 proj_matrix; }; // Light and material properties uniform vec3 light_pos = vec3(100.0, 100.0, 100.0); uniform vec3 diffuse_albedo = vec3(0.5, 0.2, 0.7); uniform vec3 specular_albedo = vec3(0.7); uniform float specular_power = 128.0; uniform vec3 ambient = vec3(0.1, 0.1, 0.1); // Outputs to the fragment shader out VS_OUT { vec3 color; } vs_out; void main(void) { // Calculate view-space coordinate vec4 P = mv_matrix * position; // Calculate normal in view space vec3 N = mat3(mv_matrix) * normal; // Calculate view-space light vector vec3 L = light_pos - P.xyz; // Calculate view vector (simply the negative of the // view-space position) vec3 V = -P.xyz; // Normalize all three vectors N = normalize(N); L = normalize(L); V = normalize(V); // Calculate R by reflecting -L around the plane defined by N vec3 R = reflect(-L, N); // Calculate the diffuse and specular contributions vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo; vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo; // Send the color output to the fragment shader vs_out.color = ambient + diffuse + specular; // Calculate the clip-space position of each vertex gl_Position = proj_matrix * P; } </code>
fragment shader
<code class="language-cpp line-numbers">#version 420 core // Output layout (location = 0) out vec4 color; // Input from vertex shader in VS_OUT { vec3 color; } fs_in; void main(void) { // Write incoming color to the framebuffer color = vec4(fs_in.color, 1.0); } </code>
1.1.6.2 Phong Shader
vertex shader
<code class="language-cpp line-numbers">#version 420 core // Per-vertex inputs layout (location = 0) in vec4 position; layout (location = 1) in vec3 normal; // Matrices we'll need layout (std140) uniform constants { mat4 mv_matrix; mat4 view_matrix; mat4 proj_matrix; }; // Inputs from vertex shader out VS_OUT { vec3 N; vec3 L; vec3 V; } vs_out; // Position of light uniform vec3 light_pos = vec3(100.0, 100.0, 100.0); void main(void) { // Calculate view-space coordinate vec4 P = mv_matrix * position; // Calculate normal in view-space vs_out.N = mat3(mv_matrix) * normal; // Calculate light vector vs_out.L = light_pos - P.xyz; // Calculate view vector vs_out.V = -P.xyz; // Calculate the clip-space position of each vertex gl_Position = proj_matrix * P; } </code>
fragment shader
<code class="language-cpp line-numbers">#version 420 core // Output layout (location = 0) out vec4 color; // Input from vertex shader in VS_OUT { vec3 N; vec3 L; vec3 V; } fs_in; // Material properties uniform vec3 diffuse_albedo = vec3(0.5, 0.2, 0.7); uniform vec3 specular_albedo = vec3(0.7); uniform float specular_power = 128.0; void main(void) { // Normalize the incoming N, L, and V vectors vec3 N = normalize(fs_in.N); vec3 L = normalize(fs_in.L); vec3 V = normalize(fs_in.V); // Calculate R locally vec3 R = reflect(-L, N); // Compute the diffuse and specular components for each // fragment vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo; vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo; // Write final color to the framebuffer color = vec4(diffuse + specular, 1.0); } </code>
参考链接
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:计算机图形学 – Flat Shading、Gouraud Shading、Phong Shading的区别
原文链接:https://www.stubbornhuang.com/2149/
发布于:2022年06月01日 11:11:39
修改于:2023年06月26日 20:03:51
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
49