Passing large arrays of data to vertex shaders

| No Comments | No TrackBacks
As a follow-on to saturday's post about sampling textures in the vertex shader, I thought I'd write up some quick notes on how you can pass data to a vertex shader through textures. Again, this is another one of those things that articles talk about doing but rarely show full examples on how to actually do it. Some times I wonder if the authors of these articles didn't actually get it working of if they kept it a secret because it gives them an advantage.

You can pass large arrays of data to a vertex shader by storing the data in a 1D or 2D texture. Sampling the texture I covered previously, you basically use the tex2Dlod() function in HLSL (texldl is the shader assembly call). The trick here is: how do you get the data into a texture and then to the vertex shader?

Currently only floating point textures are supported by today's vertex shader hardware, so the data needs to be stored in one of these formats:

D3DFMT_R32F: 32-bit float format using 32 bits for the red channel.
D3DFMT_A32B32G32R32F: 128-bit float format using 32 bits for the each channel (alpha, blue, green, red).

Direct3D doesn't allow you to modify textures stored in video memory, so you'll to create two textures. One of these textures will be stored in video memory, the other in system memory. Whenever you need to change the data passed to the vertex shader you'll need to change it in the system memory texture and then copy it over the video memory texture. Try not to do this every frame or you'll kill performance. Most papers I've read suggest doing this update in a background thread so that you don't affect rendering performance. It probably depends upon your application.

Here's how you create your two textures:

hr = D3DXCreateTexture(
m_pD3DDevice,
width,
height,
D3DX_DEFAULT,
NULL,
D3DFMT_R32F,
D3DPOOL_SYSTEMMEM,
&_systemtex);

hr = D3DXCreateTexture(
m_pD3DDevice,
width,
height,
D3DX_DEFAULT,
D3DUSAGE_RENDERTARGET ,
D3DFMT_R32F,
D3DPOOL_DEFAULT,
&_videotex);

To update the texture, do the following:

D3DLOCKED_RECT rect;
hr = _systemtex->LockRect(0, &rect, NULL, NULL);
FLOAT *pbits = (FLOAT *) rect.pBits;

for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
pbits[y * width + x] = sinf(x);
}
}

hr = _systemtex->UnlockRect(0);
hr = m_pD3DDevice->UpdateTexture(_systemtex, _videotex);

These examples assume the R32F format, obviously if you use the 4 float format things will be a little different.

No TrackBacks

TrackBack URL:

Leave a comment

Myself

Projects

Monthly Archives

Photos

About this Entry

This page contains a single entry by Robert W. Rose published on May 30, 2005 3:08 PM.

Vertex texture sampling notes was the previous entry in this blog.

On the Intel-Apple talks is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.