First-person terrain navigation frustum clipping problem

Started by
24 comments, last by JoeJ 1 year, 3 months ago

I am trying to develop first-person terrain navigation. I am able to read a terrain and render it as well as to move around the terrain by interpolating the location of the camera every time I move around. The main problem I have is that depending on the terrain, i.e. moving on a sloping terrain, the near plane clips my view (see below). What is the best way to avoid this? Presumably, I can interpolate the heights for the bottom corners of the near plane … any help would be appreciated.

enter image description here

Advertisement

I believe this can aways be an issue. I mean if you are clipping to a near plane and that plane passes through geometry, it has to do something. That being said you technically don't have to clip to a near plane at all, however many graphics APIs require it.

Another other thing to consider is once you have collision working, you can put your camera, including your near clipping plane inside a collidable object, for instance a sphere, such that this problem will never occur. If you are eventually going to make this a real first-person game, that should take care of the problem since your camera will be inside the players head. Even in a 3rd person game you can put them inside a floating sphere.

Gnollrunner said:
That being said you technically don't have to clip to a near plane at all, however many graphics APIs require it.

The near clip plane is always needed, even if you use a software rasterizer. If you don't do the clipping, vertices would flip behind the camera, causing glitches way worse than what we get from clipping.

mllobera said:
What is the best way to avoid this? Presumably, I can interpolate the heights for the bottom corners of the near plane … any help would be appreciated.

Yes, basically you want to ensure that the camera is in empty space (above the hightmap), not in solid space (below the heightmap).

But in general you can not treat the camera as a simple point, because the front clip plane requires a distance larger than zero. So ideally you build a sphere around the camera which bounds the front clip rectangle of the frustum, and then you make sure the sphere is entirely in empty space, for example.
In the specific case of your terrain not having too steep slopes however, it should work well enough to sample height below camera, add some ‘character height’, and place the camera there. That's pretty simple and usually good enough for terrain.

It's quite a difficult problem mainly for 3rd person games in levels made from architecture. It's difficult to project the camera out of solid space in ways so the motion still feels smooth and predictable.
Some games additionally fade out geometry which is too close, attempting to minimize the issue.

Imo, the ‘true’ solution to the problem would be to let the clipping happen, but rendering the interior volume of the geometry as sliced by the clipping plane.
That's pretty hard with modern rendering, which usually lacks a definition of solid or empty space. But it was easy to do in the days of Doom / Quake software rendering.
When i did such engine, it was possible to render clipped solid walls in simple black color. This felt really robust and not glitchy, so while it does not solve all related problems, i wonder why no game ever did this.

@undefined

JoeJ said:

The near clip plane is always needed, even if you use a software rasterizer. If you don't do the clipping, vertices would flip behind the camera, causing glitches way worse than what we get from clipping.

You can clip to a pyramid instead of a frustum. I used to do this many years ago on old hardware. So there is no near clipping plane. In fact you don't need a far clipping plane either.

Edit: Just wanted to add as far as I know the near and far clipping planes mostly have to do with optimizing your Z resolution. If you are dealing with that in other ways, I think they aren't strictly necessary. I currently don't even deal with the far plane and let LOD solve Z-fighting issues.

Gnollrunner said:
You can clip to a pyramid instead of a frustum.

I see. You still have front clip. It is a point, formed indirectly as the intersection of the other other frustum planes.
I've misunderstood your claim to be ‘you don't need a front clip’. But you didn't say say that. Sorry.

But now i'm curious about the experience with z precision you have had. I guess it just worked?
Which then would probably mean: All those painful compromises of ‘make front plane distant so you get acceptable depth precision for large scenes’, are a result of a bad convention being used by APIs?
Or did you use no z-Buffer?

@undefined My whole engine is based on aggressive LOD and culling. I don't do projection in the matrix. It's a post step. My Z coordinates are world distances. My current project does have a near clipping plane mainly because DirectX wants one, but it's not that relevant for my application.

Ah, so you use the pyramid for culling only. But for rasterization, the usual front clip plane at some distance i guess.

Still an interesting question if ‘some distance’ is really needed, but i guess yes.
I did some experiment about point splatting. It uses spherical projection, which is simple than planar projection:

auto WorldToScreen = [&](Vec4 w)
	{
		Vec4 local = camera.inverseWorld * w;
		if (local[2] < .1f) return (Vec3(-1)); // <- front clip at some distance of 0.1
		Vec3 screen = (Vec3&)local;
		screen[2] = length(screen); // if it was zero, i'd get NaN here
		screen[0] = (1 + screen[0] / (screen[2] * camera.fov)) / 2;
		screen[1] = (1 + screen[1] / (screen[2] * camera.fov)) / 2;
		return screen;
	}; 

Planar projection would cause division by zero too, i guess.

Thanks for all your comments! I will need to investigate how to do what Gnollrunner proposed (about putting the camera inside of a sphere).

This may be obvious, but in case it helps:

Let me note that, as a first-person camera may be more likely than a third-person camera to draw very close to geometry, it likely makes some sense to have a smaller near-plane distance for the former than the latter.

Now, this only ameliorates the problem, it doesn't remove it entirely: it means that the problem will still appear, but only if the player gets very close indeed to a surface. It's intended to be used in conjunction with one or another means of preventing the camera from approaching quite so near to a surface (such as the sphere-approach mentioned by others above).

MWAHAHAHAHAHAHA!!!

My Twitter Account: @EbornIan

Thaumaturge said:

This may be obvious, but in case it helps:

Let me note that, as a first-person camera may be more likely than a third-person camera to draw very close to geometry,

I'm not sure that's so true. I mean in both cases you have to take care of the problem somehow. The case of a first-person camera is a bit easier because it should always be in the collision boundary of the player (sphere(s), ellipsoid, capsule etc.). As along as the near plane is also within that boundary, the problem should never occur. So if you have a 10cm radius sphere and put the camera in the back of it, that gives you maybe a 10 to 15 cm camera to near clipping plane distance to play with depending on the field of view you are going for.

With a 3rd person camera, you can also get very close to terrain, in fact your camera can end up within terrain or some object if you don't do anything to solve that problem, and this will happen very often without separate camera collision. One typical way to handle this is just implement your following camera, ignoring terrain considerations. Then to figure out your camera's actual position, project a line back from the head of the avatar to the camera's ostensible position, and see if it intersects anything to get the camera's true position. In reality you should project a cylinder and not a line since your camera will need its own bounding sphere to contain the near clipping plane.

In any case this means that as you move around your camera can jump forward to clear terrain and objects. I've seen this in a few MMOs. However, when you leave blocking terrain you have the option of implementing smooth movement back to the cameras desired location. If you want to get really fancy, I guess you could try to predict when your camera will need to jump forward ahead of time and try to do smooth moment forward too. Maybe you can have a second camera bounding sphere which is somewhat larger, that would trigger smooth movement, but I think you would still need a fallback camera jump routine to be safe.

This topic is closed to new replies.

Advertisement