Here you will find tutorials for the topic Game Development.

Converting Ms3d-animations to DirectX Date: 12.5.2010 Author: Christoph P. Difficulty: Medium
Introduction to DirectX Shader Date: 15.5.2010 Author: Christoph P. Difficulty: Easy
Dual Paraboloid Shadow Mapping Date: 23.5.2010 Author: Christoph P. Difficulty: Medium
Introduction to Milkshape 3D Date: 17.6.2010 Author: Christoph P. Difficulty: Easy

Introduction to DirectX Shader


This tutorial gives an overview to Shader written in HLSL, as they are used in DirectX. Integrating the shader into a DirectX program is not part of the tutorial and should be read as needed in the DirectX SDK documentation. Also, only the two most used shader, namely Vertex Shader and Pixel Shader, will be explained using a parent sample. It should describe the basic concept of DirectX Shaders.


A Shader is a usually small program that runs on the graphics processor and is therefore very fast. DirectX supports Shader since version 8.0, initially only Vertex and Pixel Shader written in Assembler language were supported. In DirectX 9 High Level Shader Language (HLSL) was added, which allowed the programming in a C-like language. DirectX 10 introduced the Geometry Shader and DirectX 11 extended the range to the Domain-, Hull- and Compute Shader.
Since DirectX 10, Shader are the focus of DirectX, because the so-called Fixed Rendering Pipeline was abolished. In other words, if you would like to have a appealing result using DirectX, you can't avoid to use them. But frankly, the least want to work without them, because they make it possible to create beautiful surface effects, but also animations and other things can be realized with them.

Vertex Shader

The Vertex Shader is called once per vertex, gets a vertex as input, process it, and then returns it to the DirectX Pipeline. The Vertex Shader is the first Shader in the Pipeline and gets the data from the Input-Assembler. Mainly vertex transforming and illuminating takes place in the Vertex Shader, but also other calculations for special effects are possible.

Here the structure of a simple Vertex Shader:

As you see, Shaders are functions.

Like in C, the vertex data can be packaged in a structure. But in HLSL they will receive data mapping identifiers, so-called Semantics, so that DirectX knows which data should be assigned to which variables. The Semantic starting with SV is a System Value Semantic, which is provided for a system declaration, therefore the DirectX Pipeline. The input and output data can be different on a Vertex Shader, and all Shaders. In our example the position, normal, and texture coordinates are passed to the Shader and after processing in the Shader, the vertex position in world coordinates is returned in addition to the transformed data (see example below). HLSL uses its own data types, you can read that and also about the functions used in the example (intrinsic functions) in the DirectX reference of the DirectX SDK, if necessary.

Now a complete example of a Vertex Shader:

Variables must be passed to a shader in resource objects. There are several types of this objects, the most important are: cBuffer, tBuffer, Texture2D and Texture2DArray. Here, the world and the combined camera projection matrix are passed in a cBuffer (constant buffer). With the world matrix, the position and the normal of each vertex, are then transformed in the Vertex Shader. With the combined matrix, the position is transformed again to get the location in the projection space. The meaning of the normal and the position in world coordinates becomes clear when you see the Pixel Shader. The data is then returned with the copied texture coordinates. How these data can be processed we see in the next section.

Pixel Shader

The Pixel Shader is called once per pixel and gets its data from the preceding Pipeline station respectively from the preceding Shader (in our case the Vertex Shader). It calculates the pixel color (pixel depth or any values are possible) and returns them to the Pipeline. The Pixel Shader is the last Shader in the Pipeline and therefore already gives the data to the Output Merger, which determines the final pixel color. Pixel Shaders are mainly used for rendering surfaces but as all Shaders they can used for special calculations. But the two most important ways to use them are texturing and lighting, for which I will show an example after the following presentation of the structure of a Pixel Shader.

Structure of a Pixel Shader:

In principle, there is no real difference to a Vertex Shader, only the input and output data is different.

Texturing and lighting with a Pixel Shader:

Here, also a buffer for the light position in world coordinates is created and a texture and a Sampler is used. The Sampler is necessary to read the texture color on the corresponding texture coordinates (Sampling). The Pixel Shader input data received from the Vertex Shader is interpolated by DirectX. This means, for the current pixel from the three vertices of the current triangle to draw, distance- and mode-dependent "averages" are calculated. (by the way, interpolation modes can be set by variable modifiers)
Our Pixel Shader output is the computed pixel color. Creating an extra structure for this, as for other input and output data is not necessary, but this does not apply to the SV_Target Semantic, which identifies the color output for DirectX.
Now to the code in the Pixel Shader. As already mentioned, with the passed texture coordinates, the color from the texture is sampled first. Then the light ray, from the light position to the point on the triangle, represented by the Pixel Shader, (interpolated vertex position in world coordinates) is calculated and normalized, to finally compute the luminosity, using the Lambert's cosine law. (This law says, the flatter the angle of the reflective light ray, the lower the radiant intensity) Now, the color only needs multiplied by this value and returned.

I hope you have now get an insight into the world of Shaders and again, become a little smarter. The complete example is here for download.


Copyright 2015 (c) by Christoph P.
Contact    Terms