Jump to content
  • Advertisement
Sign in to follow this  
polar01

OpenGL Compute best zNear and zFar for a specific scene

This topic is 2382 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm currently working on a 3D editor and we can load very very small models or very very big ones...
The problem I have is during display, due to bad zNear and zFar... I got a lot of undesired effects.
I have search the web for a solution, but found nothing....

What I would like is to compute the zNear and zFar to use depending of my scene. By example by looking at the scene bounding box and the camera position & camera target...

I have try the following, but I can't acheive very good results... if someone can help ?


float viewportWidth = (float)surface->GetWidth();
float viewportHeight = (float)surface->GetHeight();
glViewport(0, 0, (GLsizei)viewportWidth, (GLsizei)viewportHeight); // Default
float aspectRatio = viewportWidth / viewportHeight;
//---- Set up the view
glMatrixMode(GL_PROJECTION); // Set up the projection
glLoadIdentity();
if (!camera)
{
gluPerspective(45, aspectRatio, 0.1f, 1000.f);
return;
}

// reference : http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html
// delta = z * z / ( zNear * (1<<N) - z )
//
// Where:
//
// N = number of bits of Z precision
// zNear = distance from eye to near clip plane
// z = distance from the eye to the object
// delta = the smallest resolvable Z separation at this range.
// Also see : http://sightations.wordpress.com/tag/opengl/
//---- Calculate optimal near and far Z clipping planes
float sceneRadius;
sceneRadius = (camera->GetEye() - camera->GetEyeAt()).Length() * 2.f; // Based on the current target BB
// Get buffer properties
GLint mDepthBufferResolution = 16;
glGetIntegerv(GL_DEPTH_BITS, &mDepthBufferResolution);
float zFar = 2.f * sceneRadius + (camera->GetEye() - camera->GetEyeAt()).Length();
if (zFar < 1e-20f)
zFar = 1e-20f;
float zNear;
if (mDepthBufferResolution >= 24)
zNear = 0.00001f * zFar;
else
zNear = 0.01f * zFar;
if (zNear < 1e-20f)
zNear = 1e-20f;
float Zoom = 1.f;
VNFilm* film = surface->GetScene()->GetFilm();
if (film && !film->GetAutoSize())
{
float filmHeight = (float)film->GetHeight();
Zoom = viewportHeight / filmHeight;
}
// Reference : http://www.opengl.org/resources/faq/technical/transformations.htm
float fov = camera->GetFOV() * 0.5f * (M_PI_F/180.f);
float top = tan(fov) * zNear;
float bottom = -top;
float left = aspectRatio * bottom;
float right = aspectRatio * top;
glFrustum(Zoom * left, Zoom * right, Zoom * bottom, Zoom * top, zNear, zFar);

Share this post


Link to post
Share on other sites
Advertisement
well, just to give you an idea, you could make each object in your scene (like a tree, or a ball) have a bounding sphere, which is defined by a center and a radius. This sphere would encapsulate the given object. You could search for the closest sphere, and take its position, lets call it nearest_obj_pos. Lets call the radius nearest_obj_radius.
Lets call your position player_position. Then if you do the math:
vec_to_nearest_obj = nearest_obj_pos - player_position;
length_of_vec_to_nearest_obj = length(vector_to_nearest_obj);
near_plane_distance = length_of_vec_to_nearest_obj - nearest_obj_radius;
you get the distance to the near plane. This would make the near plane optimal, since it wouldn't "cut" into any objects and it would be as far away as it can get. Of course this is just theory, so I'm sure this could be implemented better. You'd also have to pay attention to the ground and other tricky objects. The far distance could be calculated in a similar manner.

Share this post


Link to post
Share on other sites
A zNear of 0.1 probably isn't going to help you much no matter what you set your zFar to (unless it's something stupidly low) as the important thing is the ratio between them, not the difference. You'll probably find that you can get away with a much higher zNear - start at 5 or so, and push it out or pull it in until you get a good value. The likely end result of this is that many of your far plane problems will just go away, and you won't need to worry about it so much.

If your far plane calculation factors in a skybox drawn behind all other geometry, be aware that you can basically just ignore this - draw your skybox as e.g. a 10x10x10 cube centered on the viewpoint and with a depthrange of 1, 1 instead - that will automatically push it to the back of the view for you and allow you to have a lower value of zFar. You might be able to use this trick with other scene objects too (e.g. a planar object that should always be at the front of the view can be drawn with depthrange 0, 0 - or depth test disabled - thus short-circuiting the need to include it in your optimal near plane calculation).

Not a direct answer, I accept, but sometimes the best solution to a problem is one that makes the problem go away (rather than spending time beating on it). Edited by mhagain

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!