Shader "QShader/ToonShadingOne"{
Properties{
_MainColor("Main Color",Color) = (1.0,1.0,1.0,1.0)
//渐变纹理
_Ramp("Ramp Texture",2D) = "white"{
}
//控制轮廓线大小
_OutLine("Outline",Range(0,1)) = 0.1
_OutLineColor("OutLine Color",Color) = (1.0,1.0,1.0,1.0)
//高光颜色
_SpecularColor("Specular Color",Color) = (1.0,1.0,1.0,1.0)
//控制高光区域的阈值
_SpecularScale("Specular Scale",Range(0,0.1)) = 0.01
}
SubShader{
pass {
//后续可能用到所以定义一个名字 后面可以通过UsePass指令来直接使用
NAME "OUTLINE"
//我们只需要渲染三角面的背面,不需要渲染正面,所以把正面剔除掉。
Cull Front
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
#include "UnityCG.cginc"
fixed _OutLine;
fixed4 _OutLineColor;
//定义描边需要的定点着色器和片元着色器
float4 Vertex(appdata_base v) :SV_POSITION{
//至于为什么要变换到视角空间下的理解为:这是为了让描边效果可以再观察空间达到最好的效果
//将顶点转换到视角空间
float3 _pos = UnityObjectToViewPos(v.vertex.xyz);
float4 pos = float4(_pos,1);
//将法线转换到视角空间
float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV,v.normal);
//在第一个Pass中,我们会使用轮廓线颜色渲染整个背面的片面,并且在视角空间下把模型的顶点沿着法线方向
// 向外扩展一段距离,以此来让背部的轮廓线可见
//pos = pos + normal * _Outline;
// 但是如果直接使用顶点法线进行扩展,对于一些内凹的模型来说就可能发生背面片面遮挡住正面的情况。
// 所以为了应对这里处理,采取的办法是对顶点法线的z分量进行处理,让z分量等于一个定值,然后把法线归一化后再进行扩展,
// 扩展后的背面更加扁平化,从而降低了遮挡住正面的可能性。
normal.z = -0.5;
pos = pos + float4(normalize(normal) * _OutLine,0);
return UnityViewToClipPos(pos);
}
fixed4 Fragment() :SV_TARGET{
//使用轮廓线颜色渲染整个背面的片面
return float4(_OutLineColor.xyz,1);
}
ENDCG
}
//这个Pass是为了定义光照模型所在的Pass
pass {
Tags{
"LightMode" = "ForwardBase"}
Cull Back
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
#pragma multi_compile_fwdbase
#include "AutoLight.cginc"
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
SHADOW_COORDS(3)
};
fixed4 _BaseColor;
sampler2D _Ramp;
fixed4 _SpecularScale;
fixed4 _SpecularColor;
v2f Vertex(appdata_base v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
fixed4 Fragment(v2f i) :SV_TARGET{
//归一化法线向量
fixed3 worldNormal = normalize(i.worldNormal);
//归一化光源方向
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
//归一化视角方向
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
//归一化半程向量
fixed3 worldHalfDir = normalize(worldViewDir + worldLightDir);
//环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * _BaseColor.xyz;
//世界坐标下阴影值计算
UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
//半兰伯特光照模型
fixed diff = dot(worldNormal,worldLightDir);
diff = (diff * 0.5 + 0.5) * atten;
//漫反射
fixed3 diffuse = _LightColor0.xyz * _BaseColor.xyz * tex2D(_Ramp,float2(diff,diff)).xyz;
//高光
fixed specular = dot(worldHalfDir,worldNormal);
//使用fwidth对高光区域进行抗锯齿处理
fixed w = fwidth(specular) * 2.0;
//最后使用高光反射系数 和 高光反射颜色相乘 得到 高光反射部分 并且使用了step(0.0001,_SpecularScale).这是为了在
//_SpecularScale为0的时候可以完全消除高光反射的光照
specular = _SpecularColor.xyz * lerp(0,1,smoothstep(-w,w,specular + _SpecularScale - 1)) * step(0.0001,_SpecularScale);
return fixed4(ambient + diffuse + specular,1.0);
}
ENDCG
}
}
}
ToonShader-卡通渲染
猜你喜欢
转载自blog.csdn.net/qq_39691716/article/details/120580171
今日推荐
周排行