MULTIMEDIA

DirectX 10 Game Programming : 3D Introduction - The Triangle

2/17/2013 6:48:50 PM

You’ve probably realized that most examples start out with drawing a single triangle and you might wonder why. Like most programming languages, even Direct3D has its own “Hello World” example in the form of a triangle. It’s the most simple and straightforward way to describe all the steps needed for 3D drawing without introducing a bunch of extra code; things that at this point would only help to confuse and take away from the lesson.

After you’ve endured the triangle, you’ll build on this simple example, adding complexity but always understanding why and how it all comes together.

Vertices

The most basic element making up any 3D object is the vertex. Vertices are the building blocks from which all other primitives are constructed. Even a triangle relies on three vertices to make up its simple shape. The vertices dictate the exact location in space where the sides of the triangle come together.

Vertices, at their most simple form contain at least a position coordinate. This coordinate contains the same number of components as the space has axes. For a 2D coordinate system, a vertex will define its position by using only X and Y component values. When moving into a 3D space, a third component, Z, is needed.

Vertices are commonly defined in Direct3D using either the D3DXVECTOR2 or D3DXVECTOR3 structure types. Both of these types contain multiple float values, each one referring to a separate axis. Below you can see an example of how the D3DXVECTOR3 structure is defined. As you can see, there are three components allowing for positioning within 3D space.

typedef struct D3DXVECTOR3 {
    FLOAT x;
    FLOAT y;
    FLOAT z;
} D3DXVECTOR3;

An individual D3DXVECTOR3 structure can represent a single vertex; because triangles have three sides, three of these structures must be filled out. Direct3D also has a D3DXVECTOR4 type, which is useful when storing vertex colors.

Custom Vertex Structure

As you progress into the world of 3D, you’ll find that all the objects you create will be made up of different types of vertices. Vertices can have any number of properties associated with them, from position, color, texture coordinates, and normals. Because of the dynamic nature of vertices, Direct3D requires you to define the properties of the vertices you’ll be using. Vertices are defined using a structure, allowing you to group all the properties needed together. An example vertex structure containing only the property for position is shown here:

struct VertexPosStruct
{
    D3DXVECTOR3 Pos;
};

The vertex structure is then used to declare an array of vertices, containing all the vertices that are needed to make up an object. To demonstrate, a triangle can be defined using the vertices in the array below.

// Define the vertices for a triangle
VertexPosStruct vertices[] =
{
    D3DXVECTOR3(0.0f, 0.5f, 0.5f),
    D3DXVECTOR3(0.5f, -0.5f, 0.5f),
    D3DXVECTOR3(-0.5f, -0.5f, 0.5f),
};

Most of the objects you create will be much more complicated than a simple triangle, but even this one triangle requires the same set up and rendering path as a complicated 3D monster.

Vertex Input Layout

Now that you’ve defined what your vertex structure will look like, it’s time to put it into a format that Direct3D can understand: the input layout.

The input layout defines how the vertices will be fed through the pipeline. As vertices are passed through the pipeline, Direct3D needs to know how to access the properties contained within each vertex. The input layout defines not only the order of the vertex properties, but also their size and type.

When defining an input layout, each property of a vertex can be described using a D3D10_INPUT_ELEMENT_DESC structure.

typedef struct D3D10_INPUT_ELEMENT_DESC {
    LPCSTR SemanticName;
    UINT SemanticIndex;
    DXGI_FORMAT Format;
    UINT InputSlot;
    UINT AlignedByteOffset;
    D3D10_INPUT_CLASSIFICATION InputSlotClass;
    UINT InstanceDataStepRate;
} D3D10_INPUT_ELEMENT_DESC;

Each vertex property needs one of these input element structures filled out. The structures are then included in an array and used by Direct3D to create the input layout.

The following code shows an example of how to define a layout for a vertex with both a position and a color.

// The vertex input layout
D3D10_INPUT_ELEMENT_DESC layout[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
D3D10_INPUT_PER_VERTEX_ DATA, 0 },
};

// Calculate the number of elements in the layout array
UINT numElements = ( sizeof(layout) / sizeof(layout[0]) );

A few of the members of the D3D10_INPUT_ELEMENT_DESC structure are detailed next.

SemanticName is the name that the property will be referenced by within a shader. Most properties in a vertex have a default semantic name that can be used.

The member Format describes the size of the data this property represents. The position property uses the DXGI_FORMAT_R32G32B32_FLOAT value. This gives each position a 32-bit long float variable to use as storage.

AlignedByteOffset is the number of bytes that this property is offset from the start of the layout. For instance, position is first in the input layout so it has an AlignedByteOffset of 0. Color, which follows the position, has an offset of 12. This says that position requires 12 bytes at the front of the input layout. As it may be a bit confusing as to where the value of 12 came from, each member of the vertex position requires 32 bits or 4 bytes to store their value. Since there are three values needed to store a vertex position, it would take 12 bytes to hold this information.

Now that you’ve described the vertex properties, you can create the input layout object. The input layout object allows the input stage of the pipeline to know beforehand the format of the data it is ingesting. For more details on the input stage of the pipeline. The input layout object is based on the ID3D10InputLayout interface and is created using the CreateInputLayout function. The following code shows how this function is called.

// Get the pass description
D3D10_PASS_DESC PassDescription;
pTechnique->GetPassByIndex(0)->GetDesc(&PassDescription);

// Create the vertex input layout
hr = pD3DDevice->CreateInputLayout(layout,
     numElements,
     PassDescription.pIAInputSignature,
     PassDescription.IAInputSignatureSize,
     &modelObject->pVertexLayout);

if(FAILED(hr))
{
    return false;
}

You’ll notice that a call was made to fill in a D3D10_PASS_DESC object. D3D10_PASS_DESC is used to gather information about the shader that will be used when drawing this object, specifically the input signature. This makes sure that the vertex format used to define the object is the same format the shader expects later when drawing the object.

Note

Each object within a scene may be based on a different layout of vertex properties. Some may need only position, while others may require position and color. Not all objects are the same, so you’ll need to define a vertex input layout for objects using unique vertex properties.


Right before an object is drawn, the input layout for the object needs to be set. Since multiple items with different layouts can be drawn sequentially, Direct3D needs a way of knowing the layout of the next item it is about to draw. The IASetInputLayout function is used to do this. It takes the input layout object you created and makes it the active layout.

// Set the input layout
pD3DDevice->IASetInputLayout( pVertexLayout );
Other  
 
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone