雾化 透明度测试 以及 用户裁剪:Fog AlphaTest & ClipPlane - MartinRGB/GLES30_ProgrammingGuide_NDK GitHub Wiki

雾化

为了避免几何体突现的状况,可以考虑使用雾化:

1.雾化需要两个输入 像素到眼睛的距离(u_eyePos) 以及 雾化颜色(u_fogColor)。除此之外,还要提供雾化覆盖的最小和最大范围

2.线性雾化因子公式 Factor = (MaxDist - EyeDist)/(MaxDist - MinDist),然后用 Factor 乘以雾化颜色,最后和总体颜色进行线性插值

例:

Vertex:

uniform mat4 u_matViewProjection;
uniform mat4 u_matView;
uniform vec4 u_eyePos;

in vec4 a_vertex;
in vec2 a_texCoord0;

out vec2 v_texCoord;
out float v_eyeDist;

void main( void )
{
    // Transform vertex to view-space
    vec4 vViewPos = u_matView * a_vertex;
    
    // Compute the distance to eye
    v_eyeDist = sqrt( (vViewPos.x - u_eyePos.x) *
                      (vViewPos.x - u_eyePos.x) +
                      (vViewPos.y - u_eyePos.y) *
                      (vViewPos.y - u_eyePos.y) +
                      (vViewPos.z - u_eyePos.z) *
                      (vViewPos.z - u_eyePos.z) );                      

    gl_Position = u_matViewProjection * a_vertex;
    v_texCoord  = a_texCoord0.xy;
}

Fragment:

precision mediump float;

uniform vec4 u_fogColor;
uniform float u_fogMaxDist;
uniform float u_fogMinDist;
uniform sampler2D baseMap;

in vec2 v_texCoord;
in float v_eyeDist;

layout( location = 0 ) out vec4 outColor;

float computeLinearFogFactor()
{
   float factor;
   
   // Compute linear fog equation
   factor = (u_fogMaxDist - v_eyeDist) /
            (u_fogMaxDist - u_fogMinDist );
   
   // Clamp in the [0,1] range
   factor = clamp( factor, 0.0, 1.0 );
            
   return factor;            
}

void main( void )
{
    float fogFactor = computeLinearFogFactor();
    vec4 baseColor = texture( baseMap, v_texCoord );
    
    // Compute final color as a lerp with fog factor
    outColor = baseColor * fogFactor + 
    		   u_fogColor * (1.0 - fogFactor); 
}

Alpha 测试

Fragment:

precision mediump float;

uniform sampler2D baseMap;

in vec2 v_texCoord;
layout( location = 0 ) out vec4 outColor;

void main( void )
{
   vec4 baseColor = texture( baseMap, v_texCoord );
    
   if( baseColor.a < 0.25 )
   {
      discard;
   }
   else
   {
      outColor = baseColor;
   }
}

用户裁剪

Vertex:计算裁剪屏幕到顶点的距离

#version 300
uniform vec4 u_clipPlane;
uniform mat4 u_matViewProjection;
in vec4 a_vertex;

out float v_clipDist;

void main( void )
{
    // Compute the distance between the vertex and
    // the clip plane
    v_clipDist = dot( a_vertex.xyz, u_clipPlane.xyz ) + 
                 u_clipPlane.w;
    gl_Position = u_matViewProjection * a_vertex;
}

Fragment: 决定是否要裁剪片段

#version 300
precision mediump float;
in float v_clipDist;
layout( location = 0 ) out vec4 outColor;
void main( void )
{
    // Reject fragments behind the clip plane
    if( v_clipDist < 0.0 )
       discard;
       
    outColor = vec4( 0.5, 0.5, 1.0, 0.0 );    
}