镜面反射计算公式:
float3 reflectVector=reflect(-lightDir,normal)---光线方向和法线方向求出反射方向
float specDot=max(dot(reflectionVector,eyeDir),0.0)---反射方向和眼睛方向求点积
float spec=pow(specDot,specExponent)---最后一个参数是镜面反射强度
1、设置反射颜色和反射强度的属性
_SpecColor("Specular Matirals Color",Color)=(1,1,1,1) _Shiness("Shiness",float)=10
2、矩阵乘法转化为世界坐标系
float _Shiness;
v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.vetexWorld = mul(unity_ObjectToWorld, v.vertex); }
3、正则化表示和计算
fixed4 frag (v2f i) : SV_Target { float3 normalDirection = normalize(i.worldNormal); float3 viewDirection = normalize(UnityWorldSpaceViewDir(i.vetexWorld)); float3 LightDirection = normalize(UnityWorldSpaceLightDir(i.vetexWorld)); //漫反射 float4 tex = tex2D(_DiffuseTex, i.UV); float nl = max(_Ambient, dot(normalDirection, _WorldSpaceLightPos0.xyz)); //镜面反射 float3 ReflectDirection = reflect(-LightDirection, normalDirection); float3 SpecularDot = max(0.0, dot(ReflectDirection, viewDirection)); float3 Specular = pow(SpecularDot, _Shiness); float4 SpecularTerm = float4(Specular, 1)*_SpecColor*_LightColor0; float4 diffuseTerm = nl * tex*_Color*_LightColor0; float4 finalyColor = diffuseTerm + SpecularTerm; return finalyColor; }
完整代码:
Shader "Custom/SpecularShader" { Properties { _Color("Color",Color) = (1,0,0,1) _DiffuseTex("Texture",2D) = "white"{} _Ambient("Ambient",Range(0,1))=0.25 _SpecColor("Specular Matirals Color",Color)=(1,1,1,1) _Shiness("Shiness",float)=10 } SubShader { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase"} LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include"UnityLightingCommon.cginc" fixed4 _Color; sampler2D _DiffuseTex; float4 _DiffuseTex_ST; float _Ambient; float _Shiness; struct appdata { float4 vertex : POSITION; float3 normal:Normal; float2 UV:TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float3 worldNormal : TEXCOORD1; float2 UV:TEXCOORD0; float4 vetexWorld:TEXCOORD2; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.vetexWorld = mul(unity_ObjectToWorld, v.vertex); float3 worldNormal = UnityObjectToWorldNormal(v.normal); o.worldNormal = worldNormal; o.UV = TRANSFORM_TEX(v.UV, _DiffuseTex); return o; } fixed4 frag (v2f i) : SV_Target { float3 normalDirection = normalize(i.worldNormal); float3 viewDirection = normalize(UnityWorldSpaceViewDir(i.vetexWorld)); float3 LightDirection = normalize(UnityWorldSpaceLightDir(i.vetexWorld)); //漫反射 float4 tex = tex2D(_DiffuseTex, i.UV); float nl = max(_Ambient, dot(normalDirection, _WorldSpaceLightPos0.xyz)); //镜面反射 float3 ReflectDirection = reflect(-LightDirection, normalDirection); float3 SpecularDot = max(0.0, dot(ReflectDirection, viewDirection)); float3 Specular = pow(SpecularDot, _Shiness); float4 SpecularTerm = float4(Specular, 1)*_SpecColor*_LightColor0; float4 diffuseTerm = nl * tex*_Color*_LightColor0; float4 finalyColor = diffuseTerm + SpecularTerm; return finalyColor; } ENDCG } } }
多光源完整代码:
Shader "Custom/SpecularShaderForwardAdd" { Properties { _Color("Color",Color) = (1,0,0,1) _DiffuseTex("Texture",2D) = "white"{} _Ambient("Ambient",Range(0,1))=0.25 _SpecColor("Specular Matirals Color",Color)=(1,1,1,1) _Shiness("Shiness",float)=10 } SubShader { Pass { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase"} LOD 100 CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" #include"UnityLightingCommon.cginc" fixed4 _Color; sampler2D _DiffuseTex; float4 _DiffuseTex_ST; float _Ambient; float _Shiness; struct appdata { float4 vertex : POSITION; float3 normal:Normal; float2 UV:TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float3 worldNormal : TEXCOORD1; float2 UV:TEXCOORD0; float4 vetexWorld:TEXCOORD2; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.vetexWorld = mul(unity_ObjectToWorld, v.vertex); float3 worldNormal = UnityObjectToWorldNormal(v.normal); o.worldNormal = worldNormal; o.UV = TRANSFORM_TEX(v.UV, _DiffuseTex); return o; } fixed4 frag (v2f i) : SV_Target { float3 normalDirection = normalize(i.worldNormal); float3 viewDirection = normalize(UnityWorldSpaceViewDir(i.vetexWorld)); float3 LightDirection = normalize(UnityWorldSpaceLightDir(i.vetexWorld)); //漫反射 float4 tex = tex2D(_DiffuseTex, i.UV); float nl = max(_Ambient, dot(normalDirection, _WorldSpaceLightPos0.xyz)); //镜面反射 float3 ReflectDirection = reflect(-LightDirection, normalDirection); float3 SpecularDot = max(0.0, dot(ReflectDirection, viewDirection)); float3 Specular = pow(SpecularDot, _Shiness); float4 SpecularTerm = float4(Specular, 1)*_SpecColor*_LightColor0; float4 diffuseTerm = nl * tex*_Color*_LightColor0; float4 finalyColor = diffuseTerm + SpecularTerm; return finalyColor; } ENDCG } Pass { Tags { "RenderType" = "Opaque" "LightMode" = "Forwardadd"} Blend one one LOD 100 CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdadd #include "UnityCG.cginc" #include"UnityLightingCommon.cginc" fixed4 _Color; sampler2D _DiffuseTex; float4 _DiffuseTex_ST; float _Ambient; float _Shiness; struct appdata { float4 vertex : POSITION; float3 normal:Normal; float2 UV:TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float3 worldNormal : TEXCOORD1; float2 UV:TEXCOORD0; float4 vetexWorld:TEXCOORD2; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.vetexWorld = mul(unity_ObjectToWorld, v.vertex); float3 worldNormal = UnityObjectToWorldNormal(v.normal); o.worldNormal = worldNormal; o.UV = TRANSFORM_TEX(v.UV, _DiffuseTex); return o; } fixed4 frag(v2f i) : SV_Target { float3 normalDirection = normalize(i.worldNormal); float3 viewDirection = normalize(UnityWorldSpaceViewDir(i.vetexWorld)); float3 LightDirection = normalize(UnityWorldSpaceLightDir(i.vetexWorld)); //漫反射 float4 tex = tex2D(_DiffuseTex, i.UV); float nl = max(0.0, dot(normalDirection, _WorldSpaceLightPos0.xyz)); //镜面反射 float3 ReflectDirection = reflect(-LightDirection, normalDirection); float3 SpecularDot = max(0.0, dot(ReflectDirection, viewDirection)); float3 Specular = pow(SpecularDot, _Shiness); float4 SpecularTerm = float4(Specular, 1)*_SpecColor*_LightColor0; float4 diffuseTerm = nl * tex*_Color*_LightColor0; float4 finalyColor = diffuseTerm + SpecularTerm; return finalyColor; } ENDCG } } }