HuldaGnodim 发表于 2022-8-26 14:48

[Unity Shader效果]3d场景扫光效果

最近玩暗黑不朽,它实现了一个扫光效果,我觉得很有意思,想着模仿下,看到国外的一个博主的实现思路,觉得性能与效果都能保证。油管视频 链接
我实现了下,效果如下:


https://www.zhihu.com/video/1544698577267707904
1.思路

思路上是渲染一个球体,同时采样当前的深度图。从而得到当前的z轴差值,大于某个值的当成纯透明的过滤掉实现
2.代码

首选创建好测试场景,并将摄像机的深度图开关打开





打开深度图

创建一个unlit shader,删除多余方法。设置为透明层。并且Blend为Alpha


采样深度,直接用unity的hlsl的方法 。SampleSceneDepth(在 DeclareDepthTexture.hlsl中)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
...
v2f vert (appdata v)
{
...
o.screenPos = ComputeScreenPos(o.vertex);
...
}
half4 frag (v2f i) : SV_Target
{
...
float2 uv = i.screenPos.xy / i.screenPos.w;
float depth = LinearEyeDepth(SampleSceneDepth(uv),_ZBufferParams);
...
}计算View坐标下的顶点位置,然后取z值,计算与深度图之间的差值
...
v2f vert (appdata v)
{
...
o.viewPos = TransformWorldToView(TransformObjectToWorld(v.vertex));
...
}
half4 frag (v2f i) : SV_Target
{
...
float2 uv = i.screenPos.xy / i.screenPos.w;
float depth = LinearEyeDepth(SampleSceneDepth(uv),_ZBufferParams);
float off = depth -(i.viewPos.z * -1);
return half4(off,off,off,off);
...
}注意,这里view坐标系的z坐标在负轴,所以要乘以-1。
创建一个圆形模型,做个测试。


可以看出来,越贴近地面的部位越接近透明,这和我们要的效果正好相反,所以直接做个1-off。
off = 1 - saturate(off);

效果有点类似,但是只剩半个圆,这是因为unity shader模型用了Cull Back,裁剪掉背面的模型,以及深度测试的影响。因此这里关闭cull和深度写入。


查看下效果:


效果差不多了,为了调整边框大小,加一个Range的参数,作为off值的倍数。
off *= _Range;

https://www.zhihu.com/video/1544707472723816448
再加一个Color值调整光环颜色。
half4 frag (v2f i) : SV_Target
{
...
float4 col = _BaseColor;
col *= off;
return col;
...
}效果完成。
源码

附上工程源码 https://github.com/whitecostume/unity_3dscan_effect
页: [1]
查看完整版本: [Unity Shader效果]3d场景扫光效果