首页 > 其他分享 >3d渲染的shading模型

3d渲染的shading模型

时间:2022-12-28 19:12:26浏览次数:64  
标签:1.0 渲染 color light uniform vec4 vec3 shading 3d

flat shading

FLAT指的是把三角形的三个顶点的发现向量都指定为该三角形所在平面的法线向量,这种方式绘制出来的效果能清楚地看到模型上的三角面片。它是块渲染,而不是插值渲染。

#version 410 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 perspective;
// 定义材质:物体的三个颜色 + 镜面光的光泽度(镜面反光度)
struct materials{
    vec3 k_a;
    vec3 k_d;
    vec3 k_s;
    float shiness;
 };
uniform materials material;
// 光照颜色
struct lights{
    vec3 l_pos;  // 光线位置(世界坐标)
    vec3 l_a;    // 环境光颜色(
    vec3 l_d;    // 漫反射颜色
    vec3 l_s;    // 镜面光颜色
};
uniform lights light;
flat out vec4 color_light; // 最终输出颜色
void main(){
    // 1. 首先处理矩阵
    mat4 mv = view * model;    // 处理与位置有关的坐标变换
    mat3 n_mv = mat3(vec3(mv[0]), vec3(mv[1]), vec3(mv[2]));   //处理与位置无关的坐标变换(比如法向量):去掉最后一列的位移
    // 2. 变换法向量与顶点坐标,光线坐标
    vec3 n = normalize(n_mv * aPos);  // 变换后的法向量:我们采用球体的顶点作为初始法向量;
    vec3 v_pos = vec3(mv * vec4(aPos,1.0));       // 变换后的顶点
    vec3 v_light = vec3(view * vec4(light.l_pos, 1.0));   // 变换后灯光的位置(灯光不受物体变换影响,只受照相机影响)

    // A.环境光
    vec3 a_out = material.k_a * light.l_a;
    // B.漫反射光
    //    B1. 计算灯光方向
    vec3 s = normalize(vec3(v_light - v_pos));
    //    B2. 计算漫反射因子
    float diff = max(dot(s, n),0.0);   // 计算内积,并确保不为负数
    vec3 d_out = material.k_d * light.l_d * diff;   // 添加漫反射因子
    // C.镜面光
    //    C1. 照相机视角方向
    vec3 v = normalize(-v_pos);  // 在照相机坐标,观察者就在原点,所以观察者向量就是原点-物体向量
    //    C2. 光想反正方向
    vec3 r = reflect(s, n);
    //    C3. 计算镜面光因子
    float specular = max(dot(r, v), 0.0);
    //    C4. 镜面光输出
    vec3 s_out = material.k_s * light.l_s * pow(specular, material.shiness);
    // 最终的颜色输出
    vec3 color_out = a_out +  d_out + s_out;
    color_light = vec4(color_out, 1.0f); 
    gl_Position = perspective * view * model * vec4(aPos, 1.0);
}

smooth shading

采用的是Lambert反射模型下的Gouraud shading。着色是针对每个顶点计算,而后对每个顶点的结果颜色进行线性插值得到片元的颜色。这个方法有时也称为逐顶点着色(per-vertex shading)。

 // Vertex shader program
 attribute vec4 a_Position;
 // attribute vec4 a_Color;// Defined constant in main()
 attribute vec4 a_Normal;
 uniform mat4 u_MvpMatrix;
 uniform mat4 u_ModelMatrix;// Model matrix
 uniform mat4 u_NormalMatrix;// Transformation matrix of the normal
 uniform vec3 u_LightColor;// Light color
 uniform vec3 u_LightPosition;// Position of the light source
 uniform vec3 u_AmbientLight;// Ambient light color
 varying vec4 v_Color;
 void main() {
     vec4 color = vec4(1.0, 1.0, 1.0, 1.0);// Sphere color
     gl_Position = u_MvpMatrix * a_Position;
     // Calculate a normal to be fit with a model matrix, and make it 1.0 in length
     vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));
     // Calculate world coordinate of vertex
     vec4 vertexPosition = u_ModelMatrix * a_Position;
     // Calculate the light direction and make it 1.0 in length
     vec3 lightDirection = normalize(u_LightPosition - vec3(vertexPosition));
     // The dot product of the light direction and the normal
     float nDotL = max(dot(lightDirection, normal), 0.0);
     // Calculate the color due to diffuse reflection
     vec3 diffuse = u_LightColor * color.rgb * nDotL;
     // Calculate the color due to ambient reflection
     vec3 ambient = u_AmbientLight * color.rgb;
     // Add the surface colors due to diffuse reflection and ambient reflection
     v_Color = vec4(diffuse + ambient, color.a);
 }

 // Fragment shader program
 #ifdef GL_ES
 precision mediump float;
 #endif
 varying vec4 v_Color;
 void main() {
    gl_FragColor = v_Color;
 }

glossy shading

采用的是Phong反射模型下Phong shading。它对三角形的每个片元进行着色计算。这个方法有时也称为逐片元着色(per-pixel shading)。由于颜色是按片元着色的,因此得到的结果比Gouraud着色好,尤其是用于光亮表面。

// Vertex shader program
attribute vec4 a_Position;
//attribute vec4 a_Color;// Defined constant in main()
attribute vec4 a_Normal;
uniform mat4 u_MvpMatrix;
uniform mat4 u_ModelMatrix;// Model matrix
uniform mat4 u_NormalMatrix;// Transformation matrix of the normal
varying vec4 v_Color;
varying vec3 v_Normal;
varying vec3 v_Position;
void main() {
   vec4 color = vec4(1.0, 1.0, 1.0, 1.0);// Sphere color
   gl_Position = u_MvpMatrix * a_Position;
   // Calculate the vertex position in the world coordinate
   v_Position = vec3(u_ModelMatrix * a_Position);
   v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));
   v_Color = color;
}

// Fragment shader program
#ifdef GL_ES
precision mediump float;
#endif
uniform vec3 u_LightColor;// Light color
uniform vec3 u_LightPosition;// Position of the light source
uniform vec3 u_AmbientLight;// Ambient light color
varying vec3 v_Normal;
varying vec3 v_Position;
varying vec4 v_Color;
void main() {
   // Normalize the normal because it is interpolated and not 1.0 in length any more
   vec3 normal = normalize(v_Normal);
   // Calculate the light direction and make it 1.0 in length
   vec3 lightDirection = normalize(u_LightPosition - v_Position);
   // The dot product of the light direction and the normal
   float nDotL = max(dot(lightDirection, normal), 0.0);
   // Calculate the final color from diffuse reflection and ambient reflection
   vec3 diffuse = u_LightColor * v_Color.rgb * nDotL;
   vec3 ambient = u_AmbientLight * v_Color.rgb;
   gl_FragColor = vec4(diffuse + ambient, v_Color.a);
}

 

摘自

聊聊图形学中的Flat shading、Gouraud shading、Phong shading - 知乎 (zhihu.com)

GL02-04:OpenGL的flat修饰与双面渲染 - 简书 (jianshu.com)

 

标签:1.0,渲染,color,light,uniform,vec4,vec3,shading,3d
From: https://www.cnblogs.com/koala999/p/17011064.html

相关文章