码迷,mamicode.com
首页 > 其他好文 > 详细

water effect(1)

时间:2015-10-19 00:42:11      阅读:299      评论:0      收藏:0      [点我收藏+]

标签:

  在GPU Gems1的第一小节中,可以看到通过Gerstner wave function来模拟海洋的波浪效果,同时在Unity自带的Water(Pro)效果中,FX/Water4中的部分水波效果正是通过该公式来模拟的。

  首先来看看FX-Water4.shader的代码。

    Tags {"RenderType"="Transparent" "Queue"="Transparent"}

    Lod 500
    ColorMask RGB
    
    GrabPass { "_RefractionTex" }
    Pass {    
            #pragma vertex vert
            #pragma fragment frag    
    }
}

Subshader 
{     
    Tags {"RenderType"="Transparent" "Queue"="Transparent"}
    
    Lod 300
    ColorMask RGB
    
    Pass { 
            #pragma vertex vert300
            #pragma fragment frag300      
    }    
}
Subshader 
{     
    Tags {"RenderType"="Transparent" "Queue"="Transparent"}
    
    Lod 200
    ColorMask RGB
    
    Pass {
            #pragma vertex vert200
            #pragma fragment frag200
    }    
}

Fallback "Transparent/Diffuse"
其中包含三个subshader,具体执行哪一个Subshader,是通过waterBase.cs来设置sharedMaterial.shader.maximumLOD设置的。我们从low quality开始分析,顶点着色器的代码如下。
    v2f_simple vert200(appdata_full v)
    { 
        v2f_simple o;
        //计算出顶点的世界坐标
        half3 worldSpaceVertex = mul(_Object2World, v.vertex).xyz;
        half2 tileableUv = worldSpaceVertex.xz;
                
        //通过设置的 _BumpDirection.xy值来模拟第一个方向,zw值模拟另一个方向, _BumpTiling.xy模拟第一个方向的速率,zw模拟第二个方向的变化速率。
        o.bumpCoords.xyzw = (tileableUv.xyxy + _Time.xxxx * _BumpDirection.xyzw) * _BumpTiling.xyzw;    

       //viewInterpolator是用来计算相机到该顶点的方向。
        o.viewInterpolator.xyz = worldSpaceVertex-_WorldSpaceCameraPos;
        
        //pos暂时无用。
        o.pos = mul(UNITY_MATRIX_MVP,  v.vertex);
        
        o.viewInterpolator.w = 1;//GetDistanceFadeout(ComputeScreenPos(o.pos).w, DISTANCE_SCALE); 
    
        return o;

    }                                                                                                                

 在片元着色器中,我们可以看到法线的计算是通过PerPixelNormal函数实现的,在WaterInclude.cginc中可以找到该函数。

inline half3 PerPixelNormal(sampler2D bumpMap, half4 coords, half3 vertexNormal, half bumpStrength) 
{
//计算normal map中两个不同方向的值。
    half4 bump = tex2D(bumpMap, coords.xy) + tex2D(bumpMap, coords.zw);

//计算出法线方向
    bump.xy = bump.wy - half2(1.0, 1.0);

//通过bumpStrength来增大x,z相对于Y的比例,即增加纹理的凹凸感,在unity 中可以看到,bumpStrength越大,水面反光效果越明显。
    half3 worldNormal = vertexNormal + bump.xxy * bumpStrength * half3(1,0,1);

//归一化计算。
    return normalize(worldNormal);
} 

 得到法线方向后,具体的片元着色器代码如下。

    half4 frag200( v2f_simple i ) : SV_Target
    {        
//法线计算
        half3 worldNormal = PerPixelNormal(_BumpMap, i.bumpCoords, half3(0,1,0), PER_PIXEL_DISPLACE);

//归一化视角向量
        half3 viewVector = normalize(i.viewInterpolator.xyz);

//暂时无用
        half3 reflectVector = normalize(reflect(viewVector, worldNormal));

//半角向量计算,减少计算光线与法线之间的计算量(Jim Blinn),与binnPhong高光模型计算一致          
        half3 h = normalize ((_WorldLightDir.xyz) + viewVector.xyz);

        float nh = max (0, dot (worldNormal, -h));
        float spec = max(0.0,pow (nh, _Shininess));    

//通过Fresnel参数控制缩放
        worldNormal.xz *= _FresnelScale;    

//计算出fresnel反射率。
        half refl2Refr = Fresnel(viewVector, worldNormal, FRESNEL_BIAS, FRESNEL_POWER);    

        half4 baseColor = _BaseColor;

//通过fresnel反射率混合折射与反射颜色。
        baseColor = lerp(baseColor, _ReflectionColor, saturate(refl2Refr * 2.0));

//fresnel反射率越大,alpha越大,水下物品越看不清。
        baseColor.a = saturate(2.0 * refl2Refr + 0.5);

//与高光混合,最终颜色计算。
        baseColor.rgb += spec * _SpecularColor.rgb;
        return baseColor;    
    }

核心是fresnel反射率的计算,fresnel的基本原理是视线与法线的角度越小,即与平面越垂直,反射越小,折射越大,水下的物品越清晰,视线与平面越平行,反射越大,水下物品越看不清。在WaterINclude.cginc中有简易的fresnel的计算公式。

inline half Fresnel(half3 viewVector, half3 worldNormal, half bias, half power)
{
//夹角的计算。
    half facing =  clamp(1.0-max(dot(-viewVector, worldNormal), 0.0), 0.0,1.0);
//反射率的计算。    
    half refl2Refr = saturate(bias+(1.0-bias) * pow(facing,power));    
    return refl2Refr;    
}

  这一节主要是通过UV纹理的变化来模拟简易水波,但无法在相同的normal map下实现大波浪似的效果。下一节主要介绍Gerstner wave function如何更实现高级的水波效果。

water effect(1)

标签:

原文地址:http://www.cnblogs.com/VanHu/p/4890495.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!