Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 9 of 9

Thread: Billboard Help

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2015
    Posts
    14

    Billboard Help

    Working on a solar system project and I've just implemented a billboard vertex shader. The billboard works as it should, it is pointed parallel to the camera viewing angle. However I want to make it point towards the camera.

    Vertex Shader
    Code :
    #version 330
     
    in vec3 vertIn;
    in vec2 uvIn;
     
    uniform mat4 proj;
    uniform mat4 model;
    uniform mat4 view;
    uniform float scale;
     
    out vec2 uv;
     
    void main()
    {
    	mat4 model_view = view * model;
     
    	//settting the rotational part of the matrix to the identy matrix * scale
    	model_view[0][0] = scale; // 1 * scale
    	model_view[0][1] = 0;
    	model_view[0][2] = 0;
     
    	model_view[1][0] = 0;
    	model_view[1][1] = scale; // 1 * scale
    	model_view[1][2] = 0;
     
    	model_view[2][0] = 0;
    	model_view[2][1] = 0;
    	model_view[2][2] = scale; // 1 * scale
     
    	model_view *= scale;
     
    	gl_Position = proj * model_view * vec4(vertIn, 1);
    	uv = uvIn;
    }

    I can get a vector from the camera position to the center of the object but from there I don't know where to head. Maybe create a rotation matrix from that???

    Here are the images showing the problem.
    The first one is the viewing with the sun as the focus, however when I focus other planes, the billboard doesn't point towards the camera.

    imgurDOTcom/a/Lp0mZ ( i wish they weren't so restrictive with links and images)

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,401
    You can't determine the rotation simply from a vertex position. You need at least the object-space position of the billboard's centre and the position of the vertex within the billboard (i.e. which corner it is). The latter might be uvIn if the billboard maps to the complete texture (i.e. the four vertices have uvIn equal to one of (0,0), (1,0), (0,1) or (1,0))

    If the billboard is aligned to the screen, then just transform the centre position to eye space and offset it by the relative vertex position.

    E.g.
    Code :
    in vec3 centerIn;
    in vec2 uvIn;
     
    uniform mat4 proj;
    uniform mat4 modelview;
    uniform float scale;
     
    void main()
    {
        vec4 c = modelview * vec4(centerIn, 1.0);
        vec4 p = c + vec4((uvIn * 2 - 1) * scale, 0.0, 0.0);
        gl_Position = proj * p;
    }

    If the billboard is aligned to the world, it's slightly more complex (and you have the issue that the orientation is undefined if the up vector points directly towards the camera).

    E.g.
    Code :
    in vec3 centerIn;
    in vec2 uvIn;
     
    uniform mat4 proj;
    uniform mat4 modelview;
    uniform vec3 up;
    uniform float scale;
     
    void main()
    {
        vec4 c = modelview * vec4(centerIn, 1.0);
        vec4 u = modelview * vec4(up, 0.0); // w=0 as this is a direction, not a position
        vec2 y = normalize(u.xy); // this will fail if the transformed up vector is (0,0,z)
        mat2 m = mat2(y.y, -y.x, y.x, y.y);
        vec4 p = c + vec4(m * (uvIn * 2 - 1) * scale, 0.0, 0.0);
        gl_Position = proj * p;
    }

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2015
    Posts
    14
    The first shader you gave me does exactly what my current one does. However the second one seems to stick the billboard to my screen but not around the sun. So when I move to a new planet, it is still in the left hand side of the screen, and not around the sun. For the second shader, what would be the up vector? The camera up vector?

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,401
    Quote Originally Posted by Raptor2277 View Post
    The first shader you gave me does exactly what my current one does. However the second one seems to stick the billboard to my screen but not around the sun. So when I move to a new planet, it is still in the left hand side of the screen, and not around the sun. For the second shader, what would be the up vector? The camera up vector?
    The second shader is identical to the first, except that it rotates the billboard so that the billboard's orientation is fixed in model space rather than screen space. The up vector is a vector in model space which determines the billboard's orientation.

    The first shader is appropriate for e.g. labels which should follow a particular point in world space but be oriented in screen space. The second shader is appropriate for billboards which should also be oriented in world-space (e.g. pre-rendered objects).

  5. #5
    Junior Member Newbie
    Join Date
    Nov 2015
    Posts
    14
    Quote Originally Posted by GClements View Post
    The second shader is identical to the first, except that it rotates the billboard so that the billboard's orientation is fixed in model space rather than screen space. The up vector is a vector in model space which determines the billboard's orientation.

    The first shader is appropriate for e.g. labels which should follow a particular point in world space but be oriented in screen space. The second shader is appropriate for billboards which should also be oriented in world-space (e.g. pre-rendered objects).
    Ok, I made a mistake using the second shader. They now both look identical. However, the billboard is still not facing the camera, but is instead parallel to it. Here is what I mean.
    Click image for larger version. 

Name:	ntclBE4.jpg 
Views:	212 
Size:	10.3 KB 
ID:	2190

    Don't know how to make image bigger.
    imgur.com/ntclBE4.png

  6. #6
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,401
    Quote Originally Posted by Raptor2277 View Post
    Here is what I mean.
    Code :
        vec4 c = modelview * vec4(centerIn, 1.0);
        vec4 u = modelview * vec4(up, 0.0); // w=0 as this is a direction, not a position
        vec3 z = -c.xyz;
        vec3 x = normalize(cross(u, z));
        vec3 y = normalize(cross(z, y));
        mat2x3 m = mat2x3(x, y);
        vec4 p = c + vec4(m * (uvIn * 2 - 1) * scale, 0.0);
        gl_Position = proj * p;

  7. #7
    Junior Member Newbie
    Join Date
    Nov 2015
    Posts
    14
    Quote Originally Posted by GClements View Post
    Code :
        vec4 c = modelview * vec4(centerIn, 1.0);
        vec4 u = modelview * vec4(up, 0.0); // w=0 as this is a direction, not a position
        vec3 z = -c.xyz;
        vec3 x = normalize(cross(u, z));
        vec3 y = normalize(cross(z, y));
        mat2x3 m = mat2x3(x, y);
        vec4 p = c + vec4(m * (uvIn * 2 - 1) * scale, 0.0);
        gl_Position = proj * p;
    At vec3 x = normalize(cross(u, z)); you do the cross of a 4d vecotor(u) with a 3d vector(z), I assume you want the xyz of u. vec3 x = normalize(cross(u.xyz, z));
    At vec3 y = normalize(cross(z, y)); you declare y as a normalized cross of z and y, that cant be done. Did you mean to use the y from "vec2 y = normalize(u.xy);" but if you did that would make y a 2d vector, which wouldn't work.

  8. #8
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,401
    Quote Originally Posted by Raptor2277 View Post
    At vec3 x = normalize(cross(u, z)); you do the cross of a 4d vecotor(u) with a 3d vector(z), I assume you want the xyz of u. vec3 x = normalize(cross(u.xyz, z));
    Yes; good catch. For some reason, AMD's GLSL didn't notice that.

    Quote Originally Posted by Raptor2277 View Post
    At vec3 y = normalize(cross(z, y)); you declare y as a normalized cross of z and y,
    Sorry, that should be:
    Code :
        vec3 y = normalize(cross(z, x));
    (the compiler did pick that one up; I forgot to copy the change to my post).

  9. #9
    Junior Member Newbie
    Join Date
    Nov 2015
    Posts
    14
    Quote Originally Posted by GClements View Post
    Yes; good catch. For some reason, AMD's GLSL didn't notice that.


    Sorry, that should be:
    Code :
        vec3 y = normalize(cross(z, x));
    (the compiler did pick that one up; I forgot to copy the change to my post).
    It worked. Thank you very much GClements.

    For anyone interested, here is the final code.
    Code :
    #version 330
     
    in vec3 vertIn;
    in vec2 uvIn;
     
    uniform mat4 proj;
    uniform mat4 model;
    uniform mat4 view;
     
    uniform float scale;
    uniform vec3 center;
    uniform vec3 up;
     
    out vec2 uv;
     
    void main()
    {	
        mat4 modelview = view * model;
     
        vec4 c = modelview * vec4(center, 1.0);
        vec4 u = modelview * vec4(up, 0.0); // w=0 as this is a direction, not a position
        vec3 z = -c.xyz;
        vec3 x = normalize(cross(u.xyz, z));
        vec3 y = normalize(cross(z, x));
        mat2x3 m = mat2x3(x, y);
        vec4 p = c + vec4(m * (vertIn.xy) * scale, 0.0);
        gl_Position = proj * p;
     
        uv = uvIn;
    }

    "center" is the center of the rectangle in world coordinates. "up" is the up vector in object coordinates. The "vertIn" are the vertices of the billboard in 2d object space. Ex. x,y,0. The position of each vertex is ultimately determined by the it's "center" and offset by each of its "vertIn". The "scale" is used to scale the billboard. For example the mesh of the sun is a sphere with a radius of 1 (diameter of 2), that is scaled up by 40. The other planets are the same mesh with a different scale. When I create the vertices of the billboard, I create a square the length of 2 and pass in the sun's scale to the shader.

    Here is the final result.
    i.imgur.com/eKRmoGI.png

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •