Skip to content

Commit

Permalink
+CPU per cell frustum culling, can render 10M grass on adreno612 now
Browse files Browse the repository at this point in the history
  • Loading branch information
ColinLeung-NiloCat committed Aug 1, 2020
1 parent 01e3adb commit 8ef84a1
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
//cullingComputeShader.SetMatrix("_VPMatrix", p * v); //set from C#
float4x4 _VPMatrix;
float _MaxDrawDistance;
StructuredBuffer<float3> _AllInstancesTransformBuffer; //will not change until instance count change
AppendStructuredBuffer<uint> _VisibleInstanceOnlyTransformIDBuffer; //will set counter to 0 per frame, then fill in by this compute shader
uint _StartOffset;
StructuredBuffer<float3> _AllInstancesPosWSBuffer; //will not change until instance count change
AppendStructuredBuffer<uint> _VisibleInstancesOnlyPosWSIDBuffer; //will set counter to 0 per frame, then fill in by this compute shader

[numthreads(1024,1,1)]
[numthreads(64,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
//posWS -> posCS
float4 absPosCS = abs(mul(_VPMatrix,float4(_AllInstancesTransformBuffer[id.x],1.0)));
float4 absPosCS = abs(mul(_VPMatrix,float4(_AllInstancesPosWSBuffer[id.x + _StartOffset],1.0)));

//do culling test in clip space, result is the same as doing test in NDC space.
//prefer clip space here because doing culling test in clip space is faster than doing culling test in NDC, because we can skip 1 division.
Expand All @@ -21,5 +22,5 @@ void CSMain (uint3 id : SV_DispatchThreadID)
//y test allow 50% more threshold (hardcode for grass)
//x test allow 10% more threshold (hardcode for grass)
if (absPosCS.z <= absPosCS.w && absPosCS.y <= absPosCS.w*1.5 && absPosCS.x <= absPosCS.w*1.1 && absPosCS.w <= _MaxDrawDistance)
_VisibleInstanceOnlyTransformIDBuffer.Append(id.x);
_VisibleInstancesOnlyPosWSIDBuffer.Append(id.x + _StartOffset);
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Material:
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.41936636, g: 0.7169812, b: 0.29423285, a: 1}
- _BoundSize: {r: 55.9017, g: 55.9017, b: 0, a: 0}
- _BoundSize: {r: 661.4378, g: 661.4378, b: 0, a: 0}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _GroundColor: {r: 0.2195755, g: 0.46226418, b: 0.2581851, a: 1}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InstancedIndirectGrassPosDefine : MonoBehaviour
{
[Range(1, 40000000)]
public int instanceCount = 1000000;
public float drawDistance = 125;

int cacheCount = -1;

// Start is called before the first frame update
void Start()
{
UpdatePosIfNeeded();
}

private void UpdatePosIfNeeded()
{
if (instanceCount == cacheCount)
return;

Debug.Log("UpdatePos (Slow)");

//same seed to keep grass visual the same
UnityEngine.Random.InitState(123);

//auto keep density the same
float scale = Mathf.Sqrt((instanceCount / 4)) / 2f;
transform.localScale = new Vector3(scale, transform.localScale.y, scale);

//////////////////////////////////////////////////////////////////////////
//can define any posWS in this section, random is just an example
//////////////////////////////////////////////////////////////////////////
List<Vector3> positions = new List<Vector3>(instanceCount);
for (int i = 0; i < instanceCount; i++)
{
Vector3 pos = Vector3.zero;

pos.x = UnityEngine.Random.Range(-1f, 1f) * transform.lossyScale.x;
pos.z = UnityEngine.Random.Range(-1f, 1f) * transform.lossyScale.z;

//transform to posWS in C#
pos += transform.position;

positions.Add(new Vector3(pos.x, pos.y, pos.z));
}

//send all posWS to renderer
InstancedIndirectGrassRenderer.instance.allGrassPos = positions;
cacheCount = positions.Count;
}
private void Update()
{
UpdatePosIfNeeded();
}
private void OnGUI()
{
GUI.Label(new Rect(300, 50, 200, 30), "Instance Count: " + instanceCount/1000000 + "Million");
instanceCount = Mathf.Max(1, (int)(GUI.HorizontalSlider(new Rect(300, 100, 200, 30), instanceCount / 1000000f, 1, 10)) * 1000000);

GUI.Label(new Rect(300, 150, 200, 30), "Draw Distance: " + drawDistance);
drawDistance = Mathf.Max(1, (int)(GUI.HorizontalSlider(new Rect(300, 200, 200, 30), drawDistance / 25f, 1, 8)) * 25);
InstancedIndirectGrassRenderer.instance.drawDistance = drawDistance;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8ef84a1

Please sign in to comment.