8

How to create a billboard translation matrix from a point in space using glm?

genpfault
  • 51,148
  • 11
  • 85
  • 139
SystemParadox
  • 8,203
  • 5
  • 49
  • 57

2 Answers2

6
mat4 billboard(vec3 position, vec3 cameraPos, vec3 cameraUp) {
    vec3 look = normalize(cameraPos - position);
    vec3 right = cross(cameraUp, look);
    vec3 up2 = cross(look, right);
    mat4 transform;
    transform[0] = vec4(right, 0);
    transform[1] = vec4(up2, 0);
    transform[2] = vec4(look, 0);
    // Uncomment this line to translate the position as well
    // (without it, it's just a rotation)
    //transform[3] = vec4(position, 0);
    return transform;
}
SystemParadox
  • 8,203
  • 5
  • 49
  • 57
6

Just set the upper left 3×3 submatrix of the transformation to identity.


Update: Fixed function OpenGL variant:

void makebillboard_mat4x4(double *BM, double const * const MV)
{
    for(size_t i = 0; i < 3; i++) {
    
        for(size_t j = 0; j < 3; j++) {
            BM[4*i + j] = i==j ? 1 : 0;
        }
        BM[4*i + 3] = MV[4*i + 3];
    }

    for(size_t i = 0; i < 4; i++) {
        BM[12 + i] = MV[12 + i];
    }
}

void mygltoolMakeMVBillboard(void)
{
    GLenum active_matrix;
    double MV[16];

    glGetIntegerv(GL_MATRIX_MODE, &active_matrix);

    glMatrixMode(GL_MODELVIEW);
    glGetDoublev(GL_MODELVIEW_MATRIX, MV);
    makebillboard_mat4x4(MV, MV);
    glLoadMatrixd(MV);
    glMatrixMode(active_matrix);
}
Community
  • 1
  • 1
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Of which matrices? Model and view but not projection? Whilst simpler overall, this approach may not be suitable when porting existing applications using an FFP stack. – SystemParadox Mar 10 '13 at 18:23
  • 1
    @SystemParadox: Just the modelview matrix. The projection should be used for defining the "lens" only. This works equally well for FFP and shader based programming. In fact, doing it in the vertex shader, like suggested in your code just wastes GPU resources, as this is executed for each and every vertex, while doing it once on the CPU suffices. Note that I've seen your approach numerous times, years, and years ago (mid 1990-ies), and it was then even more inefficient. – datenwolf Mar 10 '13 at 18:26
  • `j` is not defined for the final for-loop. – SystemParadox Mar 10 '13 at 18:45
  • @SystemParadox: Copypasta-Error, fixed it. – datenwolf Mar 10 '13 at 18:54