GpuParticleSortPrepare.bsl 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. shader GpuParticleSortPrepare
  2. {
  3. featureset = HighEnd;
  4. code
  5. {
  6. Texture2D gPosAndTimeTex;
  7. Buffer<uint2> gInputIndices;
  8. RWBuffer<uint> gOutputKeys;
  9. RWBuffer<uint2> gOutputIndices;
  10. cbuffer Input
  11. {
  12. uint gIterationsPerGroup;
  13. uint gNumExtraIterations;
  14. uint gNumParticles;
  15. uint gOutputOffset;
  16. uint gSystemKey;
  17. float3 gLocalViewOrigin;
  18. };
  19. [numthreads(NUM_THREADS, 1, 1)]
  20. void csmain(uint3 groupThreadId : SV_GroupThreadID, uint3 groupId : SV_GroupID)
  21. {
  22. uint threadId = groupThreadId.x;
  23. uint inputIdx;
  24. uint numIterations;
  25. if(groupId.x < gNumExtraIterations)
  26. {
  27. inputIdx = groupId.x * (gIterationsPerGroup + 1);
  28. numIterations = gIterationsPerGroup + 1;
  29. }
  30. else
  31. {
  32. inputIdx = groupId.x * gIterationsPerGroup + gNumExtraIterations;
  33. numIterations = gIterationsPerGroup;
  34. }
  35. inputIdx = inputIdx * NUM_THREADS + threadId;
  36. uint outputIdx = gOutputOffset + inputIdx;
  37. for(uint i = 0; i < numIterations; ++i)
  38. {
  39. if(inputIdx >= gNumParticles)
  40. break;
  41. uint3 pixelPos;
  42. pixelPos.xy = gInputIndices[inputIdx];
  43. pixelPos.z = 0;
  44. float3 position = gPosAndTimeTex.Load(pixelPos).xyz;
  45. float dist = length(position - gLocalViewOrigin);
  46. uint key = f32tof16(dist);
  47. // Flip the sign to sort from furthest to nearest. This works because positive float bits
  48. // will still compare properly. Negative ones won't be those are invisible behind the camera anyway.
  49. key = ((~key) & 0xFFFF) | gSystemKey;
  50. gOutputKeys[outputIdx] = key;
  51. gOutputIndices[outputIdx] = pixelPos.xy;
  52. inputIdx += NUM_THREADS;
  53. outputIdx += NUM_THREADS;
  54. }
  55. }
  56. };
  57. };