DirectX SDK

Accessing the Contents of a Vertex Buffer

[C++]

Vertex buffer objects enable applications to directly access the memory allocated for vertex data. You can retrieve a pointer to vertex buffer memory by calling the IDirect3DVertexBuffer7::Lock method, then access the memory as needed to fill the buffer with new vertex data, or to read any data it already contains.

The IDirect3DVertexBuffer7::Lock method accepts three parameters. The first, dwFlags, tells the system how the memory should be locked, and can be used to hint how the application will be accessing the data within the buffer. (You can hint for read-only or write-only access, which allows the driver to lock the memory to provide the best performance given the requested access type. These hints are not required, but can improve performance for memory access in some situations.) Because vertex buffers use DirectDrawSurface objects to contain vertex data, the flags that IDirect3DVertexBuffer7::Lock accepts are identical to those accepted by the IDirectDrawSurface7::Lock method, with identical results.

The second parameter accepted by the Lock method, lplpData, is the address of an LPVOID variable that will contain a valid pointer to the vertex buffer memory if the call succeeds. The last parameter, lpdwSize, is the address of a variable that will contain the size, measured in bytes, of the buffer at lplpData after the call returns. You can set lpdwSize to NULL if your application doesn't need information about the buffer size.

Performance Notes  Use the DDLOCK_READONLY flag if your application will only be reading from the vertex buffer memory. Including this flag enables Direct3D to optimize its internal procedures to improve efficiency, given that access to the memory will be read-only. Although it is possible to write to memory locked with the DDLOCK_READONLY flag, doing so can produce unexpected results. In addition, attempting to read from a vertex buffer that was created with the D3DVBCAPS_WRITEONLY flag can be extremely slow, even if you lock the buffer for read-only access.

In C++, you directly access the memory allocated for the vertex buffer. As such, you must take care that your application properly accesses the allocated memory, or risk rendering that memory invalid. Use the stride of the vertex format your application uses to move from one vertex in the allocated buffer to another. The vertex buffer memory itself is a simple array of vertices, specified in flexible vertex format. If your application is uses the legacy vertex structures, D3DVERTEX, D3DLVERTEX, and D3DTLVERTEX, the stride is simply the size of the structure, in bytes. If you are using a vertex format different from the legacy formats, use the stride of whatever vertex format structure you define. You can calculate the stride of each vertex at run time by examining the flexible vertex format flags contained within the vertex buffer description. The following table shows the size for each vertex component.

Vertex Format Flag Size
D3DFVF_DIFFUSE sizeof(DWORD)
D3DFVF_NORMAL sizeof(float) × 3
D3DFVF_SPECULAR sizeof(DWORD)
D3DFVF_TEXn sizeof(float) × 2 × n
D3DFVF_XYZ sizeof(float) × 3
D3DFVF_XYZRHW sizeof(float) × 4

The number of texture coordinates present in the vertex format is described by the D3DFVF_TEXn flags (where n is a value from 0 to 8). Because each set of texture coordinates in the vertex format occupies the space of two float variables, multiply the number of texture coordinate sets by the size of one set of texture coordinates to calculate the memory required for that number of texture coordinates.

Use the total vertex stride to increment and decrement the memory pointer as needed to access particular vertices.

[Visual Basic]

Vertex buffers enable Visual Basic applications to easily update the vertex data they contain. You prepare to access the contents of the vertex buffer by calling the Direct3DVertexBuffer7.Lock method. The Lock method offers the flags parameter to tell the system how the memory should be locked. The flags parameter hints to the system how the application will be accessing the data within the buffer. (You can request read-only or write-only access, which allows the driver to lock the memory to provide the best performance given the requested access type. These hints are not required, but can improve performance for memory access in some situations.) Because vertex buffers use DirectDrawSurface objects to contain vertex data, the flags that Direct3DVertexBuffer7.Lock accepts are identical to those accepted by the DirectDrawSurface7.Lock method, with identical results.

Performance Notes  Use the DDLOCK_READONLY flag if your application will only be reading from the vertex buffer memory. Including this flag enables Direct3D to optimize its internal procedures to improve efficiency, given that access to the memory will be read-only. Although it is possible to write to memory locked with the DDLOCK_READONLY flag, doing so can produce unexpected results. In addition, attempting to read from a vertex buffer that was created with the D3DVBCAPS_WRITEONLY flag can be extremely slow, even if you lock the buffer for read-only access.

Once the vertex buffer is locked, you can call the Direct3DVertexBuffer7.GetVertices method to fill an array with the current contents of the vertex buffer. Set the first parameter to the zero-based index of the first vertex in the buffer to need and set the second parameter to the total number of vertices to retrieve. The last parameter should be the first element in an array that uses the same vertex format as the vertex buffer, which will contain the requested data after the call.

The vertex buffer memory itself is a simple array of vertices, specified in flexible vertex format. The number of texture coordinates present in the vertex format is described by the D3DFVF_TEXn flags (where n is a value from 0 to 8). Because each set of texture coordinates in the vertex format occupies the space of two Single variables, multiply the number of texture coordinate sets by the size of one set of texture coordinates to calculate the memory required for that number of texture coordinates.

To change the contents of the vertex buffer after it is locked, modify the contents of the array, then call the Direct3DVertexBuffer7.SetVertices method to copy the vertices into the buffer. You must also unlock the vertex buffer by way of the Direct3DVertexBuffer7.Unlock method before performing any vertex buffer processing or rendering operations.