Welcome to Game Rendering!

Uncategorized | Wednesday 24 September 2008 2:03 am

While developing games I’ve been collecting lots of links to useful pages and as they increased in amount I needed some way to organize them. I realized that they might be useful for others too so I decided to create a simple website with the links and other information I’ve collected. I’m currently studying for a Master degree in Software engineering and is especially interested in computer graphics and game rendering. This site is therefore also created as a learning project for me and can therefore contain information that is incorrect somewhere. If you ever find something that’s wrong I would be happy if you informed me by commenting the site. I would also love suggestions about interesting techniques that I’ve missed.

New articles will be posted as often I can, hopefully at least once per week.

/ Robert

Radial Blur Filter

Special Effects | Saturday 20 December 2008 3:43 am

Radial blur is an effect that is often used in racing games and FPS-games. In racing games it can give the feel of speed and in fps games it’s often used when something important has happened, for example the player has been hit by an enemy. Radial blur is one of many blur filters that can be created in a shader
The image below shows to the left the original image and to the right the radial blurred one.

Radial Blur in the right image. The left image is the original.

The effects work like the following. First render the scene normally to a texture, then draw a full-screen quad with the radial blur shader.

The radial blur shader blurs the image in the direction towards the center of the screen. When considering uv-mapping, the center of the screen is the coordinates 0.5,0.5 because the uv-mapping starts with 0,0 and ends with 1,1. When drawing a fragment, we know it’s current uv-mapping coordinates (this can be the black dot in the image below) since it’s passed down by the vertex shader. We can simply create the direction vector by subtracting the current fragments uv-coordinates from the center of the screen coordinates. This vector will have an distance which can be used when blurring so that the image is more blurred the further it’s away from the middle (like the image above). Of course you can also remove this distance check and do a constant radial blur over the whole screen.

Radial Blur

The GLSL vertex shader:

varying vec2  uv;
// this vertex shader is from AMD RenderMonkey
void main(void)
{
   gl_Position = vec4( gl_Vertex.xy, 0.0, 1.0 );
   gl_Position = sign( gl_Position );
   
   // Texture coordinate for screen aligned (in correct range):
   uv = (vec2( gl_Position.x, - gl_Position.y ) + vec2( 1.0 ) ) / vec2( 2.0 );
}

The GLSL fragment shader:

// This texture should hold the image to blur.
// This can perhaps be a previous rendered scene.
uniform sampler2D tex;
 
// texture coordinates passed from the vertex shader
varying vec2 uv;
 
// some const, tweak for best look
const float sampleDist = 1.0;
const float sampleStrength = 2.2; 
 
void main(void)
{
   // some sample positions
   float samples[10] =
   float[](-0.08,-0.05,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.05,0.08);
 
    // 0.5,0.5 is the center of the screen
    // so substracting uv from it will result in
    // a vector pointing to the middle of the screen
    vec2 dir = 0.5 - uv; 
 
    // calculate the distance to the center of the screen
    float dist = sqrt(dir.x*dir.x + dir.y*dir.y); 
 
    // normalize the direction (reuse the distance)
    dir = dir/dist; 
 
    // this is the original colour of this fragment
    // using only this would result in a nonblurred version
    vec4 color = texture2D(tex,uv); 
 
    vec4 sum = color;
 
    // take 10 additional blur samples in the direction towards
    // the center of the screen
    for (int i = 0; i < 10; i++)
    {
      sum += texture2D( tex, uv + dir * samples[i] * sampleDist );
    }
 
    // we have taken eleven samples
    sum *= 1.0/11.0;
 
    // weighten the blur effect with the distance to the
    // center of the screen ( further out is blurred more)
    float t = dist * sampleStrength;
    t = clamp( t ,0.0,1.0); //0 &lt;= t &lt;= 1
 
    //Blend the original color with the averaged pixels
    gl_FragColor = mix( color, sum, t );
} 

This shader is mostly inspired and copied from a CG-shader in Ogre3D.
www.ogre3D.org

Screen Space Blurred Shadow Mapping

Shadow Mapping | Tuesday 25 November 2008 2:44 pm

This is probably the first technique one will think for creating soft shadows when doing shadow mapping.  The shadows are rendered to a texture (in screen space) and this texture is then blurred (in screen space) and later applied to the screen. This is a very easy technique for getting soft shadows. The main drawbacks are shadow bleeding and the cost of the extra passes.

Screen Space Blured Shadow Mapping

An article about it on gamedev.net:
http://www.gamedev.net/reference/articles/article2193.asp

Uniform Grid

Spatial Data Structure | Monday 17 November 2008 10:54 pm

This is maybe the easiest way to manage the objects in a scene and is also often a very good choice. It’s a simple uniform grid with equally sized cells/buckets/patches (or whatever you want to call it). When rendering, all that is needed for culling is to check the view frustum against these cells to determine which ones are visible. This grid can most of the time be in only 2D but can of course in special cases be 3D if necessary. This spatial data structure works well with both static and dynamic objects.

A Uniform Grid
Some information of traversing a grid structure

Cull Levels

Culling | Monday 17 November 2008 10:07 pm

These are the different levels culling algorithms can work on.

Triangle Level

Description: Determine for each triangle if it should be culled or not.
Primary goal: Minimize triangle count.
Culling technique example: BSP 
Usage: Not used anymore, cost to much CPU.

Object Level

Description: Check each object (a group of triangles in one buffer) if they should be culled or not.
Primary goal: Minimize triangle count and keep state changes low.
Culling technique example: View Frustum Culling of Bounding Box Hierarchies
Usage: Often used.

Batch Level

Description: Will check whole batches (a group of objects in one buffer)  if they should be culled or not.
Primary goal: Minimize draw calls and triangle count.
Culling technique example:  Uniform Grid Culling
Usage: Often used.

Basic Triangle

Rendering Methods | Monday 17 November 2008 9:50 pm

The triangle is the basic geometry that is used when rendering. All other shapes of geometry you want to draw must be divided into triangles.

Basic Triangle

The triangle parts:

  1. Face, the triangle itself, the area is what is gonna be rasterized (with normal fill mode at least).
  2. Face normal, the normal to the plane which the triangle is parallell too. It is mostly used for calculating the vertex normal.
  3. Vertex, a triangle has three vertices with x,y,z coordinates, they are located in the triangle corners. All transformations apply to these ones.
  4. Edge, the line between vertices are called edges, a triangle has three edges. Are used for example shadow volumes.
  5. Vertex normal, each vertex has a normal which decides the smoothness of the geometry.

Other data often used per vertex:

  • Tangent and Binormal for per pixel lighting
  • Texture coordinates (uvw-coords), sometimes more than one per vertex

Tutorial to render a triangle in DirectX10
http://msdn.microsoft.com/en-gb/library/bb172486(VS.85).aspx

Tutorial to render a triangle in OpenGL
 http://60hz.csse.uwa.edu.au/workshop/workshop0/workshop1.html

Tutorial to render a triangle in XNA
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/The_first_triangle.php

Tutorial to render a triangle in OpenGL ES 2.0
http://www.webreference.com/programming/opengl_es/

Percentage Closer Filtering for Shadow Mapping

Shadow Mapping | Saturday 15 November 2008 5:08 pm

This is a technique for making softer shadows when doing shadow mapping. It works by filtering the result of the depth comparison. So when comparing a depth, some depths around should also be compared and the result should be averaged. This will give a softer look on the shadow edges.

An example of the the soft shadows when using PCF Shadow Mapping

It can be implemented as simple as this in a the pixel shader:

float result;
result = shadow2DProj(shadowMap,texCoord+offset[0]);
result += shadow2DProj(shadowMap,texCoord+offset[1]);
result += shadow2DProj(shadowMap,texCoord+offset[2]);
result += shadow2DProj(shadowMap,texCoord+offset[3]);
result /= 4.0; // now result will hold the average shading

The samples are often either taken in a grid-based square around the original sample location or randomly scattered around it.

Optimization:

NVIDIA has built in hardware support for doing bilinear interpolation between four samples.

ATI has fetch4 which will fetch four texture samples at the same time.  

The original paper for PCF:
http://graphics.pixar.com/library/ShadowMaps/paper.pdf

A technique that is similar (percentage-closer soft shadows)
http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf

A paper including lot’s of shadow mapping information, including different ways to do PCF (the image in this article is borrowed from this presentation):
http://developer.amd.com/media/gpu_assets/Isidoro-ShadowMapping.pdf

Real-Time Cloud Rendering

Sky | Thursday 13 November 2008 5:24 pm

A very fast technique to render clouds as imposters which are only updated when the viewport has changed enough to make a visible error. Here’s the abstract from the paper:

This paper presents a method for realistic real-time rendering of clouds for flight simulators and games. It describes a cloud illumination algorithm that approximates multiple forward scattering in a preprocess, and first order anisotropic scattering at runtime. Impostors are used to accelerate cloud rendering by exploiting frame-to-frame coherence in an interactive flight simulation. Impostors are particularly well suited to clouds, even in circumstances under which they cannot be applied to the rendering of polygonal geometry. The method allows hundreds of clouds with hundreds of thousands of particles to be rendered at high frame rates, and improves interaction with clouds by reducing artifacts introduced by direct particle rendering.”

Cloud Rendering
Link to a webpage with much more information about this technique:
http://www.markmark.net/clouds/

Link to the paper:
http://www.markmark.net/PDFs/RTCloudsForGames_HarrisGDC2002.pdf

Regression Testing a Renderer

Software Engineering | Friday 7 November 2008 1:46 pm

These are two types of regression test that might be good to do when working on a renderer and you want to be sure that the new code won’t break something else. When doing refactoring, these tests are very important too.

The easy way to do testing is to make some test scenes and manually run them all and look for errors after each change. But this will be cumbersome so more automation is needed.

Regression testing (functionality)

Create a couple of tests with scenes that contains all that should be tested. Run them and manually control so they are working. When running, the test should save a screen shot of the perfect rendered scene for later comparison.

Then a new feature has been added, the test scenes should be automatically run again and new screen shots should be rendered and compared against the original ones. Some sources suggests that the comparison can be a simple bit to bit comparison and that any difference should be noted and reported as a failure.

Regression testing (performance)

Save the fps for all performance tests and whenever a feature has been added. It should automatically run all tests again and report if any performance has changed. It’s most important if performance has decreased, but increased performance might be good to know too if your working on optimizations.

Information about how Unity does testing of their graphics code
http://aras-p.info/blog/2007/07/31/testing-graphics-code/

Some info about how to compare images in these kinds of tests:
http://www.tilander.org/aurora/2008/03/comparing-images.html

A link to information about all kinds of automated testing in games:
http://www.gamasutra.com/features/20050329/roken_pfv.htm

These developers uses a “monkey” to test their code, which seems to work good for them:
http://powerof2games.com/node/25

Some info about what regression testing is and why it is needed:
http://en.wikipedia.org/wiki/Regression_testing

Screen Space Ambient Occlusion

Image Enhancements, Lighting | Tuesday 4 November 2008 11:24 pm
SSAO is the new technique that most new games just must include because of the hype around it since the computer game Crysis. It’s a technique for creating a rude approximation of ambient occlusion by using the a depth of the rendered scene. This works by comparing the current fragments depth with some random sample depths around it to see if the current depth is occluded or not. The current fragment is occluded if the sample is closer to the eye than the current fragment. Although it sounds very bad to do so, in practice it does work beyond all expectations.

How to take the samples is a big concern as it will impact what will occlude and how much. The currently best implementations takes random samples in a hemisphere in the direction of the normal. This limits the amount of self occlusion. Another problem is that if you only take the depth into consideration then a flat surface might occlude itself because of the perspective. By also comparing the normal when calculating the AO, this problem will go away.

One of the hard parts of implementing SSAO is to choose the correct smoothing technique. Because of the big cost of taking occlusion samples you want to take as few samples as possible but this will give much noise in the SSAO so the result needs smoothing. Just doing a simple gaussian blur will not be good as the blur will make the SSAO bleed. Instead a blur that considers the depth and/or normals is needed. One of those is the bilateral filter which often is used in combination with SSAO.

The steps of a simple SSAO implementation:

  1. Render the scene. Save the linear depth in a texture. Save the normals in eye space in a texture.
  2. Render a full screen quad with the SSAO shader. Save the result to a texture.
  3. Blur the result in X
  4. Blur the result in Y
  5. Blend the blurred SSAO texture with the scene, or use it directly when rendering the scene.

An optimization is to render the SSAO in a lower resolution than the screen and upsample it when blurring. Another optimization is to store both the normals and the depth in a single texture.

SSAO in the NVIDIA SDK

SSAO in the NVIDIA SDK

Probably one of the best implementations of SSAO is this one by NVIDIA (although it’ rather slow). The SDK 10 has a paper about the technique and also source code!
http://developer.download.nvidia.com/SDK/10.5/direct3d/samples.html

And here’s three papers/presentations from NVIDIA describing their SSAO in detail:
http://developer.download.nvidia.com/presentations/2008/GDC/GDC08_Ambient_Occlusion.pdf
http://developer.download.nvidia.com/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf
http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/ScreenSpaceAO/doc/ScreenSpace AO.pdf

SSAO in Starcraft II

SSAO in Starcraft II

Some information of how Starcraft II will use SSAO is included in this paper ( see chapter 5.5 ):
http://ati.amd.com/developer/SIGGRAPH08/Chapter05-Filion-StarCraftII.pdf

SSAO in Two Worlds

SSAO in Two Worlds

A link to a description of the SSAO implementation in the game Two Worlds:
http://www.drobot.org/pub/GCDC_SSAO_RP_29_08.pdf

SSAO in Crysis

SSAO in Crysis

The paper and game that started it all (look in the chapter 8.5.4.3):
http://delivery.acm.org/10.1145/1290000/1281671/p97-mittring.pdf?key1=1281671&key2=9942678811&coll=ACM&dl=ACM&CFID=15151515&CFTOKEN=6184618

Hardware Accelerated Ambient Occlusion

Hardware Accelerated Ambient Occlusion

One of the papers that probably inspired the Crysis team:
http://perumaal.googlepages.com/

Kindernoiser SSAO

Kindernoiser SSAO

A simple but smart SSAO implementation, here with well commented shader source code:
http://rgba.scenesp.org/iq/computer/articles/ssao/ssao.htm

A gamedev.net thread with lots of discussion about SSAO
http://www.gamedev.net/community/forums/topic.asp?topic_id=463075

Next Page »