Cook-Torrance光照模型


  Cook-Torrance光照模型將物體粗糙表面看作由很多微平面組成,每一個微平面都可以看成一個理想的鏡面反射體,物體表面粗糙程度由微平面斜率的變化來表示。越粗糙的表面由斜率變化越大,反之越小。

 

  Cook-Torrance模型將光分為兩個方面考慮,漫反射光強和鏡面反射光強:Ic-t=Idiff+Ispec

 

  Idiff是漫反射光強,計算方式參照理想漫反射體(Lambert模型)的計算方式。Ispec是鏡面反射光強,Ispec=KsIlRsCook-Torrance模型與phong、blinn-phong 模型的不同之處在於 Rs 的計算方法。Cook-Torrance的Rs計算公式如下:

  

 

  F是菲涅爾反射系數。真實世界中,當視線和表面的夾角不同時,反射效果會有差別。例如,站在湖邊上,自己腳邊的水面,反射不明顯,可以看到水下的東西;遠處的水面,反射則十分明顯。

  D表示微平面分布函數。該項模擬物體表面是由無數微小的像鏡子一樣的平面組成,每一個微平面對於光線會根據自身的方向反射光線。最常使用的微平面分布函是 Backmann 分布函數:

   

 

  m值用於度量表面的粗糙程度,較大的m 值對應於粗糙平面,較小的m 值對應與較光滑的表面;α 是頂點法向量 N 和半角向量 H 的夾角。其中可推導:

 

 

  所以最終可得:

  

 

  G是遮擋項。微平面間會出現三種情況:部分入射光被遮擋;部分反射光被遮擋;入射光反射光都沒有被遮擋。

     G=min(1,G1,G2)

  

   

 

   代碼實現如下:

Shader "Custom/Cook-Torrance" {
    Properties {        
        mainTexture ("Texture", 2D) = "white" {}
        specularColor("SpecularColor", Color) = (1,1,1,1)         
        fresnel0 ("Fresnel", Range(0,1)) = 0.5
        roughness ("Roughness", Range(0,1)) = 0.5
        ks("Ks",Range(0,1))=0.5
    }
    SubShader {
    
        Tags { "LightMode"="ForwardBase" }
        LOD 200
        Pass{
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc" 
        //#include "Light.cginc" 
        
        // Use shader model 3.0 target, to get nicer looking lighting
         
        uniform float4 _LightColor0;

        sampler2D mainTexture;
        float4 mainTexture_ST;
        uniform float4 specularColor;
        uniform float fresnel0;
        uniform float roughness;
        uniform float ks;

        struct v2f{
            float4 pos:SV_POSITION;
            float4 worldPos:TEXCOORD0;
            float3 normal:NORMAL;
            float2 uv:TEXCOORD1;
        };

        v2f vert(appdata_full v){
            v2f o;
            o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
            o.worldPos=mul(_Object2World,v.vertex);
            o.normal=v.normal;
            o.uv=TRANSFORM_TEX(v.texcoord, mainTexture);
            return o;
        }

        float4 frag(v2f o):COLOR
        {
            float4 worldPos=o.worldPos;
            float3 worldNormal=normalize(mul(float4(o.normal,0),_World2Object).xyz);            
            float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
            float3 viewDir=normalize(_WorldSpaceCameraPos-worldPos).xyz;            
            float3 halfAngleDir=normalize(viewDir+lightDir);

            float vhDot=saturate( dot(viewDir,halfAngleDir));
            float nhDot=saturate(dot(worldNormal,halfAngleDir));
            float nlDot=saturate(dot(worldNormal,lightDir));
            float nvDot=saturate(dot(worldNormal,viewDir));

            float3 texColor= tex2D(mainTexture, o.uv);

            float3 Ispec;
            float3 Idiff=(_LightColor0*specularColor*nlDot).xyz*texColor;
            if(nlDot>0){
                //F項         
                float F =pow((1.0-vhDot),5.0);
                F *= (1.0-fresnel0);
                F += fresnel0;

                //D項
                float d1=1/(roughness*roughness*pow(nhDot,4));    
                float d2=exp((nhDot*nhDot-1)/(roughness*roughness*nhDot*nhDot));
                float D=d1*d2;

                //G項
                float g1=2*nhDot*nlDot/vhDot;
                float g2=2*nhDot*nvDot/vhDot;
                float G=min(1,min(g1,g2));

                float Rs=saturate((F*D*G)/(nvDot*nlDot));

                 Ispec=(Rs*specularColor*ks).xyz;
             }
             else
                return float4(Idiff,1);

            

            float3 finalColor=Idiff+Ispec;
             
            return float4(finalColor,1);
        }
         
        ENDCG
    }
    }
    FallBack "Diffuse"
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM