티스토리 뷰

















Software Rendering School, Part II: Projection
 
 


30/11/2003






Legality Info


The tutorials in this series as well as the source that comes with them are intellectual property of Mihail Ivanchev and Hans T?rnqvist. You may not claim that they are your property, nor copy, redistribute, sell, or anything of the nature, the tutorials without permission from the authors. All other articles, documents, materials, etc. are property of their respective owners. Please read the legality info shipping with them before attempting to do anything with them!

Projection


Hi again! Back for some more software rendering huh? Very well! This time we will talk about projection and you will also see some sample source. We won’t waste time and space so let’s move on...

Projection in itself isn’t a very hard concept, which we will show eventually. But, after this tutorial is through with everything it’s supposed to cover, there will be some unanswered questions. The reason is that the solutions to the problems are tricky and should be taught when the general projection-procedure is fully understood. Don’t worry, we will cover the problems in this text and, even better, we will release a tutorial later on to solve the problems.

Now, let’s get back to the point.

Projection is usually a method which converts 3D coordinates to 2D screen coordinates. We will cover two methods in this tutorial, and to make things simple, we’ll start with the most basic projection method known to the human kind ? the parallel projection.

Parallel projection, which is also known as orthographic projection, simply converts the 3D coordinates to 2D coordinates by completely ignoring the Z-coordinate (the depth value). This results in the effect that each vertex will be mapped to the screen exactly as it appeared in the 3D world, dead on. The drawback with this methods is that we see things flat and equally sized, no matter how far away objects are. We need to see the stuff in perspective as our eyes does. However, keep in mind that this projection technique is perfectly suitable for some cases, like for example the viewports in a 3D modelling program. Here is a little sample image of how the parallel projection works:


The next question is of course how to use the parallel projection to project points. Well here is some code:
	x’ = x + viewportWidth/2
y’ = -y + viewportHeight/2
z’ = 0

where x’, y’, z’ are the coordinates of the screen point and x, y, z are the coordinates of the 3D point.

We add half of the sizes of the viewport because we would like the origin of the 3D world to be in the middle of the screen. The origin of the screen is in the upper-left corner, however. That’s why we shift the coordinates a little to center them on the screen.

It’s pretty easy to transform the point by multiplication with a matrix and here’s the projection matrix for the parallel projection:
           | 1 0 0 w |
matProj = | 0 1 0 h |
| 0 0 0 0 |
| 0 0 0 1 |

where w = viewportWidth/2 and h = viewportHeight/2. Multiply a 3D point by this matrix to get the screen point.

Now let’s move to something more useful and better looking ? the perspective projection! The perspective projection is just about everything we need in order to start doing cool looking 3D graphics. To get things going, here’s another image for you to look at:


The further away an object is, the more it shrinks on the screen. The reason is that light-rays converge into our eyes.

Objects emit or reflect light and the rays can go in almost any direction. Now, only a part of this light reaches our eyes and these rays go from all points of the objects towards a point in our eyes. Therefore, the rays converge into a point, making distant objects smaller visually than close objects, because then the rays have converged a lot when they reach our eyes.

Compare the sphere and the cube in the above image to see this effect. So, how do we perform this converging? This is a simple matter. Which is best solved with another image:


where:

v = 3D point
v’ = projection screen point
y, z = Y- and Z-coordinates from v
y’ = Y-coordinate from v’
d = distance to projection plane
α = Field of View (FOV)

The projection plane could be thought of as the screen, where all 3D points are projected onto. We want to solve y’, the Y-coordinate for the screen. If you look closely, you can see that there are two similar triangles: eye-v-Zaxis and eye-v’-Zaxis. This gives us:
     y’    z’    d
--- = --- = ---
y z z

The distance to the projection plane is the same as the Z-distance for the projection plane. Solving for y’ gives:
    y’ = d * y / z

And that’s it! Do the same for X and you got your 2D screen coordinates.

One thing remaining, what is d? For this, we need to make use of some trigonometry. First of all, we assume the projection plane is going from -1..1 in X and Y (making it 2x2):
             1
tan α = ---
d

1
d = ------- = cot α
tan α

And we got d. One thing to take care of is the aspect ratio of the screen. To make sure things get projected correctly for rectangular projection planes, you must scale the d for the X-projection by the aspect ratio. Usually, d for the Y-projection is kept as the source. Remember also, that our projection plane’s dimensions ranged from -1 to 1. In order to make that fit our screen, or viewport, we get:
    d = cot α
dx = (d / (width / height) + 1) * viewportWidth/2
dy = (d + 1) * viewportHeight/2

For dx, we scale d by the aspect ratio of the screen. Then we add 1 to create the range 0..2. At last, we multiply by half of the viewport width to get correct pixel coordinates. Pretty much the same for dy, except there is no aspect ratio correction.

It’s quite some math involved, we admit that. But we give you a thorough walk through the concept of perspective projection, something that will come in handy later on.

Now after we’ve seen the good sides, let’s see the bad too. First of all, you MUST make sure that the Z-coordinate of the vertices will NEVER be 0 because the perspective projection will cause a division by zero. There are methods to avoid that though, one of them is to add some kind of offset to the z coordinate of the vertices (like 0.001 or 0.0001) before projecting. Although simple this method is not very correct or robust. The best way is to set a near clipping plane just in front of the projection plane and clip the vertices against it. Clipping will be discussed in another tutorial but we wanted to tell you that there are solutions. When we clip against some plane we make sure that everything behind the plane will not be considered for further processing.

Another related, very serious problem is that when the Z-coordinates get negative the X- and Y-coordinates get flipped. To avoid this problem one can use the same trick as for the z equal to 0 problem ? to use a near clipping plane.

Well that’s it about projection really. It’s enough to start creating some neat graphics.

This tutorial also comes with sample commented source in which you can check the stuff that you don’t understand and to see how projection is implemented practically.

Next time, we will talk about geometry in 3D and triangle rasterizing. 'Till then, cya!

Download source code for this article

원본 사이트 : http://www.devmaster.net/articles/software-rendering/part2.php