View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Billboarding

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

3 replies to this topic

### #1Psychopathetica  Members

Posted 23 January 2012 - 11:47 PM

I been long searching hard for the right code to do proper billboarding regardless of camera angle used. I tried a few samples but found that they either don't seem to work right in certain camera angles, or only billboard for me when I translate the camera around the world with camera angles not having any affect on them billboardwise, cause when I rotate the camera it still rotates the polygon when its not suppose to, Then finally I found some useful code over on this site http://www.mvps.org/..._billboards.htm . This works flawlessly regardless of camera angle and position. However there is just one problem. I do not like the fact I'm stuck having to work with a diamond shaped polygon. I tried making it just a regular square but everything I tried fails. Even tried rotating the poly itself by its Z axis 45 degrees but then I end up losing the billboard effect. Is there anyway I can use this technique and work with regular squares / rectangles rather than the "diamond" that microsoft was using? Thanks in advance.

### #2speciesUnknown  Members

Posted 24 January 2012 - 02:29 AM

I found a simple solution to this. Here is how I build the 4 vertices of each quad when I fill an array of particles:
	 #region setting up verts
int si = i * 4;
float age = pData[i + offset].age;
int z = nDrawn & 1;
float rev = ( z == 1 ) ? -1f : 1f;
Matrix rotm = Matrix.CreateRotationZ(age * 5f * rev);
// point sprite style rendering - use the first 2 points of the normal to encode the coordinates,
// relative to the Position, of each of the 4 verts
// use the 3rd component of the normal to encode the age, for shaders to apply their own age dependent logic
StaticBuffer[si].Position = pData[i + offset].pos;
StaticBuffer[si].TextureCoordinate.X = 0;
StaticBuffer[si].TextureCoordinate.Y = 0;
StaticBuffer[si].Normal.X = -0.5f;
StaticBuffer[si].Normal.Y = -0.5f;
StaticBuffer[si].Normal.Z = age;
si++;
StaticBuffer[si].Position = pData[i + offset].pos;
StaticBuffer[si].TextureCoordinate.X = 1;
StaticBuffer[si].TextureCoordinate.Y = 0;
StaticBuffer[si].Normal.X = 0.5f;
StaticBuffer[si].Normal.Y = -0.5f;
StaticBuffer[si].Normal.Z = age;
si++;
StaticBuffer[si].Position = pData[i + offset].pos;
StaticBuffer[si].TextureCoordinate.X = 1;
StaticBuffer[si].TextureCoordinate.Y = 1;
StaticBuffer[si].Normal.X = 0.5f;
StaticBuffer[si].Normal.Y = 0.5f;
StaticBuffer[si].Normal.Z = age;
si++;
StaticBuffer[si].Position = pData[i + offset].pos;
StaticBuffer[si].TextureCoordinate.X = 0;
StaticBuffer[si].TextureCoordinate.Y = 1;
StaticBuffer[si].Normal.X = -0.5f;
StaticBuffer[si].Normal.Y = 0.5f;
StaticBuffer[si].Normal.Z = age;
#endregion


See how I am encoding the distance from the centre of the billboard into the X and Y of its normal. If I came up with my own vertex format this wouldnt be necessary, and there are other ways.

My shader is very simple; only the vertex shader has anything notable in it:

output.Position = mul( mul( mul(input.Position, matWorld) , matView), matProjection) + float4(input.Normal.xy * input.Normal.z, 0, 0);


Now, there are other ways to do this; you could use the texcoords to achieve the same effect, or instead you could use a single index which picks from an array within a shader, but I implemented this in a hurry.
Don't thank me, thank the moon's gravitation pull! Post in My Journal and help me to not procrastinate!

### #3Ripiz  Members

Posted 24 January 2012 - 03:16 AM

Inverse of camera's rotation matrix (3x3 part) will negate camera's rotation effect and your quad will always face camera.

  struct QuadPoint {
D3DXVECTOR3 xyz;
D3DXVECTOR2 tex;
} points[4];
points[0].xyz = D3DXVECTOR3(-0.05, -0.05, 0);
points[0].tex = D3DXVECTOR2(0, 0);
points[1].xyz = D3DXVECTOR3(-0.05, 0.05, 0);
points[1].tex = D3DXVECTOR2(0, 1);
points[2].xyz = D3DXVECTOR3(0.05, -0.05, 0);
points[2].tex = D3DXVECTOR2(1, 0);
points[3].xyz = D3DXVECTOR3(0.05, 0.05, 0);
points[3].tex = D3DXVECTOR2(1, 1);

You can duplicate this quad into many quads and then add positions of particles, but personally I used this quad as base mesh and instanced particle positions.

Then get inverse of view:
   ViewInverse = *camera.GetViewMatrix();
D3DXMatrixInverse(&ViewInverse, 0, &ViewInverse);
ViewInverse._41 = 0;
ViewInverse._42 = 0;
ViewInverse._43 = 0;

Last 3 lines remove camera's translation part.

Then in shader it's simple: OutPosition = QuadVertex.Position * ViewInverse * View * Proj;
I used instancing, so for me it was OutPosition = (QuadVertex.Position * ViewInverse + QuadInstancedPosition) * View * Proj;

### #4Psychopathetica  Members

Posted 25 January 2012 - 12:39 AM

I managed to pull it off. And I think the technique I was looking for is called View Oriented Billboarding. I ran into this site here: http://www.toymaker...._faq.html#D3D10 but it was missing something big cause it seemed incomplete. It needed to multiply the matrix "result" by the vertices you have for your polgon.Here is the solution to my problem:

Private Sub D3DXMatrixMultiplyByVertex(VOut As D3DVECTOR, M As D3DMATRIX, V As D3DVECTOR)

VOut.X = (V.X * M.m11) + (V.Y * M.m21) + (V.Z * M.m31)
VOut.Y = (V.X * M.m12) + (V.Y * M.m22) + (V.Z * M.m32)
VOut.Z = (V.X * M.m13) + (V.Y * M.m23) + (V.Z * M.m33)

End Sub

Private Sub Draw_Billboard_Polygon()

Dim Vertex(3) As D3DVECTOR
Dim Camera_Inverse As D3DMATRIX
Dim Result As D3DMATRIX
Dim Temp As D3DMATRIX
Dim Billboard_Vertex(3) As D3DVECTOR

Device.GetTransform D3DTS_VIEW, Camera_Matrix
D3DXMatrixInverse Camera_Inverse, 0, Camera_Matrix

Camera_Inverse.m41 = 0
Camera_Inverse.m42 = 0
Camera_Inverse.m43 = 0

D3DXMatrixIdentity Temp
D3DXMatrixMultiply Result, Temp, Camera_Inverse

Result.m41 = Position.X
Result.m42 = Position.Y
Result.m43 = Position.Z

Device.SetTransform D3DTS_WORLD, World_Matrix

Vertex(0).X = -50: Vertex(0).Y = 50: Vertex(0).Z = 0
Vertex(1).X = 50: Vertex(1).Y = 50: Vertex(1).Z = 0
Vertex(2).X = -50: Vertex(2).Y = -50: Vertex(2).Z = 0
Vertex(3).X = 50: Vertex(3).Y = -50: Vertex(3).Z = 0

D3DXMatrixMultiplyByVertex Billboard_Vertex(0), Result, Vertex(0)
D3DXMatrixMultiplyByVertex Billboard_Vertex(1), Result, Vertex(1)
D3DXMatrixMultiplyByVertex Billboard_Vertex(2), Result, Vertex(2)
D3DXMatrixMultiplyByVertex Billboard_Vertex(3), Result, Vertex(3)

Vertex_List(0) = Create_Custom_Vertex(Billboard_Vertex(0).X, Billboard_Vertex(0).Y, Billboard_Vertex(0).Z, D3DColorRGBA(255, 255, 255, 255), 0, 0)
Vertex_List(1) = Create_Custom_Vertex(Billboard_Vertex(1).X, Billboard_Vertex(1).Y, Billboard_Vertex(1).Z, D3DColorRGBA(255, 255, 255, 255), 1, 0)
Vertex_List(2) = Create_Custom_Vertex(Billboard_Vertex(2).X, Billboard_Vertex(2).Y, Billboard_Vertex(2).Z, D3DColorRGBA(255, 255, 255, 255), 0, 1)
Vertex_List(3) = Create_Custom_Vertex(Billboard_Vertex(3).X, Billboard_Vertex(3).Y, Billboard_Vertex(3).Z, D3DColorRGBA(255, 255, 255, 255), 1, 1)

Device.SetTexture 0, Texture
Device.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, Vertex_List(0), Len(Vertex_List(0))

End Sub


You are now no longer limited to "diamonds" as microsoft had and can make the shape pretty much anything you want whether its a triangle, rectangle, square, etc. and it'll always face the user. I can't believe that after a ton of samples I attempted, some of which are horrible, didn't even do it right. Out of curiosity I heard there are many other Billboarding techniques out there such as these in this sitehttp://www.flipcode....eringi_2E.shtml along with spherical billboarding and cylindrical billboarding. Where can I find how to these different techniques with source code examples? Would be interesting to learn how.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.