效果
思路
在漫反射计算时,对渐变纹理进行针对性取样。
在模型背光面的顶点颜色,取样渐变纹理uv上,较暗的即可。
比如在背光面时,法线方向与光源方向相反,进行点乘后结果为负数,再进行半兰伯特计算,得到的最终结果会是接近0的正数,对应渐变纹理上就是左边偏暗的地方。
核心算法如下:
fixed halfLambert = 0.5 * dot ( worldNormal, worldLightDir ) + 0.5;
//这里使用半兰伯特计算后的结果,去取样渐变图uv颜色
fixed3 diffuseColor = tex2D( _RampTex, fixed2( halfLambert, halfLambert)).rgb * _Color.rgb;
实现
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Custom/RampTexture" { //9
Properties{
_Color("Color",Color) = (1,1,1,1)
_RampTex ("RampTex" , 2D) = "white" {}
_Specular ("Specular" , Color) = (1,1,1,1)
_Gloss("Gloss", Range(2,200)) = 20
}
SubShader{
Pass{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
fixed4 _Specular;
sampler2D _RampTex;
float _Gloss;
float4 _RampTex_ST;
struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert (a2v v){
v2f f;
f.pos = UnityObjectToClipPos(v.vertex);
f.worldNormal = UnityObjectToWorldNormal( v.normal);
f.worldPos = mul( unity_ObjectToWorld, v.vertex).xyz;
f.uv = TRANSFORM_TEX(v.texcoord, _RampTex );
return f;
};
fixed4 frag (v2f f) : SV_Target {
fixed3 worldNormal = normalize( f.worldNormal );
fixed3 worldLightDir = normalize( UnityWorldSpaceLightDir(f.worldPos ) );
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed halfLambert = 0.5 * dot ( worldNormal, worldLightDir ) + 0.5;
//这里使用半兰伯特计算后的结果,去取样渐变图uv颜色
fixed3 diffuseColor = tex2D( _RampTex, fixed2( halfLambert, halfLambert)).rgb * _Color.rgb;
fixed3 diffuse = _LightColor0.rgb * diffuseColor;
fixed3 viewDir = normalize ( UnityWorldSpaceViewDir (f.worldPos) );
fixed3 halfDir = normalize( worldLightDir + viewDir );
fixed3 specular = _LightColor0 * _Specular.rgb * pow ( saturate( dot ( worldNormal, halfDir )), _Gloss );
return fixed4 ( diffuse + ambient ,1);
};
ENDCG
}
}
FallBack "Diffuse" //后备方案
}