Quote:Original post by spek
About building those matrices, you mean I should pass arrays with the positions, rotations, and maybe one with scales?
That would mean to keep a dedicated VBO per terrain patch. While this will work (and doesn't require CPU interference), it will take more memory and is less flexible.
If you have SM 3.0 capable hardware, then one could build it like this:
* Create a single generic VBO, that contains a number of origin centered squares, all aligned along the z axis. In addition to the vertex positions, each vertex gets a vertex attribute that assigns it to a patch ID. So, all four vertices forming a quad would get the same ID. This is so that the vertex shader can see to what patch a vertex belongs to.
* Create a patch attribute texture map: a group of texels represents one patch, and contain data about it's position, rotation and scale, as well as type (index into a texture atlas), and several other optional parameters.
* When rendering a terrain patch set, bind the corresponding grass patch attribute map so that you can access it in a vertex shader. Then, render the shared VBO, with as many quads as you need for the current patch.
* The vertex shader will use the patch ID index from the vertex to address the right attribute texels in the attribute map. It will then read back the patch attributes, and use them (combined with the current camera matrix) to form an billboard alignment matrix. Each pregenerated standard quad vertex gets transformed by this matrix. Finally, additional vertex parameters, such as texcoords, colours, etc, are also generated using the patch attributes.
Of course, depending on how smart you compress the attributes, this can take a few texture reads in the VS. And such reads are not (yet) as fast as one would like them to be. On the other hand, the fact that vertex attributes are stored as textures opens a whole new world for animation: you can use the GPU to modify the map. Using pixel shader tricks, you can animate the grass patches without ever needing the CPU (by rendering the original attribute map to a second one, and swapping them - think double buffering).