The process of adding another property to
a vertex definition isn’t very complicated but does require a change to
the layout of the vertex in memory. To demonstrate the process, I’m
going to walk you through adding vertex colors to the vertex structure.
1. Vertex Colors
Vertex colors allow each vertex in an object to
have a color associated with them. When drawing an object, the edges are
colored based on the color of the vertices. Sometimes the vertex colors
are all the same, but most of the time they’re different, allowing for a
shift in the color during rendering.
In the previous examples,
you weren’t specifically passing around a color for your vertices, but
one was defined for you. Within the vertex shader in the simple.fx file
you’ve been using, a default color was being passed along from the
vertex shader to the pixel shader causing your objects to appear yellow.
You’ll see the code for the vertex shader here with the color portion
in bold.
////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS(float4 Pos : POSITION)
{
PS_INPUT psInput;
psInput.Pos = Pos;
psInput.Color = float4(1.0f, 1.0f, 0.0f, 1.0f);
return psInput;
}
Instead of the shader implementing this
functionality with a default color, you’re going to learn how to set the
color of each vertex when you create it and then how to pass this value
down to the shader to be used.
Updating the Custom Vertex Structure
The first step to adding the support for vertex
colors is the updating of the custom vertex structure. Since vertex
colors can support any 32-bit RGBA color value, they’re going to be
stored using a D3DXVECTOR4 type. You can see the updated vertex structure here:
struct VertexPosColorStruct
{
D3DXVECTOR3 Pos;
D3DXVECTOR4 Color;
};
I’ve updated the name of the structure to
reflect the change to the included types. As you build new vertex
structures, it helps to make sure the structure name gives a hint to the
type of data it contains.
Now that the vertex structure is updated, you
can create arrays of vertices using the new format. Each item in the
array in the following code contains both a position and vertex color.
// Create vertex buffer
// Define both a position and a vertex color
VertexPosColorStruct vertices[] =
{
{ D3DXVECTOR3(0.0f, 0.5f, 0.5f), D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f) },
{ D3DXVECTOR3(0.5f, -0.5f, 0.5f), D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f) },
{ D3DXVECTOR3(-0.5f, -0.5f, 0.5f), D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f) },
};
Each vertex being
created has a different color associated with it. Any new properties
that you add to the vertex structure can be initialized with a default
value in this manner.
At this point you can create arrays of vertices
using the new properties, but Direct3D still isn’t aware of the change;
you need to update the vertex layout. The following layout supports both
a vertex position and color but can be updated to support any number of
new properties.
// 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 },
};
That’s all there really is to it. Any new
vertices you define using the updated structure will contain the new
property. Even though it seems like very little effort, I wanted to walk
through the entire process to make sure you knew every piece that was
involved. At this point, all the changes are done for the code side of
things, but there is a small change to be made to the shader before
rendering will work properly.
Shader Changes
Previously, the color of the vertex was
determined by a hard coded color value in the shader. Now that the
vertex structure allows the color to be defined within the vertex
structure, the shader needs to change slightly to handle this.
The vertex shader was only allowing for a vertex
position to be passed in before. To support vertex colors properly, the
vertex shader needs to allow for the color to be passed in as well as
the position. This gives the vertex shader access to the color value
defined in the vertex structure. Since the shader is going to allow the
color to remain as it was set, it will just pass the color value along
to the pixel shader without making any changes. You can see in the
following shader code where the psInput.Color is set to the input color value passed into the vertex shader.
The pixel shader doesn’t actually have to be
changed in any way since the color from the vertex shader was already
being passed out as the final color value.
// PS_INPUT - input variables to the pixel shader
// This struct is created and filled in by the
// vertex shader
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};
////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS(float4 Pos : POSITION, float4 Color : COLOR)
{
PS_INPUT psInput;
// Pass through both the position and the color
psInput.Pos = Pos;
psInput.Color = Color;
return psInput;
}
///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
float4 PS(PS_INPUT psInput) : SV_Target
{
return psInput.Color;
}
Vertex colors were just an example of the types of information that can be added to a vertex definition.
Figure 1 shows the updated triangle.