Chad Vernon
  • Home
  • Reel/Resume
  • Work
  • Resources
  • About
  • Contact
sideBar

Search

Categories

  • CG
  • cvxporter
  • Maya
    • API
    • Plug-ins
  • Personal

Archives

  • September 2011
  • June 2011
  • March 2011
  • December 2010
  • November 2010
  • September 2010
  • August 2010
  • July 2010
  • May 2010
  • April 2010
  • March 2010
  • December 2009
  • October 2009
  • September 2009
  • August 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007

Rss

  • Main Entries RSS
  • Comments RSS
Home » Resources » DirectX 9 » Dynamic Buffers

Dynamic Buffers

  CU_DynamicBuffers.zip (28.1 KiB, 2,529 hits)

In the Vertex and Index Buffers tutorial, we worked with static buffers. We didn’t alter the vertex data once we put it in the buffer. Dynamic vertex buffers allow us to alter data in a vertex buffer, which lets objects deform and change shape. When we use dynamic buffers, we usually change the contents of the buffer each frame. Some uses for dynamic buffers include particle engines and skinned meshes.

Static buffers are filled up once and then sent off to be rendered. Dynamic buffers, on the other hand, are filled up, rendered, filled up again with updated geometry, rendered, and so on. This tutorial shows you how to use a dynamic vertex buffer to create a basic particle effect. Each frame we will fill up the buffer with particles that are moved slightly from their previous positions.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Initialize application-specific resources and states here.
Returns: TRUE on success, FALSE on failure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL CGameApp::Initialize()
{

g_positions = new D3DXVECTOR3[1000];
g_speeds = new D3DXVECTOR3[1000];

// Seed random number generator
srand( (UINT)time(NULL) );
for ( int i = 0; i < 1000; i++ )
{

g_speeds[i].x = ((float)rand() / RAND_MAX * 1000.0f – 500.0f) / 50.0f;
g_speeds[i].y = ((float)rand() / RAND_MAX * 1000.0f – 500.0f) / 50.0f;
g_speeds[i].z = 0.0f;

g_positions[i].x = g_positions[i].y = g_positions[i].z = 0.0f;

}
return TRUE;

}

First, we’ll create two D3DXVECTOR3 arrays to store each particles’ position and velocity vector. The speeds are all randomly generated. We need to keep track of each particles’ position and speed in order to update the particles every frame.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary:
This callback function will be called immediately after the Direct3D device has been created. This is the best location to create D3DPOOL_DEFAULT resources. Resources created here should be released in the OnLostDevice callback.
Parameters:
[in] pDevice – Pointer to a DIRECT3DDEVICE9 instance
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void CGameApp::OnResetDevice( LPDIRECT3DDEVICE9 pDevice )
{

// Create the buffer
m_VB.CreateBuffer( pDevice, 1000, D3DFVF_XYZ | D3DFVF_DIFFUSE, sizeof( CUSTOMVERTEX ), TRUE );

// Clip…

float pointSize = 3.0f;
pDevice->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&pointSize) );

}

Second, we create the vertex buffer. Dynamic vertex buffers cannot be made in the D3DPOOL_MANAGED memory pool, therefore, we’ll create in in the D3DPOOL_DEFAULT memory pool. Since it is in the default memory pool, we create it in the OnResetDevice method. The CVertexBuffer class that we created in the vertex and index buffers tutorial supports the creation of dynamic buffers; we just set the last parameter to TRUE, which if not specified, is FALSE by default.

We can control the size of each particle by setting the D3DRS_POINTSIZE render state.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Creates the vertex buffer.
Parameters:
[in] pDevice – Pointer to IDirect3DDevice9
[in] numVertices – Max number of vertices allowed in the buffer
[in] FVF – Flexible Vertex Format
[in] vertexSize – Size of the vertex structure
[in] dynamic – TRUE for dynamic buffer, FALSE for static buffer
Returns: TRUE on success, FALSE on failure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL CVertexBuffer::CreateBuffer( LPDIRECT3DDEVICE9 pDevice, UINT numVertices, DWORD FVF, UINT vertexSize, BOOL dynamic )
{

Release();
m_numVertices = numVertices;
m_FVF = FVF;
m_vertexSize = vertexSize;

// Dynamic buffers can’t be in D3DPOOL_MANAGED
D3DPOOL pool = dynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
DWORD usage = dynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : D3DUSAGE_WRITEONLY;
if ( FAILED( pDevice->CreateVertexBuffer( m_numVertices * m_vertexSize, usage, m_FVF, pool, &m_pVB, NULL ) ) )
{

SHOWERROR( “CreateVertexBuffer failed.”, __FILE__, __LINE__ );
return FALSE;

}

return TRUE;

}

This is the buffer creation method in CVertexBuffer. When we specify a dynamic buffer, it will place the buffer in the D3DPOOL_DEFAULT memory pool and use D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC as its usage flag.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Updates the current frame.
Parameters:
[in] pDevice – Pointer to a DIRECT3DDEVICE9 instance
[in] elapsedTime – Time elapsed since last frame
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void CGameApp::OnUpdateFrame( LPDIRECT3DDEVICE9 pDevice, float elapsedTime )
{

// Create the new vertices
CUSTOMVERTEX verts[1000];
for ( int i = 0; i < 1000; i++ )
{

g_positions[i] += g_speeds[i] * elapsedTime;
// Constrain points
if ( g_positions[i].x < -7.0f || g_positions[i].x > 7.0f ||
g_positions[i].y < -5.0f || g_positions[i].y > 5.0f )
{

g_positions[i].x = 0.0f;
g_positions[i].y = 0.0f;

}
// Form colors based on distance from origin
// Lots of parabola shift and squeeze math going on.
float distanceFromOrigin = D3DXVec3Length( &g_positions[i] );
int red = -(int)(distanceFromOrigin * distanceFromOrigin * 15.0f) + 255;
red = (red < 0) ? 0 : red;
red = (red > 255) ? 255 : red;
int green = -(int)((distanceFromOrigin – 5) * (distanceFromOrigin – 5) * 15) + 255;
green = (green < 0) ? 0 : green;
green = (green > 255) ? 255 : green;
int blue = -(int)((distanceFromOrigin – 8) * (distanceFromOrigin – 8) * 15) + 255;
blue = (blue < 0) ? 0 : blue;
blue = (blue > 255) ? 255 : blue;
D3DCOLOR color = D3DCOLOR_XRGB( red, green, blue );
ZeroMemory( &verts[i], sizeof( CUSTOMVERTEX ) );
verts[i].x = g_positions[i].x;
verts[i].y = g_positions[i].y;
verts[i].z = g_positions[i].z;
verts[i].color = color;

}
// Fill up the buffer with the new vertices
m_VB.SetData( 1000, verts );

}

This is the heart of dynamic buffers: updating it’s contents. Each frame, we update the particles’ position with the corresponding velocity vector. To create the illusion of particles being emitted, I reset the position of a particle to the origin whenever the particle goes outside of the bounding rectangle. The color is calculated based on the distance of the particle from the origin. The exact numbers took some tweeking until I got the effect that I wanted. Basically, I used the parabola equation y = x^2 for each color component. Using our clever math skills, we know we can shift a parabola with y = (x-shift)^2, and we can squeeze a parabola with y = (squeeze)x^2. Color components must have a value between 0 and 255 so I constrain the values to this range. Once all the positions and color values are set, I can insert_ the vertex data into the vertex buffer the SetData method that we implemented.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Renders the current frame.
Parameters:
[in] pDevice – Pointer to a DIRECT3DDEVICE9 instance
[in] elapsedTime – Time elapsed since last frame
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void CGameApp::OnRenderFrame( LPDIRECT3DDEVICE9 pDevice, float elapsedTime )
{

pDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 );
pDevice->BeginScene();

m_VB.Render( pDevice, 1000, D3DPT_POINTLIST );

pDevice->EndScene();
pDevice->Present( 0, 0, 0, 0 );

}

Since we want to render a series of points, we use the D3DPT_POINTLIST primitive type. As you can see, dynamic buffers can be used to create many interesting effects.

No Responses to “Dynamic Buffers”

Subscribes to this topic Comment RSS or TrackBack URL

Leave A Reply

Allowed tag : <blockquote>, <p>, <code>, <em>, <small>, <ul>, <li>, <ol>, <a href=>..

 Username

 Email Address

 Website

Sticky: Always double check your comment before posting Please Note: Comment Moderation Maybe Active So There Is No Need To Resubmit Your Comments
Home » Resources » DirectX 9 » Dynamic Buffers

© 2011 Chad Vernon