PDA

View Full Version : Depth testing of points



eldritch
06-03-2010, 02:41 PM
Hi,

I have this small problem where I need to render some "light points" on an object. They are not actual light sources, just points that represent lights, for example lanterns on a boat or plane, runway lights, etc.

I can render these points either as textured billboard quads, point sprites, or simply with GL_POINTS with a suitable size and attenuation factor.

Now, the problem is that when such a point is placed close to another object, it is clipped due to the depth test, and I don't want that, I want to always render the whole point if it is visible at all.

For example a runway light placed close to the ground will only show the upper half of the light point since the lower half will be underground.

What I would need is a way to say that if one point has passed the depth test, the whole object should pass.

Is there any way to do that? Or any other ideas that might work?

Cheers

DmitryM
06-03-2010, 05:16 PM
Sure, you can just do the depth testing in vertex shader by hands.

Alfonse Reinheart
06-03-2010, 05:52 PM
The most you can do to get the effect you want is to use occlusion queries and conditional rendering. And depending on how many of these you need to draw, that may not be particularly fast.

Also, I'm not sure you fully understand what this is going to look like if you did get it to work. If any fragment of the object is visible, you'll see the whole thing, regardless of how close other objects are or how much of the object is covered.

I can't imagine this looking right if you could get it to work.


Sure, you can just do the depth testing in vertex shader by hands.

That's not actually possible. The vertex shader can't read from the depth buffer unless you have bound it as a texture (in which case, you cannot write to it). Also, the vertex shader has no control over what fragments are actually rasterized.

Jan
06-03-2010, 06:35 PM
Sounds a lot like he wants to do coronas:

Take a look at the "Soft coronas" demo:
http://www.humus.name/index.php?page=3D&&start=48

It explains how to use occlusion queries to achieve your desired effect. It's what Alfonse meant.

Jan.

Ilian Dinev
06-03-2010, 06:55 PM
It's been used in games, via occlusion-queries. (thus for few lamp-objects)
The depth-test in a vtxshader is the correct way to go for many many lamps, imho. Each vertex of the billboard quad will do the same check (if you can't use geom. shaders) and reset its gl_position to a fixed value (i.e vec4(0,0,0,1) if the center-point is outside of frustum behind zbuffer (to generate degenerate triangles).



//-----[ attributes, constant for the 4 vertices ]-----------------[
in vec4 inPos; // center-position of lamp
in float inLampRadius;
//-----------------------------------------------------------------/

//----[ attributes, different for each of the 4 vtces ]-------[
in vec2 inCorner; // = vec2(1,1) or vec2(0,1) or vec2(0,0) or vec2(1,0)
//------------------------------------------------------------/


out vec2 varTexCoord0;




uniform mat4 u_MVP; // modelviewprojection

uniform vec4 u_FrustumPlanes[6];


uniform sampler2D texDepthBuffer;

void main(){
bool isInFrustum=true;

//-------[ check if in frustum ]---------[
for(int i=0;i<6;i++){
if(dot(u_FrustumPlanes[i],inPos) < -inLampRadius){ // verify this yourself, I'm typing by memory...
isInFrustum=false;
}
}
//---------------------------------------/
if(!isInFrustum){
gl_Position = vec4(0,0,0,1);
return;
}


vec4 pos = u_MVP * inPos;


//-----------[ zbuffer check ]---------------------[
vec3 texPos;
texPos.xyz = (pos.xyz/pos.w)*0.5+0.5; // in [0;1] screenspace

float depthFromZBuffer = texture2D(texDepthBuffer,texPos.xy).x;

if(depthFromZBuffer< texPos.z){ // behind zbuffer
gl_Position = vec4(0,0,0,1);
return;
}
//-------------------------------------------------/


//-----[ yay, visible, so construct position and texcoord ]-------------------------[
gl_Position = pos + vec4(inCorner,0,0); // construct different corner position


varTexCoord0 = inCorner*0.5+0.5; // construct [0;1] texcooord
//----------------------------------------------------------------------------------/
}


Of course, don't forget to disable depth-writes if you're drawing to the same single-sampled FBO; or use a resolved depth-tex from the multisampled FBO.

P.S Also disable depth-test, to achieve precisely what you wanted.

eldritch
06-04-2010, 01:27 AM
Hi folks,

The corona example was exactly what I was looking for, thank you so much!

I just implemented it now with ARB_occlusion_query and it works brilliantly :-)

The ARB_occlusion_query should be available in core after OpenGL 1.5, right?

Cheers

DmitryM
06-04-2010, 06:21 AM
That's not actually possible. The vertex shader can't read from the depth buffer unless you have bound it as a texture (in which case, you cannot write to it).

Assuming you render point sprites (as light source contributions), you don't need the depth write enabled. So it's pretty possible.



Also, the vertex shader has no control over what fragments are actually rasterized.

The question was about culling a complete sprite rather than it's fragments (other way, this would be solved with a regular depth check).

When a check over the depth texture is performed, you can discard the complete sprite by using ClipDistance or simply by setting the glPointSize=0.0