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

Additional info


Latest Forum posts

 Backup DVD Escape Plan
  Posted by: Applefly
  When: 17/04/2014 at 06:00:12

 Disney DVDs to MP4
  Posted by: Applefly
  When: 17/04/2014 at 05:56:07

 DVD movies through media streamer
  Posted by: VIKIVannessa
  When: 16/04/2014 at 02:25:09

 DVD movies to play on Galaxy Tab 3 10.1
  Posted by: VIKIVannessa
  When: 16/04/2014 at 02:20:51

 Blu-ray to Apple ProRes
  Posted by: Applefly
  When: 12/04/2014 at 00:47:46

 HD H.264 MP4 format
  Posted by: Applefly
  When: 12/04/2014 at 00:43:23

 DVD collection to computer
  Posted by: VIKIVannessa
  When: 04/04/2014 at 07:13:33

 DVD movies to play on Galaxy Tab 3 10.1
  Posted by: VIKIVannessa
  When: 04/04/2014 at 07:11:27

 DVD movies to play on Galaxy Tab 3 10.1
  Posted by: VIKIVannessa
  When: 04/04/2014 at 07:11:27

 DVD Ripper to populate
  Posted by: Applefly
  When: 04/04/2014 at 05:01:35


Ads

Drawing the triangle using custom Shaders

Up to this point, we have a vertex buffer, filled with only 3 vertices defining a single triangle. We also have the metadata: the VertexDeclaration, which describes what kind of data is contained in the vertex data, together with the offset to that kind of data.

We also have a very simple vertex shader. From our vertex stream, it extracts only the position data. For each vertex, this 3D position is transformed to 2D screen coordinates, and passed on to the pixel shader. To perform this transformation, we multiply each vertex with the matrix which is the combination of the View and Projection matrix, which is at this point not yet being specified by our XNA code.

In our XNA app, it is time to load our own effect file we created, and set the transformation matrix. So load the effect file into the Content entry of the Solution Explorer, like you have done before with images. You should see the OurHLSLfile.fx as an additional asset in your Solution Explorer. Find the line in the LoadEffect method that loads my .fx file into the effect variable, and replace it with this line:


effect = Content.Load<Effect> ("OurHLSLfile");
Weíre ready to move on to the Draw method. To draw our triangle using our own technique, we first have to specify our technique and set its parameters. In our case, the only parameter we have to set is xViewProjection, which is the combination of the viewMatrix and the projectionMatrix. So replace the existing code before the line where your Begin your effect with this code:

 effect.CurrentTechnique = effect.Techniques["Simplest"];
 effect.Parameters["xViewProjection"].SetValue(viewMatrix*projectionMatrix);

Make sure you remove the lines where you try to set other parameters such as xView, xWorld,.. because these donít exist (yet) in our .fx file.

Our XNA code is ready! However, when you try to run your program, youíll get an error stating ĎBoth a valid vertex shader and pixel shader (or valid effect) must be set on the device before draw operations may be performedĎ. This is because although our technique contains a vertex shader, it doesnít yet contain a valid pixel shader! So letís go back to our .fx file.

The pixel shader is called for each pixel of the screen that needs to be drawn. In most cases, the pixel shader only needs to calculate the correct color.

The pixel shader receives its input (position and color, in our case) from our vertex shader, and needs to output only color. So letís define its output structure at the top of our .fx file:

struct PixelToFrame
{
    float4 Color        : COLOR0;
};

Our first pixel shader will be a very simple method, here it is:

PixelToFrame OurFirstPixelShader(VertexToPixel PSIn)
{
    PixelToFrame Output = (PixelToFrame)0;    

    Output.Color = PSIn.Color;    

    return Output;
}

First, an output structure is created, and the color received from the vertex shader is put in the output structure. Thatís all it does!

Now we still need to set this method as pixel shader for our technique, at the bottom of the file:

PixelShader = compile ps_2_0 OurFirstPixelShader();

Thatís it! We have 3 colored 3D vertices, pass them to the vertex shader which transforms them into 2D positions and pass them on to the pixel shader, which simply puts the color on the screen. Try to run your XNA program!

You should see the same as the image below: a white triangle. White, because we coded our vertex shader to draw every vertex white. Not a lot of fun, so letís add some color to it. Go to the vertex shader in your .fx file, and update it to this code:

VertexToPixel SimplestVertexShader( float4 inPos : POSITION, float4 inColor : COLOR0)
{
    VertexToPixel Output = (VertexToPixel)0;
    
    Output.Position =mul(inPos, xViewProjection);
    Output.Color = inColor;

    return Output;
}

Note the changes in the first line: now, our vertex shader also expects the vertices to carry color information. In our case, this is OK as the MyOwnVertexFormat contains both position and color information.

The only change that has been made to the interior of the method, is that we simply route this color we get from our XNA app immediately to the output of the vertex shader, instead of simple white.

Now, when you run this code, you should see the same colored triangle as before. Our vertex shader simply transforms the 3D coordinates to 2D screen coordinates, and passes these coordinates together with the correct color to the pixel shader. This pixel shader doesnít change anything to the color, and passes it on to the screen.




DirectX Tutorial 5 - Pixel 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:
  • invalid arguments?
          Hi In order to get a better understanding of sh...
  • XNA 2.0 Strugglers
          //This will display the white triangle, you will h...
  • triangle doesn't show up
          i don't know whats going on. my triangle seems to...
  • Where do the variables com from?
          When you make the methods, you put in code like no...
  • hlsl
          Hi I dont understand the section about adding t...



    I know, I may have rushed this chapter a bit by introducing the pixel shader. This simply is because you need one to show something on the screen. Donít worry, next chapter weíll explore the pixel shader in some more depth.

    You can try these exercises to practice what you've learned:
  • Adjust your vertex shader so your triangle is rendered in solid yellow.
  • Make the colors in the vertices dependant on their 3D position.
     using System;
     using System.Collections.Generic;
     using Microsoft.Xna.Framework;
     using Microsoft.Xna.Framework.Audio;
     using Microsoft.Xna.Framework.Content;
     using Microsoft.Xna.Framework.GamerServices;
     using Microsoft.Xna.Framework.Graphics;
     using Microsoft.Xna.Framework.Input;
     using Microsoft.Xna.Framework.Net;
     using Microsoft.Xna.Framework.Storage;
     
     namespace XNAseries3
     {
         public struct MyOwnVertexFormat
         {
             public Vector3 position;
             public Color color;
     
             public MyOwnVertexFormat(Vector3 position, Color color)
             {
                 this.position = position;
                 this.color = color;
             }
     
             public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
                  (
                      new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                      new VertexElement(sizeof(float) * 3, VertexElementFormat.Color, VertexElementUsage.Color, 0)
                  );
         }
     
         public class Game1 : Microsoft.Xna.Framework.Game
         {
             GraphicsDeviceManager graphics;
             GraphicsDevice device;
     
             Effect effect;
             Matrix viewMatrix;
             Matrix projectionMatrix;
             VertexBuffer vertexBuffer;
             Vector3 cameraPos;
     
             public Game1()
             {
                 graphics = new GraphicsDeviceManager(this);
                 Content.RootDirectory = "Content";
             }
     
             protected override void Initialize()
             {
                 graphics.PreferredBackBufferWidth = 500;
                 graphics.PreferredBackBufferHeight = 500;
                 graphics.IsFullScreen = false;
                 graphics.ApplyChanges();
                 Window.Title = "Riemer's XNA Tutorials -- Series 3";
     
                 base.Initialize();
             }
     
             protected override void LoadContent()
             {
                 device = GraphicsDevice;
     

                effect = Content.Load<Effect> ("OurHLSLfile");
                 SetUpVertices();
                 SetUpCamera();
             }
     
             private void SetUpVertices()
             {
                 MyOwnVertexFormat[] vertices = new MyOwnVertexFormat[3];
     
                 vertices[0] = new MyOwnVertexFormat(new Vector3(-2, 2, 0), Color.Red);
                 vertices[1] = new MyOwnVertexFormat(new Vector3(2, -2, -2), Color.Green);
                 vertices[2] = new MyOwnVertexFormat(new Vector3(0, 0, 2), Color.Yellow);
     
                 vertexBuffer = new VertexBuffer(device, MyOwnVertexFormat.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
                 vertexBuffer.SetData(vertices);
             }
     
             private void SetUpCamera()
             {
                 cameraPos = new Vector3(0, 5, 6);
                 viewMatrix = Matrix.CreateLookAt(cameraPos, new Vector3(0, 0, 1), new Vector3(0, 1, 0));
                 projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 200.0f);
             }
     
             protected override void UnloadContent()
             {
             }
     
             protected override void Update(GameTime gameTime)
             {
                 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                     this.Exit();
     
                 base.Update(gameTime);
             }
     
             protected override void Draw(GameTime gameTime)
             {
                 device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.DarkSlateBlue, 1.0f, 0);
     
                 effect.CurrentTechnique = effect.Techniques["Simplest"];
                 effect.Parameters["xViewProjection"].SetValue(viewMatrix * projectionMatrix);
     
                 foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                 {
                     pass.Apply();
     
                     device.SetVertexBuffer(vertexBuffer);
                     device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
                 }
     
                 base.Draw(gameTime);
             }
         }
     }

    The HLSL code:

    float4x4 xViewProjection;

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


    struct PixelToFrame
    {
        float4 Color        : COLOR0;
    };

     
     VertexToPixel SimplestVertexShader( float4 inPos : POSITION, float4 inColor : COLOR0)
     {
         VertexToPixel Output = (VertexToPixel)0;
         
         Output.Position = mul(inPos, xViewProjection);
         Output.Color = inColor;
     
         return Output;
     }
     
     
     PixelToFrame OurFirstPixelShader(VertexToPixel PSIn)
     {
         PixelToFrame Output = (PixelToFrame)0;    
     
         Output.Color = PSIn.Color;    
     
         return Output;
     }
     
     technique Simplest
     {
         pass Pass0
         {
             VertexShader = compile vs_2_0 SimplestVertexShader();
             PixelShader = compile ps_2_0 OurFirstPixelShader();
         }
     }
     


    Google
     
    Webwww.riemers.net


    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

    Contents

    News
    Home
    Forum
    XNA 2.0 Recipes Book (8)
    XNA 3.0 Recipes Book (8)
    Downloads
    Extra Reading (3)
    Matrices: geometrical
    Matrix Mathematics
    Homogenous matrices
    Community Projects (1)
    Tutorials (160)
    XNA 4.0 using C# (89)
    2D Series: Shooters (22)
    3D Series 1: Terrain (13)
    3D Series 2: Flightsim (14)
    3D Series 3: HLSL (18)
    Starting point
    HLSL introduction
    Vertex format
    Vertex shader
    Pixel shader
    Per-pixel colors
    Textured triangle
    Triangle strip
    World transform
    World normals
    Per-pixel lighting
    Shadow map
    Render to texture
    Projective texturing
    Real shadow
    Shaping the light
    Preshaders
    3D Series 4: Adv. terrain (19)
    Short Tuts (3)
    DirectX using C# (54)
    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!