如果代码中有什么不清楚请查看以下基础知识
Shader基础知识
unity3d 中 七种坐标知识详解
带模糊效果的 2D 阴影着色器教程(带代码详解)
一、效果预览
该 Shader 实现2D 物体 + 模糊阴影的双层渲染效果:一层渲染带 Box 模糊的偏移阴影,一层渲染物体本身(可叠加贴图与颜色),支持自定义阴影颜色、偏移量和模糊强度,适合 2D 游戏角色、UI 元素的阴影美化。
上笑狗图:

二、代码结构与核心部分说明
1. 属性面板(Properties)
Properties
{
_MainTex ("贴图", 2D) = "black" {} // 物体主贴图(默认黑色)
_Color ("颜色", Color) = (0.3, 0.59, 0.11,1) // 物体本身叠加色
_ShadowColor ("阴影颜色", Color) = (0.3, 0.59, 0.11,1) // 阴影颜色(含透明度)
_ShadowOffset ("阴影偏移", Vector) = (0.3, 0.59,0,0) // 阴影偏移(x/y控制左右上下,z无效)
_BlurSize("模糊尺寸", vector) = (256,256,0,0) // 模糊采样尺寸(对应贴图分辨率,x=宽,y=高)
_BlurOffset("模糊偏移", Range(1, 10)) = 1 // 模糊强度(值越大模糊越明显)
}
- 核心作用:暴露参数,在 Unity 编辑器实时调节物体颜色、阴影位置与模糊效果。
2. SubShader 基础设置
SubShader
{
LOD 200 // 细节层级(200适配中等性能)
Tags
{
"Queue" = "Transparent" // 透明队列(确保阴影/物体在不透明物体后渲染)
"IgnoreProjector" = "True" // 不受投影器影响(2D专用)
"RenderType" = "Transparent" // 透明类型(适配后处理)
}
- 关键作用:配置 2D 透明渲染规则,避免阴影与物体遮挡异常。
3. Pass 1:阴影渲染(带模糊)
(1)Pass 基础配置
Pass
{
Cull Off // 关闭背面裁剪(2D物体无正反面)
Lighting Off // 关闭光照(阴影无需光照计算)
ZWrite Off // 关闭深度写入(避免阴影遮挡物体)
Fog { Mode Off } // 关闭雾效
Blend SrcAlpha OneMinusSrcAlpha // 透明混合(阴影半透效果)
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// 声明属性变量
sampler2D _MainTex;
fixed4 _ShadowColor;
fixed4 _ShadowOffset;
float4 _BlurSize;
fixed _BlurOffset;
(2)数据结构定义
struct a2v
{
float4 vertex : POSITION; // 模型空间顶点坐标
float2 texcoord : TEXCOORD0; // 贴图UV
fixed4 color : COLOR; // 顶点颜色(预留)
};
struct v2f
{
float4 vertex : SV_POSITION; // 裁剪空间顶点坐标
half2 texcoord : TEXCOORD0; // 传递UV
fixed4 color : COLOR; // 传递顶点颜色
};
(3)Box 模糊工具函数(filter)
float4 filter(float3x3 filter, sampler2D tex, float2 coord, float2 texSize)
{
float4 outCol = float4(0,0,0,0);
// 遍历3x3矩阵(采样当前像素周围8个像素+自身)
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
// 计算偏移后的采样坐标(_BlurOffset控制偏移幅度)
float2 newCoord = float2(coord.x + (i-1)*_BlurOffset, coord.y + (j-1)*_BlurOffset);
float2 newUV = float2(newCoord.x / texSize.x, newCoord.y / texSize.y); // 转UV坐标
outCol += tex2D(tex, newUV) * filter[i][j]; // 采样颜色×滤波权重,累加
}
}
return outCol;
}
- 核心原理:3x3 Box 滤波(权重均为 1/9),实现均匀模糊效果。
(4)阴影顶点着色器(vert)
v2f vert (a2v v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); // 模型→裁剪空间
o.vertex.x += _ShadowOffset.x; // 阴影X轴偏移
o.vertex.y += _ShadowOffset.y; // 阴影Y轴偏移
o.texcoord = v.texcoord;
o.color = v.color;
return o;
}
- 关键操作:给顶点坐标加偏移,实现阴影与物体分离。
(5)阴影片元着色器(frag)
fixed4 frag (v2f v) : COLOR
{
// 定义3x3 Box滤波矩阵(权重平均,实现模糊)
float3x3 boxFilter =
{
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
};
// 计算贴图实际采样坐标(UV×模糊尺寸)
float2 coord = float2(v.texcoord.x * _BlurSize.x, v.texcoord.y * _BlurSize.y);
fixed4 f = filter(boxFilter, _MainTex, coord, _BlurSize); // 模糊采样
fixed4 color = f;
color.rgb = _ShadowColor.rgb; // 替换为阴影颜色
color.a = color.a * _ShadowColor.a; // 控制阴影透明度
return color;
}
4. Pass 2:物体本身渲染
Pass
{
// 同阴影Pass的基础配置(Cull Off、Lighting Off等,略)
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed4 _Color;
// 数据结构同Pass1(a2v、v2f,略)
// 物体顶点着色器(无偏移,直接传递坐标)
v2f vert (a2v v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); // 模型→裁剪空间
o.texcoord = v.texcoord;
o.color = v.color;
return o;
}
// 物体片元着色器
fixed4 frag (v2f v) : COLOR
{
fixed4 color = tex2D(_MainTex, v.texcoord); // 采样主贴图
color.rgb = color.rgb + _Color.rgb; // 叠加物体颜色
color.a = color.a * _Color.a; // 控制物体透明度
return color;
}
ENDCG
}
- 核心逻辑:无模糊、无偏移,直接渲染物体本身,与阴影 Pass 叠加形成最终效果。
三、使用步骤(3 步完成)
-
创建 Shader 与材质:Unity 中右键→Create→Shader→Unlit Shader,替换代码并命名 “Custom / 阴影着色器”;创建 Material,将 Shader 设为该自定义 Shader。
-
参数调节:拖入贴图到
_MainTex;调_Color改物体颜色;_ShadowColor设阴影色;_ShadowOffset控制阴影位置;_BlurOffset调模糊强度;_BlurSize设为贴图分辨率(如 256,256)。 -
应用物体:将材质赋给 2D Quad 或 Sprite,运行即可看到 “物体 + 模糊阴影” 效果。
完整代码
Shader "Custom/阴影着色器"
{
Properties
{
//图片设置
_MainTex ("贴图", 2D) = "black" {}
_Color ("颜色", Color) = (0.3, 0.59, 0.11,1)
//阴影设置
_ShadowColor ("阴影颜色", Color) = (0.3, 0.59, 0.11,1)
_ShadowOffset ("阴影偏移", Vector) = (0.3, 0.59,0,0)
//模糊
_BlurSize("模糊尺寸", vector) = (256,256,0,0)
//模糊偏移
_BlurOffset("模糊偏移", Range(1, 10)) = 1
}
SubShader
{
LOD 200
Tags
{
//透明队列
"Queue" = "Transparent"
//不被任何投影或贴图影响。一般应用在sprite和GUI
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
//阴影
Pass
{
//2d关闭
Cull Off
Lighting Off
ZWrite Off
Fog { Mode Off }
// Offset -1, -1
//正常透明度混合
Blend SrcAlpha OneMinusSrcAlpha
//ColorMaterial AmbientAndDiffuse | Emission 颜色材质 环境漫反射光照 及放射光
// ColorMaterial AmbientAndDiffuse
CGPROGRAM
//顶点与片元着色器
#pragma vertex vert
#pragma fragment frag
//unity宏
#include "UnityCG.cginc"
//阴影相关
sampler2D _MainTex;
fixed4 _ShadowColor;
fixed4 _ShadowOffset;
fixed4 _Color;
//模糊
float4 _BlurSize;
fixed _BlurOffset;
struct a2v
{
//顶点位置
float4 vertex : POSITION;
//贴图
float2 texcoord : TEXCOORD0;
//颜色
fixed4 color : COLOR;
};
struct v2f
{
//像素位置
float4 vertex : SV_POSITION;
//贴图
half2 texcoord : TEXCOORD0;
//颜色
fixed4 color : COLOR;
};
//对忒图滤波
float4 filter(float3x3 filter, sampler2D tex, float2 coord, float2 texSize)
{
float4 outCol = float4(0,0,0,0);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
//计算采样点,得到当前像素附近的像素的坐标
float2 newCoord = float2(coord.x + (i-1)*_BlurOffset, coord.y + (j-1)*_BlurOffset);
float2 newUV = float2(newCoord.x / texSize.x, newCoord.y / texSize.y);
//采样并乘以滤波器权重,然后累加
outCol += tex2D(tex, newUV) * filter[i][j];
}
}
return outCol;
}
//顶点着色器
v2f vert (a2v v)
{
v2f o;
//将顶点从模型空间转换为裁剪空间,因为2d就是平面映射。
o.vertex = UnityObjectToClipPos(v.vertex);
//偏移
o.vertex.x += _ShadowOffset.x;
o.vertex.y += _ShadowOffset.y;
o.vertex.z += _ShadowOffset.z;
o.texcoord = v.texcoord;
o.color = v.color;
return o;
}
// 片元着色器
fixed4 frag (v2f v) : COLOR
{
//模糊
//定义滤波核
float3x3 boxFilter =
{
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
};
float2 coord = float2(v.texcoord.x * _BlurSize.x, v.texcoord.y * _BlurSize.y);
fixed4 f = filter(boxFilter, _MainTex, coord, _BlurSize);
//像素颜色
// fixed4 color = tex2D(_MainTex, v.texcoord) ;
fixed4 color = f;
//像素颜色 点乘 灰度因子
color.rgb = _ShadowColor.rgb;
//透明度
color.a = color.a * _ShadowColor.a;
return color;
}
ENDCG
}
//正常着色
Pass
{
//2d关闭
Cull Off
Lighting Off
ZWrite Off
Fog { Mode Off }
// Offset -1, -1
//正常透明度混合
Blend SrcAlpha OneMinusSrcAlpha
//ColorMaterial AmbientAndDiffuse | Emission 颜色材质 环境漫反射光照 及放射光
// ColorMaterial AmbientAndDiffuse
CGPROGRAM
//顶点与片元着色器
#pragma vertex vert
#pragma fragment frag
//unity宏
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed4 _Color;
struct a2v
{
//顶点位置
float4 vertex : POSITION;
//贴图
float2 texcoord : TEXCOORD0;
//颜色
fixed4 color : COLOR;
};
struct v2f
{
//像素位置
float4 vertex : SV_POSITION;
//贴图
half2 texcoord : TEXCOORD0;
//颜色
fixed4 color : COLOR;
};
//顶点着色器
v2f vert (a2v v)
{
v2f o;
//将顶点从模型空间转换为裁剪空间,因为2d就是平面映射。
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = v.texcoord;
o.color = v.color;
return o;
}
// 片元着色器
fixed4 frag (v2f v) : COLOR
{
//像素颜色
fixed4 color = tex2D(_MainTex, v.texcoord) ;
//像素颜色 点乘 灰度因子
color.rgb = color.rgb + _Color.rgb;
//透明度
color.a = color.a * _Color.a;
return color;
}
ENDCG
}
}
}
本文介绍了一种在Unity中为UGUI和Sprite生成动态阴影的Shader技术,通过两个着色程序块实现正常显示与阴影效果,支持颜色调节和模糊设置。
&spm=1001.2101.3001.5002&articleId=104047216&d=1&t=3&u=5ac6de957f9e481681d70fce878c4ae4)
1598

被折叠的 条评论
为什么被折叠?



