3
votes

I have the need to orientate an instance of THREE.Mesh to always face the camera. I know I could just use the [THREE.Mesh].lookAt() method, but I'm trying to work on my GLSL chops a bit more and want to be able to do this in a vertex shader.

I've read through NeHe's Billboarding tutorial, and it makes sense to me. Well, all apart from the bit where one applies these orientation vectors to each vertex.

I feel like I'm very close to getting this working, but as it stands at the moment, my vertex shader is looking more like a 90s rave video than a billboard:

Progress so far fiddle: http://jsfiddle.net/RZ4XE/2/

Below is my vertex shader (the fragment shader just assigns a vec4 color). It's making use of various default uniforms / attributes that THREE.js provides, listed below just in case someone unfamiliar with THREE.js is reading this :)

  • cameraPosition (vec3),
  • position (vertex position, another vec3),
  • projectionMatrix (camera's projectionMatrix, mat4),
  • modelViewMatrix (camera.matrixWorldInverse * object.matrixWorld, mat4)

    void main() {
    
        vec3 look = normalize( cameraPosition - position );
    
        if( length( look ) == 0.0 ) {
            look.z = 1.0;
        }
    
        vec3 up = vec3( 0.0, 1.0, 0.0 );
        vec3 right = normalize( cross( up, look ) );
        up = normalize( cross( look, right ) );
    
    
        mat4 transformMatrix;
    
        transformMatrix[0][0] = right.x;
        transformMatrix[0][1] = right.y;
        transformMatrix[0][2] = right.z;
    
        transformMatrix[1][0] = up.x;
        transformMatrix[1][1] = up.y;
        transformMatrix[1][2] = up.z;
    
        transformMatrix[2][0] = look.x;
        transformMatrix[2][1] = look.y;
        transformMatrix[2][2] = look.z;
    
        gl_Position = projectionMatrix * modelViewMatrix * transformMatrix * vec4( position, 1.0 );
    }
    

Thanks in advance.

1
Just do this: mesh.quaternion = camera.quaternion; and use any three.js material ( jsfiddle.net/RZ4XE/3 )... or use a THREE.Sprite.WestLangley
Thanks - that does solve the problem, but it doesn't help me on my quest to master GLSL and fully understand matrix transforms.SquareFeet
Yes, I know.... just showing you how to let three.js do the work for you. :-)WestLangley
Yeah, I appreciate it :)SquareFeet

1 Answers

5
votes

Apparently this works:

gl_Position = projectionMatrix * (modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) + vec4(position.x, position.y, 0.0, 0.0));

I'm actually trying to figure out how to do axis aligned billboards.