Unity Shader - URP - 抄作业 - Deep Crack - 裂痕深坑 - SRP Batch优化


环境

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

猜你喜欢

转载自blog.csdn.net/linjf520/article/details/124478011