效果如下
![请添加图片描述](https://img-blog.csdnimg.cn/e60be1a9e6f745399cebfdff1ef248f9.gif)
属性栏如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/4c4bb45cae27445fa42b0dea535da22f.png)
属性块:
关于属性的内容可以看这篇:【Unity Shader 中Properties 相关介绍】
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_Color("Main Color", Color) = (1,1,1,1)
_ChromAberrAmount("ChromAberr Amount", Range(0, 1)) = 1
_ChromAberrAlpha("ChromAberr Alpha", Range(0, 1)) = 0.4
_GlitchAmount("Glitch Amount", Range(0, 20)) = 3
_GlitchSize("Glitch Size", Range(0.25, 5)) = 1
_PixelateSize("Pixelate size", Range(4,512)) = 32
}
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 _ChromAberrAmount, _ChromAberrAlpha;
half _GlitchAmount, _GlitchSize;
half _PixelateSize;
属性声明详细解释如下
名称 | 注释 |
---|
sampler2D _MainTex; | 声明了一个名为_MainTex 的2D纹理采样器。这通常用于存储和采样主纹理图像。 |
名称 | 注释 |
---|
half4 _MainTex_ST, _MainTex_TexelSize, _Color; | 声明了三个half4 类型的属性: |
_MainTex_ST | 通常用于存储纹理的平铺(tiling)和偏移(offset)参数。 |
_MainTex_TexelSize | 存储纹理的像素尺寸,这有助于进行像素级的纹理操作。 |
_Color | 一个颜色值,用于修改或混合纹理的颜色。 |
名称 | 注释 |
---|
_ChromAberrAmount | 这是一个半精度浮点数变量,用于存储色像差(Chromatic Aberration)的量。色像差是一种光学现象,其中不同波长的光在通过透镜时聚焦在不同的点上,导致图像边缘出现颜色分离。在图形渲染中,色像差可以用来模拟镜头效果或创造特定的视觉效果。 |
_ChromAberrAlpha | 这是另一个半精度浮点数变量,可能用于控制色像差效果的透明度或强度。例如,它可以决定色像差效果在图像中的混合程度。 |
_GlitchAmount | 这个变量用于存储"glitch"效果的量。Glitch效果通常指的是图像或视频中的随机干扰或错误,可以用来创造一种数字故障或复古的视觉效果。 |
_GlitchSize | 这个变量可能用于控制glitch效果的尺寸或范围,比如干扰区域的大小或者干扰效果的强度。 |
_PixelateSize | 这个变量用于控制像素化(Pixelation)效果的大小。像素化是一种将图像分割成大块像素区域的效果,使得图像看起来更加粗糙或低分辨率。 |
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代码块的结束。
rand结构体:
half rand(half2 seed, half offset) {
return (frac(sin(dot(seed, half2(12.9898, 78.233))) * 43758.5453) + offset) % 1.0;
}
代码 | 解释 |
---|
half rand(half2 seed, half offset) { | 定义了一个名为rand 的函数,它接受两个参数,seed 是一个half2 类型,即包含两个半精度浮点数的向量,通常用于生成随机数的种子;offset 是一个half 类型,用于对生成的随机数进行偏移。 |
return (frac(sin(dot(seed, half2(12.9898, 78.233))) * 43758.5453) + offset) % 1.0; | 这是函数的主体,它执行以下操作: |
dot(seed, half2(12.9898, 78.233)) | 计算seed 向量与常数向量(12.9898, 78.233) 的点积。点积是一种向量运算,可以产生一个标量值。 |
sin(...) | 对点积的结果应用正弦函数。正弦函数是一种周期性函数,可以产生在-1到1之间的值。 |
* 43758.5453 | 将正弦函数的结果乘以一个常数。这个常数可能是为了调整结果的分布或范围。 |
frac(...) | 应用frac 函数,即取小数部分,这将正弦函数的结果限制在0到1的范围内(不包括1)。 |
+ offset | 将frac 函数的结果加上offset 参数,实现对随机数的偏移。 |
% 1.0 | 对上一步的结果取模1.0,确保最终结果也在0到1的范围内(不包括1)。 |
} | 结束函数定义。 |
小结:
这个rand
函数的目的是生成一个基于种子和偏移的伪随机数。在图形编程中,这种类型的随机数生成器通常用于创建纹理、噪声或其他需要随机性效果的场景。由于使用了sin
和dot
函数,这个随机数生成器能够产生相对平滑的随机分布,而不是完全随机的值。通过调整seed
和offset
参数,可以在不同的纹理坐标或不同的效果之间生成不同的随机数序列。
rand2CustomTime结构体:
half rand2CustomTime(half2 seed, half offset, half customTime) {
return (frac(sin(dot(seed * floor(50 + (customTime % 1.0) * 12.), half2(127.1, 311.7))) * 43758.5453123) + offset) % 1.0;
}
片段着色器代码
half4 frag (v2f i) : SV_Target
{
float2 uvRect = i.uv;
i.uv = floor(i.uv * _PixelateSize) / _PixelateSize;
half4 col = tex2D(_MainTex, i.uv) * i.color;
half2 uvGlitch = uvRect;
uvGlitch.y -= 0.5;
half lineNoise = pow(rand2(floor(uvGlitch * half2(24., 19.) * _GlitchSize) * 4.0, _RandomSeed), 3.0) * _GlitchAmount
* pow(rand2(floor(uvGlitch * half2(38., 14.) * _GlitchSize) * 4.0, _RandomSeed), 3.0);
col = tex2D(_MainTex, i.uv + half2(lineNoise * 0.02 * rand2(half2(2.0, 1), _RandomSeed), 0)) * i.color;
half4 r = tex2D(_MainTex, i.uv + half2(_ChromAberrAmount/10, 0)) * i.color;
half4 b = tex2D(_MainTex, i.uv + half2(-_ChromAberrAmount/10, 0)) * i.color;
col = half4(r.r * r.a, col.g, b.b * b.a, max(max(r.a, b.a) * _ChromAberrAlpha, col.a));
col *= _Color;
return col;
}
具体的代码注释如下:
片段着色计算 | 注释 |
---|
half4 frag (v2f i) : SV_Target | 定义了一个片段着色器函数frag ,它接收一个从顶点着色器传递过来的结构体v2f i ,输出颜色为SV_Target 。 |
float2 uvRect = i.uv; | 将传入的纹理坐标赋值给uvRect 。 |
i.uv = floor(i.uv * _PixelateSize) / _PixelateSize; | |
i.uv | 是传入片段着色器的纹理坐标。 |
floor(...) | 向下取整函数,将坐标值向下取整到最近的整数。 |
* _PixelateSize | 将纹理坐标乘以一个像素化大小的值,再通过floor 函数处理,实现像素化效果。 |
/ _PixelateSize | 将处理后的坐标重新除以_PixelateSize ,确保纹理坐标在正确的范围内。 |
half4 col = tex2D(_MainTex, i.uv) * i.color; | |
tex2D(_MainTex, i.uv) | 从主纹理_MainTex 中采样颜色,使用处理后的纹理坐标i.uv 。 |
* i.color | 将采样得到的颜色与传入的片段颜色i.color 相乘,应用颜色混合。 |
half2 uvGlitch = uvRect; | |
uvRect | 可能是从顶点着色器传入的纹理坐标。将这些坐标赋值给uvGlitch ,用于后续的glitch效果处理。 |
uvGlitch.y -= 0.5; | 将uvGlitch 的y坐标减去0.5,这可能是为了调整glitch效果的位置。 |
片段着色计算 | 拆解 |
---|
half lineNoise = pow(rand2(floor(uvGlitch * half2(24., 19.) * _GlitchSize) * 4.0, _RandomSeed), 3.0) * _GlitchAmount * pow(rand2(floor(uvGlitch * half2(38., 14.) * _GlitchSize) * 4.0, _RandomSeed), 3.0); | 拆解分析如下 |
rand2(...) | 可能是一个自定义的随机数生成函数,用于生成纹理坐标的随机偏移。 |
floor(...) | 对纹理坐标乘以一个常数向量和_GlitchSize ,然后向下取整,生成随机偏移的基础值。 |
pow(...) | 将随机数的值的三次方,增加随机效果的强度。 |
* _GlitchAmount | 将生成的随机值乘以_GlitchAmount ,控制glitch效果的强度。 |
片段着色计算 | 拆解 |
---|
col = tex2D(_MainTex, i.uv + half2(lineNoise * 0.02 * rand2(half2(2.0, 1), _RandomSeed), 0)) * i.color; | 再次从_MainTex 纹理中采样颜色,但这次纹理坐标i.uv 加上了由lineNoise 计算出的随机偏移,实现glitch效果。 |
* i.color | 将采样得到的颜色与传入的片段颜色i.color 相乘,应用颜色混合。 |
half4 r = tex2D(_MainTex, i.uv + half2(_ChromAberrAmount/10, 0)) * i.color; | 从主纹理中采样红色通道的颜色,纹理坐标i.uv 加上了色像差偏移(_ChromAberrAmount/10 ),模拟色像差效果。 |
half4 b = tex2D(_MainTex, i.uv + half2(-_ChromAberrAmount/10, 0)) * i.color; | 从主纹理中采样蓝色通道的颜色,纹理坐标i.uv 减去了色像差偏移(-_ChromAberrAmount/10 ),模拟色像差效果。 |
col = half4(r.r * r.a, col.g, b.b * b.a, max(max(r.a, b.a) * _ChromAberrAlpha, col.a)); | 将红色通道的值与红色通道的透明度相乘,蓝色通道的值与蓝色通道的透明度相乘,然后将它们组合成一个新的颜色值。 |
max(...) | 取红色和蓝色通道透明度的最大值,并乘以_ChromAberrAlpha ,控制色像差效果的透明度。 |
max(max(r.a, b.a) * _ChromAberrAlpha, col.a) | 取色像差透明度和原始颜色透明度的最大值,确保最终颜色的透明度。 |
col *= _Color; | 将颜色与主颜色相乘。 |
return col; | 返回最终颜色。 |
返回
Fallback "Sprites/Default"
}
完整代码
Shader "Television"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_Color("Main Color", Color) = (1,1,1,1)
_ChromAberrAmount("ChromAberr Amount", Range(0, 1)) = 1
_ChromAberrAlpha("ChromAberr Alpha", Range(0, 1)) = 0.4
_GlitchAmount("Glitch Amount", Range(0, 20)) = 3
_GlitchSize("Glitch Size", Range(0.25, 5)) = 1
_PixelateSize("Pixelate size", Range(4,512)) = 32
}
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 _ChromAberrAmount, _ChromAberrAlpha;
half _GlitchAmount, _GlitchSize;
half _PixelateSize;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.color = v.color;
return o;
}
half rand(half2 seed, half offset) {
return (frac(sin(dot(seed, half2(12.9898, 78.233))) * 43758.5453) + offset) % 1.0;
}
half rand2(half2 seed, half offset) {
return (frac(sin(dot(seed * floor(50 + (_Time % 1.0) * 12.), half2(127.1, 311.7))) * 43758.5453123) + offset) % 1.0;
}
half rand2CustomTime(half2 seed, half offset, half customTime) {
return (frac(sin(dot(seed * floor(50 + (customTime % 1.0) * 12.), half2(127.1, 311.7))) * 43758.5453123) + offset) % 1.0;
}
half4 frag (v2f i) : SV_Target
{
float2 uvRect = i.uv;
i.uv = floor(i.uv * _PixelateSize) / _PixelateSize;
half4 col = tex2D(_MainTex, i.uv) * i.color;
half2 uvGlitch = uvRect;
uvGlitch.y -= 0.5;
half lineNoise = pow(rand2(floor(uvGlitch * half2(24., 19.) * _GlitchSize) * 4.0, _RandomSeed), 3.0) * _GlitchAmount
* pow(rand2(floor(uvGlitch * half2(38., 14.) * _GlitchSize) * 4.0, _RandomSeed), 3.0);
col = tex2D(_MainTex, i.uv + half2(lineNoise * 0.02 * rand2(half2(2.0, 1), _RandomSeed), 0)) * i.color;
half4 r = tex2D(_MainTex, i.uv + half2(_ChromAberrAmount/10, 0)) * i.color;
half4 b = tex2D(_MainTex, i.uv + half2(-_ChromAberrAmount/10, 0)) * i.color;
col = half4(r.r * r.a, col.g, b.b * b.a, max(max(r.a, b.a) * _ChromAberrAlpha, col.a));
col *= _Color;
return col;
}
ENDCG
}
}
Fallback "Sprites/Default"
}