Glitch - 故障效果
平面故障效果
图块抖动
![]() |
- 主要原理是对uv进行分层,然后使用噪声函数对不同层级的uv进行抖动。
1 | void TileJitterGlitch(out half2 uv, half jitterPower, half aspectRatio) |
RGB颜色分离
![]() |
- 主要原理是对RGB三个通道采用不同的uv偏移值进行分别采样。一般会选取一个通道采用原始uv值,另两个通道使用偏移后的uv进行采样。
1 | half4 RGBSplitGlitch(half2 uv, half jitterPower) |
三维故障效果
后处理方案
- 主要思路是:把Glitch对象单独拿出来,在场景绘制完后,再将Glitch对象的颜色与深度单独绘制到RT上,并进行Glitch处理,处理完毕后再融回主相机的ColorTarget中。
- 具体实现:
- 新增Layer,命名为Glitch,并将Glitch对象的Layer设置为Glitch。
- 将主相机FilteringSettings中的Glitch Layer去掉,可以得到不含Glitch对象的颜色图和深度图:场景颜色场景深度
- 绘制完场景之后,将RenderTarget设置为新的RT,再将Glitch对象的颜色和深度绘制到RT上:角色颜色角色深度
- 最终对Glitch对象的颜色图和深度图进行Glitch处理,并利用深度图处理与场景物体的遮挡关系,再将颜色图融回主相机的ColorTarget中。
- 注意:该方案使用了额外的RT,增加了带宽的消耗。
投影器方案
- 主要思路是:为Glitch对象创建一个可以包裹住自身的Cube对象,在绘制完场景之后,将Glitch对象投影到Cube对象上,最终再对Cube对象进行Glitch处理。
- 具体实现:
- 在Glitch对象上添加Glitcher脚本,在运行时Glitcher脚本会根据其节点下的Renderer对象计算出最大的包围盒,并以此为依据创建Cube对象。
- 在Cube对象使用的材质球中,根据_CameraDepthTexture获取其包裹对象所占用的像素,再根据_CameraOpaqueTexture获取包裹对象的颜色,最终再进行Glitch处理。
- 根据_CameraDepthTexture获取其包裹对象所占用的像素:
Get Depth Step 1
2
3
4
5
6
7
8
9
10
11
12
13half GetDepthStep(Varyings input)
{
half2 screenUV = (input.positionCS.xy / _ScaledScreenParams.xy);
half depth = SampleSceneDepth(screenUV);
#ifndef UNITY_REVERSED_Z
depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, depth);
#endif
float3 worldPos = ComputeWorldSpacePosition(uv, depth, UNITY_MATRIX_I_VP);
float3 objectPos = mul(UNITY_MATRIX_I_M, float4(worldPos, 1));
half max_step = step(step(0.5, objectPos.x) + step(0.5, objectPos.y) + step(0.5, objectPos.z), 0);
half min_step = step(-0.5, objectPos.x) * step(-0.5, objectPos.y) * step(-0.5, objectPos.z);
return max_step * min_step;
}
- 在Glitch对象上添加Glitcher脚本,在运行时Glitcher脚本会根据其节点下的Renderer对象计算出最大的包围盒,并以此为依据创建Cube对象。
附录
噪声模拟
1 | half RandomNoise(half val) |
- 推导过程:f(x) = frac(x)f(x) = sin(x)f(x) = frac(sin(x))f(x) = frac(sin(x) * 10)f(x) = frac(sin(x) * 100)frac(sin(x) * 100) * 2 - 1
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 鹏の箱庭!