• Create Account

Banner advertising on our site currently available from just \$5!

# Compute best zNear and zFar for a specific scene

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

2 replies to this topic

### #1polar01  Members   -  Reputation: 114

Like
0Likes
Like

Posted 10 May 2012 - 10:49 AM

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
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
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);


--------------------------------------------------------------------------------Aurora Studio - PureLight - Animation & rendering software and API.http://www.polarlights.net

### #2Yours3!f  Members   -  Reputation: 1425

Like
0Likes
Like

Posted 10 May 2012 - 01:36 PM

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.

### #3mhagain  Crossbones+   -  Reputation: 9652

Like
0Likes
Like

Posted 10 May 2012 - 03:32 PM

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, 10 May 2012 - 03:33 PM.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS