文章目录
环境
Unity : 2020.3.18f1
Pipeline : URP
之前看了一下公司里有位同学买了 taecg 老师的课程
里面有讲到 裂痕深坑 的制作方式(做法有多种,这课程中只是其中一种)
那么下面我将一些后续的优化讲一下(不使用双 pass,直接使用多网格,区别材质,调整 RenderQueue)
思路
- 将深坑部分的网格绘绘制出来(会增加 overrdraw)
- 再将裂痕表面部分写入深度(可以使用 Offset 调整一下深度)
- 再正常绘制其他不透明对象即可
建模
Houdini
课程里面 使用的是 Houdini 的 Geometry + Curve + Extrude 来建模的
我也使用 Houdini 按这种方式实现了,但是挤出的底部面片有面的点顺序错乱问题,我那位同事使用 Houdini 18 版来建模,没有问题,我使用的是 Houdini 19 就问题(反正我不熟悉 Houdini,第一次用,希望后续有机会用此神器来程序化建模)
设置好
Top View 参考图片
Geometry + Curve + Extrude
- Geometry 节点下添加 Curve
- Curve 勾勒除刨面剪影
- Extrude 挤出剪影深度
最后导出到 unity Assets 下
导出之后,使用 ms 的 3d view 查看到底部有问题(目测点序错乱)
3ds max
因为 Houdini 导出后的 FBX 的底部面片顶点错乱
所以后续我使用了 3ds max 2020 来建模(虽然我也不熟悉,但是起码一些基础的操作也是会一丢丢的)
- 设置好 系统单位、显示单位:米
- 设置好仅旋转轴 X 90
在顶视图下设计
设置好参考背景图
下面是设置好的效果
使用:创建/图形/线,来勾勒刨面
封口刨面
这样大致的刨面剪影就 OK了
转为可编辑多边形
导出用于仅仅写入深度的面片
上面的网格,我们在导出前,要记得 塌陷 一下,目的是:将所有的修改器合并,变换都重定向一下
挤出裂痕深度
我们将上面的仅仅用于写入深度的面片复制一份
挤出一下,用来绘制裂痕深坑部分
导出带挤出裂痕模型
OK,看着没有 Houdini 中点序错乱的问题
最终效果
发布 Google Pixel 6 Pro 上的效果:
优化
我们上面的方式是:不使用 URP 中的双 pass 因为会打断合批
我先使用 SRP Batcher 合批绘制第一批深坑部分
我之前也概要描述了一下 SRP Batch 和其他 Batch 的区别:Unity - DrawCall, Batch, SetPassCall区别
再绘制裂痕表面部分,用于写入深度
再图像上是看不到内容的,因为我们设置了 ColorMask 0
所以我们先屏蔽 ColorMask 0
并输出一下白色,便于查看
下面白色部分是裂痕表面仅仅写入深度的像素部分
最后绘制场景其他不透明部分 + Bloom 后效
最终我们这么多的 裂痕深坑,只要两个 SRP Batch 就可以完事:
之前说过,这种方式是不用双pass 的方式,这样尽可能让 SRP Batcher 生效
但是这种方式只能使用:Prefab 裹起来
而且会对出一个 GameObject 对象,会占用额外的 GameObject 的一些消耗(生命周期、内存、等,虽然可以使用 DOTS+ESC 来优化)
除了这种方式外,还可以使用另一种方式:
使用 URP Render Feature 给 DeepCrack 独立的两个 Feature 来绘制即可,这样也是可以让 SRP Batcher 尽可能生效,但就是需要增加 Render Feature ,有丢丢麻烦,Render Feature 的一些基础使用可以参考我之前写得:Unity - URP RenderFeature - 实现类似多 Pass 的 XRay: Rim、Pattern
所有实现方式都是根据项目情况来选择
再次优化
其实还可以再次优化:使用 Instancing 方式
因为我们的 Mesh、Material 都是相同的
这是用 Instancing 再适合不过
这部分我就不写了
优缺点
没有完美的方案,只有最适合的方案
优点:可以比较好的把控裂痕边缘的清晰度,和坑内内容
缺点:只能适用于特定的表面形状来实现,比如:上面只适合 平地 上的深坑,一旦有不平整的都不会有效果,如:上面的球体、立方体底部,可以看到
其他的裂痕方案
以前看到过使用 SSD (Space Space Decal) 来实现
还将过有些是再配合上 视差来制作位深度来实现
总之每一种方案都有优缺点,没有完美的方案,根据实际项目来选择对应的实现方案才是最适合的
可以参考我之后另一篇:DCC - Photoshop - Nvidia NormalMapFilter - 法线生成工具 - 顺便测试 Unity URP 12.1 中的 Decal System
理论上还有一些方案使用的是:Parallex Map 配合 Decal 来做裂痕效果也是可以的(还没试过)
完整的 Shader
深坑部分
// jave.lin 2022/04/27
// 裂痕深坑的深坑部分
Shader "Test/DeepCrack_URP_USING_DEPTH"
{
Properties
{
_Color0 ("Color0", Color) = (1, 1, 1, 1)
[HDR] _Color1 ("Color1", Color) = (0, 0, 0, 0)
_Height0 ("Height0", Range(-10, 10)) = 0
_Height1 ("Height1", Range(-10, 10)) = -1
_HeightScale ("HeightScale", Range(0.001, 1)) = 1
_HeightPower ("Height Power", Range(0.01, 10)) = 1
[Toggle] _TWINKLE ("Twinkle On", Int) = 1
}
SubShader
{
Tags {
"RenderType"="Opaque" "Queue"="Geometry-2" }
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature _ _TWINKLE_ON
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
};
struct Varings
{
float4 positionCS : SV_POSITION;
half3 color : COLOR;
half fogFactor : TEXCOORD1;
};
CBUFFER_START(UnityPerMaterial)
half4 _Color0;
half4 _Color1;
float _Height0;
float _Height1;
float _HeightScale;
float _HeightPower;
CBUFFER_END
Varings vert (Attributes i)
{
Varings o = (Varings)0;
o.positionCS = TransformObjectToHClip(i.positionOS.xyz);
o.fogFactor = ComputeFogFactor(o.positionCS.z);
half height_col_lerp_t = smoothstep(_Height0, _Height1, i.positionOS.y * _HeightScale);
height_col_lerp_t = pow(height_col_lerp_t, _HeightPower);
o.color = lerp(_Color0.rgb, _Color1.rgb, height_col_lerp_t);
#ifdef _TWINKLE_ON
o.color *= sin(_Time.z) * 0.3 + 0.7;
#endif
return o;
}
half4 frag (Varings i) : SV_Target
{
i.color = MixFog(i.color, i.fogFactor);
return half4(i.color, 1);
}
ENDHLSL
}
}
}
裂痕表面部分
// jave.lin 2022/04/27
// 裂痕深坑的表面部分:仅仅写入顶层深度
Shader "Test/DeepCrack_URP_USING_WRITE_TOP_DEPTH"
{
Properties
{
_DepthOffset1 ("DepthOffset1", Float) = 0
_DepthOffset2 ("DepthOffset2", Float) = 0
}
SubShader
{
Tags {
"RenderType"="Opaque" "Queue"="Geometry-1" }
Pass
{
Offset [_DepthOffset1], [_DepthOffset2]
ZTest Always
ColorMask 0
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
float4 vert (float4 positionOS : POSITION) : SV_POSITION
{
positionOS.y = 0;
return TransformObjectToHClip(positionOS.xyz);
}
half4 frag (float4 positionCS : SV_POSITION) : SV_Target
{
return 0;
}
ENDHLSL
}
}
}
Project
学习、备忘用,不公开,上面公开的内容已经够多了,而且都是参考 taecg 老师的一些课程
TestDeepCrackEffect_2020_3_18f1.rar
References
- Unity VFX - Ground Cracks | Fissure | Hole Effect Tutorial - youtube 1年前的表面裂痕效果,但是 VFX 制作的,估计原来的这个效果,多少有一些抄袭成分