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

Defining our own vertex format

Let’s have a look at the staring point in our flowchart: the big arrow starting in our XNA app, going to our vertex shader:



It represents the flow of vertex data from our XNA app to the vertex shader on the graphics card. This is triggered every time we issue some kind of draw command in XNA. When we pass the vertex data from our XNA 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 shaders, you need to specify exactly what information can be found in the stream, and where.

So what we need is:
  • a structure that can hold the necessary data for each vertex and
  • a definition of the data, so the vertex shader knows which data is included with every vertex.

    In the starting code, we’ve been using the VertexPositionColor struct which satisfies both requirements. Here, we’re going to define a new struct, MyOwnVertexFormat, that will be exactly the same as the VertexPositionColor struct, to see what’s in there and why it is needed. This will allow us to expand it further on in this series.

    For a far more detailed explanation on creating custom vertex formats, read Recipe 5-14.

    To satisfy the 2 requirements, in the example of a simple colored triangle, we need our vertices to hold 3D Position data as well as Color data. So this is how we start our struct (you can put this at the top of our code):

     struct MyOwnVertexFormat
     {
         private Vector3 position;
         private Color color;
     
         public MyOwnVertexFormat (Vector3 position, Color color)
         {
             this.position = position;
             this.color = color;
         }
     }

    We simply defined a new structure, and defined it so it can hold a Vector3 and a Color. We also defined a constructor, so later in our program we can create and fill a new instance of this struct in one line. The first requirement has been satisfied.

    Next, we need a way to tell our graphics card that the data we are sending actually contain Position and Color data. Although we gave the elements straightforward names (position, color), the graphics card needs to be told explicitly which data it will receive.

    As seen in the previous series, this is done by means of setting a VertexDeclaration before rendering triangle. However, when we created this VertexDeclaration, we always used the VertexElements property of the type of vertices we were rendering from. Since we are defining our own kind of vertices, we also need to define its VertexElements.

    The VertexDeclaration will contain 1 entry for each type of data accompanying each vertex. Put this code inside our struct, at the very end:

     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)
     );

    For each type of data, we define what it is used for, and where it can be found. The following paragraph contains a brief summary of the explanation in Recipe 5-14.

    The first 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.

    Next, we indicate how that kind of data is stored, such as int, float1, short4 and more. A position comes in a Vector3 (which is composed of 3 floats). The next argument is the most important one: it describes the kind of information, such as position, color, texture coordinate, tangent, etc you are passing. This is needed, so XNA can automatically link the right data from our vertex stream to the right variables in our vertex shaders.

    For the last argument, suppose you would like to add 2 textures to a triangle. This implicates you would have to pass 2 sets of texture coordinates along with each vector. For this, you can use the last argument, which is the index of each info. Since we’ll only be passing 1 position and 1 color for each vertex, this will be 0 for both lines.

    For our color, we do pretty much the same. It is still part of vertexstream 0, but because it is preceded by the position it can’t be found at offset 0. The position consists of 3 floats, this is what we need to indicate (a float occupies 4 bytes, so sizeof(float)*3 is 12, which is the offset in bytes to the color information). Although a color is in fact a Vector4 (4 floats: the RGBA values), we need to specify Color, because each value needs to be mapped within the range [0..1] before it can be passed to the vertex shader as a color. This is an exception.

    Now let’s change our code so we’ll be using our MyOwnVertexFormat instead of the VertexPositionColor struct. Change our SetUpVertices to this:

     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);
     }

    Easy enough, since we provided all details needed in our struct. Even better, since the vertexbuffer knows which kind of vertices it stores, we don’t have to change anything else.

    OK, we have recreated the pre-built VertexPositionColor struct. When you run the code, you should see the same triangle. Only this time, you know how what the VertexDeclaration contains and, more important, you know how to extend a vertex format. We will practice this in a later chapter.




    DirectX Tutorial 3 - Vertex format

    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:
  • Need light in my scene
          Hi everyone well i stoped folowing the chapter ca...
  • passing non-displayed data to the GPU?
          When I first had the idea of creating bones for an...
  • why float*3 instead of Vector3?
          Hey, In the static VertexElements we define an ...
  • Question about SizeInBytes Equation
          Hi - I had a question on some ambiguity I encounte...


    This is what the XNA code should look like, with the integration of our own vertex format:

     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> ("effects"); 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["ColoredNoShading"];
                 effect.Parameters["xView"].SetValue(viewMatrix);
                 effect.Parameters["xProjection"].SetValue(projectionMatrix);
                 effect.Parameters["xWorld"].SetValue(Matrix.Identity);
     
                 foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                 {
                     pass.Apply();
     
                     device.SetVertexBuffer(vertexBuffer);
                     device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
                 }
     
                 base.Draw(gameTime);
             }
         }
     }
     


    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!