Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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;
}
share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

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).

share|improve this answer
    
Ahhh, its so simple! Just need to change the up vector to my direction vector. Thanks for putting me on the right track! –  user8709 Oct 23 '12 at 5:06
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.