ofVBO Mesh instancing & transformations

I’m finally starting to using ofVboMesh’s drawInstanced() function to create multiple copies of a mesh.

It’s not too difficult to change the position and color of each instance, but I’m at a loss to figure out how to rotate or scale them.

Here’s the vertex shader I’m using with for instancing … it’s using an array of positions

#version 120
#extension GL_EXT_gpu_shader4 : require

uniform vec3 positions[300];		// positions of shape (testing)
uniform vec3 colors[300];			// color of shape (testing)
varying vec4 colorVarying;			// color of shape (varying)

  // ---------------------------------------------------------------------- 

 void main() {

// when drawing instanced geometry, we can use gl_InstanceID
// this tells you which primitive we are currently working on

// make 'em boxes red
colorVarying = vec4(colors[gl_InstanceID], 1.0);

// add it to the position of each vertex
vec4 vPos = gl_Vertex + vec4(positions[gl_InstanceID], 0); //( x, y, z, 0);

// then multiply by the mv projection matrix
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vPos;
 
}

Thanks a million for any tips

1 Like

Ended up figuring this out with a little help from @joshuajnoble.

The trick was to use individual matrices for each instance. This is done by giving the shader a pointer to an array of ofMatrix4x4s. The following snipped is a modification of vboMeshDrawInstancedExample that ships with OF.

// orientation of instances
ofMatrix4x4 mats[4];
mats[0].makeRotationMatrix( ofGetFrameNum()+66, ofVec3f(0, 1, 0));
mats[1].makeRotationMatrix( ofGetFrameNum(), ofVec3f(1, 0, 0));
mats[2].makeRotationMatrix( ofGetFrameNum()+265, ofVec3f(0, 0, 1));
mats[3].makeRotationMatrix( ofGetFrameNum()+220, ofVec3f(1, 1, 0));

// set transformations (mat4)
GLuint loc = glGetUniformLocation(mShdInstanced->getProgram(), "transformMatrix");
if( loc != -1 ) glUniformMatrix4fv(loc, 4, GL_FALSE, mats[0].getPtr()); 

Seems like there’s some need in ofShader for a function that allows for passing an array of matrices.

void setUniformMatrix4f(const string & name, const ofMatrix4x4 & m, int count);

For those who are interested, I put it all together in a 'lil gist: https://gist.github.com/mantissa/8220909

Jeremy

4 Likes

Awesome! Will try this out shortly. Passing a matrix to a shader is usually done by interleaving a set of vec4 or just assembled shader side, but we could provide something nice in OF to wrap it.

Edit - I’m wrong about the mat4, it’s actually easy, that’s what I get for writing this on my phone :slight_smile:

@joshuajnoble glad to hear that – i was slightly concerned this might not be a snappy & efficient approach