2
\$\begingroup\$

I have succesfully created a GLSL shader for a billboarding effect. I want to tweak this to restrict the billboarding to an arbitrary axis, i.e. a billboarded quad only rotates itself about the y-axis. I use the y-axis as an example, but essentially I would like this to be an arbitrary axis. Can anyone show me how to modify my existing shader below, or if I need to start from scratch, point me towards some resources that could be helpful?

precision mediump float; 

uniform mat4 u_modelViewProjectionMat;      
uniform mat4 u_modelMat;               
uniform mat4 u_viewTransposeMat;   

uniform vec3 u_axis; // <------------ !!! the arbitrary axis to restrict rotation around

attribute vec3 a_position0;     
attribute vec2 a_texCoord0;     

varying vec2 v_texCoord0;      

void main()
{
    vec3 pos = (a_position0.x * u_viewTransposeMat[0] + a_position0.y * u_viewTransposeMat[1]).xyz;
    vec4 position = vec4(pos, 1.0);

    v_texCoord0 = a_texCoord0;

    gl_Position = u_modelViewProjectionMat *  position;
}

EDIT - The modified shader for cylindrical billboarding. Its very straight forward! Just swap out the up vector for the axis to restrict rotation about.

precision mediump float; 

uniform mat4 u_modelViewProjectionMat;      
uniform mat4 u_modelMat;               
uniform mat4 u_viewTransposeMat;   

uniform vec3 u_axis; // <------------ !!! the arbitrary axis to restrict rotation around

attribute vec3 a_position0;     
attribute vec2 a_texCoord0;     

varying vec2 v_texCoord0;      

void main()
{
    vec3 pos = (a_position0.x * u_viewTransposeMat[0] + a_position0.y * vec4(normalize(u_axis), 0.0)).xyz;
    vec4 position = vec4(pos, 1.0);

    v_texCoord0 = a_texCoord0;

    gl_Position = u_modelViewProjectionMat *  position;
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

While I ended up with a similar approach to yours, I can tell you about an implementation I went through on my way there. It's probably a bit simpler to understand, so it should be easier to modify.

Basically, I use the normal of the vertex to tell the vertices which way to shift in the view plane. More specifically, that can be done like this:

float xVal = Position.x - ((CameraRight.x * Normal.x) + (CameraUp.x * Normal.y));
float yVal = Position.y - ((CameraRight.y * Normal.x) + (CameraUp.y * Normal.y));
float zVal = Position.z - ((CameraRight.z * Normal.x) + (CameraUp.z * Normal.y));
vec4 vertexPos = vec4(xVal, yVal, zVal, 1.0);
gl_Position = ProjectionMatrix * ModelViewMatrix * vertexPos;

Where I'm setting the camera up and camera right as uniforms at the beginning of each frame. The normal positions are set like so:

//position x, y and z, then normal x, y, and z then float2 texture coords, then color
billboards.add(pos.x, pos.y, pos.z, bbhs, -bbhs, 0, texture[0], backColor);
billboards.add(pos.x, pos.y, pos.z, bbhs, bbhs, 0, texture[1], backColor);
billboards.add(pos.x, pos.y, pos.z, -bbhs, -bbhs, 0, texture[2], backColor);
billboards.add(pos.x, pos.y, pos.z, -bbhs, bbhs, 0, texture[3], backColor);

You could easily modify the axis being modified by changing the normal coordinates. Or if you only wanted the y axis, you always pass the camera up as (0,1,0).

\$\endgroup\$
1
  • \$\begingroup\$ Ahhh, its so simple! Just need to change the up vector to my direction vector. Thanks for putting me on the right track! \$\endgroup\$
    – user8709
    Oct 23, 2012 at 5:06

You must log in to answer this question.

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