一.渐变纹理
利用半兰伯特构建float2变量,以此对一张渐变纹理进行采样。漫反射的颜色靠此方式获得。
Shader "Custom/Edu/RampTexture" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
//_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Specular("Specular",Color) = (1,1,1,1)
_RampTex("Ramp Texture",2D) = "white"{}
_Gloss("Gloss",Range(9,256)) = 40
}
SubShader {
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _Color;
//sampler2D _MainTex;
sampler2D _RampTex;
float4 _RampTex_ST;
fixed4 _Specular;
float _Gloss;
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 o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.worldNormal = mul(v.normal,(float3x3)_World2Object);
o.worldPos = mul((float3x3)_Object2World,v.vertex);
//o.uv = TRANSFORM_TEX(v.texcoord,_RampTex);
return o;
}
fixed4 frag(v2f i):SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
float3 worldNormal = normalize(i.worldNormal);
float3 worldLightDir = normalize( UnityWorldSpaceLightDir(i.worldPos) );
float halfLambert = dot(worldNormal,worldLightDir) * 0.5 + 0.5;
fixed3 diffuseColor = tex2D(_RampTex,float2(halfLambert,halfLambert)).rgb;
fixed3 diffuse = diffuseColor * _LightColor0.rgb;
float3 worldViewDir = UnityWorldSpaceViewDir(i.worldPos);
float3 halfDir = normalize(worldViewDir + worldLightDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow( saturate(dot(worldNormal,halfDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
效果图:
二.遮罩纹理
这遮罩纹理的使用是对高光效果进行遮罩,使用同一组uv坐标,对同一位置处的遮罩纹理进行采样,这里只使用了r分量。
同样,可以分为切线空间下计算以及世界空间下计算。
1.切线空间下的高光遮罩纹理实现:
Shader "Custom/Edu/MaskTexTangent" {
Properties
{
_MainTex("MainTex",2D) = "white"{}
_BumpMap("BumpMap",2D) = "white"{}
_BumpScale("BumpScale",float) = 1
_SpecularMask("SpecularMask",2D) = "white"{}
_Specular("Specular",Color) = (1,1,1,1)
_Color("ColorTint",Color) = (1,1,1,1)
_Diffuse("DIffuse",Color) = (1,1,1,1)
_SpecularScale("SpecularScale",float) = 1.0
_Gloss("Gloss",Range(8,256)) = 8
}
SubShader
{
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;float4 _MainTex_ST;
sampler2D _SpecularMask;float4 _SpecularMask_ST;
sampler2D _BumpMap;float4 _BumpMap_ST;
float _BumpScale;
fixed4 _Specular;
fixed4 _Color;
fixed4 _Diffuse;
float _Gloss;
float _SpecularScale;
struct a2v
{
float4 vertex:POSITION;
float3 normal:NORMAL;
//注意因为我们要使用tangent的w分量,所以这里的类型是float4
float4 tangent:TANGENT;
float4 texcoord:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float3 viewDir:TEXCOORD1;
float3 lightDir:TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
float3 bionormal = cross(normalize(v.normal),normalize(v.tangent.xyz))*v.tangent.w;
//float3x3是一种类型,不需要类型转换时不用加括号
float3x3 rotation = float3x3(v.tangent.xyz,bionormal,v.normal);
//or just use TANGENT_SPACE_ROTATION;
//注意,注意取xyz分量
o.viewDir = mul(rotation,ObjSpaceViewDir(v.vertex)).xyz;
o.lightDir = mul(rotation,ObjSpaceLightDir(v.vertex)).xyz;
//o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//o.uv.zw = v.texcoord.xy * _BumpTex_ST.xy + _BumpMap_ST.zw;
o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex);
//o.uv.zw = TRANSFORM_TEX(v.texcoord,_BumpMap);
return o;
}
fixed4 frag(v2f i):SV_Target
{
float3 tangentViewDir = normalize(i.viewDir);
float3 tangentLightDir = normalize(i.lightDir);
//使用的是fixed3类型
fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap,i.uv));
tangentNormal.xy *= _BumpScale;
tangentNormal.z = sqrt(1.0-saturate(dot(tangentNormal.xy,tangentNormal.xy)));
fixed3 albedo = tex2D(_MainTex,i.uv).rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
//半兰伯特模型
//fixed3 halfLambert = dot(tangentNormal,tangentLightDir) * 0.8 + 0.2;
//fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;
fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse * saturate(dot(tangentNormal,tangentLightDir));
//潜意识中的错误写法,误以为和渐变纹理的使用方式一样?!
fixed3 halfDir = normalize(tangentViewDir + tangentLightDir);
//fixed3 maskColor = tex2D(_MaskTex,float2(halfDir,halfDir)).rgb;
//正确写法:通过uv对MaskTex对应位置进行采样!!!
//fixed3 specularMask = tex2D(_MaskTex,i.uv.xy).rgb * _SpecularScale;
//不好意思上面仍然不是正确的写法
//所谓的 specularMask 实际上只利用采样纹理的一个分量通道,这里仅仅利用r。
fixed specularMask = tex2D(_SpecularMask,i.uv).r * _SpecularScale;
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal,halfDir)),_Gloss) * specularMask;
return fixed4(ambient + diffuse + specular,1.0);
}
ENDCG
}
}
}
2.世界空间下高光遮罩纹理实现:
Shader "Custom/Edu/MaskTexWorld" {
Properties {
_Color ("ColorTint", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Gloss ("Gloss", Range(8,256)) = 20
_BumpMap("BumpMap",2D) = "white"{}
_BumpScale("BumpScale",Range(-1,1)) = 1
_Specular("Specular",Color) = (1,1,1,1)
_SpecularMask("SpecularMask",2D) = "white"{}
_SpecularScale("SpecularScale",float) = 1.0
}
SubShader {
Pass
{
Tags{"LgihtMode" = "ForwarBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _Gloss;
sampler2D _BumpMap;
float _BumpScale;
fixed4 _Specular;
sampler2D _SpecularMask;
float _SpecularScale;
struct a2v
{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
float4 tangent:TANGENT;
};
struct v2f
{
float4 pos:SV_POSITION;
float4 TtoW0:TEXCOORD0;
float4 TtoW1:TEXCOORD1;
float4 TtoW2:TEXCOORD2;
float2 uv:TEXCOORD3;
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
//需要归一化么?(其实返回的结果已经归一化了)
float3 worldNormal = normalize( UnityObjectToWorldNormal(v.normal) );
float3 worldTangent = normalize( UnityObjectToWorldDir(v.tangent.xyz) );
float3 worldBionormal = cross(worldNormal,worldTangent)*v.tangent.w;
float3 worldPos = mul(_Object2World,v.vertex);
o.TtoW0 = float4(worldTangent.x,worldBionormal.x,worldNormal.x,worldPos.x);
o.TtoW1 = float4(worldTangent.y,worldBionormal.y,worldNormal.y,worldPos.y);
o.TtoW2 = float4(worldTangent.z,worldBionormal.z,worldNormal.z,worldPos.z);
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag(v2f i):SV_Target
{
float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
//为啥老是忘记归一化呢
float3 worldLightDir =normalize(UnityWorldSpaceLightDir(worldPos));
//为啥老是忘记归一化呢
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
float3 bump = UnpackNormal(tex2D(_BumpMap,i.uv));
bump.xy *= _BumpScale;
bump.z = sqrt(1-saturate(dot(bump.xy,bump.xy)));
float3 worldNormal = normalize( float3(dot(bump,i.TtoW0.xyz),dot(bump,i.TtoW1.xyz),dot(bump,i.TtoW2.xyz)) );
fixed3 albedo = tex2D(_MainTex,i.uv).rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(worldNormal,worldLightDir));
fixed specularMask = tex2D(_SpecularMask,i.uv).r * _SpecularScale;
fixed3 halfDir = normalize(worldLightDir + worldViewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfDir)),_Gloss) * specularMask;
return fixed4(ambient + diffuse + specular,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
3.效果图:
两种方式看不出任何差别。