#pragma kernel Main struct IndirectDrawIndexedArgs { uint indexCountPerInstance; uint instanceCount; uint startIndex; uint baseVertexIndex; uint startInstance; }; RWStructuredBuffer _InstanceTriangles; RWStructuredBuffer _IndirectDrawIndexedArgs; uint grassOriginPointCount; uint grassBladesPerPoint; uint grassSegments; [numthreads(1,1,1)] void Main (uint id : SV_DispatchThreadID) { /* Grass Triangle index generation: (all index are x + grassBladesPerPoint * Index Per Blade) 6 . LastSegment { n*2, n*2+2, n*2 + 1} / \ / \ 4 .-----. 5 | /| | / | N Segment { n*2, n*2 + 3, n*2 + 1 } + { n*2, n*2 + 2, n*2 + 3 } | / | | / | 2 .-----. 3 | /| | / | | / | Zero Segment: { 0, 3, 1 } + { 0, 2, 3 } (if more than one segment) | / | 0 .-----. 1 */ uint indexPerBlade = ((grassSegments-1) * 3 * 2 + 3); uint indexPerInstance = grassBladesPerPoint * indexPerBlade; if (id >= indexPerInstance) // No more index to process { return; } uint bladeIndex = id / indexPerBlade; uint IndexInsideBlade = id % indexPerBlade; uint segmentIndex = IndexInsideBlade / 6; uint IndexInsideSegment = IndexInsideBlade % 6; uint uniqueIndexPerBlade = grassSegments * 2 + 1 ; if (segmentIndex == grassSegments-1){ // Last Segment if (IndexInsideSegment == 0){ _InstanceTriangles[id] = segmentIndex * 2; } if (IndexInsideSegment == 1){ _InstanceTriangles[id] = segmentIndex*2 + 2; } if (IndexInsideSegment == 2){ _InstanceTriangles[id] = segmentIndex*2 + 1; } } else{ // First triangle if (IndexInsideSegment == 0){ _InstanceTriangles[id] = segmentIndex * 2; } if (IndexInsideSegment == 1){ _InstanceTriangles[id] = segmentIndex*2 + 3; } if (IndexInsideSegment == 2){ _InstanceTriangles[id] = segmentIndex*2 + 1; } // Second triangle if (IndexInsideSegment == 3){ _InstanceTriangles[id] = segmentIndex * 2; } if (IndexInsideSegment == 4){ _InstanceTriangles[id] = segmentIndex*2 + 2; } if (IndexInsideSegment == 5){ _InstanceTriangles[id] = segmentIndex*2 + 3; } } _InstanceTriangles[id] += uniqueIndexPerBlade * bladeIndex; if (id == 0) { _IndirectDrawIndexedArgs[0].indexCountPerInstance = indexPerInstance; _IndirectDrawIndexedArgs[0].instanceCount = grassOriginPointCount; _IndirectDrawIndexedArgs[0].startIndex = 0; // not used _IndirectDrawIndexedArgs[0].baseVertexIndex = 0; // not used _IndirectDrawIndexedArgs[0].startInstance = 0; // not used } }