Billboard with a pivot

Started by
6 comments, last by clapton 18 years, 1 month ago
Hello! I am having some terrible troubles with mathematics behind 'billboarding'. Actually, it's not just a simple case of standard billboards. The problem is rather tricky. This is very important for me and I would be grateful if you could help. Sometimes you want to have a billboard with a 'pivot point' - that is, a quad which is always parralel to the screen's surface (XY plane of the camera) and moves around a static point (the pivot). For instance, you can think of a 3D tree mesh with leaves represented as billboards which are attached to branches of the tree. Here is where problems begin. The first thing is that I don't know how to make a billboard which would rotate about a given point (I believe the difficulty comes from my beginners mathematics). The second thing is that the billboarding *MUST* be implemented on a vertex shader (since I don't have an acess to the engine's code). Perhaps some pictures may help : Image Hosted by ImageShack.us ... a tree with leaves attached to the branches. Free Image Hosting at www.ImageShack.us ... a billboard from top (note that leaves rotate about the pivot). Now, to be more specific about what I can do. Every single leaf is represented by a simple mesh-object (quad). Thus, every leaf has its own modelview matrix. The vertex shader (GLSL) as an input gets some pre-declared attributes (vertex position in local coordinates, modelview, inverse of the modelview etc...). Plus, I have no possibility to pass any custom uniform parameters. :( Of course, we can assume that vertices of the leaf-mesh are arbitrarily prepared by the modeller (say, some extra info stored in texture coordinates). The pivot point can be stored as a (0,0,0) in a local leaf-coordinates (but fell free to change it if you don't think it's a good idea). I hope it makes sense... and I hope it's possible to do in a shader. I'd be thankful if you could give me some suggestion/advice/links/tutorials/books titles or anything! I've been sitting three days on this one and I still can't figure that out. Thanks in advance
___Quote:Know where basis goes, know where rest goes.
Advertisement
Why not make the whole tree rotate and not just the leaves? It would be easier!

S
Making the whole tree as the billboard instead of just leaves won't give the same result at all.

Now, to the problem, you simply need sprites. Googling for "sprites OpenGL" (or DirectX, but in this case, the ID3DXSprite interface will do the job) will give you pretty good results.

I use the following approach. I build a vertex and and index buffer. For each vertex, I use the following structure
struc SVertex{   D3DXVECTOR3    position;   D3DXVECTOR2    uv;   D3DXVECTOR2    size;};


Each quad is composed of 4 vertices, and 6 indices. Now, for each 4 vertices, I store the PIVOT point in "position". In "uv", I store the correct uv, and in "size" I store the width / height of the quad in WORLD coordinates. Well, it's not really the width / height. For example, for the upper left vertex, the size will be {-width / 2, height / 2} and for the upper right {width / 2, height / 2}. It's

Now, I use the following shader :

void BillboardVS(in  float3  iPosition  : POSITION,                 in  float2  iTexCoord0 : TEXCOORD0,                 in  float2  iSize      : TEXCOORD1,                 out float4  oPosition  : POSITION,                 out float2  oTexCoord0 : TEXCOORD0      ){   // transform the vertex in camera space   iPosition   = mul(iPosition, g_mWorldView);   // decal the vertex to form the quad   iPosition.x += iSize.x;   iPosition.y += iSize.y;   // finally transform the vertex in screen space   oPosition = mul(iPosition, g_mProjection);   // copy the tex coord for the pixel shader   oTexCoord0 = iTexCoord0;}


Ok, now the explanation. When going into camera space, the X and Y axis are aligned to the screen, and the dimension are still in world space ! That makes it a lot easier to handle your quads : you have the sizes in world space, and you can move the vertices easily in a plane aligned to the screen.

That's a really simple shader, it's easy to work with. The only drawback is that you have 2 matrix multiplications. But on the other hand, you very few additional instructions and it's very easy to create the vertices for this shader.

Hope that helps ^^
Hi, guys! Great thanks for your post, piac. It's very explanatory! :)

Anyway, I would like to make myself sure that I understand your idea completly. Firstly, what do you mean by storing the pivot point in 'position'? For me, a pivot is a fixed point that the billboard 'rotates' about. Storing the pivot in a vertex position (in local coordinates - as input in the vertex shader) would mean that every vertex of the quad would have the same position (since there is only one pivot point)!

Perhaps there I missed something important. I'd be glad if you could make this clear for me.

Thank you for your help
___Quote:Know where basis goes, know where rest goes.
Hi,

Yes, the 4 vertices store the same position. But the 2 following lines
   iPosition.x += iSize.x;   iPosition.y += iSize.y;

are here to create the quad. For example, if you want a quad centered on <5 5 5> and with a width / height of 3, then you would have the following structure :

SVertex vertices[] = { {5.0f, 5.0f, 5.0f,   0.0f, 0.0f,   -2.5f,  2.5f},                       {5.0f, 5.0f, 5.0f,   0.0f, 1.0f,   -2.5f, -2.5f},                       {5.0f, 5.0f, 5.0f,   1.0f, 0.0f,    2.5f,  2.5f},                       {5.0f, 5.0f, 5.0f,   1.0f, 1.0f,    2.5f, -2.5f} };


So, for each vertex, the position is transformed into camera space, so that the X and Y axis become screen aligned, BUT your units are still world units (e.g., if in world space, 1 unit == 1 meter, then in camera space, 1 unit still == 1 meter, on the contrary of screen space where 1 unit == 1 pixel)

And the lines
   iPosition.x += iSize.x;   iPosition.y += iSize.y;

will then "kind of" extrude your quad : the first vertex will be move upper left, the second, down left, the third upper right, and the last one down right.

I don't know how to explain better, I'm not really good at explaining things in english. But I hope this example clarified your ideas ^^
You've explained it perfectly, paic. I wish there where more people on the forum who can give such a clear explanations. :)

OK, I need to consult the artist and I am right into your solution!

Thanks
___Quote:Know where basis goes, know where rest goes.
Quote:Original post by clapton
You've explained it perfectly, paic. I wish there where more people on the forum who can give such a clear explanations. :)

OK, I need to consult the artist and I am right into your solution!

Thanks


Hi Clapton,

The way I do my billboards is as such.

Create a vertex buffer containing my texture coordinates which I know will never change: (0,0), (1,0), (0, 1), (1,1)

Create another vertex buffer containing positions and radii.

Then (in DirectX at least) you can use the stream frequency function. Set it to divide by 4 on the vertex buffer containing the positions and radii. Set it to modulo by 4 on the vertex buffer containing the texture coordinates. This will have the same effect but less than 1/4 the size of data.

In my vertex shader I simply use the texture coordinates to offset the corners of my quad by converting the range of the UVs from [0,1] to [-1,1].

Cheers,
Tom.
Quote:Original post by hogwash
In my vertex shader I simply use the texture coordinates to offset the corners of my quad by converting the range of the UVs from [0,1] to [-1,1].

Yes, it is a good idea.

Thanks, Tom! :)

___Quote:Know where basis goes, know where rest goes.

This topic is closed to new replies.

Advertisement