OpenGL(十五)雾效 的 shader 实现

雾效 可以表现出一个线性的颜色变化,常用于烘托场景气氛。这种效果的实现原理并不复杂,本文着重讨论如何通过shader编写完成雾效的实现。

核心原理

雾效 的核心在于:计算视点与物体之间的距离,然后根据一个衰减公式进行颜色混合。常规的算法有线性衰减,指数衰减,指数幂衰减。

线性雾效

使用线性差值衰减,即可达到这种 雾效 。示意图如下:

OpenGL(十五)雾效 的 shader 实现_第1张图片

对应shader如下:

//vs
varying vec3 V_Normal;
varying vec3 V_WorldPos;
varying vec4 V_EyeSpacePos;
void main()
{
    V_Normal=mat3(NM)*normal;
    vec4 worldPos=M*vec4(pos,1.0);
    V_WorldPos=worldPos.xyz;
    //将物体换算到视口坐标系
    V_EyeSpacePos=V*worldPos;
    gl_Position=P*V*worldPos;
}
//fs
uniform float U_FogStart;
uniform float U_FogEnd;
uniform vec4 U_FogColor;
varying vec3 V_Normal;
varying vec3 V_WorldPos;
varying vec4 V_EyeSpacePos;
float LinearFog(float distance)
{
    float fogAlpha=(distance-U_FogStart)/(U_FogEnd-U_FogStart);
    fogAlpha=clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}
void main()
{
    //color calculate
    ...
    //
    float fogAlpha = LinearFog(abs(V_EyeSpacePos.z/V_EyeSpacePos.w));
    gl_FragColor=mix(color,U_FogColor,fogAlpha);
}

指数雾效

指数雾效与上面的shader大体相同,唯一要更改的是衰减算法。添加一个density参数来控制曲线的弧度。

//fs
uniform vec4 U_Density;
float ExpFog(float distance)
{
    float fogAlpha=exp(-distance * U_Density);
    fogAlpha=1.0-clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}

指数幂雾效

通过Gradiant可以控制雾效的衰减速度。

//fs
uniform vec4 U_Density;
uniform vec4 U_Gradiant;
float ExpFog(float distance)
{
    float fogAlpha=exp(-pow(distance * U_Density,UGradiant));
    fogAlpha=1.0-clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}

总结

本文通过三种shader实现,介绍了如何制作 雾效 来烘托氛围效果。

你可能感兴趣的:(OpenGL,OpenGL,从入门到起飞)