Advertisement

Decals

Started by January 15, 2002 05:25 PM
23 comments, last by Locke 23 years, 1 month ago
quote:

About polygon offset, I agree that it''s useful when the surfaces do not perfectly match, but I disagree about the non-existence of the artefacts.
Polygon offset is by definition an artefact.



How yo you define artifact ? Z-fighting is obviously one (and a very bad one), and a polygon offset eliminates it. I''m not aware of any artifacts that polygon offset *creates*. In fact, you could draw your whole scene with a polygon offset, and you wouldn''t notice the slighest difference, it''s just a zbuffer offset. It doesn''t affect projection or rasterization in any other way. It''s nothing more than a kind of ''GL_APPROXIMATE'' depth buffer function with an adjustable epsilon. Don''t see any problems with that.
The problem comes from the solution of the particular cases. (very deep, but does not mean anything :b)

With polygon offset, you can tell OpenGL that an object is in front of another when in reality it is at the same place or behind. (You can also reverse the effect, but it doesn''t matter).

The thing is, it''s obviously good for any polygon you want to create effects like decal. It is a desirable effect.

But, also, there could be polygons where this effect could appear whithout you were thinking of it. The undesirable effect.

Imagine a floor. It is textured and lightmapped (just to consume the texture units and not let use multitexturing for decal), and you add a "decal" : you write the "decal" part in front of the floor thanks to polygon offset. That''s okay.
Now imagine that a leaf falls. The leaf ends very close to the floor. But if you don''t take care of the polygon offset, the "decal" of the floor will draw "over" the leaf. That''s bad.

Do you see the kind of *artefact* I am talking about ?

To my mind, depth testing is not an artefact since an entire scene draw with depth testing looks real whatever the scene is (except for translucency). But polygon offset is, IMO, an artefact since it may add weird effects like this one.
Advertisement
I can''t really see what the problem would be?

I assume you''re also using decals to draw the leaves? in which case draw the original decal with a very small offset, then draw the leave with a slightly larger offset!

Look at Q3A for example - can you tell that the bullet marks on walls are use glPolygonOffset? I somehow doubt it! I haven''t tried but I suspect you could layer several decals over each other without noticing.
quote:

With polygon offset, you can tell OpenGL that an object is in front of another when in reality it is at the same place or behind. (You can also reverse the effect, but it doesn''t matter).



That''s correct.

quote:

Imagine a floor. It is textured and lightmapped (just to consume the texture units and not let use multitexturing for decal), and you add a "decal" : you write the "decal" part in front of the floor thanks to polygon offset. That''s okay.
Now imagine that a leaf falls. The leaf ends very close to the floor. But if you don''t take care of the polygon offset, the "decal" of the floor will draw "over" the leaf. That''s bad.


No it will not. Remember, that polygon offset actually shifts the value written to the zbuffer. Note, that I didn''t say the z coordinate, but the *value* in depth buffers internal fixed point format. It will move it perhaps 10 units away (if you specify it like that). Modern zbuffers have at least 24bit. That''s a dynamic range of 16777216 units. The leaf that falls onto the ground will stop at least 1000-2000 units away from the floor (it is visually allready on the floor, since 1000 zbuffer units are visually indistinguishable). Now, what does the 10 little polygon offset units will do ? Nothing. And this becomes even more precise, if the camera is near the leaf, since the zbuffer precision is concentrated in the near view field.

Well parametrized polygon offsetting is visually perfect. No artifacts. You could literally draw thousands of layers one over the other with offsetting - It would still look perfect.

quote:

To my mind, depth testing is not an artefact since an entire scene draw with depth testing looks real whatever the scene is (except for translucency)



Not always. If you have to faces that intersect at a small angle, then you''ll get an effect known as z-fighting. It''s due to accuracy problems of the zbuffer, and that''s a *very* ugly artifact. Look at eg. Half-life, it was full of those not so nice effects.
NB: moi aussi, j''suis français...

On est envahi par des français


Shag: In this example I wouldn't like to see the "decal" on the leaf. That's why there is a problem.


quote:
Well parametrized polygon offsetting is visually perfect.

Of course, but that depends on how you define "well parametrized".
In your example, you reckon there's a 24bit depth buffer and that you know how to tweak a polygon offset to 10 units while you know that you won't let your leaf fall closer than 1000 units to the floor. In that case, the user knows exactly what he does. That's why it is perfect.
What I pointed out is, if you don't use the polygon offset wisely, you could have 1000 units offset while there are 10 units between the leaf and the floor. And that case may happen if the programmer doesn't master OpenGL.


quote:
If you have to faces that intersect at a small angle, then you'll get an effect known as z-fighting.

True about that.
Also, you can correct it too with polygon offset, but that's a waste of time for real-time rendering (unless you have a very poor zbuffer, like 8bit).

Edited by - vincoof on January 17, 2002 3:30:48 AM
> On est envahi par des français

Hehe.. mais je suis breton, pas vraiment français, quoi

quote:

Of course, but that depends on how you define "well parametrized".
In your example, you reckon there''s a 24bit depth buffer and that you know how to tweak a polygon offset to 10 units while you know that you won''t let your leaf fall closer than 1000 units to the floor. In that case, the user knows exactly what he does. That''s why it is perfect.
What I pointed out is, if you don''t use the polygon offset wisely, you could have 1000 units offset while there are 10 units between the leaf and the floor. And that case may happen if the programmer doesn''t master OpenGL.



I agree on your general point. If you get more and more used to OGL, then it''s pretty obvious that you''ll get visually better results, knowing how to use particular functions the way they were intended to be used.

But this is true for lots of different parts in OpenGL, not only polygon offset. Polygon offset isn''t that difficult to parametrize either.

How many newbies do things like: glDepthRange(0.00001, 10000.0), and then they wonder why they have z tearing all over the place, even with 24bit+ zbuffers. Correct parametrization is a very important issue in a complex graphics system, and I agree that especially the whole zbuffer handling is not easy to get right. But I wouldn''t go that far and call a function like polygon offset an artifact by definition, simply because it isn''t. Yes, it can create artifacts, when handled in a wrong way, but allmost every function in OGL could. So, it''s entirely upon the programmer.

quote:

> If you have to faces that intersect at a small angle, then you''ll get an effect known as z-fighting.
True about that.
Also, you can correct it too with polygon offset, but that''s a waste of time for real-time rendering (unless you have a very poor zbuffer, like 8bit).



Well, I wouldn''t use a poly offset to correct those kind of problems either. It''s not intended for that, and would probably make the problem worse than it was before, if the 2 faces actually intersect instead of being coplanar. A good parametrization of the depth range can almost always avoid those problems, and if not, you can still split the faces at the intersection point.

Advertisement
> Hehe.. mais je suis breton, pas vraiment français, quoi
LOL


quote:
If you get more and more used to OGL, then it''s pretty obvious that you''ll get visually better results, knowing how to use particular functions the way they were intended to be used.

I agree, but I don''t know why I still think polygon offset is something fake in the graphics pipeline.
But in reality, 3D CG is fake in its whole ! So why should I set polygon offset as an exception ? Well, huh, dunno


quote:
How many newbies do things like: glDepthRange(0.00001, 10000.0)

And I would even say "glDepthRange(0., 0.1)"
Hey, that happened to me too in the beginning ! Don''t ROFL !


quote:
> > If you have to faces that intersect at a small angle, then you''ll get an effect known as z-fighting.
> True about that.
> Also, you can correct it too with polygon offset, but that''s a waste of time for real-time rendering.
Well, I wouldn''t use a poly offset to correct those kind of problems either. It''s not intended for that.

So who said you what it was intended for ? Eh eh, you can use every effect wherever you want if you can master it, right ?
I know it''s not a good way, but for realistic rendering it may be a solution. And remember you can not always tweak the depth range.


quote:
you can still split the faces at the intersection point

Hem, no.
I don''t see how it can correct the problem. Your polygons will still have close depth fragments, and the artefact will still be visible.
quote:

And I would even say "glDepthRange(0., 0.1)"
Hey, that happened to me too in the beginning ! Don''t ROFL !



The weird thing is, glDepthRange(0, 0) can actually have interesting applications when trying to get very advanced effects, dealing with z masking and depth textures.
quote:

So who said you what it was intended for ? Eh eh, you can use every effect wherever you want if you can master it, right ?
I know it''s not a good way, but for realistic rendering it may be a solution. And remember you can not always tweak the depth range.



Well, yes, you *could* of course use it. But you''d need a very special engine structure to sort those ''offending'' faces apart, then switch on poly offset, at the right level, render them, etc.. You''ll find yourself constantly switching states, it''s going to be slow as hell, if you do that for an entire scene. Though I agree that it can be usefull for very few, but critical problems, that can''t be removed otherwise.

On the other hand: a 24bit zbuffer is really enough, if you know how to use it. You can do really large ranges without getting artifacts, if you are carefull about your geometry. I try to avoid those degenerated faces in the first place Isn''t there an OGL extension, that uses the value 1/z in the buffer (kind of w-buffering) and enhances the dynamic range ? Something like float_depth_buffer or similar, I''ll have to check the ext-registry.

quote:

> you can still split the faces at the intersection point
Hem, no.
I don''t see how it can correct the problem. Your polygons will still have close depth fragments, and the artefact will still be visible.



Depends. There are 2 distinct artifacts created by the zbuffer, they are essentially the same phenomena, but one can be eliminated that way, the other not. If you have 2 faces that intersect, but are not really coplanar, they you might get tearing at the intersection line, since this intersection isn''t geometric, but created by the zbuffer at fragment level. You can 100% eliminate that effect by splitting your geometry.
The other artifact is z-fighting with almost coplanar faces, intersecting or not, you''ll get problems. This effect can only be solved by polygon offset, or a 64bit zbuffer, as some SGI systems have...
quote:
The weird thing is, glDepthRange(0, 0) can actually have interesting applications when trying to get very advanced effects, dealing with z masking and depth textures.

Huh, I''ve never heard about anything about this technique !?
Could you tell a little bit more please ? Give an example if possible ?
Thanks in advance.


quote:
But you''d need a very special engine structure to sort those ''offending'' faces apart, then switch on poly offset, at the right level, render them, etc.. You''ll find yourself constantly switching states, it''s going to be slow as hell, if you do that for an entire scene.

I know. That''s why I''ve written it may not used for real-time rendering. I''ve also written it''s good for realistic rendering. What could I say on top of that ?


quote:
Isn''t there an OGL extension, that uses the value 1/z in the buffer (kind of w-buffering)

I think the hardware decides it automatically for us.
But I may be wrong...


quote:
If you have 2 faces that intersect, but are not really coplanar, they you might get tearing at the intersection line, since this intersection isn''t geometric, but created by the zbuffer at fragment level. You can 100% eliminate that effect by splitting your geometry.

I''m sorry but I still don''t get that.
Je crois que si on ne parle pas français on ne se comprendra pas suffisamment ^^
Si 2 face s''intersectent, forcément elles ne sont pas coplanaires (sinon il y a comme qui dirait un pépin). Mais une question que je me pose : parles-tu d''une intersection en L, en T ou en X ?
En L je suis d''accord au détail près qu''il faut être tordu pour ne pas avoir les mêmes cordonnées dans l''angle. Donc ce ne peut logiquement pas être de cela dont tu parles, car la solution n''est pas de découper les polygones.
En T je suis d''accord uniquement si on voit le T de dos (c''est-à-dire si la caméra est au dessus de la lettre T).
En X je ne suis pas d''accord, car tu ne pourras pas te débarraser du "z-fighting" même en découpant les polygones.


quote:
or a 64bit zbuffer, as some SGI systems have

Well, of course it may be a little bit better. But it''s just about pushing the limits of the buffer a bit further. It does not really eliminate the problem.
quote:

>The weird thing is, glDepthRange(0, 0) can actually have interesting applications when trying to get very advanced effects, dealing with z masking and depth textures.
Huh, I''ve never heard about anything about this technique !?
Could you tell a little bit more please ? Give an example if possible ?
Thanks in advance.


No probs. One application, for example, are reflection. Everybody always told you, that you need a stencil buffer to make good multiple reflection in your scene, right ? Wrong. You don''t need a stencil buffer at all, all you need is glDepthRange. Effectively, calling glDepthRange(0,0) degenerates the z value written to the zbuffer to always be zero, but does not effect other raterization properties of the face. This makes it a perfect mask. Instead of a stencil mask, you can just write a z-mask with this method (if you use GL_LESS as depth buffer test on your scene, then the masked z buffer (being zero at masked pixels) will make sure that *no* geometry can draw into the masked region). You can unmask the region with glDepthRange(1,1). Here you go, perfect refllections, no stencil needed, works on every card that supports a zbuffer.

quote:

> Isn''t there an OGL extension, that uses the value 1/z in the buffer (kind of w-buffering)
I think the hardware decides it automatically for us.
But I may be wrong...



No it uses a linear zbuffer by default. The extension is called wgl_depth_float, I just looked it up. My 3D card does not support it, though.
quote:

Si 2 face s''intersectent, forcément elles ne sont pas coplanaires (sinon il y a comme qui dirait un pépin). Mais une question que je me pose : parles-tu d''une intersection en L, en T ou en X ?
En L je suis d''accord au détail près qu''il faut être tordu pour ne pas avoir les mêmes cordonnées dans l''angle. Donc ce ne peut logiquement pas être de cela dont tu parles, car la solution n''est pas de découper les polygones.
En T je suis d''accord uniquement si on voit le T de dos (c''est-à-dire si la caméra est au dessus de la lettre T).
En X je ne suis pas d''accord, car tu ne pourras pas te débarraser du "z-fighting" même en découpant les polygones.



Je parles du dernier cas, 2 faces qui s''intersectent en X. Hmm, comment expliquer ça, c''est pas évident... Ça à avoir avec la façon qu''OpenGL rasterise les triangles. Par l''interpolation de la valeur Z sur le triangle, OGL perds tout d''abord de la précision, et puis il n''est pas garanti, qu''un certain pixel reçoit la même valeur z, si les vertex bougent un tout petit peu. Disons, que tu as 2 faces en X, l''une d''entre elles bouge lentement en X ou Y. Regardes l''intersection de plus proche, tu verras qu''il y a une sorte de scintillement dans les pixel qui font l''intersection. C''est un effet comparable à celui créer par les vertex T. Ça doit pas nécessairement être énorme, mais selon les couleurs et le contrast, ça peut être assez génant. Par contre, si tu découpes les faces à l''intersection, cette ligne est mathématiquement précise, elle aura toujours les même valeurs z, même si elle bouge en X ou Y. L''intersection sera toujours claire et sans défauts. Les faces coplanaires sont un cas différent, là il faut le poly offset.

quote:

>or a 64bit zbuffer, as some SGI systems have
Well, of course it may be a little bit better. But it''s just about pushing the limits of the buffer a bit further. It does not really eliminate the problem.



I would say, it practically does eleminate the problem. Keep in mind, that the range of a 64bit buffer is around 1,100,000,000,000 times higher than the range of a 24bit buffer... means that instead of have two values mapping over the range of one single z unit in your 24 bit buffer, they map to a range of over 1 trillion units in the 64 bit buffer... That should *really* be enough

This topic is closed to new replies.

Advertisement