Unity Shader 入门精要——渐变纹理

效果图:

Unity Shader 入门精要——渐变纹理_第1张图片

 代码:

Shader "CustomShader/Texture/RampShader"
{
	Properties
	{
		_RampTex ("Texture", 2D) = "white" {}
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
	}
	SubShader
	{
		Pass
		{
			Tags {"LightMode" = "ForwardBase"}
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
 
			sampler2D _RampTex;    //渐变纹理
			float4 _RampTex_ST;    //纹理属性变量
			fixed4 _Color;
			fixed4 _Specular;
			float _Gloss;
 
			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};
 
			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				float3 worldPos : TEXCOORD1;
				float3 worldNormal : TEXCOORD2;
			};
 
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
                //内置宏TRANSFORM_TEX计算经过平铺和偏移后的纹理坐标
				o.uv = TRANSFORM_TEX(v.uv, _RampTex);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
 
				return o;
			}
 
			fixed4 frag (v2f i) : SV_Target
			{
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
 
				fixed halfLambert = dot(worldNormal, lightDir) * 0.5 + 0.5;
				fixed3 color = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb * _Color.rgb;
 
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
 
				fixed3 diffuse = _LightColor0.rgb * color;
 
				fixed3 halfDir = normalize(viewDir + lightDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
 
				return fixed4(ambient + diffuse + specular, 1.0);
			}
			ENDCG
		}
	}
 
	FallBack "Specular"
}

在片段着色器中使用半兰伯特光照模型:

fixed halfLambert = dot(worldNormal, lightDir) * 0.5 + 0.5;
fixed3 color = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb * _Color.rgb;

在上面的代码中,通过对法线方向和光照方向的点积做一次0.5倍的缩放以及一个0.5大小的偏移来计算半兰伯特部分halfLambert。这样,我们得到的halfLambert 的范围被映射到了[0,1]之间。之后,我们使用halfLambert 来构建一个纹理坐标,并用这个纹理坐标对渐变纹理_RampTex进行采样。由于_RampTex实际就是一个一维纹理(它在纵轴方向上颜色不变),因此纹理坐标的u和v方向我们都使用了halfLambert。 然后,把从渐变纹理采样得到的颜色和材质颜色Color相乘,得到最终的漫反射颜色。剩下的代码就是计算高光反射和环境光,并把它们的结果进行相加。

fixed2(halfLambert, halfLambert) 这句其实我们只关心其x坐标,y坐标没意义。那么halfLambert为什么可以与纹理坐标联系起来呢,我们从漫反射的公式中看出,法线与光照方向的夹角决定了光照系数,夹角越小,光照系数越大,漫反射越强,反之,系数越小,漫反射越弱,那么我们用渐变纹理的x轴表示其系数变化,x轴也就是系数越小,就采样越黑的颜色,表示漫反射越弱,系数越大也就是x越大,就采样越白的颜色,表示漫反射越强,所以我们的渐变纹理是从左到右从黑到白,就是这个原理。
————————————————
版权声明:本文为CSDN博主「Aimar_Johnny」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lzhq1982/article/details/77659332

需要注意的是,我们需要把渐变纹理的Wrap Mode 设为Clamp模式,以防止对纹理进行采样时由于浮点数精度而造成的问题。

你可能感兴趣的:(shader,shader)