I’ve been largely googling but found nothing about it. I’d like to replace a call to glTranslated function in order to improve performance in my code. In its current status it looks like:
glVertexPointer(3, GL_DOUBLE, 0, &Vertex);
glTranslated(d->r[j].x, d->r[j].y, d->r[j].z);
glDrawArrays(GL_TRIANGLES, 0, Vertex.size()/3);
What I’d want is to do translation myself to “Vertex” data and so I’ll be able to bring it out of the loop. This way I’ll be able to render some millions of objects using one call to “glDrawArrays”.
Any help would be appreciated.
Thanx in advance.
Perhaps I’m misunderstanding what you want to do, but modifying the vertex data (moving the vertices to translated position) does not seem the way to improve performance - after all you would move operations from the GPU to the CPU.
If you need to render millions of copies of your object you could move away from the fixed function pipeline, store the transformations for all objects in a buffer object that is accessible to your shaders, and use instanced draw calls (glDrawArraysInstanced, etc.) to draw all copies at once. The shader would use the instance id to determine the correct transformation to apply to the current copy of the object.
Thanx Mr Neumann. At this point “Vertex” has positions & normals describing an icosahedron, say 5000-50000 triangles. I plot millions of such icosahedrons/spheres in different positions. As you see in the code I put all triangles in “Vertex” array, plot the ball, translate it, plot again, …
I’ll be happy if I find the way to store in “Vertex” not a ball but 1000 balls and then plot them.
But what you propose seems better. Could you give me a pointer to a tutorial to help me in replacing my code?
If I’m not wrong what I’ve used us called a vertex array object (VAO) plotted with glDrawArrays, and what you propose is a VBO, but can’t imagine how to plot it.
What you’re using is a vertex array. A VAO is something else (specifically, a container object for state related to vertex arrays).
What Carsten Neumann is suggesting is instanced rendering, where you store the vertices for one ball in an array and 1000 transformations in another array, then render the “product” of the two arrays to create 1000 balls.
Instanced rendering requires the use of a vertex shader to combine the two pieces of data (the vertex position and the transformation). Shaders are a substantial topic, but one which is worth learning because modern OpenGL revolves around them (e.g. OpenGL ES 2/3 and WebGL require the use of shaders; you can’t render anything without them).
The main issue with using instanced rendering is that it requires at least OpenGL 3.3, so if you need to support ancient hardware, it isn’t an option.
Search for “OpenGL shader tutorial” and/or “GLSL” for tutorials about using OpenGL with shaders. The first step should be to get something similar to your existing code working using a vertex shader (and optionally a fragment shader, but that’s less important right now). You should also be able to replace the use of glVertexPointer() with glVertexAttribPointer().
Once you have that, instanced rendering involves replacing glDrawArrays() with glDrawArraysInstanced(), replacing the uniform variable holding the transformation matrix with a vertex attribute, creating an attribute array for the transformations, and using glVertexAttribDivisor() to make the data in that array per-instance rather than per-vertex. The preceding sentence should make more sense to you once you’re familiar with using vertex shaders.
If you can’t use instanced rendering, and want to put 1000 distinct balls into a single vertex array, then you simply need to translate the vertex positions based upon the ball to which they belong. That is simply a case of adding d->r[j] to each vertex position.
Thanks a lot. I think my problem seems to be converting my old OpenGL code to new version of the library. I’m begining with it.
Anyway I’ll face the same problem I mentioned in my first post: simply adding d->r to each vertex doesn’t work because previous rotations in data. I need to make the same work as “glTranslated”, which must involve getting the model matrix, multiplying by translation matrix to all data and restoring previous matrix or so.
Previous transformations don’t matter. Each new transformation is multiplied on the right, so the effect is the same as applying the transformations to the data in the reverse order. (A.B).v = A.(B.v). So this
glTranslatef(dx, dy, dz);
glVertex3f(x, y, z);
is equivalent to this:
glVertex3f(x+dx, y+dy, z+dz);
regardless of any previous transformations:
If you need to apply multiple transformations to the data, compose them into a matrix then use the matrix to transform the data.
I think kzanol means that the translation from the previous frame is added to the vertex positions. If that is indeed the problem, you’ll have to keep an unmodified copy of the data around.