// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unlit/NewUnlitShader"
{
Properties
{
//定义与unity通信的变量名
_MainColor("Main Color", Color) = (0.5,0.5,0.5,1)
_OutlineColor("Outline Color",Color) = (0,0,0,1) //轮廓颜色
_Outline("Outline width",Range(0.0,10)) = 0.005 //轮廓线宽度
}
SubShader
{
Tags { "RenderType"="Transparent" }
LOD 100
//固定管线渲染器。背面剔除,并在深度缓冲区中留下背面剔除的深度值
Pass{
Name "BASE"
//剔除背面
Cull Back
//保存缓冲区
Blend Zero One
SetTexture[_OutlineColor]
{
ConstantColor(1,0,0,0)
Combine constant
}
}
//顶点/片段着色器。正面剔除,那些经过法线伸展后的点会因为与深度剔除的缓存值比较后无法通过而被剔除
//也就是说仅仅剩下正面与背面的边缘处因为伸展的原因保留了下来, 于是轮廓就出现了,这就是大体过程了
Pass{
Name"OUTLINE"
Tags{"LightMode" = "Always"}
Cull Front
Blend One OneMinusDstColor
//顶点片元着色器代码
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//引入unitycg库
#include "UnityCG.cginc"
//定义从应用到顶点着色器的数据,此处用于获取顶点位置信息和法线信息
struct appdata{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
//定义顶点着色器输出给片元着色器的数据,此处输出片元位置,及颜色
struct v2f{
float4 pos :POSITION;
float4 color : COLOR;
};
uniform float _Outline;
uniform float4 _OutlineColor;
//顶点着色器程序块
v2f vert(appdata v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV,v.normal);
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z* _Outline;
o.color = _OutlineColor;
return o;
}
//片段着色器代码块
half4 frag(v2f i) :COLOR{
return i.color;
}
ENDCG
}
}
}
Shader "Custom/Catoon" {
Properties{
_MainTex("Base (RGB)", 2D) = "white" {}
_OutlineColor("Outline Color", Color) = (1,1,0,1) //描边颜色
_Outline("Outline width", Range(0.0, 0.5)) = 0.03 // 描边宽度
}
CGINCLUDE
#include "UnityCG.cginc"
//获取顶点、法线、纹理坐标
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
//
struct v2f {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Outline;
float4 _OutlineColor;
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
v2f vert_outline(appdata_t v)
{
v2f o;
// 方式一,观察空间 下往法线偏移顶点
float4 viewPos = mul(UNITY_MATRIX_MV, v.vertex);
//float3 viewNorm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
float3 viewNorm = mul(v.normal, (float3x3)UNITY_MATRIX_T_MV);
float3 offset = normalize(viewNorm) * _Outline;
viewPos.xyz += offset;
o.vertex = mul(UNITY_MATRIX_P, viewPos);
//方式二,世界空间 下往法线偏移顶点
//float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//float3 worldNormal = UnityObjectToWorldNormal(v.normal);
//float3 offset = normalize(worldNormal) * _Outline;
//worldPos.xyz += offset;
//o.vertex = mul(UNITY_MATRIX_VP, worldPos);
return o;
}
ENDCG
SubShader{
Tags{ "Queue" = "Transparent" "RenderType" = "Opaque" }
Pass{ // 正常绘制
Stencil
{
Ref 1
Comp Always
Pass Replace
ZFail Replace
}
ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.texcoord);
return col;
}
ENDCG
}
Pass{ // 遮挡部分绘制描边
ZTest Greater
ZWrite Off
//Blend DstAlpha OneMinusDstAlpha
Stencil{
Ref 1
Comp NotEqual
}
CGPROGRAM
#pragma vertex vert_outline
#pragma fragment frag
half4 frag(v2f i) :COLOR
{
return _OutlineColor;
}
ENDCG
}
}
}
Shader "Custom/Cartoon" {
Properties{
//主贴图
_MainTex("MainTex",2D) = "white"{}
//主颜色
_Color("Color",Color) = (1,1,1,1)
//漫反射色调纹理
_RampTex("Ramp",2D) = "white"{}
//描边宽度
_Outline("Outline",Range(0,1)) = 0.1
//描边颜色
_OutlineColor("OutlineColor",Color) = (0,0,0,1)
//高光反射颜色
_Specular("SpecularColor",Color) = (1,1,1,1)
//高光阈值
_SpecularScale("Specular Scale",Range(0,0.1)) = 0.01
}
SubShader{
//该段pass 的作用是描边
Pass{
NAME "OUTLINE"
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
//定义与unity通信的变量
fixed _Outline;
fixed4 _OutlineColor;
//定义应用到顶点阶段用的结构
struct a2v {
float4 vertex:POSITION;
float3 normal:NORMAL;
};
//定义顶点到片元阶段用的结构
struct v2f {
float4 pos:SV_POSITION;
};
//定点找色器
v2f vert(a2v v) {
v2f o;
//当前的模型观察矩阵, 用于将顶点/方向数据从模型空间变换到观察空间
float4 pos = mul(UNITY_MATRIX_MV,v.vertex);
//UNITY_MATRIX_MV的逆转置矩阵,用于将法线从模型空间变换到观察空间,也可以用于得到UNITY_MATRIX_MV的逆矩阵
float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV,v.normal);
normal.z = -0.5;
pos = pos + float4(normalize(normal),0)*_Outline;
o.pos = mul(UNITY_MATRIX_P,pos);
return o;
}
fixed4 frag(v2f i) :SV_Target{
return fixed4(_OutlineColor.rgb,1);
}
ENDCG
}
//该段作用时上色
Pass{
Tags{"LightMode" = "ForwardBase"}
//裁剪后方
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "Lighting.cginc"
#include "UnityCG.cginc"
#include "AutoLight.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
sampler2D _RampTex;
fixed4 _Specular;
fixed _SpecularScale;
//应用到顶点着色器的数据
struct a2v {
//顶点位置,法线与贴图
float4 vertex:POSITION;
float3 normal:NORMAL;
float2 texcoord:TEXCOORD0;
};
//顶点到片段着色器的数据
struct v2f {
//顶点信息、uv信息、世界坐标法线信息和世界坐标信息。
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
float3 worldPos:TEXCOORD2;
SHADOW_COORDS(3)
};
//顶点着色器正文
v2f vert(a2v v) {
v2f o;
//将模型坐标转换为裁剪坐标
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
//片段着色器 指定输出为SV_Target
fixed4 frag(v2f i) :SV_Target{
//获取模型在世界空间的法线向量 计算与输入向量方向相同的单位向量
fixed3 worldNormal = normalize(i.worldNormal);
//仅用于向前渲染中,输入一个世界空间中的顶点位置, 返回世界空间中从该点到光源的光照方向。没有被归一化
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
//输入一个世界空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
//计算与输入向量方向相同的单位向量
fixed3 worldHalf = normalize(worldLightDir + worldViewDir);
fixed4 c = tex2D(_MainTex,i.uv);
fixed3 albedo = c.rgb*_Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
fixed diff = dot(worldNormal,worldLightDir);
diff = (diff*0.5 + 0.5)*atten;
fixed3 diffuse = _LightColor0.rgb*albedo*tex2D(_RampTex,float2(diff,diff)).rgb;
fixed spec = dot(worldNormal,worldHalf);
fixed w = fwidth(spec)*2.0;
fixed3 specular = _Specular.rgb*lerp(0,1,smoothstep(-w,w,spec + _SpecularScale - 1))*step(0.0001,_SpecularScale);
//最后添加的step(0.0001,_SpecularScale);是为了控制当Specular为0时,不出现高光效果
return fixed4(ambient + diffuse + specular,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
//这里的回调需要注意包含能够处理阴影的特殊Pass
}
Shader "Custom/ScrollSurfaceShader"
{
Properties{
//叠加颜色
_Color("Color", Color) = (1,1,1,1)
//指定贴图
_MainTex("Albedo (RGB)", 2D) = "white" {}
//光泽
_Glossiness("Smoothness", Range(0,1)) = 0.5
//金属度
_Metallic("Metallic", Range(0,1)) = 0.0
//x轴滚动
_ScrollXSpeed("X Scroll Speed", Range(0, 10)) = 0.2
//y轴滚动
_ScrollYSpeed("Y Scroll Speed", Range(0, 10)) = 0.2
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
//没在pass中,因为时表面着色器
CGPROGRAM
//声明表面着色器
#pragma surface surf Standard fullforwardshadows // Physically based Standard lighting model, and enable shadows on all light types
#pragma target 3.0 // Use shader model 3.0 target, to get nicer looking lighting
sampler2D _MainTex;
//定义输入结构
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
fixed _ScrollXSpeed;
fixed _ScrollYSpeed;
//表面着色器正文 第一个参数为输入,第二个参数为输出
void surf(Input IN, inout SurfaceOutputStandard o)
{
//输入的速度值 * 时间
fixed2 scrollValue = fixed2(_ScrollXSpeed * _Time.y, _ScrollYSpeed * _Time.y);
//uv = 当前的uv值+根据时间变动的值
float2 scrolledUV = IN.uv_MainTex + scrollValue;
//返回小数部分 这是i因为uv 的满值是1,要接受1以内的小数
scrolledUV = frac(scrolledUV);
//镜像播放
//scrolledUV = sin(scrolledUV);
// 设置主色,由贴图颜色 * color设置颜色
fixed4 c = tex2D(_MainTex, scrolledUV) * _Color;
o.Albedo = c.rgb;
//金属
o.Metallic = _Metallic;
//平滑
o.Smoothness = _Glossiness;
//透明度
o.Alpha = c.a;
}
ENDCG
}
//默认效果
FallBack "Diffuse"
}
Shader "Custom/SurfaceShader"
{
SubShader
{
Tags { "RenderType" = "Opaque" "ForceNoShadowCasting" = "True" "IgnoreProjector" = "True"}
LOD 130
Pass
{
//CG代码块
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//引入unityCG处理库
#include "UnityCG.cginc"
//定义一个数据结构,该结构包含一个4维向量,一个三维向量
struct v2f
{
//获取位置
float4 pos : SV_POSITION;
//获取颜色
float2 color : COLOR0;
};
//顶点程序代码,用于计算位置和颜色。 v2f是刚才新建的数据结构,vert是在cgprogram注册的用于顶点计算的程序名
//该方法输入值appdata_base v是与模型关联后自动输入的
//该方法输入值appdata_base v是与模型关联后自动输入的,他的输出值会自动传入到片段代码块。所以相关联的顶点和片段方法的输出和输入类型一定要一致
v2f vert(appdata_base v)
{
//创建v2f数据 o
v2f o;
//计算位置
o.pos = UnityObjectToClipPos(v.vertex);
//计算颜色
o.color = v.normal* 0.5 + 0.5;
//返回该v2f数据
return o;
}
//片段程序代码
//该代码块会自动接受顶点着色器的输出值,而他的输出值会交给像素着色器最终显示在屏幕上
half4 frag(v2f i) : COLOR
{
//返回输入的颜色,并设置透明度为1
return half4(i.color,0.5,0.1);
}
ENDCG
}
}
Fallback "VertexLit"
}
Shader "Custom/duibidu"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Brightness("Brightness", Float) = 1 //调整亮度
_Saturation("Saturation", Float) = 1 //调整饱和度
_Contrast("Contrast", Float) = 1 //调整对比度
}
SubShader
{
Pass
{
ZTest Always
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
sampler2D _MainTex;
half _Brightness;
half _Saturation;
half _Contrast;
//vert和frag函数
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
struct appdata_t
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
//从vertex shader传入pixel shader的参数
struct v2f
{
float4 pos : SV_POSITION; //顶点位置
half2 uv : TEXCOORD0; //UV坐标
half4 color : COLOR;
};
//vertex shader
v2f vert(appdata_t v)
{
v2f o;
//从自身空间转向投影空间
o.pos = UnityObjectToClipPos(v.vertex);
o.color = v.color;
//uv坐标赋值给output
o.uv = v.texcoord;
return o;
}
//fragment shader
fixed4 frag(v2f i) : COLOR
{
//从_MainTex中根据uv坐标进行采样
fixed4 renderTex = tex2D(_MainTex, i.uv)*i.color;
//brigtness亮度直接乘以一个系数,也就是RGB整体缩放,调整亮度
fixed3 finalColor = renderTex * _Brightness;
//saturation饱和度:首先根据公式计算同等亮度情况下饱和度最低的值:
fixed gray = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
fixed3 grayColor = fixed3(gray, gray, gray);
//根据Saturation在饱和度最低的图像和原图之间差值
finalColor = lerp(grayColor, finalColor, _Saturation);
//contrast对比度:首先计算对比度最低的值
fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
//根据Contrast在对比度最低的图像和原图之间差值
finalColor = lerp(avgColor, finalColor, _Contrast);
//返回结果,alpha通道不变
return fixed4(finalColor, renderTex.a);
}
ENDCG
}
}
//防止shader失效的保障措施
FallBack Off
}
Shader"Alphatest"
{
Properties
{
_MainTex("Base(RGB)",2D)="white"{}
_Cutoff("Value",Range(0,1))=0.5
}
SubShader
{
CGPROGRAM
#pragma surface surf Lambert alphatest:_Cutoff//(1)
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN,inout SurfaceOutput o)
{
half4 c =tex2D(_MainTex,IN.uv_MainTex);
o.Albedo=c.rgb;
o.Alpha = c.r;//(2)
}
ENDCG
}
FallBack"Diffuse"
}
Shader "Custom/MiniMap_s_new"
{
Properties
{
//当然就是材质啦
_MainTex ("Texture", 2D) = "white" {}
//要被替换的目标颜色
_TargetColor ("Target Color", Color) = (1, 1, 1, 1)
//要被替换的颜色范围
_TargetRange ("Target Color Range", Range(0, 1)) = 0.01
//替换成什么颜色
_ReplaceColor ("Replace Color", Color) = (1, 1, 1, 1)
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 _TargetColor;
fixed _TargetRange;
fixed4 _ReplaceColor;
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//替换颜色
_TargetColor = _TargetColor + _TargetRange;
if(col.r < abs(_TargetColor.r) && col.g < abs(_TargetColor.g) && col.b < abs(_TargetColor.b)){
col = _ReplaceColor;
//如果透明度小于等于0.就不显示
if(col.a <= 0){
discard;
}
}
return col;
}
ENDCG
}
}
}
参考文章
https://blog.csdn.net/qq_38572472/article/category/7364961 这个老兄的十篇shader入门文章写的都很好,帮推一下。
https://blog.csdn.net/sdqq1234/article/details/61437045