cs_gdr_occlude_props.sc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright 2018 Kostas Anagnostou. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. #include "bgfx_compute.sh"
  6. SAMPLER2D(s_texOcclusionDepth, 0);
  7. BUFFER_RO(instanceDataIn, vec4, 1);
  8. BUFFER_RW(drawcallInstanceCount, uint, 2);
  9. BUFFER_WO(instancePredicates, bool, 3);
  10. uniform vec4 u_inputRTSize;
  11. uniform vec4 u_cullingConfig;
  12. NUM_THREADS(64, 1, 1)
  13. void main()
  14. {
  15. bool predicate = false;
  16. //make sure that we not processing more instances than available
  17. if (gl_GlobalInvocationID.x < uint(u_cullingConfig.x) )
  18. {
  19. //get the bounding box for this instance
  20. vec4 bboxMin = instanceDataIn[2 * gl_GlobalInvocationID.x] ;
  21. vec3 bboxMax = instanceDataIn[2 * gl_GlobalInvocationID.x + 1].xyz;
  22. int drawcallID = int(bboxMin.w);
  23. //Adapted from http://blog.selfshadow.com/publications/practical-visibility/
  24. vec3 bboxSize = bboxMax.xyz - bboxMin.xyz;
  25. vec3 boxCorners[] = {
  26. bboxMin.xyz,
  27. bboxMin.xyz + vec3(bboxSize.x,0,0),
  28. bboxMin.xyz + vec3(0, bboxSize.y,0),
  29. bboxMin.xyz + vec3(0, 0, bboxSize.z),
  30. bboxMin.xyz + vec3(bboxSize.xy,0),
  31. bboxMin.xyz + vec3(0, bboxSize.yz),
  32. bboxMin.xyz + vec3(bboxSize.x, 0, bboxSize.z),
  33. bboxMin.xyz + bboxSize.xyz
  34. };
  35. float minZ = 1.0;
  36. vec2 minXY = vec2(1.0, 1.0);
  37. vec2 maxXY = vec2(0.0, 0.0);
  38. UNROLL
  39. for (int i = 0; i < 8; i++)
  40. {
  41. //transform World space aaBox to NDC
  42. vec4 clipPos = mul( u_viewProj, vec4(boxCorners[i], 1) );
  43. #if BGFX_SHADER_LANGUAGE_GLSL
  44. clipPos.z = 0.5 * ( clipPos.z + clipPos.w );
  45. #endif
  46. clipPos.z = max(clipPos.z, 0);
  47. clipPos.xyz = clipPos.xyz / clipPos.w;
  48. clipPos.xy = clamp(clipPos.xy, -1, 1);
  49. clipPos.xy = clipPos.xy * vec2(0.5, -0.5) + vec2(0.5, 0.5);
  50. minXY = min(clipPos.xy, minXY);
  51. maxXY = max(clipPos.xy, maxXY);
  52. minZ = saturate(min(minZ, clipPos.z));
  53. }
  54. vec4 boxUVs = vec4(minXY, maxXY);
  55. // Calculate hi-Z buffer mip
  56. ivec2 size = ivec2( (maxXY - minXY) * u_inputRTSize.xy);
  57. float mip = ceil(log2(max(size.x, size.y)));
  58. mip = clamp(mip, 0, u_cullingConfig.z);
  59. // Texel footprint for the lower (finer-grained) level
  60. float level_lower = max(mip - 1, 0);
  61. vec2 scale = vec2_splat(exp2(-level_lower) );
  62. vec2 a = floor(boxUVs.xy*scale);
  63. vec2 b = ceil(boxUVs.zw*scale);
  64. vec2 dims = b - a;
  65. // Use the lower level if we only touch <= 2 texels in both dimensions
  66. if (dims.x <= 2 && dims.y <= 2)
  67. mip = level_lower;
  68. #if BGFX_SHADER_LANGUAGE_GLSL
  69. boxUVs.y = 1.0 - boxUVs.y;
  70. boxUVs.w = 1.0 - boxUVs.w;
  71. #endif
  72. //load depths from high z buffer
  73. vec4 depth =
  74. {
  75. texture2DLod(s_texOcclusionDepth, boxUVs.xy, mip).x,
  76. texture2DLod(s_texOcclusionDepth, boxUVs.zy, mip).x,
  77. texture2DLod(s_texOcclusionDepth, boxUVs.xw, mip).x,
  78. texture2DLod(s_texOcclusionDepth, boxUVs.zw, mip).x,
  79. };
  80. //find the max depth
  81. float maxDepth = max( max(depth.x, depth.y), max(depth.z, depth.w) );
  82. if ( minZ <= maxDepth )
  83. {
  84. predicate = true;
  85. //increase instance count for this particular prop type
  86. atomicAdd(drawcallInstanceCount[ drawcallID ], 1);
  87. }
  88. }
  89. instancePredicates[gl_GlobalInvocationID.x] = predicate;
  90. }