I'm currently adding a billboard mode to animated sprites and static sprites in my 3D engine.

The code below works fine, but I want to know if a more optimized solution exists. I've heard about another method using the transpose the view matrix, but this make some weird things in my case.

getModelMatrix() {
  let matrix = Utils.MAT4_IDENTITY();
  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_TRANSLATE(this.position[0], this.position[1], this.position[2]));
  if (this.billboardMode) {
    let viewMat = view.getCameraViewMatrix();
    matrix = Utils.MAT4_MULTIPLY(matrix, view.getCameraMatrix()); // used to cancel the view camera matrix multiplication
    matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_TRANSLATE(viewMat[12], viewMat[13], viewMat[14])); // but keep position !

    // or just do that, but not working
    // matrix = Utils.MAT4_MULTIPLY(matrix, transpose(view.getCameraViewMatrix()));

  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_ROTATE_Y(this.rotation[1]));
  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_ROTATE_X(this.rotation[0])); // y -> x -> z
  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_ROTATE_Z(this.rotation[2]));
  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_SCALE(this.scale[0], this.scale[1], this.scale[2]));
  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_SCALE(1 / this.pixelsPerUnit, 1 / this.pixelsPerUnit, 0));
  matrix = Utils.MAT4_MULTIPLY(matrix, Utils.MAT4_TRANSLATE(-this.offset[0], -this.offset[1], 0));
  return matrix;

What is the common way to transform a sprite to billboard ?

  • 2
    \$\begingroup\$ We can't help you solve problems when the symptoms are vaguely stated like "weird things" or "don't work" — so if you want help with that issue, you'll need to describe or show the problem in more detail. \$\endgroup\$
    – DMGregory
    Commented Jul 30, 2022 at 13:14
  • \$\begingroup\$ I don't have problem, i just ask what is the common way to transform sprite to billboard. \$\endgroup\$
    – Ra1jin
    Commented Jul 30, 2022 at 13:28

1 Answer 1


You don't actually need to transform the sprite in world space at all. You can project the position of the sprite into view space (with the view matrix), and then generate the corner vertex positions in view-space directly (simply by setting their xy coordinates). The units will be the same as those in world space (e.g. meters). You can apply any scaling/rotation you need in this conveniently view-aligned coordinate system, and then simply apply the usual projection matrix to the resulting vertices as you would with any other model.

  • \$\begingroup\$ Unfortunately my rendering system compute a MVP matrix and multiply this matrix with all drawable so i can't use your method. If i understand your solution remove one matrix multiplication that's correct ? \$\endgroup\$
    – Ra1jin
    Commented Aug 2, 2022 at 22:51
  • \$\begingroup\$ Do you not have control over the vertex shader? Generally being able to control the vertex shader is an important part of high-performance particle rendering; the calculation of the transformation itself isn't very expensive compared to being forced to draw every single particle as an independent object with its own MVP, which is extremely inefficient. \$\endgroup\$ Commented Aug 2, 2022 at 22:58
  • \$\begingroup\$ Yes I have one simple vertex shader (like: posGL = mvp * pos). My mvp is compute one time at the start of each frame. If I understand what do you mean I need another vertex shader for billboard object without compute the view matrix (just for positionning) ? \$\endgroup\$
    – Ra1jin
    Commented Aug 2, 2022 at 23:17
  • \$\begingroup\$ Yes, if you want to make use of optimizations like this. For basic models you might be able to get away with a simple vertex shader like you described but for instancing or particles or other similar effects, you will want to write specialized vertex shaders to write more efficient rendering algorithms. \$\endgroup\$ Commented Aug 2, 2022 at 23:26

You must log in to answer this question.

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