I am using a compute shader to populate a Unity Terrain with trees. However, I am facing issues with the AppendStructuredBuffer. What I want to do, is let a probability check determine if a tree should be spawned or not. If not, then I return, otherwise I append to the buffer.
If I don't filter (i.e. probability is 100%), everything goes well, all trees look correct. However, if I filter, I get artifacts (in this case on the height). Upon closer inspection it seems that the count reflects the maximum amount of elements I expect (allocated in the C# ComputeBuffer), however this should not be the case... I use the SetCounterValue(0) to properly set the counter for the buffer.
Compute Shader:
AppendStructuredBuffer<TreeInstance> Result;
struct TreeInstance
{
float3 position;
float widthScale;
float heightScale;
float rotation;
int color;
int lightmapColor;
int prototypeIndex;
float temporaryDistance;
};
[NUMTHREADS]
void CSMain(uint3 id : SV_DispatchThreadID)
{
// random function is functioning as it should.
if (random(id.xy) > globalProbability)
{ return; }
TreeInstance tree;
// some code that initializes the TreeInstance values.
Result.Append(tree);
}
relevant C# code:
ComputeBuffer treeInstances =
new ComputeBuffer(total, Marshal.SizeOf<TreeInstance>(), ComputeBufferType.Append);
treeInstances.SetCounterValue(0);
treeInstances.GetData(someInitializedArray,0,0,treeInstances.count);
treeInstances.Release();
Thanks for your time :)
Yes, the count property is the actual buffer size, it does not reflect the number of elements appended (this is because internally in dx11 the "counter" is not stored in the buffer itself but in the UAV, in dx12 it is contained in another buffer.
In order to get the counter, you need to perform the following, create another buffer (one element, and a stride of 4)
then use ComputeBuffer.CopyCount to copy that into that small buffer.
The small buffer now contains the counter, you can use
GetData(Array counterResult, 0, 0, 1);
counterResult[0] will now contain the number of added elements