I’ve been trying to create grass for a while now and learned about GPU instancing. However when i tried to implement it and created ~100k grass objects the game had about 20 fps but with just using instantiate i got about 40fps. I think it might be that my GPU is a lot worse compared to the CPU (A ryzen 5 5600 with a gt 1030), but it shouldn’t create THAT big of a difference, right? Im very new to GPU instancing so it could also be something wrong with my code.
Creating grass using instantiate (~40fps):
void Start()
RaycastHit hit;
{
spawnGrass();
}
void spawnGrass()
{
for (int minValZ = 0 - chunkSize, maxValZ = 0, rowsGenerated = 0, a = 0; rowsGenerated < chunkAmount; rowsGenerated++, maxValZ += chunkSize, minValZ += chunkSize, a+= chunkAmount)
{
for (int minValX = 0 - chunkSize, maxValX = 0, chunksGenerated = 0, grassCounter = 0; chunksGenerated < chunkAmount; maxValX += chunkSize, minValX += chunkSize, chunksGenerated++, grassCounter += grassDensity)
{
for (int i = 0; i < Instances; i++) // instances = 10
{
Vector3 grassPos = new Vector3(UnityEngine.Random.Range(chunkStart.x + maxValX, chunkStart.x + minValX), 35, UnityEngine.Random.Range(chunkStart.y + maxValZ, chunkStart.y + minValZ));
Vector3 dir = new Vector3(0, -1, 0);
if (Physics.Raycast(grassPos, dir, out hit))
{
if (hit.point.y > grassRange)
{
GameObject grassClone = Instantiate(GrassLOD1, hit.point, Quaternion.Euler(0, UnityEngine.Random.Range(0, 360), UnityEngine.Random.Range(87, 93)));
grassClone.transform.localScale = scale;
}
}
}
}
}
}
GPU instanced grass (~20fps):
private List<List<Matrix4x4>> Batches = new List<List<Matrix4x4>>();
RaycastHit hit;
void Start()
{
spawnGrass();
}
private void Update()
{
RenderBatches();
}
void spawnGrass()
{
for (int minValZ = 0 - chunkSize, maxValZ = 0, rowsGenerated = 0, a = 0; rowsGenerated < chunkAmount; rowsGenerated++, maxValZ += chunkSize, minValZ += chunkSize, a+= chunkAmount)
{
for (int minValX = 0 - chunkSize, maxValX = 0, chunksGenerated = 0, grassCounter = 0; chunksGenerated < chunkAmount; maxValX += chunkSize, minValX += chunkSize, chunksGenerated++, grassCounter += grassDensity)
{
for (int i = 0; i < Instances; i++)
{
Vector3 grassPos = new Vector3(UnityEngine.Random.Range(chunkStart.x + maxValX, chunkStart.x + minValX), 35, UnityEngine.Random.Range(chunkStart.y + maxValZ, chunkStart.y + minValZ));
Vector3 dir = new Vector3(0, -1, 0);
if (Physics.Raycast(grassPos, dir, out hit))
{
if (hit.point.y > grassRange)
{
int addedMatrices = 0;
Batches.Add(new List<Matrix4x4>());
if (addedMatrices < 1000)
{
Batches[Batches.Count - 1].Add(Matrix4x4.TRS(hit.point, Quaternion.Euler(rotation), scale));
addedMatrices += 1;
}
else
{
Batches.Add(new List<Matrix4x4>());
addedMatrices = 0;
}
}
}
}
}
}
}
private void RenderBatches()
{
foreach (var Batch in Batches)
{
for (int i = 0; i < mesh.subMeshCount; i++)
{
Graphics.DrawMeshInstanced(mesh, i, Materials[i], Batch);
}
}
}