效果如下
属性栏如下
属性块:
关于属性的内容可以看这篇:【Unity Shader 中Properties 相关介绍】
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_Color("Main Color", Color) = (1,1,1,1)
_RoundWaveStrength("Wave Strength", Range(0, 1)) = 0.7
_RoundWaveSpeed("Wave Speed", Range(0, 5)) = 2
}
Properties
块定义了可以在材质编辑器中调整的属性。
SubShader块:
SubShader
{
Tags {"Queue" = "Transparent" "RenderType"="Opaque" "IgnoreProjector" = "True" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Cull Off
- 定义了一个子着色器。
Tags
定义了渲染队列、渲染类型和投影忽略标记。Blend
定义了混合模式。ZWrite
和Cull
控制深度写入和剔除。
CGPROGRAM:
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
- 定义了一个渲染通道。
- 使用了CGPROGRAM和相关指令来指定顶点和片段着色器。
appdata:
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
half4 color : COLOR;
};
v2f:
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
half4 color : COLOR;
};
声明采样:
sampler2D _MainTex;
half4 _MainTex_ST, _MainTex_TexelSize, _Color;
float _RandomSeed;
half _RoundWaveStrength, _RoundWaveSpeed;
属性声明详细解释如下
名称 | 注释 |
---|
sampler2D _MainTex; | 声明了一个名为_MainTex 的2D纹理采样器。这通常用于存储和采样主纹理图像。 |
名称 | 注释 |
---|
half4 _MainTex_ST, _MainTex_TexelSize, _Color; | 声明了三个half4 类型的属性: |
_MainTex_ST | 通常用于存储纹理的平铺(tiling)和偏移(offset)参数。 |
_MainTex_TexelSize | 存储纹理的像素尺寸,这有助于进行像素级的纹理操作。 |
_Color | 一个颜色值,用于修改或混合纹理的颜色。 |
名称 | 注释 |
---|
half | 这是一个数据类型,通常用于着色器语言中。half 代表一个16位的浮点数,它比标准的32位浮点数(即float 类型)占用更少的内存和带宽,但精度较低。在图形渲染中,使用half 类型可以减少内存使用,尤其是在处理大量数据时,比如纹理坐标、顶点属性等。 |
_RoundWaveStrength | 这是一个变量名。在着色器语言中,变量名通常以下划线_ 开头,表示这是一个私有变量,仅在当前着色器中使用。RoundWaveStrength 这个名字暗示这个变量可能用于控制某种“圆形波纹”效果的强度。 |
_RoundWaveSpeed | 这同样是一个变量名,以下划线_ 开头。RoundWaveSpeed 这个名字暗示这个变量可能用于控制“圆形波纹”效果的移动速度。 |
v2f vert顶点着色器函数:
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.color = v.color;
return o;
}
片段着色器结构体:
half4 frag (v2f i) : SV_Target
{
}
ENDCG
}
}
- 片段着色器函数,负责渲染最终像素颜色。
ENDCG
标记CGPROGRAM代码块的结束。
片段着色器代码
half4 frag (v2f i) : SV_Target
{
float2 uvRect = i.uv;
half xWave = ((0.5 * _MainTex_ST.x) - uvRect.x);
half yWave = ((0.5 * _MainTex_ST.y) - uvRect.y) * (_MainTex_TexelSize.w / _MainTex_TexelSize.z);
half ripple = -sqrt(xWave*xWave + yWave* yWave);
i.uv += (sin((ripple + (_Time.y + _RandomSeed) * (_RoundWaveSpeed/10.0)) / 0.015) * (_RoundWaveStrength/10.0)) % 1;
half4 col = tex2D(_MainTex, i.uv) * i.color;
col *= _Color;
return col;
}
具体的代码注释如下:
片段着色计算 | 注释 |
---|
half4 frag (v2f i) : SV_Target | 定义了一个片段着色器函数frag ,它接收一个从顶点着色器传递过来的结构体v2f i ,输出颜色为SV_Target 。 |
float2 uvRect = i.uv; | 这行代码声明了一个名为uvRect 的float2 类型变量,并将传入的i.uv 赋值给它。i.uv 通常是纹理坐标,表示纹理图像在屏幕空间中的位置。 |
half xWave = ((0.5 * _MainTex_ST.x) - uvRect.x); | 这里计算了波纹效果在x方向的偏移量。_MainTex_ST.x 是纹理的缩放因子,uvRect.x 是当前纹理坐标的x分量。通过从0.5(纹理坐标的中心)减去uvRect.x ,可以得到相对于纹理中心的偏移量。 |
half yWave = ((0.5 * _MainTex_ST.y) - uvRect.y) * (_MainTex_TexelSize.w / _MainTex_TexelSize.z); | 这行代码计算了波纹效果在y方向的偏移量。_MainTex_ST.y 是纹理的垂直缩放因子,uvRect.y 是当前纹理坐标的y分量。通过将(0.5 * _MainTex_ST.y) - uvRect.y 的结果乘以_MainTex_TexelSize.w / _MainTex_TexelSize.z ,可以调整波纹的幅度。 |
half ripple = -sqrt(xWave*xWave + yWave* yWave); | 计算波纹的“波峰”位置。这里使用平方根函数sqrt 计算xWave 和yWave 平方和的平方根,然后取负值。这将创建一个从中心向外扩散的波纹效果。 |
i.uv += (sin((ripple + (_Time.y + _RandomSeed) * (_RoundWaveSpeed/10.0)) / 0.015) * (_RoundWaveStrength/10.0)) % 1; | 这行代码将波纹效果应用到纹理坐标上。首先计算波纹的正弦值,其中ripple 是波峰位置,_Time.y 是当前时间,_RandomSeed 是一个随机种子,_RoundWaveSpeed 是波纹速度。通过将这些值相加并乘以_RoundWaveStrength ,可以调整波纹的强度。最后,使用% 1 确保纹理坐标在0到1的范围内循环。 |
half4 col = tex2D(_MainTex, i.uv) * i.color; | 使用修改后的纹理坐标i.uv 从纹理_MainTex 中采样颜色,并将其与传入的颜色i.color 相乘。tex2D 是采样纹理的函数,half4 是一个包含四个半精度浮点数的颜色值。 |
col *= _Color; | 将采样得到的颜色与一个全局颜色_Color 相乘,这可以用于调整最终颜色的亮度或色调。 |
return col; | 返回最终计算得到的颜色值。 |
返回
Fallback "Sprites/Default"
}
完整代码
Shader "RoundWave"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_Color("Main Color", Color) = (1,1,1,1)
_RoundWaveStrength("Wave Strength", Range(0, 1)) = 0.7
_RoundWaveSpeed("Wave Speed", Range(0, 5)) = 2
}
SubShader
{
Tags {"Queue" = "Transparent" "RenderType"="Opaque" "IgnoreProjector" = "True" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
half4 color : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
half4 color : COLOR;
};
sampler2D _MainTex;
half4 _MainTex_ST, _MainTex_TexelSize, _Color;
float _RandomSeed;
half _RoundWaveStrength, _RoundWaveSpeed;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.color = v.color;
return o;
}
half4 frag (v2f i) : SV_Target
{
float2 uvRect = i.uv;
half xWave = ((0.5 * _MainTex_ST.x) - uvRect.x);
half yWave = ((0.5 * _MainTex_ST.y) - uvRect.y) * (_MainTex_TexelSize.w / _MainTex_TexelSize.z);
half ripple = -sqrt(xWave*xWave + yWave* yWave);
i.uv += (sin((ripple + (_Time.y + _RandomSeed) * (_RoundWaveSpeed/10.0)) / 0.015) * (_RoundWaveStrength/10.0)) % 1;
half4 col = tex2D(_MainTex, i.uv) * i.color;
col *= _Color;
return col;
}
ENDCG
}
}
Fallback "Sprites/Default"
}