FishMan的技术专栏 Game Developer/Technical Artist

中级Shader教程14 天空渲染

2018-04-23
Jiepeng Tan

1.实现原理

1.使用FBM 来模拟基本的云层形状 2.在FBM的过程中对不同layer位置进行随时间不同程度的偏移

2.源码

1.单层FBM中不同的层之间移动速度随时间的偏移

float TimeFBM( float2 p,float t )
{
    float2 f = 0.0;
    float s = 0.5;
    float sum =0;
    for(int i=0;i<5;i++){
        p += t;//位置添加时间偏移
        t *=1.5;//每一层时间偏移不同 等到不同分层不同移速的效果
        f += s*tex2D(_NoiseTex, p/256).x; p = mul(float2x2(0.8,-0.6,0.6,0.8),p)*2.02;
        sum+= s;s*=0.6;
    }
    return f/sum;    
}

2.大的云层分布

float3 Cloud(float3 bgCol,float3 ro,float3 rd,float3 cloudCol,float spd, float layer)
{
    float3 col = bgCol;
    float time = _Time.y*0.05*spd;
    //对不同的大的分层 添加不同的基本高度
    for(int i=0; i<layer; i++){
        float2 sc = ro.xz + rd.xz*((i+3)*40000.0-ro.y)/rd.y;
        //颜色与背景色混合叠加
        col = lerp( col, cloudCol, 0.5*smoothstep(0.5,0.8,TimeFBM(0.00002*sc,time*(i+3))) );
    }
    return col;
}

3.其他部分的绘制

// create by JiepengTan 
// https://github.com/JiepengTan/FishManShaderTutorial2018-04-14  email: jiepengtan@gmail.com
float4 ProcessRayMarch(float2 uv,float3 ro,float3 rd,inout float sceneDep,float4 sceneCol)  {
    fixed4 sph = fixed4(0.0,0.0,0.0, 0.5);
    fixed3 col = fixed3(0.0,0.0,0.0);  
    float3 light1 = normalize( float3(-0.8,0.4,-0.3) );
    float sundot = clamp(dot(rd,light1),0.0,1.0);
   
    
    //基本的天空颜色过渡
    col = float3(0.2,0.5,0.85)*1.1 - rd.y*rd.y*0.5;
    col = lerp( col, 0.85*float3(0.7,0.75,0.85), pow( 1.0-max(rd.y,0.0), 4.0 ) );
    
    //太阳绘制 
    col += 0.25*float3(1.0,0.7,0.4)*pow( sundot,5.0 );
    col += 0.25*float3(1.0,0.8,0.6)*pow( sundot,64.0 );
    col += 0.2*float3(1.0,0.8,0.6)*pow( sundot,512.0 );
    // 云
    col = Cloud(col,ro,rd,float3(1.0,0.95,1.0),1,1);
    // 过滤掉地平线以下的部分
    col = lerp( col, 0.68*float3(0.4,0.65,1.0), pow( 1.0-max(rd.y,0.0), 16.0 ) );
    sceneCol.xyz = col;
    return sceneCol;
} 

配套视频


Similar Posts

Comments