[Solved] Rookie Instanced Rendering Questions

I’m pretty new to (mesh based) instance rendering, so I hope you’ll bare with me on four rookie questions:

Q 1

Do OpenGL state calls impact instanced rendering? For example, will gl::scale() change the scale of any mesh rendered via the drawInstanced() call?

My testing so far suggests ‘No’. Which leads to these follow up questions:

Q 2

Do any OpenGL state calls impact instance rendering? Enabling/Disabling the depth buffer definitely impacts the instance rendering as intended. So my assumption is that states that aren’t ‘mesh rendering’ related, work as normal, but anything that might touch the instance mesh won’t work?

Q 3

This being the case, if I wanted to scale my instances, it would seem that there are two ideal approaches to this:

If I want to scale all instances the same: Create a shader uniform value and have that alter the model matrix in the vertex shader.

If I want to scale all instances differently: Attach a custom value (float or full on transform matrix) to the Vbo and apply this in the shader.

Does this sound reasonable?

Q 4

Is it possible to pass per-vertex coloring to geometry rendered via instanced rendering?

Thanks to awesome libcinder, it’s pretty easy to get some default color variety when instancing meshes. All it takes (apparently) is this type of call: ci::gl::VboMesh::create( ci::geom::Cube().colors() );, where colors() is used, and then ensuring that the shaders also support the incoming color values.

But what if I wanted to replace the colors of a cube instance with per-vertex colors?

If I want to have a single color per-instance (not per vertex), I believe the call to setup the Vbo layout looks as follows:

ci::geom::BufferLayout instanceDataLayout;
instanceDataLayout.append( ci::geom::Attrib::COLOR, 4, sizeof( ci::ColorA ), 0, 1 );

The last parameter being set to 1 I believe is the ‘per instance’ count.

Is this the value I need to tweak to be equal to ‘vertex count per mesh’ to have it work like a per-vertex per-instance effect…?

~Gazyou

Hi!

  1. Yes, gl::scale() and the likes will impact the instanced meshes, but only if your vertex shader supports it. Cinder provides the current model matrix as a uniform: ciModelMatrix. There are also combined matrices like ciModelView or ciModelViewProjection. In your vertex shader, you can then do something like:
uniform mat4 ciModelViewProjection;

in vec4 ciPosition;

in vec4 iParams; // per instance, could be anything

void main(void) {
    // Do something per instance, up to you:
    vec4 position = ciPosition;
    position.xyz = position.xyz * iParams.w + iParams.xyz;
    // Apply current model, view and projection matrices.
    gl_Position = ciModelViewProjection * position; 
}
  1. All states impact instance rendering, as long as the pipeline applies the state. This goes for depth testing, culling, scissors, draw color, etc. Just remember that instanced rendering requires you to write a custom vertex shader and the shader needs to use the state. See 1.

  2. Correct, but instead of creating your own uniform value, use Cinder’s built-in uniforms if you can.

  3. Yes. Per-vertex colors are accessible in the vertex shader as the in vec4 ciColor attribute. This color can be altered using per-instance data and passed to the fragment shader. Your code will replace Cinder’s default functionality with per-instance color data and each instance will get its own color.

~Paul

1 Like

Hello Paul - ltnr! :slight_smile:

Thanks for taking your time to respond.

  1. I looked into the vertex shader which I’d been using from the ‘quakes’ example from the cinder samples and turns out the Model matrix wasn’t being applied - so no wonder scale wasn’t doing anything.

  2. Gotcha!

  3. Good advice! In my case I wish to scale down each instance and then move into it’s own (per-instance) position. As I understand it, I can’t do that via a uniform, i.e. I have to define my own per-instance matrix, right?

  4. Appreciate the confirmation - I’ve not a need for it right now, but I could see it become useful in the near future. I guess then I have to figure out which order of colors apply to which order of vertices for the geom object I choose.

~Gazoo

Minor follow-up:

  1. I’m pretty convinced that per-instance matrix instances are required for individual behavior. Technically it wouldn’t have to be a full matrix, it could also just be a single float or something else.

Either way - very much appreciate the feedback @paul.houx !

Hi Gazoo,

in the example code I posted you can see that I use a vec4 to scale and translate the mesh. Because iParams is per-instance, all vertices of the instance will scale and translate the same. So, you don’t need a matrix for this, unless the transform is so complex that you can’t describe it otherwise.

~Paul