Hi there, it’s my first topic in five years using Unity but I don’t really know how to manage this. I’ve done a compute shader supported by a c# script to generate grass in a Unity Terrain Layer. It works fine as you can see in the image, but I have a great performance issue. The valid positions of the terrain are sampled using an alpha map generated by the Unity Terrain Layer and its height map. But when I try to do this heavy operation in the cpu, a bottleneck is created for managing too much information between the cpu to gpu. I would like to implement it in the compute shader, but the something happens in the transformation and the position is not well calculated. I would appreciate any help from the people who know about compute shaders or procedural generation ![]()
These are the function I use for sending de data. They already work, but I want them to be in the compute.
private void ConfigureComputeShaderWithPositions()
{
GraphicsBuffer positionsBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, validPositions.Count, sizeof(float) * 3);
positionsBuffer.SetData(validPositions);
computeShader.SetBuffer(kernel, "_ValidPositions", positionsBuffer);
computeShader.SetInt("_TotalPositions", validPositions.Count);
}
private void GeneratePositionsFromAlphaMap(TerrainData terrainData)
{
float[,,] alphamap = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
Vector3 terrainPos = terrain.transform.position;
Vector3 terrainSize = terrainData.size;
int totalSamples = Mathf.CeilToInt(baseSamples * densityFactor);
for (int i = 0; i < totalSamples; i++)
{
float x = Halton(i, 2) * terrainSize.x;
float z = Halton(i, 3) * terrainSize.z;
int alphaX = Mathf.FloorToInt((x / terrainSize.x) * terrainData.alphamapWidth);
int alphaZ = Mathf.FloorToInt((z / terrainSize.z) * terrainData.alphamapHeight);
alphaX = Mathf.Clamp(alphaX, 0, terrainData.alphamapWidth - 1);
alphaZ = Mathf.Clamp(alphaZ, 0, terrainData.alphamapHeight - 1);
if (alphamap[alphaZ, alphaX, terrainLayerIndex] >= grassThreshold)
{
Vector3 localPos = new Vector3(x, 0, z);
Vector3 worldPos = localPos + terrainPos;
localPos.y = terrain.SampleHeight(worldPos) - terrainPos.y;
validPositions.Add(localPos);
}
}
}
