123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- #version 450
-
- #extension GL_ARB_separate_shader_objects : enable
- #extension GL_ARB_shading_language_420pack : enable
-
- layout (constant_id = 0) const int MAX_LOD_LEVEL = 5;
-
- struct InstanceData
- {
- vec3 pos;
- float scale;
- };
-
- // Binding 0: Instance input data for culling
- layout (binding = 0, std140) buffer Instances
- {
- InstanceData instances[ ];
- };
-
- // Same layout as VkDrawIndexedIndirectCommand
- struct IndexedIndirectCommand
- {
- uint indexCount;
- uint instanceCount;
- uint firstIndex;
- uint vertexOffset;
- uint firstInstance;
- };
-
- // Binding 1: Multi draw output
- layout (binding = 1, std430) writeonly buffer IndirectDraws
- {
- IndexedIndirectCommand indirectDraws[ ];
- };
-
- // Binding 2: Uniform block object with matrices
- layout (binding = 2) uniform UBO
- {
- mat4 projection;
- mat4 modelview;
- vec4 cameraPos;
- vec4 frustumPlanes[6];
- } ubo;
-
- // Binding 3: Indirect draw stats
- layout (binding = 3) buffer UBOOut
- {
- uint drawCount;
- uint lodCount[MAX_LOD_LEVEL + 1];
- } uboOut;
-
- // Binding 4: level-of-detail information
- struct LOD
- {
- uint firstIndex;
- uint indexCount;
- float distance;
- float _pad0;
- };
- layout (binding = 4) readonly buffer LODs
- {
- LOD lods[ ];
- };
-
- layout (local_size_x = 16) in;
-
- bool frustumCheck(vec4 pos, float radius)
- {
- // Check sphere against frustum planes
- for (int i = 0; i < 6; i++)
- {
- if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0)
- {
- return false;
- }
- }
- return true;
- }
-
- layout (local_size_x = 16) in;
-
- void main()
- {
- uint idx = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x;
-
- // Clear stats on first invocation
- if (idx == 0)
- {
- atomicExchange(uboOut.drawCount, 0);
- for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++)
- {
- atomicExchange(uboOut.lodCount[i], 0);
- }
- }
-
- vec4 pos = vec4(instances[idx].pos.xyz, 1.0);
-
- // Check if object is within current viewing frustum
- if (frustumCheck(pos, 1.0))
- {
- indirectDraws[idx].instanceCount = 1;
-
- // Increase number of indirect draw counts
- atomicAdd(uboOut.drawCount, 1);
-
- // Select appropriate LOD level based on distance to camera
- uint lodLevel = MAX_LOD_LEVEL;
- for (uint i = 0; i < MAX_LOD_LEVEL; i++)
- {
- if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance)
- {
- lodLevel = i;
- break;
- }
- }
- indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex;
- indirectDraws[idx].indexCount = lods[lodLevel].indexCount;
- // Update stats
- atomicAdd(uboOut.lodCount[lodLevel], 1);
- }
- else
- {
- indirectDraws[idx].instanceCount = 0;
- }
- }
|