渐变纹理
Contents
渐变纹理是用来做什么的
渐变纹理的主要作用是可以让模型呈现出插画、卡通风格的渲染效果
渐变纹理的基本原理
利用半兰伯特光照公式后半部分计算出来的0~1之间的值,构建一个UV相同的 坐标,然后从渐变纹理中取出对应的颜色进行叠加
决定漫反射明暗的不再是由 0~1这个值决定而是由渐变纹理中取出的颜色进行叠加达到最终效果
fixed halfLarbertNum = 0.5 + dot(wNormal,lightDir) * 0.5;
fixed3 rampColor = _LightColor0.rgb * _MainColor.rgb * tex2D(_RampTex,fixed2(halfLarbertNum,halfLarbertNum));修改渐变纹理设置 避免黑点出现
避免渐变纹理接缝处有黑点
我们需要将 Wrap Mode(循环模式)切换为 Clamp(拉伸模式)
出现黑点的原因是:
- 浮点数计算可能存在误差,会出现超过1的值(1.00001)
- 如果使用Repeat(重复模式),会舍弃整数部分,保留小数0.00001
- 这时对应的颜色会是最左边的值,因此会出现黑色
渐变纹理的基本实现
Shader "Unlit/Gradient"
{
Properties
{
_MainColor("MainColor",Color) = (1,1,1,1)
_RampTex("RampTex",2D) = ""{}
_SpecularColor("SpecularColor", Color) = (1,1,1,1)
_SpecularNum("SpecularNum", Range(8, 256)) = 18
}
SubShader
{
Pass
{
Tags { "LightMode" ="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
float3 normal:NORMAL;
float4 wpos : TEXCOORD1;
};
sampler2D _RampTex;
float4 _RampTex_ST;
fixed4 _MainColor;
fixed4 _SpecularColor;
float _SpecularNum;
v2f vert (appdata_base v)
{
v2f data;
data.vertex = UnityObjectToClipPos(v.vertex);
data.normal = UnityObjectToWorldNormal(v.normal);
data.wpos = mul(unity_ObjectToWorld,v.vertex);
return data;
}
fixed4 frag (v2f i) : SV_Target
{
float3 wNormal = normalize(i.normal);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed halfLarbertNum = 0.5 + dot(wNormal,lightDir) * 0.5;
fixed3 rampColor = _LightColor0.rgb * _MainColor.rgb * tex2D(_RampTex,fixed2(halfLarbertNum,halfLarbertNum));
//Phong
float3 viewDir = normalize(_WorldSpaceCameraPos - i.wpos);
float3 halfDir = normalize(lightDir + viewDir);
fixed3 specularColor = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0,dot(wNormal,halfDir)),_SpecularNum);
fixed3 color = UNITY_LIGHTMODEL_AMBIENT.rgb + rampColor + specularColor;
return fixed4(color,1);
}
ENDCG
}
}
}渐变纹理综合实现
Shader "Unlit/Gradient2"
{
Properties
{
_MainTex("MainTex",2D) = ""{} //主贴图
_NormalTex("NormalTex",2D) = ""{} //法线贴图
_BumpScale("BumpScale",range(0,1)) = 1 //凹凸度
_DiffuseColor("DiffuseColor",Color) = (1,1,1,1) //漫反射颜色
_RampTex("RampTex",2D) = ""{} //渐变贴图
_SpecularColor("SpecularColor", Color) = (1,1,1,1) //高光反射颜色
_SpecularNum("SpecularNum", Range(8, 256)) = 18 //光泽度
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float4 wpos : TEXCOORD1;
float3 viewDir:TEXCOORD2;
float3 lightDir:TEXCOORD3;
};
//漫反射
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _DiffuseColor;
sampler2D _RampTex;
//法线
sampler2D _NormalTex;
float4 _NormalTex_ST;
float _BumpScale;
//高光反射
fixed4 _SpecularColor;
float _SpecularNum;
v2f vert (appdata_full v)
{
v2f data;
//坐标转换
data.pos = UnityObjectToClipPos(v.vertex);
data.wpos = mul(unity_ObjectToWorld,v.vertex);
//uv贴图
data.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
data.uv.zw = v.texcoord.xy * _NormalTex_ST.xy + _NormalTex_ST.zw;
//计算 切线空间 变换矩阵
float3 bitangent = cross(v.tangent.xyz,v.normal) * v.tangent.w;
float3x3 rotation = float3x3(v.tangent.xyz,bitangent,v.normal);
//切线空间下的 视角和灯光向量
data.viewDir = mul(rotation,ObjSpaceViewDir(v.vertex));
data.lightDir = mul(rotation,ObjSpaceLightDir(v.vertex));
return data;
}
fixed4 frag (v2f i) : SV_Target
{
//法线
float4 packedNoraml = tex2D(_NormalTex,i.uv.zw);
float3 unpackNormal = UnpackNormal(packedNoraml);
//凹凸度
unpackNormal.xy *= _BumpScale;
unpackNormal.z = sqrt(1 -saturate(dot(unpackNormal.xy,unpackNormal.xy)));
//漫反射
fixed3 uvColor = tex2D(_MainTex,i.uv.xy) * _DiffuseColor.rgb;
fixed halfLarbertNum = dot(i.lightDir,unpackNormal) * 0.5 + 0.5;//渐变贴图
fixed3 diffuseColor = _LightColor0 * uvColor * tex2D(_RampTex,fixed2(halfLarbertNum,halfLarbertNum));
//高光
float3 halfDir = normalize(i.viewDir + i.lightDir);
fixed3 specularColor = _LightColor0 * _SpecularColor * pow(max(0,dot(halfDir,unpackNormal)),_SpecularNum);
//blinn-phong
fixed3 blinnPhongColor = UNITY_LIGHTMODEL_AMBIENT * uvColor + diffuseColor + specularColor;
return fixed4(blinnPhongColor,1);
}
ENDCG
}
}
}