Cook-Torrance光照模型
Posted pj2933
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cook-Torrance光照模型相关的知识,希望对你有一定的参考价值。
Cook-Torrance光照模型将物体粗糙表面看作由很多微平面组成,每一个微平面都可以看成一个理想的镜面反射体,物体表面粗糙程度由微平面斜率的变化来表示。越粗糙的表面由斜率变化越大,反之越小。
Cook-Torrance模型将光分为两个方面考虑,漫反射光强和镜面反射光强:Ic-t=Idiff+Ispec。
Idiff是漫反射光强,计算方式参照理想漫反射体(Lambert模型)的计算方式。Ispec是镜面反射光强,Ispec=KsIlRs。Cook-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光照模型》