OpenGL 4.0 GLSL 实现 平面着色 Implementing flat shading

在逐顶点shader光照模型中  要计算每个顶点的颜色,然后用这些点的颜色经过插值来产生光华的表面效果(The colors are then interpolated across the face of the polygon to produce a smooth shading effect),这个被称作Gouraund Shading。这在早期的OpenGL 版本中,经过每个顶点颜色插值来实现光照模型是其默认实现。


然而有时候  想为每个polygon 使用一个单一的颜色,这样看起来每个polygon有种平面效果(each polygon to have a flat appearance),这在表面看起来就是这个平面的效果

的模型上很有用,如鱼鳞(个人认为)。为每个polygon用单一颜色的技术通常叫做Flat shading。


如图:

OpenGL 4.0 GLSL 实现 平面着色 Implementing flat shading_第1张图片


在OpenGL 4.0 中 使用flat模型 ,在其out变量前面添 flat限定符即可。


vertex shader

#version 430

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;

flat out vec3 LightIntensity;

struct LightInfo {
  vec4 Position; // Light position in eye coords.
  vec3 La;       // Ambient light intensity
  vec3 Ld;       // Diffuse light intensity
  vec3 Ls;       // Specular light intensity
};
uniform LightInfo Light;

struct MaterialInfo {
  vec3 Ka;            // Ambient reflectivity
  vec3 Kd;            // Diffuse reflectivity
  vec3 Ks;            // Specular reflectivity
  float Shininess;    // Specular shininess factor
};
uniform MaterialInfo Material;

uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 MVP;

void main()
{
    vec3 tnorm = normalize( NormalMatrix * VertexNormal);
    vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0);
    vec3 s = normalize(vec3(Light.Position - eyeCoords));
    vec3 v = normalize(-eyeCoords.xyz);
    vec3 r = reflect( -s, tnorm );
    float sDotN = max( dot(s,tnorm), 0.0 );
    vec3 ambient = Light.La * Material.Ka;
    vec3 diffuse = Light.Ld * Material.Kd * sDotN;
    vec3 spec = vec3(0.0);
    if( sDotN > 0.0 )
       spec = Light.Ls * Material.Ks *
              pow( max( dot(r,v), 0.0 ), Material.Shininess );

    LightIntensity = ambient + diffuse + spec;
    gl_Position = MVP * vec4(VertexPosition,1.0);
}

片元shader 

#version 430

flat in vec3 LightIntensity;

layout( location = 0 ) out vec4 FragColor;

void main() {
    FragColor = vec4(LightIntensity, 1.0);
}


前面的flat限定符 是告诉shader 在数据到达片元shader之前不要进行插值来计算。最终一个polygon的颜色有组成这个polygon的第一个顶点或最后一个顶点的颜色确定。这个顶点叫做Provoking  vertex ,这个可以通过OpenGL的函数glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); 配置。或者GL_LAST_VERTEX_CONVENTION


你可能感兴趣的:(OpenGL 4.0 GLSL 实现 平面着色 Implementing flat shading)