Why Clip Transformed Vertices in Clip-Space?

As a noob in rendering pipelines and computer graphics in general, something that was very puzzling to me and I’d just accepted as-is without truly grasping was that in a 3D rendering pipeline, the operation of clipping transformed vertices takes place in another space, oddly named “clip-space” before perspective division is done. Why the hell?!

As you may know, GPUs invoke a user-defined program, called vertex shader for each vertex of a given primitive so that the primitive will be transformed from whatever space they were defined or modeled in to the clip-space. The result of this invocation will be a 4-elemetn vector in homogeneous coordinates that is used during the clip test such that only those primitives (more like their vertices but anyways) that survive the clip test are passed down the pipeline and the rest are clipped, i.e. removed from the pipeline. The reason GPUs do clipping is not only to increase performance and b/w by clipping primitives that’d have been otherwise a waste of compute because they would be out of viewport but also to guarantee that rasterizers, poor guys having to deal with lots of corner cases already, work within a well-defined distance away from eye/camera/viewpoint via the inclusion of viewport and not deal with arbitrarily positioned vertices (think of numerical precision). That is the clipping operation in a nutshell, however it might not be immediately obvious to you, as it was not to me why we invent yet another confusing space only to apply clipping.

If you think about it, there are 3 candidate locations in the whole 3D pipeline where we could handle the clipping:

  1. Before perspective/orthographic/what-have-you projection using the planes of view frustumfrust
  2. In 4D clip-space before perspective division4d.PNG
  3. In 3D space after perspective division, i.e. working in NDCgl_projectionmatrix01.png

The first doesn’t seem so suitable to me as the calculations would be tied to the way camera (Is it perspective? Is it orthographic?) in a 3D application will be modeled, how about you?

The second, hmm let’s set it aside for a second.

The third looks like a good candidate; we are already done with projecting vertices and dividing by w to give the good old feeling of three-dimensional perspective and able to work within view-volume cuboid handling all degenerate cases like NaNs/Infs nice and easy. Let’s see what happens to the vertices behind the eye/camera/viewpoint:


What is going on in this picture is, the point behind origin, Q2 with a negative w value, when simply transformed via vertex shader to projection-space first and then perspective-divided, projects to a point in front of viewer as if it was visible, which is wrong. What we want is: determine such points with negative w values before applying perspective-division because unless we do something to restore the fact that this point had w=w<0 value and was behind camera, we will lose this information as after perspective division, it’ll have been projected to a point in front of the eye.

Besides the fact that it simplifies the math to do inside/outside tests for clip-planes a lot to apply clipping in 4D clip-space, it also helps us clip primitives behind the camera rather easily. And if you think that it’s rather a rare case when vertices happen to be behind a camera in a 3D application, think again!

Now, even though what’s actually done in a GPU HW can be waaaay different than what’s outlined here in terms of actual computations or implementations, it’s not that far from the truth and what you’d see in the wild.

Please note that I tried and over-simplified a lot such as what happens to partially visible primitives? or guardband-clipping or does HW really check intersection with each half-plane? Really?! for the sake of clarity; maybe these will be get to be an excuse for me to dust off my writing.

Musings on Raytracing vs Rasterisation

Intend: While working on a simple raytracer project , I got to think about the pros and cons of current rendering techniques, namely rasterisation and raytracing so wanted to write down a few points as a reminder for future me.

Although most of my current knowledge on 3D graphics is based on rasterisation algorithms, I did learn about raytracing before for sure yet never come to implement it from scratch. I have to say, it’s a pure joy as I have a background on math (graduated from mathematical engineering) and aytracing is all about tracing the natural steps of light-matter interaction.

So what’s raytracing anyways? Simply put, it’s the process of rendering objects in 3D by shooting rays from a virtual camera towards the scene and coming up with a color value for the current pixel, given the material properties of the object that this very pixel is a part of. What kind of material properties for example? you may ask. It can be the type of material such as glass, water, sand or reflectivitiy and transparency coefficients. Due to its nature, features that are hard or costy to implement with current real-time rendering techniques such as soft shadows, global illumination etc. are inherently easier with it. The main benefit of raytracing comes from the fact that it holds the overall scene data within every cell, which is also the reason why it’s waaaay too slower compared to rasterisation.

So if raytracing is so nice but a bit slower, can’t we just use it with faster computers soon for mind-blowingly beautiful real-time rendering? The thing is, eventhough there exist dozen spatial acceleration structures and optimizations for better data coherency, it’s still nowhere near the rasterisation on speed. The reason being is what makes raytraced scenes look so natural and beautiful, scene structure. Rasterisation simply works with primitives such as triangles at its deepest and requires just a little bit information on current pixel to shade it. We can currently render millions of vertices on 60 FPS on an average PC GPU whereas raytracing can take as many time as days or even weeks with multi-pc and threading setup!

I think smart rendering people of the past made quite a choice going (read: forcedly going) with rasterisation instead of raytracing eventhough it is sometimes absurd how cheap approximations are made to compensate performance to implement a much-natural feature in raytracing. Given that there is nowadays some steps taken towards special raytracing-based hardware, my hopes are high for that in a mid-term we can see a simple game with amazing content on PCs.