Game Development Community

Problem with Z-buffer

by Vyacheslav Maltsev · in Torque Game Engine · 09/05/2007 (12:03 am) · 20 replies

Let me explain. Two objects (planes) which are in parallel to each other are dynamically added to scene. These objects set on different destination from the camera. Both objects are half-transparent, i.e. contain alpha channel. In this situation z-buffer works incorrectly, namely pixels of the distant object recovers pixels of the near object. It's totally impossible to work! Please help me in solving this problem.
I think that problem contains in one of these:
1. Depth buffer of OpenGL - GL_DEPTH
2. Blending buffer of OpenGL - GL_BLEND
3. Z-sorting of Torque - rendering in order of distance.
Please give me advise what to check or where to search. May be I've just missed one option?
Thank you.

#1
09/09/2007 (10:41 pm)
Hi everyone!
We have solved this problem! The TGE included it. If anyone interested - write to us - we will help you necessarily.
#2
09/17/2007 (11:04 pm)
Would be nice if you can explain how to fix that.
I have too problems with alpha-transparent textures, sometime a other alpha-transparent texture after the first one would not shown at all.
#3
09/17/2007 (11:51 pm)
Hi, Alex! I'll translate solvation tomorrow, so wait a little. Any way, you may knock to my icq now: 338174186. We'll communicate more. Welcome!
#4
09/19/2007 (5:07 am)
Here you are:

When Torque gives to OpenGL command to render - it set custom (by its own decision) display mode for every object. For objects with alpha channel Torque commands to turn off Z-buffer and draw object by "Artist algorithm" (order of rendering depends on distance from camera). But by some weird reason Artist algorith doesn't work! So we have to make Z-buffer still turned on even in case of half-transparent objects.

See render function in TSShapeInstance.cc. Before render we turn on AlphaTest and after rendering - turn it off. Here goes code:

void TSShapeInstance::render(S32 dl, F32 intraDL, const Point3F * objectScale)
..................
//Debuggggg
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);

for (i=start; i mMeshObjects[i].render(od,mMaterialList);

//Debuggggg
glDisable(GL_ALPHA_TEST);
...................

In TSMesh.cc module we remming one string so Z-buffer is turned on:

void TSMesh::setMaterial(S32 matIndex, TSMaterialList* materials)
.................................
if (flags & TSMaterialList::Translucent)
{
if (TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_TWO_PASS
(TSMaterialList::Additive|TSMaterialList::Subtractive))
{
glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.fogTE);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
TSShapeInstance::smRenderData.vertexAlpha.fog = 1.0f - TSShapeInstance::smRenderData.fogColor.w;
}
glEnable(GL_BLEND);
|| TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_TWO_PASS_TEXGEN)
{
TSShapeInstance::smRenderData.vertexAlpha.fog = 1.0f - TSShapeInstance::smRenderData.fogColor.w;
}
else if ((TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_MULTI_1 ||
TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_MULTI_1_TEXGEN) &&
flags &

//DEBUGGGGGGGGGGGGGGG Here it is!
// glDepthMask(GL_FALSE);

}
...............................

And that is all. In the end we have Blending, AlphaTest and Z-buffer turned on so half-transparent objects drawn well.
I hope this helps.
#5
09/19/2007 (7:38 am)
That is a big help. Thanks.
#6
09/19/2007 (3:02 pm)
This is VERY cool!
I just ran some experiments useing some previously UN-usable DTS shapes, because of the sorting errors.

I could not find any performance loss, no graphical anomaly. And my DTS shapes sorted perfectly.

I did my tests with a glAlphaFunc(GL_GREATER, 0.44f);
Because my alpha map is very sloppy, but clean art would not need this.(EDIT TGE1.42)
#7
01/28/2008 (12:03 am)
Don't know if this is related, but how do you prevent text (names) and other graphics (drawn in GUIShapebase or GUICrosshairHUD) from appearing over cockpits that should obstruct it in 1st person mode?

It almost *sounds* like a z-sorting order problem.
#8
01/28/2008 (8:41 am)
That's a draw-order problem. See GuiShapeNameHud for where those names get drawn.
#9
01/29/2008 (10:55 pm)
Hmm i noticed the code is slightly different with torque 1.5.2 can anyone show me how to make the proper changes with it?
#10
03/10/2008 (9:08 pm)
@Vyacheslav
I tried throwing in your code blindly assuming that the added code above would be sufficient. After looking at it you use variables that mean nothing. For the TSShapeInstance::render add on, you use variables, i, start, end and od. What are these values????
The second part for tsMesh has a whole wack of errors. Could you please maybe just paste the whole
if (flags & TSMaterialList::Translucent) block of code. That would be super fantastic.
Thx in advance.
DALO
#11
03/10/2008 (9:26 pm)
After looking at it more I see that in this block of code
if (!supportBuffers || !renderMeshesX(ss,od)){.....
which is inside the TSShapeInstance::render function, that is where it defines the start and end. You just have to call the gl calls before the for loop and after. Just in case anyone else tries this out.
Also in the tsMesh.cc file, just simply comment this line out glDepthMask(GL_FALSE); And I think that should do it. Please correct me if I'm wrong.
#12
03/11/2008 (7:41 am)
Quote:You just have to call the gl calls before the for loop and after.

Which loop? Do you mean, before and after the "if" statement?
#13
03/11/2008 (7:42 am)
Can you post a "before and after" of the code in question? Thanks!
#14
03/11/2008 (9:09 am)
In tsShapeInstance (roughly line 682):

if (!supportBuffers || !renderMeshesX(ss,od)){
// run through the meshes
smRenderData.currentTransform = NULL;
S32 start = smNoRenderNonTranslucent ? mShape->subShapeFirstTranslucentObject[ss] :
mShape->subShapeFirstObject[ss];
S32 end = smNoRenderTranslucent ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss];

// -> dalo
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
// <- dalo
S32 i = 0;
for (i=start; i mMeshObjects[i].render(od,mMaterialList);
}
// -> dalo
glDisable(GL_ALPHA_TEST);
// <- dalo

****NOTE**** the lines inbetween the //-> dalo marks are the newly added lines.
#15
03/11/2008 (9:12 am)
Yep... that's what the original patch was supposed to do. The lines following the "//Debugggg" comments were added.
#16
03/11/2008 (9:16 am)
The depth mask helps with certain blending issues, but it causes other problems with translucent things, unfortunately.
#17
03/11/2008 (9:18 am)
Yes, I have noticed that as well. I have a transparent image around my weapon to give it a glow effect and it renders that transparent image really funky and wrong. I have actually commented out the above code......oh well.
#18
03/11/2008 (9:26 am)
In the original patch above, the "glDisable(GL_ALPHA_TEST)" call is *inside* the "if" statement, not after its closing brace.
#19
03/11/2008 (10:11 am)
Oh right you are. It still doesn't seem to work for me though :-(
Do you have any issues with particle effects that fight with the z-buffer, in terms of which should be rendered first?
#20
03/11/2008 (11:10 am)
Disabling the z-buffer, but enabling the alpha stuff is better that without the alpha stuff at least.

Regarding particles, that's another subject altogether. The guy that made AFX has a .plan (or other resource), I think, that talks about dealing with particle draw-order issues in various ways.