Of course.
I have 2 step algorithm:
- 1st step is an occluding for whole scene that has one output SSBO with instanceIds of accepted objects.
- 2d step drawing all accepted objects.
All objects of the scene organised as sorted map ‘Mesh -> array of objects’.
Map sorted by Mesh to guarantee the same order of them for occluding and drawing stages.
Actually the difference between objects related one Mesh is just model matrix.
I try to describe both steps in detail sкipping stuff that does not matter.
Occluding:
I use one ‘transform feedback’ (TF) loop for whole scene.
In the scope of that TF I call glDrawElementsInstanced (with GL_POINTS - centres of mesh) for each Mesh using own ‘occlusion query’.
For occluding I use center and parameters defained bounding box (BB).
The occluding technically the such as in ‘Mountains with HiZ’ example.
The vertex shader define occluding fact for center using BB, then send the flag to geometry shader.
The geometry shader just rejects or accepts current object (actually just center of it) using flag as input.
Output of geometry shader is the instanceId of current object.
So, as a result I have set of ‘occluding query’ results for each mesh and filled SSBO with instanceIds for each Mesh.
Drawing:
I call glDrawElementsInstanced (with full data) for each Mesh.
Using ‘occluding query’ results I can calculate offset for SSBO to define needed data region in it.
So, using current instanceId and offset for current Mesh I can get accepted instanceId from SSBO.
Using accepted instanceId I get all needed info for current object from additional buffers.
So basically that is it.
In my case I reduce the scene to make it simple.
I have 3 meshes: just cubes with different textures.
The first Mesh has 3 objects, and others have 2 objects each.
So SSBO result of occluding if all objects are visible is: 0, 1, 2, 0, 1, 0, 1;
0, 1, 2 - instanceIds for 1st mesh (occluding quesy result: 3)
0, 1 - instanceIds for 2st mesh (occluding quesy result: 2)
0, 1 - instanceIds for 3d mesh (occluding quesy result: 2)
Thus if I draw 3d mesh instances I just calculate offset using query result for prev instances: 3 + 2.
It seems I can describe what is wrong with my occluding step.
If all of 1st Mesh objects are invisible (occuding query result is zero), then output SSBO has trash like:
-383292386, 0, 838237456, 0 (2 objects per 2d and 3d meshes)
If any object of 1st Mesh is visible, then everything is ok: 2, 0, 1, 0, 1