Advertisement

Is there a way of figuring if an object is visible or not ?

Started by January 10, 2002 03:33 AM
9 comments, last by rodzilla 23 years, 1 month ago
Hi ! I''m looking for a fast way of knowing if an object is visible in an opengl scene or not. An easy method for me would be : - select a vectex in the object (the one I wanna see) when drawing the object and getting its coordinates on the screen and its depth (after the object has been drawn). - draw the rest of the scene. - query the depth buffer to know if another object hides the vertex I selected. So is it possible to - compute the screen coordinates of a vertex from its coordinates (using the current matrix) ? - query the depth-buffer ? Thanx a lot in advance. Rod.
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
I think what you''re looking for is ''frustum culling''. Run a search for it on this message board and on google.. Its very easy to implement and understand.
Advertisement
Thanx a lot !

But this solves only part of the problem. Now how do I
know if the object will be hidden by another ?

Rod.
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
Depth sorting your objects is a good idea. Look up on occlusion culling to do the rest.

Death of one is a tragedy, death of a million is just a statistic.
If at first you don't succeed, redefine success.
Well, depth sorting "can" be good, but may not in some particular cases, depending on how you implement it.

rodzilla, there are many ways of doing what you want. It depends on what you look for.
Do you need to be ABSOLUTELY sure that the geometry is visible, or do you need to be ALMOST sure (allowing some errors) ?
Do you need to know if the object is visible in the field of view, or do you need to know if the object is drawn in "only" one pixel on screen ?
Do you have transparent objects in your scene ?
Is your scene ordered in a scene graph ?

And, the most important to me, how "fast" do you look for fast ? I mean, do you need to compute that for each frame in a real-time application, or do you need that at one time in a particular (rare) moment ?
To be a bit more precise, what I want is to know if a "light
source" is visible to figure whether I have to draw the
corresponding halo/lens flares.

- I''d like to be *absolutely* sure that the vertex is visible
but almost sure could be enough.
- I wanna know if the object is visible. I don''t care about
how big it is.
- I may have transparent objects in the scene.
- my scene is not ordered in a scene graph yet, but it will
if this is necessary.
- It''s an animated scene, so it should be as fast as
possible.

Thanx a lot !
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
Advertisement
Ok I think I''ve got what you need.
The only problem is, on translucent objects it may yield some weird results. But, heh, on ne se refait pas

You have one or more light source(s), and you''d like to make halos and lens-flares.
So I bet you''ll draw your flares in a 2D post-rendering, won''t you ?

In that case, you can display your scene as usual, and you''ll just have to add an extra work at the end of the 3D rendering, just before the 2D post-rendering.
That extra work is to test if your light source is visible or not !

To test this, I recommend to compute the screen position (in pixels) of where you light source will project (you should be able to do this if you have stored the camera parameters somewhere) and get the current depth fragment at this position. (Make sure the transformation matrix is NOT in the 2D projection yet, or else the depth value may be wrong). This fragment contains the distance to the camera of the nearest object to the camera. In fact, it''s not the distance : it''s the Z value.
Then compute what would be the Z value of the light source if it was projected on screen. It''s possible using the following method :
dot_product( vector_from_the_viewpoint_to_the_light_source, viewpoint_direction ), where you may make sure that the coordinates are in the world coordinates. Note that you have to divide to the viewpoint_direction''s length if its length is not 1.
Then you have the Z value of the nearest object, and the Z value of the light source. Simple depth test (in software) : if the light source is closer, then it is visible, and then you can display your halo, otherwise an object hides the light source and no halo may be drawn.

Known problems :
- if a very tiny object is in front of the light source (just the center), all the halo effect will disappear. Do you need some information of how to correct it ?
- if some translucent objects are between the viewpoint and the light source, the halo will appear either completely or not at all, whereas it should be halfed instead. Do you mind of such artefact, and do you know how to attenuate it ?
vincoof: thanks for the solution. I would be also interested in the last two issues ie. in translucent objects and in tiny objects problem.
My other question is in connection to opengl. Can I get somehow the value of the Z-buffer in a specific coordinate? If yes, How?

Thanks in advance


-- tSG --
-- tSG --
Tiny object:
A merely valuable solution consists of not taking just 1 point in the light source (say, the center).
With the current method, we check 1 vertex : if the vertex is visible, then draw the halo, else don't.
An advanced method would check a few vertices around the light source, which is the basis of Monte-Carlo raytracing : check X vertices, and Y vertices will be "visible", then display the halo blended with the percentage (100*Y/X)%. Note that it's easy to do so by modulating the alpha channel.


Translucency:
There's not very good solutions. The simplest one I can say works if opaque objects are drawn first.
First draw the opaque objects.
Then check the Z value(s) of the light source. If the light source is not visible, then decide to display no halo.
Then draw the translucent objects.
For the light sources that were visible in the latest check, check again the Z. If the light source is still visible, then show 100% of the halo. Else, it means a translucent object is between the light and the viewpoint : show the halo 50% or something like that.
The thing is that it doesn't work if translucent objects don't write into the depth buffer (which is often the case).


Get a Z value :

GLfloat depth; // output value
GLint xpos = ...; // x screen coordinate
GLint ypos = ...; // y screen coordinate
glReadPixels(xpos, ypos, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
// depth contains the depth fragment clamped between 0 (closest) and 1 (farthest)

Note that you may use the wrong y screen coordinate, especially if you are using mouse coordinates. In that case, you may use something like :
glReadPixels(xpos, window_height - ypos, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);

Please take care of this function because glReadPixels is very slow (since OpenGL is optimized for drawing the buffers, not for reading them). In this case, we just pick one value and it's fast enough. Use wisely !

Edited by - vincoof on January 10, 2002 3:41:09 PM
I guess that''s the FULL answer to my question !

Thanx a lot !
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)

This topic is closed to new replies.

Advertisement