Phong高光反射
如图,反射光与视角的夹角越小,光强越大 ---->> 光强为 反射光与视角夹角的余弦值cosΘ,即 R向量(反射光)*V向量(视角方向)
已知视角方向有现成的值,需要求反射光向量
反射光向量
注意:各个向量都当做单位向量
如图可得:
R向量(反射光) + L向量 = 2 * |L| * cosΘ * n向量(这里n向量表明方向,因为n向量为单位向量,不用除以它的模)
= 2 * cosΘ * n向量
= 2 * (L向量 * n向量) * n向量 //cosΘ = L向量*n向量,漫反射已经说过
所以: r向量 = 2 * (L向量 * n向量) * n向量 - L向量
高光反射 = 光源颜色 * 物体表面颜色 * 光强(法线与光源方向的点乘)
= 光源颜色 * 物体表面颜色 * saturate( pow(dot(反射光, 视角), 高光光泽度) )
unity内置函数reflect(i, n) 返回入射光线i对表面法线n的反射光线 可以直接得到反射光线, 注意:入射光线i与unity光源方向是相反的,需要用"-"号
Shader "Custom/VertexPhong" { Properties { _Diffuse("Diffuse", Color) = (1,1,1,1) //漫反射颜色 _Specular("Specolor", Color) = (1,1,1,1)//高光颜色 _Gloss("Gloss", Range(1, 200)) = 5 //高光光泽度 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" fixed4 _Diffuse; fixed4 _Specular; float _Gloss; struct v2f { float4 vertex : SV_POSITION; fixed3 color : COLOR; }; v2f vert (appdata_base v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); //环境光 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //漫反射 fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate((dot(worldNormal, worldLight))); //高光反射 fixed3 reflectDir = normalize(reflect(-worldLight, worldNormal)); //入射光线与unity光源方向是相反的,需要用"-"号 fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - UnityObjectToWorldDir(v.vertex));//摄像机位置 - 起点 = 视角方向 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss); o.color = diffuse + ambient + specular; return o; } fixed4 frag (v2f i) : SV_Target { return fixed4(i.color, 1); } ENDCG } } }