Normalized Device Coordinates

Cameras | Sunday 5 October 2008 3:04 am

After projection to clip space the points will no longer be normalized. This can be restored by dividing all components of the vertex by the fourth component (w). This will (together with the projection transformation) result in that the projection volume will map to a cube with minimum corner in (-1,-1,-1) and maximum corner in (1,1,1). For example in OpenGL, the near clip plane will map to -1 ( in DirectX it will be mapped to 0) and the far clip plane will map to 1.

The division by w (homogenization) is performed automatically between the vertex shader and the fragment shader in the procedure called Rasterization.

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks

Clip Space

Cameras | Sunday 5 October 2008 2:53 am

Before rendering something all objects need to be projected to the screen ( a plane ). The first step, to project to the screen, is to project entities to clip space.

The mostly used projection type in games is perspective projection and therefore only this kind of projection will be explained. An other type of projection is parallel projection which is a projection that will keep parallel lines parallel. Perspective projection gives a field of view and objects appears to be smaller when further away which will feel realistic. The projection volume is set up as the following image shows.

The Projection Volume

You apply a projection to the entities that is in eye space to get them to clip space. This is the space that will soon decide if the vertex will be culled or not. Together with homogenization it can be thougt as a mapping from the projection volume to a cube with sizes 2 (in OpenGL) and with origin at 0,0,0. This mapping is showed in the image below.

Projection volume mapped to a cube

In OpenGL you can access the projection matrix if you set the matrix mode to projection:

glMatrixMode(GL_PROJECTION);

The following vertex shaders shows some ways to transform a vertex to clip space. The fastest way is the third shader that uses the highly optimized ftransform() function.

void main()
{
    // vertex in clip space
    gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
}
void main()
{
    // vertex in clip space
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
void main()
{
    // vertex in clip space
    gl_Position = ftransform();
}

One side effect from applying perspective projection is that you end up with a non-linear z-buffer. The buffer will be more detailed closer to the screen which is often good. More about this in the z-buffer article.

After applying projection to a point p = (x,y,z,w) you will end up with a w value that is most probably not zero or one. This means you need to divide all components by this value to obtain normalized device coordinates. This will happen automatically between the vertex shader and fragment shader. Clipping will also be performed between these.

Information about different ways to transform vertices to clip space inside of a vertex shader:
http://www.lighthouse3d.com/opengl/glsl/index.php?minimal

Description of different 3D spaces:
http://vesta.astro.amu.edu.pl/Library/Linux/LinFocus/May1998/article6.html

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks

Eye Space

Cameras | Sunday 5 October 2008 1:56 am

Eye Space or often called View Space or Camera Space is the space where the camera is located in origin (0,0,0) and all objects are transformed accordingly. More specifically the camera (in OpenGL) is located in origin, looking down the negative z-axis and has the x-axis pointing to the right and the y-axis pointing up. This mean that objects further away from the camera (when looking at them) has lower z-value. In OpenGL the ModelView determines how the objects should be transformed to be end up in eye space.

A vertex can be transformed to eye space with the following vertex shader (GLSL):

void main(void)
{
   vec4 eyeSpaceVertex = gl_ModelViewMatrix * gl_Vertex;
   // now do what you want with it
}

A normal can be transformed to eye space with the following vertex shader (GLSL):

void main(void)
{
   vec3 eyeSpaceNormal = normalize(gl_NormalMatrix * gl_Normal);
   // now do what you want with it
} 

The gl_NormalMatrix can also be used to transform tangents and binormals to eye space.

void main(void)
{
   vec3 eyeSpaceNormal = normalize(gl_NormalMatrix * gl_Normal);
   vec3 eyeSpaceTangent = normalize(gl_NormalMatrix * Tangent);
   vec3 eyeSpaceBinormal = normalize(gl_NormalMatrix * Binormal);
   // now do what you want with it
} 

Note that neither of these shaders are complete because they don’t write anything to gl_Position.

Lights are passed to the shader in eye space as default and most lightning calculations take place in eye space.

Description of different 3D spaces:
http://vesta.astro.amu.edu.pl/Library/Linux/LinFocus/May1998/article6.html

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks

Linear depth texture

Rendering Methods | Sunday 28 September 2008 11:06 pm

In some occasions a linear depth texture is preferred over the usual non-linear depth buffer (z-buffer). The linearized depth could for example be used when doing SSAO or depth of field. Rendering linear z-buffers is very easy and only the following lines of code is required ( a float texture should be set as render target):

Vertex shader:

varying float depth;
void main()
{
    vec4 viewPos = gl_ModelViewMatrix * gl_Vertex; // this will transform the vertex into eyespace
    depth = -viewPos.z; // minus because in OpenGL we are looking in the negative z-direction
    gl_Position = ftransform();
}

Fragment shader:

varying float depth;
void main()
{
    gl_FragColor.r = depth;
}

 
You might want to scale the depth in the vertex shader to a more appropriate range as the the distance will otherwise be the same as the distance from the camera to the vertex. The following vertex shader will map the near and far distances to 0..1 which is often a good idea.

varying float depth;
void main()
{
    vec4 viewPos = gl_ModelViewMatrix * gl_Vertex; // this will transform the vertex into eyespace
    depth = (-viewPos.z-near)/(far-near); // will map near..far to 0..1
    gl_Position = ftransform();
}

Here’s how the shader looks like if you render a cube.

Linear Depth Rendering of a Cube

Link to a page about the depth buffer in DirectX
http://www.mvps.org/directx/articles/linear_z/linearz.htm

A good introduction to the depth buffer in OpenGL
http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks
« Previous PageNext Page »