1. 程式人生 > >Cook-Torrance光照模型

Cook-Torrance光照模型

com normal cal 處的 nsf mvp 頂點 半角 sample

  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光照模型