init commit
This commit is contained in:
65
Assets/Scripts/Lesson_1/GPUGrassInstancing.cs
Normal file
65
Assets/Scripts/Lesson_1/GPUGrassInstancing.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
public class GPUGrassRenderer : MonoBehaviour
|
||||
{
|
||||
public Mesh grassMesh; // îäíà ìîäåëü òðàâèíêè (îäèí submesh)
|
||||
public Material grassMaterial; // shader ìຠï³äòðèìóâàòè GPU instancing
|
||||
public ComputeShader computeShader;
|
||||
|
||||
public int countX = 256;
|
||||
public int countZ = 256;
|
||||
public float sizeX = 50f;
|
||||
public float sizeZ = 50f;
|
||||
public float height = 0f;
|
||||
|
||||
GraphicsBuffer matricesBuffer;
|
||||
GraphicsBuffer argsBuffer;
|
||||
int totalCount;
|
||||
|
||||
void Start()
|
||||
{
|
||||
totalCount = countX * countZ;
|
||||
|
||||
// 1) create structured buffer for matrices (float4x4 = 16 floats = 64 bytes)
|
||||
matricesBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, totalCount, 16 * sizeof(float));
|
||||
// 2) args buffer (5 uints): indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation
|
||||
uint[] args = new uint[5] { (uint)grassMesh.GetIndexCount(0), (uint)totalCount, (uint)grassMesh.GetIndexStart(0), (uint)grassMesh.GetBaseVertex(0), 0u };
|
||||
argsBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, sizeof(uint) * args.Length);
|
||||
argsBuffer.SetData(args);
|
||||
|
||||
// dispatch compute to fill matrices
|
||||
int kernel = computeShader.FindKernel("CSMain");
|
||||
computeShader.SetInt("_CountX", countX);
|
||||
computeShader.SetInt("_CountZ", countZ);
|
||||
computeShader.SetFloat("_SizeX", sizeX);
|
||||
computeShader.SetFloat("_SizeZ", sizeZ);
|
||||
computeShader.SetFloat("_Height", height);
|
||||
computeShader.SetBuffer(kernel, "matrices", matricesBuffer);
|
||||
|
||||
int threadGroups = Mathf.CeilToInt(totalCount / 64.0f);
|
||||
computeShader.Dispatch(kernel, threadGroups, 1, 1);
|
||||
|
||||
// bind buffer to material for per-instance matrix access (if shader reads it)
|
||||
grassMaterial.SetBuffer("matrices", matricesBuffer);
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
matricesBuffer?.Dispose();
|
||||
argsBuffer?.Dispose();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// set render params: use simple bounds so Unity can cull
|
||||
var bounds = new Bounds(transform.position, new Vector3(sizeX, 10f, sizeZ));
|
||||
RenderParams rparams = new RenderParams(grassMaterial);
|
||||
// the shader must use UNITY_INDIRECT_DRAW_ARGS / UnityIndirect.cginc if it needs instance id access
|
||||
|
||||
// call indirect draw
|
||||
rparams.worldBounds = new Bounds(transform.position, new Vector3(sizeX, 10f, sizeZ));
|
||||
Graphics.RenderMeshIndirect(rparams, grassMesh, argsBuffer);
|
||||
// parameters: rparams, mesh, argsBuffer, commandCount=1, startCommand=0, worldBounds
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user