Archived

This topic is now archived and is closed to further replies.

Chaucer

rendering multiple billboards at once

Recommended Posts

How would you go about rendering multiple billboards at once? Since in order to render them correctly, the world would have to be rotated to make them face the camera OR the vertices would have to be changed to face the camera each frame, I see the only way to do it is with a dynamic vertex buffer. Thanks.

Share this post


Link to post
Share on other sites
You don''t need to rotate the world nor modify the vertices. You just need to apply an apropriate world matrix transformation that would make every billboard vertex face the camera. There are plenty of tutorials out there that explain how to do this.



Mariano Ruggiero
Lead Programmer
ONIRIC GAMES

Share this post


Link to post
Share on other sites
I think one of the fastest ways is to keep a matrix that represents the position of your camera, the camera matrix.

When it comes time to render your billboards extract the X and Y orthonormals from your matrix, ie if you have a row majour matrix, then the X and Y orthonormals will be the first and second row.

You can then build your billboards using quads and the vectors, and they will automatically face the camera, or away from the camera depending on your triangle winding, so you may need to swap a fiew signs untill you get it right.

heres some code


//right is the x axis, as viewed from the end of the z axis

Vector right(cameraOrientationMatrix.m11 * halfWidth,
cameraOrientationMatrix.m21 * halfWidth,
cameraOrientationMatrix.m31 * halfWidth);

//and y is conveniently up, unless you''re an engineer

Vector up(cameraOrientationMatrix.m12 * halfHeight,
cameraOrientationMatrix.m22 * halfHeight,
cameraOrientationMatrix.m32 * halfHeight);

glBegin(GL_TRIANGLE_STRIP);
//top right

glTexCoord2f(1.0,0.0);
gVertex(right + up + location);
//top left

glTexCoord2f(0.0,0.0);
gVertex(-right + up + location);
//bottom right

glTexCoord2f(1.0,1.0);
gVertex(right - up + location);
//bottom left

glTexCoord2f(0.0,1.0);
gVertex(-right - up + location);
glEnd();

Share this post


Link to post
Share on other sites
Your code would not allow me to use a static vertex buffer.

My current billboard rendering code:

D3DXMATRIX viewMatrix, worldMatrix;
D3DXMATRIX inverseMatrix, scaleMatrix;

//scale the billboard

D3DXMatrixScaling(&scaleMatrix, m_Scale.x, m_Scale.y, m_Scale.z);

//make billboard face camera

m_pd3dDevice->GetTransform(D3DTS_VIEW, &viewMatrix);
D3DXMatrixInverse(&inverseMatrix,NULL, &viewMatrix);

//translate it to the desired position

inverseMatrix._41 = m_Position.x;
inverseMatrix._42 = m_Position.y;
inverseMatrix._43 = m_Position.z;

D3DXMatrixMultiply(&worldMatrix, &scaleMatrix, &inverseMatrix);
m_pd3dDevice->SetTransform(D3DTS_WORLD, &worldMatrix);

//set texture

m_pd3dDevice->SetTexture(textureStage, m_pTexture);

//draw the bilboard

m_pd3dDevice->SetStreamSource(0, m_pVertexBuffer, sizeof(BILLBOARD_VERTEX));
m_pd3dDevice->SetVertexShader(D3DFVF_BILLBOARD_VERTEX);
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);

//clear the texture

m_pd3dDevice->SetTexture(textureStage, NULL);

//load identity matrix

D3DXMatrixIdentity(&worldMatrix);
m_pd3dDevice->SetTransform(D3DTS_WORLD, &worldMatrix);


I''m sorry but I don''t understand how I can apply a world matrix transformation that will work for every billboard.

Share this post


Link to post
Share on other sites
Sorry, I misunderstood your question. I was talking about the way you are doing billboarding now...

So, you want to make just one DrawPrimitive() call for all your billboards... Well, in that case I think you''re right. You''ll need a dynamic VB. But I don''t think that''ll be better than what you''re doing now.



Mariano Ruggiero
Lead Programmer
ONIRIC GAMES

Share this post


Link to post
Share on other sites
You''re right, but I don''t see much need for a static vertex buffer when you''re talking about just four verticies.

The method shown was just an optimisation to avoid having to perform several matrix multiplications per billboard. By performing the camera transformation, and then calculating each vertex position within world space, so that they ended up facing the camera.

But you are right, I think you would need a dynamic vertex buffer, so that you could modify each vertex to take account of the camera location.

Share this post


Link to post
Share on other sites
For more than a few billboards you should definitely use a dynamic vertex buffer, and transform them to face the camera.

You can actually use a static buffer if you do the billboard calculations within a vertex shader or use point sprites though.

Share this post


Link to post
Share on other sites
If you transform the vertices into world space yourself then you only need one DP call, since there are no world matrix changes. The output will be the same (or should be), but it''ll be much faster.

Share this post


Link to post
Share on other sites
If you want to use static buffers, you can use indexed vertex blending, which gives you 256 matrices in software vertex processing, and Caps.MaxVertexBlendIndex matrices with hardware vertex processing. You then set the matrices using SetTransform( D3DTS_WORLDMATRIX( n ), &mat )

Note that if your vertices contain normals, then the matrices available are half the numbers mentioned.

To use it, you''ll have to add a matrix index to each of your vertices - it''s a DWORD that comes after the position, before the normal, as far as I recall. Then you''ll need to change your FVF to XYZB1 | LASTBETA_UBYTE4, enable indexed vertex blending, set rs VertexBlendFlags to D3DVBF_ZEROWEIGHTS.

Radeon8500+ support hardware indexed vertex blending (although the r8500 supports 58 matrices only), nVidia hardware doesn''t (none that I''m aware of - maybe the FX does).

You can also use a vertex shader, and pack your rotations as quaternions, thus using 2 constant registers per billboard (though that limits you if you want to do lighting or other vertex shader tricks).

My suggestion is to go with dynamic buffers, I think they''re going to be faster.

Muhammad Haggag
MHaggag''s corner

Share this post


Link to post
Share on other sites
Hello!

Try using a vertex cache (http://www.mvps.org/directx/articles/vcache.htm).
This way you just need a few changes and have great optimization.

Good luck

(\___/)
(-^.^-) Reload Me !!!
('''')___('''')

Share this post


Link to post
Share on other sites