Cook-Torrance光照模型

Posted pj2933

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
            //o.view = WorldSpaceViewDir(v.vertex);
            //o.light = WorldSpaceLightDir(v.vertex);
            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"
}

 

以上是关于Cook-Torrance光照模型的主要内容,如果未能解决你的问题,请参考以下文章

一步步学Metal图形引擎10-《BRDF:Cook-Torrance光照模型》

一步步学Metal图形引擎10-《BRDF:Cook-Torrance光照模型》

光照贴图

GLSL PBS 实现,奇怪的着色器行为

Cg入门16:Fragment shader - 片段级光照

Unity Shader 光照模型(基础公式和代码实现)