利用计算着色器进行裁剪优化


官方解释 DrawMeshInstancedIndirect

Graphics.DrawMeshInstancedIndirect

https://docs.unity3d.com/2019.4/Documentation/ScriptReference/Graphics.DrawMeshInstancedIndirect.html

image-20211221155822831

image-20211221155840560

C#层

划分逻辑上的 2D cell

image-20211221160023048

i % cellCountX :计算第几列

i / cellCountX:计算第几行

+0.5将中心移到cell中心

这两行计算确切的世界中心位置,上面只是计算逻辑上的格子位置

centerPosWS.x = Mathf.Lerp(minX, maxX, centerPosWS.x / cellCountX);

centerPosWS.z = Mathf.Lerp(minZ, maxZ, centerPosWS.z / cellCountZ);

这边默认了每个 cell 是正方形的

Vector3 sizeWS = new Vector3(Mathf.Abs(maxX - minX) / cellCountX, 0, Mathf.Abs(maxX - minX) / cellCountX);

正常非正方向的情况应该如下:

Vector3 sizeWS = new Vector3(Mathf.Abs(maxX - minX) / cellCountX, 0, Mathf.Abs(maxZ - minZ) / cellCountZ);

这边对每个 cell 进行视锥体可见性测试,而不是每个草,加快了计算速度,但计算量仍然很多

if (GeometryUtility.TestPlanesAABB(cameraFrustumPlanes, cellBound)) {

​ visibleCellIDList.Add(i);

}

设置 CumputeShader 读取的起始位置

因为内部每次都是从总共草里面读取的,这边设置一个GPU组读取数据的起始位置

image-20211221160805516

image-20211221160810497

合并连续的 cell

0,1,2,3,4

0,1,5,7

当Id连续,也就 cell 连续时,合并成一个 batch

image-20211221160927984

进行GPU划分并执行

按照每64颗草为一个组,进行 GPU的 x划分组(Group)

image-20211221161024567

每个组划分 x向的64个线程,分别对应于每一颗草

image-20211221161043447

完整代码

image-20211221161139811

调用绘制

image-20211221161506994

image-20211221161517320

image-20211221161525337

image-20211221161831506

ComputeShader 层

将世界坐标转换到裁剪空间,进行裁剪,判断是否保留

image-20211221161255242

Shader 层

image-20211221162611368 image-20211221162520535 image-20211221162807267

  目录