Dark Bit Factory & Gravity
PROGRAMMING => General coding questions => Topic started by: Raizor on October 24, 2011
-
If I have an object stored in a VBO, I can draw multiple instances of it very quickly.
However, I'm a little stumped as to the best way to draw multiple instances and have each instance translated or rotated. Is there a way to do this without using multiple glTranslate and glRotate calls? (as I imagine that will cause considerable slowdown).
Any pointers would be great (no pun intended) ;)
-
A couple things:
1. What you're talking about is called "instancing" - plenty of good info about this online; I'll have a look for you later when I have more time :)
2. Consider soon switching to another vector/matrix library instead of using the [deprecated!!] glTranslate/glRotate stuff. I *HIGHLY* recommend GLM (http://glm.g-truc.net/), which is essentially a templated C++ implementation of GLSL with added support for those old matrix functions. For instance, to set up some matrices in fixed-function OpenGL (probably with some mistakes; been awhile since I used them, hehe):
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, 16.0 / 9.0, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -20.0f); // Notice here we're actually setting up a view AND world matrix as one, which is not good (often it's quite nice to have separate matrices)
glRotatef(yRotation, 0.0f, 1.0f, 0.0f);
...and GLM:
mat4 proj = perspective(35.0f, 16.0f / 9.0f, 1.0f, 1000.0f);
mat4 view;
view = translate(view, vec3(0.0f, 0.0f, -20.0f));
view = rotate(view, yRotation, vec3(0.0f, 1.0f, 0.0f));
mat4 world; // Now we can have a separate matrix for world stuff :)
and of course you can make combinations for speed:
mat4 projView = proj * view;
mat4 projViewWorld = projView * world;
mat4 viewWorld = view * world;
And then just upload which matrices you need to your vertex shader (as uniforms), so you don't have to do all this matrix multiplication on the GPU. The REALLY kickass thing with glm is that if you know glsl, you know glm :) .
Anyways, back on the subject: it's called instancing, and you can probably find some good stuff about it with google :) feel free to post your findings; I don't actually know much about it myself and I'm quite curious.
-
Great info Ferris, thank you. I will read up on instancing and check out GLM.
I recall reading that there's a performance penalty when reading uniform variables within a shader, is this correct?
K++ (almost forgot)
-
Again, I highly recommend glm :) I use it in my demo engine and basically anywhere else I need that sort of thing (it's nice to have a vector/matrix lib that's decoupled from the graphics lib).
As far as reading uniforms, I don't recall there ever being a penalty. But, back on the subject of instancing, I suddenly remember that I actually have done it before in an Outracks demo (Partly Cloudy, with the black cube trails in the beginning).
If I remember correctly, I did it by specifying a vertex attribute that was the object's local matrix. I uploaded the matrices into a separate vertex buffer and had another index buffer that would index the matrices so I wouldn't need to store them for each vertex.. it was perfectly fine and fast to reupload just the matrix buffer each frame.
Apologies for being a bit vague about the details; it was a long time ago and done through their graphics engine, so I don't remember all of it myself :)
-
Not exactly instancing, but very much related: http://origin-developer.nvidia.com/docs/IO/8230/BatchBatchBatch.pdf?q=docs/IO/8230/BatchBatchBatch.pdf
Just had to read it for stuff I'm doing at work and found it oddly relevant :)