PDA

View Full Version : Easy depth sorting, almost, maybe?



andy753421
01-24-2010, 08:38 PM
I have a bunch of transparent overlapping/intersecting objects that I would like to render somewhat nicely. I'm not worrying about polygon splitting at this point, only sorting. I think I understand what I have to do pretty well conceptually, but I haven't found a good way to implement it yet. I'm not worried about the actual sorting algorithm either, I'm using qsort for now but may switch to radix/bucket sort if I need to.

Here's an overview of my latest attempt. I can post code if anyone wants me to.

1. Turn on feedback mode.. glRenderMode(GL_FEEDBACK);
2. Render the scene like normal.
3. Turn off feedback mode.. n_values = glRenderMode(GL_RENDER);
4. Parse the feedback buffer into a list of triangles.
5. Sort the triangles from the feedback buffer.
6. Set up an orthographic projection to mimic the screen.
7. Render each triangle from the feedback buffer in order.

The nice thing about this way is that you can sort polygons drawn with immediate mode/display lists/whatever. You can also draw objects using different projections and not have to worry about switching projection matrices for every other polygon after they're sorted. You also don't need to call gluProject on every vertex.

This way seems to work pretty well when using GL_3D_COLOR for the feedback buffer, but I haven't been able to get textures working correctly yet. For one thing, you need to switch textures, but I think you could pass the texture id with glPassThrough(). The other problem is that the textures aren't projected correctly because they're being rendered in an orthographic projection.. I'm not sure how to get around this problem, or if it's even possible.

I've thought about using a vertex/fragment shader, or using a texture matrix, but I'm not experienced enough with OpenGL to know if either of those will work, or if they will, how to do it. Any suggestions?

Pierre Boudier
01-25-2010, 02:47 AM
this approach to sort polygons might be really inefficient on current gpu architecture. one generic way to implement order independant transparency would be using some sort of a-buffer, which is now possible thanks to the generic read/write functionality in GLSL on recent gpu.

Ilian Dinev
01-25-2010, 02:47 AM
Two words: Ordering Table :) . Basically a type of rough bucket-sort. http://www.exaflop.org/docs/naifgfx/naifsort.html
With GL3.x you can sort triangles with different textures, too (texture-arrays, something like a single 3D texture).
Feedback-mode is done in software, and is quite slow as the driver has to handle whatever data layout one sends on a whim to it. So why not limit the format, and compose the optimal code for your data.

andy753421
01-25-2010, 03:43 AM
Pierre, what is an a-buffer? I tried googling it, but "a buffer" turns out to be a hard-to-search term :)

Ilian, unless I'm missing something, it seems like using an ordering table is just a special sorting algorithm.. I actually don't have that many polygons at the moment so using a regular sorting algorithm is good enough for me for now. Using an ordering table, or something similar, is it possible to use a different modelview or projection matrix for different objects? If I store a pointer to the projection with each polygon I'd need to do a glLoadMatrix for every polygon, which seems like it would be slow. The other option is to project all the vertices to the same `world' coordinates so you don't have to switch modelview matrices, but projecting all the vertices in software seems slow in itself. Is there a way around this, or is it generally not a problem?

Ilian Dinev
01-25-2010, 04:42 AM
You can store instances' 4x3 matrices in a texture-buffer, fetch them in the vertex-shader.

Pierre Boudier
01-25-2010, 05:54 AM
a-buffer == alpha buffer

when you render into a regular color buffer, you have one rgba8 color value. so if your polygon are not sorted before rendering, then your single pixel value will not be computed correctly.

what you can do instead is:
- have a list of rgba8 (and depth) value
- when rendering, you keep all the pixels written to the framebuffer in that list, instead of keeping only the most visible one (depth testing)
- once all your fragments are written, you have a post processing pass which operates for each pixel: sort based on depth, and compute the final transparent value

since in regular rendering you can't write to a list of fragments per pixels, you need to implement this algorithm with GLSL shaders (and generic read/write to memory, which is a new extension).

you can contact us if you are interested in a preliminary version of the extension that allows those new access.

andy753421
01-25-2010, 10:01 AM
You can store instances' 4x3 matrices in a texture-buffer, fetch them in the vertex-shader.
Ilian, then would I use a uniform variable to index the texture-buffer, or could I just send the entire matrix with a uniform matrix? I don't know enough about how it's implemented to know if that would be any quicker than sending it with glLoadMatrix.

It sounds like most people are creating and storing all the vertices, polygons, and matrices in software. Is there a standard set of helper functions to replace the imediate mode GL commands for creating these? I'm thinking something like xxVertex3f, xxTriangleStrip, xxRotatef, xxTranslatef, etc. It wouldn't be to hard to make my own, but if it's the normal thing to do, maybe it's already done for me :)

One more related question, if I have a vertex shader that does various cartographic projections (latitude-longitude-elevation to x-y-z), is there a way to use that from software to get z-values, or do I need to have similar routines in software to do those conversion as well?

Ilian Dinev
01-25-2010, 10:39 AM
The mat4x3 indices can/will change on every triangle, so they have to be a streamed vertex-attrib, one way or another. A nice vertex-declaration would be:



struct VTX{ // vtx attribute
float instanceIdx;
float vtxIdx;
};

struct InstanceData{ // a uniform, texture, etc
//---[ actual instance data ]------[
// there are i.e 50,000 instances in a scene
mat4x3 xform;
//---------------------------------/

//-----[ semitransparent object mesh data ]------[
// there are i.e 50 different meshes in a scene
float textureZ; // for texture-array
float firstVtxIdx; // in a buffer (texture or bindable uniform), where the mesh's vertices are
//-----------------------------------------------/
}





Is there a standard set of helper functions to replace the imediate mode GL commands for creating these?
GLIM: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=254364
I use a set of funcs I rolled on my own, which expect vertex-declarations be defined beforehand.


ilImmBegin(4,ILXSnippetDraw::DefVtxDecl_Pos);

for(int i=0;i<NumQuads;i++){
NavMesh::QUAD q=Quads[i];
if(q.vertices[3]==0xFFFF){
vec3 vs[3];
for(int j=0;j<3;j++){
int k= q.vertices[j];
vs[j].x = Vertices[k].x;
vs[j].y = VertsZ[k];
vs[j].z = Vertices[k].y;
}
ilImmTriangle(vs+2,vs+1,vs+0);
}
}

ilImmEnd();