I'm rolling my own 3D engine, in JavaScript, and using only canvas drawing, no WebGL. This is another Minecraft clone; I love boxes, don't judge me.

So far, everything works wonderfully, except for one thing: in 3D, when some vertices go behind the near clipping plane, their projection on the screen comes out weird (assuming other vertices used to trace a plane are in front).

I tried clipping these points but then I can see trough the surfaces that use these vertices. In WebGL/OpenGL the graphics card takes care of these points and the plane is rendered correctly, but I don't have access to hardware so I must code this myself.

I'm not quite sure what to make of it, currently the last thing that came to mind is to reverse the projection of points behind the player's near clipping plane, which seems logical since I must project a point to a screen which is in front of the vertex.

Here are my thoughts:

enter image description here

Here are some images to illustrate what happens:

enter image description here

From distance the blue box renders perfectly well.

enter image description here

When some of the vertices go behind the player's near clipping plane I do reverse projection, but it doesn't look right:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Note that the gray box behind is completely removed since all the vertices used to draw its faces are behind the player.

enter image description here

This is what happens when look up or down.

I don't know what to make of the math behind this, I'm hoping somebody has encountered the same problem already and can help me.

  • 1
    \$\begingroup\$ If the points are closer to the eye than the near clip plane, they should be clipped -- and this might indeed let you see "through" an object. This is the typical behavior; collision normally prevents that particular visual artifact. Was that the only thing wrong with your clipping solution? \$\endgroup\$ – Josh Jan 12 '12 at 16:02
  • \$\begingroup\$ @JoshPetrie: I understand that the points must be clipped, but if I do that the whole square will disappear as one or two of the vertices by which the drawing routine must pass are missing (in 2d) and the player would be able to see through that square. I'd like them to be "outside" of the canvas (on the projection) so that the square could still be drawn. I'm not sure if I'm clear enough. \$\endgroup\$ – Solenoid Jan 12 '12 at 16:12
  • \$\begingroup\$ You are -- I'm saying that is normal behavior and you want to prevent this from happening by preventing the player from getting that close to one of the cubes. If you really wanted to do this you should clip but reconstruct the triangles (possibly). This will still look unusual, especially if you have textures. If what I'm saying doesn't make sense, you can join us in the chat so we don't create a really chatty comment thread. \$\endgroup\$ – Josh Jan 12 '12 at 16:17
  • \$\begingroup\$ What you're saying makes sense, reconstructing takes too much time so that's not the solution. I hoped there was a way to still draw that vertex on the 2d plane that was behind the player so the lineTo(x,y) function could still be called, only I don't know how it behaves... it's a bizarre dimension, I agree. \$\endgroup\$ – Solenoid Jan 12 '12 at 16:43

The purpose of the near clipping plane is that it is a clipping plane. Triangles that are outside of a clipping plane are clipped: cut into pieces so that each piece that is left is within the clipping region.

You can attempt to ignore the near clip if you wish. Indeed OpenGL and D3D have ways of turning off near plane clipping altogether (though the depth buffer still has a minimum near value). The problem is not the near clip.

The problem is with vertices that are behind the camera.

You cannot render triangles that are behind the camera. Not with a perspective projection. Such triangles do not make sense under the math behind perspective projections. Furthermore, they are also outside of the frustum.

Turning off near clipping turns a frustum into a pyramid. The reason the pyramid stops at the point is because points above the pyramid are behind all four of the sides of the pyramid. So any point behind the camera (the tip of the pyramid) is above, below, to the left, and to the right of the visible region of the screen. All at the same time.

As I said: vertices under a perspective projection that are behind the camera don't make sense.

You must implement clipping. You must detect when any vertex of a triangle, in clip-space (before the perspective divide) is behind the camera. If it is, then you must clip that triangle, generating only triangles that are in front of the camera.

This is not a simple process. It will involve math that only makes sense if you have a full understanding of homogenous coordinate systems. Alternatively, you could just straight-up cull any triangle if any vertex of it is behind the camera.

  • \$\begingroup\$ Up until now I did cull the entire triangle, but then I saw through the plane (see pictures above). I really needed a picture to understand why it doesn't make sense geometrically. The only solution is to calculate the plane-line intersection when one of the vertices is behind the clipping plane and use that intersection to trace the line from the vertex that is in front, unfortunately this is expensive. \$\endgroup\$ – Solenoid Jan 14 '12 at 16:02

If part of the triangle in behind the near plane could you then do a per-pixel check to see if the pixel position is behind the clipping plane?

You might treat the near plane like any other clipping plane. For example clipping planes are used for things like water planes (for reflections and refractions). I would think that this clipping plane would work just like the near clipping plane, and clip on a per-pixel basis.

I know how to handle clipping planes in HLSL with DirectX, but their implementation could be proprietary. If you could get a hold of the info for that it might be helpful.

Additionally here is a link that might help you: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html

  • \$\begingroup\$ Per pixel testing is extremely expensive in an interpreted language like Javascript, I'm getting barely acceptable fps now as it is. \$\endgroup\$ – Solenoid Jan 14 '12 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.