Thursday, October 18, 2012

Using a texture for data

For coloring the world I was putting the color value into the vertex. then in the pixel shader i would multiple the color by that color percent. this worked, however it depended on the size of the triangle and even more importantly it required changing of vertex data. So I had a dynamic vertex buffer and was setting data to it each frame. However this became a problem when the grass was added as it had 17 vertices and 84 thousand objects.
So after reading an article about GPU particle systems from Jon, i realized I could use a texture to hold the color value of that area. The texture would be like a grid over the world such that every spot on the world points to a pixel in the texture (which holds a float of its color value). I can calculate that location in the pixel shader (or vertex shader for the grass) by (position.X - minWorldPosition.X) / worldSize.X. Then i can do the same for the Z axis. I do not consider the Y axis for this, although i could use a 3D texture if i wanted to include the Y axis.
The nice thing about this is to change it i do a draw call and the GPU handles it (which is very optimed for exactly this). I have a circle in a vertex buffer which is what i actually do the draw call on. I set a scale and translation matrix for that circle in the shader so the circle will be centered to where i want it and the size i want. I wrote the circle's vertex positions in screen space (which is really texture space) so i only needed to scale and translation, not project.
This would set all of the values on that circle to the color percent. However i also wanted a gradient. So I used the Z value of the vertex position (of the circle's vertices). I wasn't using the Z value because i was drawing right to a texture of floats, aka i didn't have a depth buffer and so wasn't doing any depth testing. I set the center of the circle to a Z value of 1 and the outside edges to 0. Then when the pixel shader got that value it was between 1 and 0 for how far out it is from the center. Thus i can set it darker or lighter according to how close it is to the center.
Then for lighting the world i used an alpha blending of Max. Where it would take the larger value between the value i was setting from the draw call and the value that was already on the texture. And for darkening i used a Min alpha blending.

Overall this helped the efficiency of this tremendously. Although the grass itself still needed more optimization (such as cpu visibility culling). But i learned a lot about shaders doing this process and any time i need to pass a lot of dynamic data to a shader i will first look into using a texture.

No comments:

Post a Comment