I have successfully set up a billboard shader that works, it can take in a quad and rotate it so it always points toward the screen. I am using this vertex-shader:

void main(){
vec4 tmpPos = (MVP * bufferMatrix * vec4(0.0, 0.0, 0.0, 1.0)) + (MV * vec4(
    vertexPosition.x * 1.0 * bufferMatrix[0][0], 
    vertexPosition.y * 1.0 * bufferMatrix[1][1], 
    vertexPosition.z * 1.0 * bufferMatrix[2][2], 

UV = UVOffset + vertexUV * UVScale;
gl_Position = tmpPos;

BufferMatrix is the model-matrix, it is an attribute to support Instance-drawing.

The problem is best explained through pictures:

This is the start position of the camera: start

And this is the position, looking in from 45 degree to the right: same, but 45 degrees to the right

Obviously, as each character is it's own quad, the shader rotates each one around their own center towards the camera. What I in fact want is for them to rotate around a shared center, how would I do this?

What I have been trying to do this far is:

 mat4 translation = mat4(1.0);
    translation = glm::translate(translation, vec3(pos)*1.f * 2.f);
    translation = glm::scale(translation, vec3(scale, 1.f));
    translation = glm::translate(translation, vec3(anchorPoint - pos) / vec3(scale, 1.f));

Where the translation is the bufferMatrix sent to the shader. What I am trying to do is offset the center, but this might not be possible with a single matrix..?

I am interested in a solution that doesn't require CPU calculations each frame, but rather set it up once and then let the shader do the billboard rotation. I realize there's many different solutions, like merging all the quads together, but I would first like to know if the approach with offsetting the center is possible.

If it all seems a bit confusing, it's because I'm a little confused myself.

  • \$\begingroup\$ So pretty much change the center of the transformation-matrix. \$\endgroup\$ Commented Oct 21, 2013 at 15:07
  • \$\begingroup\$ Why not rotate all the smaller quad around a single origin? \$\endgroup\$
    – vallentin
    Commented Oct 21, 2013 at 16:00
  • \$\begingroup\$ That is exactly what I want, I want to translate the center of each quad to the same center. In the code given, that point is called "anchorPoint", but how would I do that using only the translationMatrix? \$\endgroup\$ Commented Oct 21, 2013 at 16:08
  • \$\begingroup\$ Ohh, well then how do you store/render the quads using VAO, VBO, Immediate Mode, or? \$\endgroup\$
    – vallentin
    Commented Oct 21, 2013 at 16:09
  • \$\begingroup\$ I store the vertex-data in VBOs, but I render the same one multiple times using "GLDrawElementsInstanced". So the vertices are identical for each quad, to make them appear in different locations and have different UV positions etc. I am using instanced attributes. The attribute that change the position is the "bufferMatrix" which is essentially a model-matrix, and the only one that should be changed as the MVP and MV matrix are uniforms. \$\endgroup\$ Commented Oct 21, 2013 at 16:32

1 Answer 1


I hacked a few lines together and I believe this might get you what I think you want. Basically it all depends on where/when you do the local transformation. You will want to translate the quads to their respective position in clip coordinates, e.g. after the multiplication with the mvp matrix.

vec4 tmpPos = mvp * vec4(0.0, 0.0, 0.0, 1.0) + vec4((local_transform * vec4(vPosition,1.0)).xyz,0.0);

Where the local_transform matrix denotes the gl_InstanceID dependent location of each Quad relative to the rotational center (basically like your bufferMatrix I guess). The rotational center itself would be wherever the model matrix within the mvp matrix would translate the zero vector.

This is what I get with my test application: Transform after mvp

On a side note, I got your result with the following line of code:

vec4 tmpPos = mvp * local_transform * vec4(0.0, 0.0, 0.0, 1.0) + vec4(vPosition,0.0);

And again the result I get in my test: Transformation before mvp

Edit: Fixed two small mistakes. I mixed up clip coordinates with image space, and also carelessly added a 1.0 to the w-component in said clip coords. in my code above. I have corrected both now.

  • \$\begingroup\$ Like magic, all I had to do was to update the vertex shader with that one line. Thank you so much for your answer, this is a perfect answer! :) I even think I understand what is going on now, shaders are awesome. \$\endgroup\$ Commented Oct 23, 2013 at 15:39
  • \$\begingroup\$ So in order to change the origin of the rotation I would have to feed the shader a vector right? - because right now they will rotate around position (0, 0, 0) or is it possible to change the model-origin with only the local_transform matrix? \$\endgroup\$ Commented Oct 23, 2013 at 16:10
  • \$\begingroup\$ Theoretically you could do that, yes. You could for example swap the vec4(0.0, 0.0, 0.0, 1.0) with another vector which would then be the position of the billboard in the world. In practice, I think this is something which should be done via the model-view-projection matrix, specifically the model part of it should contain a translation to the world position. \$\endgroup\$
    – Invor
    Commented Oct 23, 2013 at 17:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .