OpenGL4.0 GLSL 实现逐片元光照模型 提高场景真实性

当计算光照模型(如ADS模型)的时候,通常是在vertex shader中计算每个顶点的颜色值,然后通过这些顶点插值 传入fragment shader中,这些被称为Gouraud shading.

Gouraud shading.模型有一些不尽人意的地方,例如,高光(bright  specular  highlight)可能在一个polygon的中间,这样通过这种模型计算就会影响高光显示效果。


为了提高渲染结果的准确性,我们可以把计算光照模型的计算 放到fragment  shader 中进行,我们通过插值物体表面的顶点和发向  而不是每个顶点的颜色,传递到fragment shader 中进行光照模型计算,这项技术程为:Phong shader  或者是 Phong interpolation 。这样通过phong shader 光照模型可以大大提高场景的真实性,但也会有一些小的瑕疵。

如图:Gouraud and Phong shading  对比

OpenGL4.0 GLSL 实现逐片元光照模型 提高场景真实性_第1张图片


左边是Gouraud (per-vertex) shading,右边是Phong(per-fragment)shading。 在途中可以看出 右边的效果要比左边的效果更真实些。


顶点shader

#version 430

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

out vec3 Position;
out vec3 Normal;

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

void main()
{
    Normal = normalize( NormalMatrix * VertexNormal);
    Position = vec3( ModelViewMatrix * vec4(VertexPosition,1.0) );

    gl_Position = MVP * vec4(VertexPosition,1.0);
}


片元shader

#version 430

in vec3 Position;
in vec3 Normal;

uniform vec4 LightPosition;
uniform vec3 LightIntensity;

uniform vec3 Kd;            // Diffuse reflectivity
uniform vec3 Ka;            // Ambient reflectivity
uniform vec3 Ks;            // Specular reflectivity
uniform float Shininess;    // Specular shininess factor

layout( location = 0 ) out vec4 FragColor;

vec3 ads( )
{
    vec3 s = normalize( vec3(LightPosition) - Position );
    vec3 v = normalize(vec3(-Position));
    vec3 r = reflect( -s, Normal );

    return
        LightIntensity * ( Ka +
          Kd * max( dot(s, Normal), 0.0 ) +
          Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );
}

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


你可能感兴趣的:(GLSL,GLSL,4.0,算法和特效)