Phong 光照模型
镜面反射(高光),是光线经过物体表面,反射到视野中,当反射光线与人的眼睛看得方向平行时,强度最大,高光效果最明显,夹角为90度时,强度最小。
specular = I*R*V;
specular:反射光经过物体表面反射后进入人眼的光强;
I:反射光的光强,Phong依然是理想模型,所以不考虑光的衰减,即反射光的光强和入射光的光强相等;
R:反射光线的方向;
V:视线的方向;
Shader程序
/******************************************* Phong 光照模型 1. 理想的镜面反射; *******************************************/ Shader "JQM/Specular" { Properties { _Color("Color", color) = (1.0,1.0,1.0,1.0) _SpecColor("Specular Color", color) = (1.0,1.0,1.0,1.0) _Shininess("Shininess",float) = 10 } SubShader{ Pass{ Tags { "LightMode" = "ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag //使用自定义变量 uniform float4 _Color; uniform float4 _SpecColor; uniform float _Shininess; //使用Unity定义的变量 uniform float4 _LightColor0; struct vertexInput{ float4 vertex:POSITION; float3 normal:NORMAL; }; struct vertexOutput{ float4 pos:SV_POSITION; float4 posWorld:TEXCOORD0; float3 normalDir:TEXCOORD1; }; //顶点程序 vertexOutput vert(vertexInput v) { vertexOutput o; o.posWorld = mul(_Object2World, v.vertex); o.normalDir = normalize( mul(float4(v.normal,0.0),_World2Object).xyz);//将模型空间的法线转到世界空间 o.pos = mul(UNITY_MATRIX_MVP, v.vertex); return o; } //片段程序 float4 frag(vertexOutput i):COLOR { float3 normalDirection = i.normalDir; float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz- i.posWorld.xyz);//视线方向 float3 lightDirection; float atten = 1.0; lightDirection = normalize(_WorldSpaceLightPos0.xyz);//光线方向 float3 diffuseReflection = atten * _LightColor0.xyz * max(0.0, dot(normalDirection,lightDirection));//计算兰伯特漫反射 float3 specularReflection = atten * _LightColor0.xyz * _SpecColor.rgb*max(0.0, dot(normalDirection,lightDirection))*pow(max(0,dot(reflect(-lightDirection,normalDirection),viewDirection)),_Shininess);//计算高光 float3 lightFinal = diffuseReflection +specularReflection+ UNITY_LIGHTMODEL_AMBIENT.xyz; return float4(lightFinal*_Color.rgb,1.0); } ENDCG } } }
Blinn-phong 高光
这个方式的高光是一种数学模型的优化,它将计算反射向量的过程替换为计算视线和光线的半角向量,提高了运算速度,它的效果比较平滑,运算速度快。