Unity 光照着色器
光照着色器需要考虑光照的分类,一般分为漫反射和镜面反射。
漫反射计算基本光照:
float brightness=dot(normal,lightDir) 将法线和光的入射方向进行点积运算,求出光的亮度。
float3 pixelColor=brightness*lightColor*surfaceColor 将光的亮度*光的颜色*物体表面颜色得到我们最终看到的颜色。
Shader "Unlit/DiffuseShader" { Properties { _Color("Color",Color)=(1,0,0,1) } SubShader { #新加了光照模式标签 Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"} LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "UnityLightingCommon.cginc" fixed4 _Color; struct appdata { float4 vertex : POSITION; float3 normal:NORMAL; #法线方向 }; struct v2f { float4 vertex : SV_POSITION; float3 worldNormal:TXCOORD0; # }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); float3 worldNormal=UnityObjectToWorldNormal(v.normal); o.worldNormal=worldNormal; return o; } fixed4 frag (v2f i) : SV_Target { float3 normalDirection=normalize(i.worldNormal); float nl=max(0.0,dot(normalDirection,_WorldSpaceLightPos0.xyz)); float4 diffusTerm=nl*_Color*_LightColor0; return diffusTerm; } ENDCG } } }
镜面反射具体实现:
R=2*(N*L)*N-L;
float3 reflectionVector=reflect(-lightDir,normal); //用入射光线方向和法线求出反射光线方向
float specDot=max(dot(reflectionVector,eyeDir),0.0); //反射光线和眼睛入射方法求点积
float spec=pow(specDot,spectExponent);
fixed4 frag (v2f i) : SV_Target { //标准化法向量 float3 normalDirection=normalize(i.worldNormal); float3 viewDirection=normalize(UnityWorldSpaceViewDir(i.vertexWorld)); float3 lightDirection=normalize(UnityWorldSpaceViewDir(i.vertexWorld)); //采样纹理 float4 tex=tex2D(_DiffuseTex,i.uv); //漫反射计算,使用兰帕特近似方法lambert float nl=max(0.0,dot(normalDirection,_WorldSpaceLightPos0.xyz)); float4 diffusTerm=nl*_Color*_LightColor0; //镜面反射计算,使用芳式近似方法Phong float3 reflectionDirection=reflect(-lightDirection,normalDirection); float3 specularDot=max(0.0,dat(viewDirection,reflectionDirection)); float3 specular=pow(specularDot,_shininess); //计算最终的颜色 float4 specularTerm=float4(specular,1)*_SpacColor*_LightColor; float4 finalColor=diffusTerm*specularTerm; return finalColor;