XNA for C#
DirectX 9 for C#
DirectX 9 for C++
DirectX 9 for VB
My XNA Book
       Go to section on this site

Additional info

Latest Forum posts

 Account settings
  Posted by: Anonymous
  When: 07/05/2014 at 09:48:39

 forced subtitle
  Posted by: Applefly
  When: 07/05/2014 at 06:00:48

 convert DVD into PMS
  Posted by: Applefly
  When: 07/05/2014 at 05:55:25

 DVD to Digital Copy easily
  Posted by: VIKIVannessa
  When: 05/05/2014 at 06:52:29

 DVD on Xbox 360/Xbox One Console
  Posted by: VIKIVannessa
  When: 05/05/2014 at 06:51:47

 Extract .Srt Subtitles
  Posted by: Applefly
  When: 04/05/2014 at 03:54:38

 Encode Movie collection
  Posted by: Applefly
  When: 04/05/2014 at 03:52:41

 Convert DVD to WMV
  Posted by: Applefly
  When: 29/04/2014 at 05:53:50

 rip DVDs into digital files
  Posted by: Applefly
  When: 29/04/2014 at 05:51:20

 iTunes movies/music to Kindle Fire
  Posted by: ciciyu80
  When: 29/04/2014 at 05:10:20


The first Vertex Shader

This chapter you will write your first HLSL code, together with your first vertex shader. As you can see in the image below, a vertex shader needs to receive vertices from the DirectX app. We will simply be using the vertex buffer from our starting code, and we will have our vertex buffer simply draw the triangle to screen using HLSL, without any fancy stuff. Much like a ‘Hello world’ application for shaders.

First have a look at our staring point: the big arrow starting in our DirectX app, going to our vertex shader:

When we pass the vertex data from our DirectX app to our vertex shader, we need to pass some information with it, describing what kind of data is contained in the vertex stream. Using the Fixed Function Pipeline (the standard DirectX commands), you would simply use device.VertexFormat. Because you can pass very complex data to your vertex shader, this will no longer do. Using shaders, you need to specify exactly what information can be found where in the stream.

So what we need is a VertexDeclaration object, which lets you specify all the needed information. So add this variable to the top of your code:

 private VertexDeclaration vd;

As with all resources, we need to fill it in the FillResources method. This way it will automatically be refilled on device reset. So put this code there:

 VertexElement[] velements = new VertexElement[]
      new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
      new VertexElement(0, 12, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
 vd = new VertexDeclaration(device, velements);

First we need to fill a VertexElement structure, which we then link to our vertexdeclaration. The VertexElement needs to specify what kind of data can be found where in the vertex stream. Note that the last element of a VertexElement must be VertexElement.VertexDeclarationEnd.

Because every vertex of our triangle specifies the position as well as the color, we need to include these in our VertexDeclaration. For each, we need to specify a lot of arguments. The first is the number of the datastream we’ll be describing. Because we’ll only be using one, we indicate 0. The second argument is very important. It indicates at which offset IN BYTES the type of data can found in the vertex stream. So the first type of data, the 3D position, starts at offset 0. The second type of data, the color, can be found starting from byte 12, because 1 float uses up 4 bytes, and since our 3D position uses 3 floats, one 3D position consumes 12 bytes in our vertex stream.

Next we indicate the type of data, such as int, float1, short4 and more. Although a color should be an Int32, we need to specify Color, because this int32 needs to be mapped to 4 colorvalues within the range [0..1]. This is the only exception.

Concerning the next argument, you’ll almost always want to use DeclarationMethod.Default, maybe I can write a small short tut later on the other uses. The last argument is the most important one: it describes the kind of information, such as position, color, texture coordinate, tangent, etc. This is needed, so DirectX can automatically link the right data from our vertex stream to the right variables in our shaders.

This would be a nice moment to have another look at our flowchart above. You notice the big arrow from our DirectX app toward the vertex shader. At this point, we have the vertex stream (the position and color of our 3 vertices), as well as the metadata, which describes what’s in this vertex stream.

When looking at the image, you’ll see it’s time to begin coding on our vertex shader! Although one of the main goals of my tutorials is to keep all code in 1 file, we cannot get around this one. You’ll have to create a new empty effect file and give it a name (I named mine OurHLSLfile.fx). Now you have to choose which program you’re going to use to code your .fx file. Of course you can use Visual Studio, but I don’t really like the compiler output. To code .fx files, most people use NVIDIA’s FX Composer, which you can download here for free. After installation, you can simply double-click on your .fx file (just an empty file you created with the .fx extension), and it’ll be opened in FX Composer. If you’re presented with an empty screen, the answer is in one of the forum posts on this forum, which you can find below.

To edit the file in Visual Studio, go to your Project menu, and find Add existing item. Now select your .fx file, and you’ll see that it’s been added to the solution explorer in Visual Studio.

Whether you’re using Visual Studio or NVidia’s FX Composer, you’ll be presented an empty page. We’ll now start putting some HLSL code in the .fx file. Although HLSL is not 100% the same as C# code, you will have absolutely no problem reading and writing the code. I could give you an extremely dry summary of the HLSL grammar, but I prefer to introduce you the syntax by showing some examples. At the end of this Series, you’ll be able to read and write almost any HLSL code you want.

Our DirectX application will draw the scene using a ‘technique’. An .fx file can describe one or more techniques. One technique can have multiple passes as you’ll see in the next chapters, but let’s start by defining a simple technique with only one pass. So you can already put this as your first HLSL code in your .fx file:

technique Simplest
    pass Pass0
        VertexShader = compile vs_1_1 SimplestVertexShader();
        PixelShader = NULL;

This defines a technique, Simplest, with one pass. This pass has a vertex shader (SimplestVertexShader), but no pixelshader. This indicates our vertex shader will pass its output data to the default pixel shader.

Before we start coding our vertex shader, we would better define a structure to hold the data our vertex shader will send to the default pixel shader. Our vertex shader method, SimplestVertexShader, will simply transform the vertices it receives from our DirectX app to screen pixel coordinates, and send them together with the color to the pixel shader, so put this code at the top of your .fx file:

struct VertexToPixel
    float4 Position     : POSITION;
    float4 Color        : COLOR0;

This again looks very much like C#, only for the :POSITION and :COLOR0. These are called semantics and indicate how our GPU should use the data. More on this in the next paragraph. Let’s start our SimplestVertexShader method, so you’ll better understand this. Place this method between the structure definition and our technique definition:

VertexToPixel SimplestVertexShader( float4 inPos : POSITION)
    VertexToPixel Output = (VertexToPixel)0;
    Output.Position = mul(inPos, xViewProjection);
    Output.Color = 1.0f;    
    return Output;    

This again looks a lot like C#. The first line indicates our method (our vertex shader) will return a filled VertexToPixel structure to the pixel shader. It also indicates your vertex shader receives the position from your vertex stream, as indicates by the POSITION semantic. This is very important: it links the data inside your vertex stream (as indicated in your VertexDeclaration) to your HLSL code.

Remember this method is called for every vertex in your vertex stream. The first line in the method creates an empty output structure. The second line takes the 3D coordinates of the vertex, and transforms them to 2D screen coordinates by multiplying them by the combination of the View and Projection matrix. For more information on this, you can always have a look at the Matrix sessions in my ‘Extra Reading’ section, which you can find at the left of every page.

Then we fill the Color member of the output structure. When you look at the definition of our output structure, you’ll see this has to be a float4: one float for each of the 3 color components, and an extra float for the alpha (transparency) value. You could fill this color by using the following code:

Output.Color.r = 1.0f;
Output.Color.g = 0.0f;
Output.Color.b = 1.0f;
Output.Color.a = 1.0f;

This would indicate purple, as you combine red and blue. The following code specifies exactly the same:

Output.Color.rga = 1.0f;
Output.Color.g = 0.0f;

This is called a swizzle, and helps you to code faster. Instead of rgbw, you can also use xyzw. The rgba swizzle is usually used when working with colors, while the xyzw swizzle is used in combination with coordinates. You can also use indices, which is useful for use in an algorithm:

Output.Color[0] = 1.0f;
Output.Color[1] = 0.0f;
Output.Color[2] = 1.0f;
Output.Color[3] = 1.0f;

Our SimplestVertexShader method simply sets Output.Color = 1.0f, which means the 4 components of the color are all set to 1.0f, which corresponds to white. So our vertex shader will transform our 3D vertices to 2D screen coordinates, and pass them together with the color white to the default pixel shader. This means in our case of 1 triangle, our pixel shader will draw a solid white triangle to the window.

There’s still something missing. When you press ctrl+s in NVidia’s FX Studio, you will see we still need to define xViewProjection. So put this line just above your vertex shader method:

float4x4 xViewProjection;

This indicates xViewProjection is a matrix with 4 rows and 4 columns, so it can hold a standard DirectX matrix. Our DirectX app will fill this matrix in the next chapter.

That’s it for our first HLSL code! Of course, we still need to call the technique from our DirectX app, as well as set the xViewProjection matrix. Because this chapter would otherwise become too lengthy, we’ll discuss the DirectX part in the next chapter.

Here you can find already what you should have as HLSL code:

struct VertexToPixel
    float4 Position     : POSITION;
    float4 Color        : COLOR0;

float4x4 xViewProjection;

VertexToPixel SimplestVertexShader( float4 inPos : POSITION)
    VertexToPixel Output = (VertexToPixel)0;
    Output.Position =mul(inPos, xViewProjection);
    Output.Color = 1.0f;    
    return Output;    

technique Simplest
    pass Pass0
        VertexShader = compile vs_1_1 SimplestVertexShader();
        PixelShader = NULL;

DirectX Tutorial 3 - Vertex Shader

If you appreciate the amount of time I spend creating and updating
these pages, feel free to donate -- any amount is welcome !

Click here to go to the forum on this chapter!

Or click on one of the topics on this chapter to go there:
  • compilation error
          Hi there I followed the tutorials step by step ...
  • A Few Questions...
          First of all, why is position being input to the v...
  • Problem with April SDK?
          Im trying to get a bit better terrain for my game ...
  • Error?
          I am getting an error from FXComposer saying <...


    If you appreciate the amount of time I spend creating and updating
    these pages, feel free to donate -- any amount is welcome !

    - Website design & XNA + DirectX code : Riemer Grootjans -
    ©2003 - 2011 Riemer Grootjans
  • Translations

    This site in English
    This site in Korean
    This site in Czech

    Microsoft MVP Award

    2007 - 2011 MVP Award
    DirectX - XNA


    XNA 2.0 Recipes Book (8)
    XNA 3.0 Recipes Book (8)
    Extra Reading (3)
    Matrices: geometrical
    Matrix Mathematics
    Homogenous matrices
    Community Projects (1)
    Tutorials (160)
    XNA 4.0 using C# (89)
    DirectX using C# (54)
    Series 1:Terrain (14)
    Series 2: Flightsim (19)
    Series 3: HLSL (19)
    Starting point
    HLSL Introduction
    Vertex Shader
    Shaded triangle
    Pixel Shader
    Textured Triangle
    Triangle Strip
    World transform
    Adding normals
    The first light
    Shadow mapping
    Render To Texture
    Projective texturing
    The first shadow
    Shaping the light
    Multiple lights
    Adjusting Z values
    Finishing touch
    Short Tuts (2)
    DirectX using C++ (15)
    DirectX using VB (2)
    -- Expand all --

    Thank you!

    Support this site --
    any amount is welcome !

    Stay up-to-date

    I don't have the time to keep a News section, so stay informed about the updates by clicking on this RSS file!