#### Archived

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

# rendering multiple billboards at once

This topic is 5177 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## 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 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
ONIRIC GAMES

##### 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 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 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
ONIRIC GAMES

##### 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 on other sites
If I have over a thousand billboards, over 1000 drawprim calls, it begins to slow it down pretty quick.

##### 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 on other sites
But wouldn''t the output be the same, since you call just as many DP()s and do the same amount of calculations?

--
You''re Welcome,
Rick Wong
- sitting in his chair doing the most time-consuming thing..

##### 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 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.

MHaggag''s corner

##### 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 !!!
('''')___('''')