Alright, Unbird is trying to keep me honest and requested an update so here we go.
I've mainly been working on partitioning up the grass into various cells so I can enable a greater density without the framerate hit. Even in this very early stage it seems to be working (the red lines are the cell bounds):
That's at 5 x 5 blades per 1 cell of the heightmap (although I have some doubts about what is actually being rendered which I'll get to in a moment). Previously that would slam my system down to 20 - 30 FPS but now it sits at 60FPS without any trouble. Success! Right now I have a 512M x 512M divided up in 8 x 8 chunks, obviously there is a balance there between doing visibility tests against each cell's bounds (as well as the overhead of more draw calls) but right now my system does that in another thread happily so I may play with how finely I divide up my grass cells.
I also turned on some very basic LOD to help smooth things out, Ideally I'd like to just toss the vertex away if the vertex is far away enough (and thus avoid the GS work), but I'm not sure how I could do that in the vertex shader. If anyone has any suggestions I'd appreciate it.
Here you can see the LOD zones (these are just really simply first passes, I probably need to get more aggressive):
Red > Orange > Blue > Green
Finally I noticed an annoying issue where my HLSL random function doesn't seem to actually be generating random values. Hence the large amount of uniformity in all these screenshots. You can see here where there's some small random being introduced, but then directly next to those blades sit a bunch of uniform blades:
I'm currently using the very basic GLSL random (in HLSL):
float GetRandomValue(float2 uv)
// Internet magic numbers follow...
float2 noise = (frac(sin(dot(uv, float2(12.9898, 78.233)*2.0)) * 43758.5453));
return abs(noise.x + noise.y) * 0.5;
In my shader I have a table of prime numbers which I just multiple the root vertex's UV coords by, using the GS Instance as the key into the prime numbers table:
// IN = Root position vertex passed from the Vertex Shader
// primeTable = Array of prime numbers.
// instanceId = SV_GSInstanceID
float random = GetRandomValue(IN.Uv * (float)(primeTable[instanceId]);
My thoughts are:
- Not sure how well this works if you have UV (0.0, 0.0).
- It probably just makes more sense to populate a texture coordinate with some random numbers rather than key off the UVs of the root vertex.
- I'm curious if this is causing some blades to stack on top of each other so I'm not getting the full effect currently.
Anyway, that's the latest. Comments / Thoughts / Suggestions always welcomed.