Depth Buffer and clicky

Started by
5 comments, last by Black Knight 15 years, 8 months ago
Yea so, I was thinking how to pretty much click on surfaces in the game. After a while, it seemed obvious that I could use the depth buffer. I was thinking convert the depth buffers coordinates using camera fov, pixel location, and depth buffer value, and then know exactly what the player clicks on. Is this the best way to get click coordinates?
Advertisement
I cast a ray to scene which passes through the camera position and the mouse cursor's 3d position(use gluUnProject(OGL) or D3DXVec3Unproject(D3D) to get it)
Then I intersect this line and my scene geometry.To speed things up I do bounding box/bounding sphere collisions with the ray.
For example when checking where the user clicked on the terrain.I first test the bounding boxes of the patches of the terrain.If a bounding box and my ray intersects then I check the individual triangles and find the exact point of intersection.
For entities and object a boundingbox-ray intersection is usually enough.

To correctly find which point on terrain is clicked or which entity is selected I don't just find the first intersection and finish searching.For entities I check all visible ones and return the closest to the camera which intersects the ray.Same goes for the terrain I store the first found intersection in a temp variable and test other intersections to find another one closer to the camera.This works well so far.

[Edited by - Black Knight on July 25, 2008 3:11:28 AM]
As far as I know, you cant read from the depth buffer unless you create your depth buffer with the D3DFMT_D16_LOCKABLE format (See IDirect3DSurface9::LockRect in DirectX 9 SDK). If you however do this, your performance will probably suffer a lot for two reasons.

First, you device can't use its own optimized Hyper-Z like occlusion test to increase rendering of occluded triangles, but needs to use the standard IEEE 2D floating-point array as its Z buffer.

Second, reading back from your depth buffer requires a Lock, which will stall your device. Not good for your performance either.

I don't know how bad it actually is, but to me it sounds like you'd better use a variation of Black Knight's idea.
Hi BlackKnight, thanks for your reply, but I do have a few questions. I was under the impression that the depth buffer holds the exact coordinates of every pixel.
Therefore, wherever you click, those coordinates can be checked against your bounding box, cause you have the x,y,z of the mouse?

I'm assuming that your implementation does not use the depth buffer, which I suppose is a trade-off.
Isn't accessing the depth buffer a must for stencil shadows? So you can't get away with it either way, unless you want to form your own depth buffer?
On another thought, it sounds like the 3d mouse coordinate functions actually do work on the depth buffer, unless it just converts the point at the far clipping plane or something.
Hi VprMatrix89,

Your method would work fine, mathematically. Using your view and perspective matrix, the mouse coordinates and the z-buffer, you can reconstruct the exact 3D coordinates of your mouse (I ones tried it myself). However, BlackKnight doesn't use the depth buffer at all. Thats why he uses a ray. Transforming the 2D mouse without depth information back to 3D results in a ray after all. I think his method is the most common in actual 3D DirectX games, because of performance. The click test just becomes an other LOS test, a very common operation in 3D games.

Quote:
Isn't accessing the depth buffer a must for stencil shadows? So you can't get away with it either way, unless you want to form your own depth buffer?


You do not need to read back your stencil buffer for stencil shadows, or at least, you do not need to do it yourself. When rendering a pixel, your GPU reads back the z-value and stencil value and uses it to render the pixel correctly, depending on the current render states. This, however, all happens on the GPU. The problem with your method is that you lock the buffer and read it back onto your CPU, which causes the device stall. So, reading and writing depth and stencil values is fine, as long as it happens on your GPU only.

Dietepiet
Hi dietpiet, that was a good explanation and answered my questions.
About performance, you are probably correct by my guess. Not really sure, but using the right octree boxes, collision can be speedy. Take for example COD4, hundreds of bullets just flying through walls, ect..
I will need to do ray collision eventually anyways.
The depth buffer does not hold the vertices actual 3d positions.
When you render your scene with the objects and 3d positions everything goes through transformations like world view projection.
The distance of the near plane and far plane also effect the depth values.
The depth of each pixel is written to the depth buffer and its in the range 0-1.
So lets say you have an box at 5.0f,5.0f,5.0f the depth values of this box in the depth buffer will be something between 0-1 depending on your tranformation matrices.

This topic is closed to new replies.

Advertisement