No Description

cull.comp 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #version 450
  2. #extension GL_ARB_separate_shader_objects : enable
  3. #extension GL_ARB_shading_language_420pack : enable
  4. layout (constant_id = 0) const int MAX_LOD_LEVEL = 5;
  5. struct InstanceData
  6. {
  7. vec3 pos;
  8. float scale;
  9. };
  10. // Binding 0: Instance input data for culling
  11. layout (binding = 0, std140) buffer Instances
  12. {
  13. InstanceData instances[ ];
  14. };
  15. // Same layout as VkDrawIndexedIndirectCommand
  16. struct IndexedIndirectCommand
  17. {
  18. uint indexCount;
  19. uint instanceCount;
  20. uint firstIndex;
  21. uint vertexOffset;
  22. uint firstInstance;
  23. };
  24. // Binding 1: Multi draw output
  25. layout (binding = 1, std430) writeonly buffer IndirectDraws
  26. {
  27. IndexedIndirectCommand indirectDraws[ ];
  28. };
  29. // Binding 2: Uniform block object with matrices
  30. layout (binding = 2) uniform UBO
  31. {
  32. mat4 projection;
  33. mat4 modelview;
  34. vec4 cameraPos;
  35. vec4 frustumPlanes[6];
  36. } ubo;
  37. // Binding 3: Indirect draw stats
  38. layout (binding = 3) buffer UBOOut
  39. {
  40. uint drawCount;
  41. uint lodCount[MAX_LOD_LEVEL + 1];
  42. } uboOut;
  43. // Binding 4: level-of-detail information
  44. struct LOD
  45. {
  46. uint firstIndex;
  47. uint indexCount;
  48. float distance;
  49. float _pad0;
  50. };
  51. layout (binding = 4) readonly buffer LODs
  52. {
  53. LOD lods[ ];
  54. };
  55. layout (local_size_x = 16) in;
  56. bool frustumCheck(vec4 pos, float radius)
  57. {
  58. // Check sphere against frustum planes
  59. for (int i = 0; i < 6; i++)
  60. {
  61. if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0)
  62. {
  63. return false;
  64. }
  65. }
  66. return true;
  67. }
  68. layout (local_size_x = 16) in;
  69. void main()
  70. {
  71. uint idx = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x;
  72. // Clear stats on first invocation
  73. if (idx == 0)
  74. {
  75. atomicExchange(uboOut.drawCount, 0);
  76. for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++)
  77. {
  78. atomicExchange(uboOut.lodCount[i], 0);
  79. }
  80. }
  81. vec4 pos = vec4(instances[idx].pos.xyz, 1.0);
  82. // Check if object is within current viewing frustum
  83. if (frustumCheck(pos, 1.0))
  84. {
  85. indirectDraws[idx].instanceCount = 1;
  86. // Increase number of indirect draw counts
  87. atomicAdd(uboOut.drawCount, 1);
  88. // Select appropriate LOD level based on distance to camera
  89. uint lodLevel = MAX_LOD_LEVEL;
  90. for (uint i = 0; i < MAX_LOD_LEVEL; i++)
  91. {
  92. if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance)
  93. {
  94. lodLevel = i;
  95. break;
  96. }
  97. }
  98. indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex;
  99. indirectDraws[idx].indexCount = lods[lodLevel].indexCount;
  100. // Update stats
  101. atomicAdd(uboOut.lodCount[lodLevel], 1);
  102. }
  103. else
  104. {
  105. indirectDraws[idx].instanceCount = 0;
  106. }
  107. }