getting rid of near and far clipping planes

Started by
7 comments, last by Scoob Droolins 8 years, 7 months ago

The near and far planes operation makes the depth resolution poop.

I want every object in front and in the field of view of the camera to be rendered doesn't matter the distance, until its so small it can't be seen but still rendered.

In the vertex shader after the Projection multiplication I have tried this:


float4 r = mul(Pos, Projection);

r.xy /= abs(Pos.z);
r.z = Pos.z*MAX_DEPTH;
r.w = 1.0f;
if(Pos.z<0.0f)
{
    r.w = -1.0f;
}

return r;
MAX_DEPTH is (1.0f/16777216.0f) so that any float distance gets rendered...16777216 = 2^24
but it still doesn't works, well the mesh is rendered correctly but when the camera is near and you read the depth and positions pixels across the mesh they are off and this off thing increases as the pixels gets near the camera
I want to know what is happening to SV_POSITION after it leaves the vertex shader?
I know that "xyz" get divided by the abs() of "w"
what other operations happen in that part were it gets divided by "w"?
if someone has already a way to render the way I want can you share it too?
Advertisement

Why aren't you just setting up your projection matrix using the Maximum Depth Value?

If you play arround with the forumla i think it should even be possible setting near plane to zero and far plane to infinity

The near and far planes operation makes the depth resolution poop.
I want every object in front and in the field of view of the camera to be rendered doesn't matter the distance, until its so small it can't be seen but still rendered.

with or without the depth buffer?
if with depth buffer, how would you want to map 0 to infinity into the depth buffer? there must be some kind of range you want, because you have just 32bit (usually).

In the vertex shader after the Projection multiplication I have tried this:


float4 r = mul(Pos, Projection);

r.xy /= abs(Pos.z);
r.z = Pos.z*MAX_DEPTH;
r.w = 1.0f;
if(Pos.z<0.0f)
{
    r.w = -1.0f;
}

return r;

MAX_DEPTH is (1.0f/16777216.0f) so that any float distance gets rendered...16777216 = 2^24

but it still doesn't works, well the mesh is rendered correctly but when the camera is near and you read the depth and positions pixels across the mesh they are off and this off thing increases as the pixels gets near the camera

I want to know what is happening to SV_POSITION after it leaves the vertex shader?
I know that "xyz" get divided by the abs() of "w"


no, that's not correct. xyz is divided by w (without the abs). that is actually the whole problem and why you need a near plane. you cannot divide by w<=0, it breaks the spaces. even with your abs, some w will be 0, so you divide by 0, what place on the screen should xy/0 be?
that's why you define a near plane. the near plane is not just a distance from the view origin, it is actually the distance to a little rect in the world that you draw on.

what other operations happen in that part were it gets divided by "w"?

after the vertex shader, the triangles get clipped (cut), so that z is always >= 0., because then w is always >0, then the division is made.

if someone has already a way to render the way I want can you share it too?


first, describe why you want that. what is the problem you want to solve? maybe your solution attempt is not the right one and we have a better way.

if you want a custom depth, you can have that, the pixel shader allows you to write your own depth values.
if you want infinite far view distances, you can maybe use an infinite projection matrix (check out: http://www.terathon.com/gdc07_lengyel.pdf )
if you want objects as close as 0 (and behind), then this is mathematically not really possible with projected rasterization. you can use ray tracing that can start at 0 (and even pick objects from behind), but that might not result in what you expect.

1) The near and far planes operation makes the depth resolution poop.
2) I want every object in front and in the field of view of the camera to be rendered doesn't matter the distance, until its so small it can't be seen but still rendered.

I can't help much with 2, but what would happen when walking through a wall that is larger than the camera? At some point it would have to pass through the image plane, and would get larger as you got closer, not smaller.
To implement a custom depth scheme, you can write to SV_DEPTH in the pixel shader, but there's a perf impact.

To fix #1 in D3D use a 32FLOAT depth format, swap the near/far params when building your projection matrix (so that "far" is small and "near" is large), and swap the depth test (e.g. LEQUAL TO GEQUAL).
That's the simplest way to achieve near-linear depth precision. It works by balancing out the projection matrix's hyperbolic curve (flipped back to front thanks to the inside-out proj mateix) against floating-point's logarithmic curve, giving an appropriately linear depth distribution. That's been the recommended solution to z-fighting issues since about 2005.

My final optimized solution which has a near clipping plane and an infinite far plane:

Only 2 variables of the Projection matrix are needed, the ones that modify Pos.xy so we don't need to pass the whole 16 floats of the matrix to the shaders.

Lets call these 2 variables ProjecXY

Now in the vertex shader instead of doing this:


Pos = mul(Pos, Projection);

do this:


Pos.xy*= ProjecXY;
Pos.w  = Pos.z;
Pos.z  = NEAR_PLANE; //NEAR_PLANE = 0.5f

and finally reverse the depth test instead of passing if smaller, pass when greater

Why do you need depth testing enabled at all in this case?

i use multi-pass rendering with different clip planes for each pass. this gives me a nice high rez zbuf (well, multiple ones actually - one for each pass) to avoid z fighting, a near plane distance as low as 0.1 units for the near pass (could be almost any positive value), and an arbitrarily distant far plane for the far pass. the performance hit for resetting clip planes and clearing zbuf between passes is negligible.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Here the matrix4x4 to hack an infinite perspective projection :


1.0f / tan(HalfFOV),                          0.0f,  0.0f, 0.0f
               0.0f, Width / tan(HalfFOV) / Height,  0.0f, 0.0f
               0.0f,                          0.0f,  1.0f, 1.0f
               0.0f,                          0.0f, -MinZ, 0.0f

The hack to have an infinite far plane is to modify projection matrix so that viewport-space z is always 1.0f for points on the far plane.

If you''re on DX11, you can just set DepthClipEnable = false in the D3D11_RASTERIZER_DESC structure when creating a rasterizer state. According to the docs, this causes the rasterizer to skip the 0 <= z <= w clip check, actually it just skips the z <= w part, but clips close geometry right at 0. This is a much neater solution than messing with proj matrix especially if you are using pre-defined rasterizer states.

This topic is closed to new replies.

Advertisement