Tag Archives: Rendering


Starting with DirectX Pixel Shader Model 3.0 there exist an input type called VPOS. It’s the current pixels position on the screen and it’s automatically generated. This can be useful when sampling from a previously rendered texture when rendering an arbitrarily shaped mesh to the screen. To do this, we need uv-coords that represents where to sample on the texture. These coordinates can be gained by simply dividing VPOS with the screen dimensions.
When working with older hardware, that doesn’t support shader model 3.0, there is a need to manually create the VPOS in the vertex shader and pass it to the fragment shader as a TEXCOORD. This is the way to do so ( including the scaling to uv-range which manually has to be done for VPOS if you’re using it).

Vertex Shader:

float4x4 matWorldViewProjection;
float2 fInverseViewportDimensions;
struct VS_INPUT
   float4 Position : POSITION0;
struct VS_OUTPUT
   float4 Position : POSITION0;
   float4 calculatedVPos : TEXCOORD0;
float4 ConvertToVPos( float4 p )
   return float4( 0.5*( float2(p.x + p.w, p.w - p.y) + p.w*fInverseViewportDimensions.xy), p.zw);
VS_OUTPUT vs_main( VS_INPUT Input )
   VS_OUTPUT Output;
   Output.Position = mul( Input.Position, matWorldViewProjection );
   Output.calculatedVPos = ConvertToVPos(Output.Position);
   return( Output );

Pixel Shader:

float4 ps_main(VS_OUTPUT Input) : COLOR0
   Input.calculatedVPos /= Input.calculatedVPos.w;
   return float4(Input.calculatedVPos.xy,0,1); // test render it to the screen

The image below shows an elephant model rendered with the shader above. As can be seen, the color (red and green channels) correctly represents the uv-coords for a fullscreen quad. Since 0,0,0 = black, 1,0,0 = red, 0,1,0 = green, 1, 1,0 = yellow.

VPOS Elephant
This is how the pixel shader would have looked like if VPOS were used instead (note: no special vertex shader needed in this case).
struct PS_INPUT
   float2 vPos : VPOS;
float4 ps_main(PS_INPUT Input) : COLOR0
   return float4(Input.vPos*fInverseViewportDimensions + fInverseViewportDimensions*0.5,0,1); // test render it to the screen

The original code, more info and proof can be found here:

Render Thickness

In [1] they describe a clever way of rendering the thickness of an object in a single pass. The method only correctly works for convex objects but this limitation isn’t that bad, the method can often be used to get the approximated thickness of concave objects as well. For example, [1] uses it to fake the light scattering in clouds rendered as billboards. The methods works like this:

The object is rendered and the distance from the near plane is saved in a color channel R. Also, the distance to the far plane is saved in channel G. By rendering with the blend color mode MIN, one will get the minimum distance from the near plane in R, and the minimum distance to the far plane in G. By using these two distances, one can easily calculate the thickness of the rendered object with the following formula (1-G) – R (if distance is scaled so one is the the distance between the clip planes). Alpha can be saved as well in the same render pass, by outputting it to the A channel. And selecting blend alpha mode ADD (color and alpha can have different modes). This will add up the alpha.

All this is done in only one pass. Just remember to clear to white before rendering.

The image below shows the thickness of the popular Hebe mesh rendered with this method. This model is not convex, and the problem areas are for example the arm holding the bowl. As one can see, the algorithm believes that the bowl and the shoulder are connected, and therefore believes that part of the object is the thickest.


[1] The Art and Technology of Whiteout

Instanced Billboards

In DirectX9, one can use instanced billboards to render lots of particles with good performance. Since we presume all particles to be billboards constructed from two triangles forming a quad, by using instancing, we can reuse this geometry data (only uv-coordinates needed) for each particle and therefore saving bandwidth. When rendering, two streams with different frequency should be used.  The quad-geometry data makes the first stream, the second stream consists of the per instance data that is unique for each particle. This instance data could be the position, rotation, color and more. The big drawback with this rendering approach is that it requires hardware instancing support, which means Shader Model 3.0. (or Shader Model 2.0 for ATI cards if using a trick described in the first source below).

This particle rendering approach described in details:

DirectX9 info about rendering multiple streams

DirectX9 instancing info

Fluid Simulation and Rendering

For effects like smoke or water, a fluid simulation and rendering approach is needed. There are currently two popular methods for this:

  1. Simulate the fluid on the CPU and send the result as particles to the GPU for rendering as billboards. This is often called a particle system. The technique has been around since the dawn of computer graphics.

  2. Simulate the fluid on the GPU and render the result into textures. This will then be rendered by doing volume ray casting (or ray marching) on the GPU. This technique is new and rather unexplored, and there are few real-life implementations. The result can be very realistic but slow.

Technique one burdens both CPU, bandwidth and GPU. Although in modern solutions, it’s the bandwidth that’s the bottleneck. The GPU based technique only burdens the GPU ( but a lot ).

The movie shows the GPU method of fluid simulation and rendering. More info about this particular implementation in the two last links.

Building an Advanced Particle System
Building a Million Particle System
Real-Time Simulation and Rendering of 3D Fluids
The previous page’s authors homepage: