Jump to content

  • Log In with Google      Sign In   
  • Create Account


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.

  • You cannot reply to this topic
3 replies to this topic

#1 Psychopathetica   Members   -  Reputation: 180

Like
0Likes
Like

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.

Sponsor:

#2 speciesUnknown   Members   -  Reputation: 527

Like
1Likes
Like

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!

#3 Ripiz   Members   -  Reputation: 525

Like
1Likes
Like

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.

Setup generic quad:
  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;

#4 Psychopathetica   Members   -  Reputation: 180

Like
0Likes
Like

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.SetVertexShader CUSTOM_VERTEX_FORMAT
    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.



PARTNERS