• 工资「喂饱肚子」,副业「养活灵魂」!

  • 在本站开通年度VIP,无限制下载本站资源和阅读本站文章

  • 如果觉得本站的内容有帮助,可以考虑打赏博主哦!

  • 本站由于前段时间遭受到大量临时和国外邮箱注册,所以对可注册的邮箱类型进行了限制!

  • 感谢大家访问本站,希望本站的内容可以帮助到大家!

  • 问题反馈可发送邮件到stubbornhuang@qq.com

  • 欢迎大家交换友链,可在https://www.stubbornhuang.com/申请友情链接进行友链交换申请!

  • 计算机图形学与计算几何经典必备书单整理,下载链接可参考:https://www.stubbornhuang.com/1256/

  • 本站会放置Google广告用于维持域名以及网站服务器费用。

计算机图形学 – Flat Shading、Gouraud Shading、Phong Shading的区别

计算机图形学 发布于2022-06-01 阅读 7,052次 0次评论 0次点赞 本文共3758个字,阅读需要10分钟。

1 Flat Shading、Gouraud ShadingPhong Shading区别

从下图可以看出Flat Shading、Gouraud Shading、Phong Shading三种着色模型的区别,其中a为Flat Shading,b为Gouraud Shading,c为Phong Shading。

计算机图形学 - Flat Shading、Gouraud Shading、Phong Shading的区别-第0张图片
计算机图形学 - Flat Shading、Gouraud Shading、Phong Shading的区别-第1张图片

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 三者的着色示意图如下

计算机图形学 - Flat Shading、Gouraud Shading、Phong Shading的区别-第2张图片

1.1.6 三者的GLSL shader

1.1.6.1 Gouraud Shader

vertex shader

#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;
}

fragment shader

#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);
}
1.1.6.2 Phong Shader

vertex shader

#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;
}

fragment shader

#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);
}

参考链接

欢迎扫码关注我的微信公众号,及时获取文章更新

微信公众号二维码

本文作者:StubbornHuang

版权声明:本文为站长原创文章,如果转载请注明原文链接!

原文标题:计算机图形学 – Flat Shading、Gouraud Shading、Phong Shading的区别

原文链接:https://www.stubbornhuang.com/2149/

发布于:2022年06月01日 11:11:39

修改于:2023年06月26日 20:03:51

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

文章末尾
上一篇
C++ - 在两个互有依赖关系的类中使用std::shared_ptr和std::weak_ptr进行内存管理
C++
下一篇
OpenCV/FFmpeg - 使用FFmpeg编码OpenCV中的BGR视频流为H264视频流以及解码H264视频流为OpenCV中的BGR视频流
FFmpeg
当前分类随机文章推荐

发表评论

您必须 [ 登录 ] 才能发表留言!

关注我们的公众号

微信公众号