Faster alignment of billboards

Blitz3D Forums/Blitz3D Programming/Faster alignment of billboards

Kryzon(Posted 2014) [#1]
EDIT 03/06/2016 --- Optimised version at the bottom of the thread.


Hello.
I had an idea for a method of aligning billboards with the camera plane that should be slightly faster than the usual approach of orienting a pivot and using TFormVector.
This should help making single-surface particle systems faster.

If you can try it out, please share the difference in performance of the two methods. Use the A,W,S,D keys to strafe the camera, the mouse to look and the space key to toggle the methods used for aligning the billboards.




Kryzon(Posted 2014) [#2]
If your billboards do not need to have individual rotation values - that is, they are all straight up - the method can be further optimized to this:




Rick Nasher(Posted 2014) [#3]
Oh wow! thanks Kryzon, I just feel an asteroid belt coming up. Wonderful stuff. Hope it converts to Ploppy's DX9 successfully.

Eh, forgive me my utter cluelessness, but just how would one go about adding a texture(say a png) to these boards?'
I see it probsbly needs to be done from here:

;Texture.

;VertexTexCoords( ... )
;VertexTexCoords( ... )
;VertexTexCoords( ... )
;VertexTexCoords( ... )

Obviously the usual entitytexture function doesn't apply here, any suggestions?


Kryzon(Posted 2014) [#4]
Hello.
It should work with any engine that allows mesh manipulations and something similar to the TFormNormal function, like "vector transformations" or "coordinate-context conversions."

Regarding texturing.
Each surface can only have a single diffuse texture. You can blend other textures on top of this one since surfaces have texture layers (their brushes do, to be exact), but you can't have different 'individual' textures on a mesh without using additional surfaces.
The idea of storing all of your geometry in a single complex surface - something that is faster to render than several simpler surfaces - involves merging all of your different texture elements into a single texture element usually called the "texture atlas" or "texture sheet," such as the following:



The more different elements on the atlas, the more different objects you can represent with a single surface.
You can assign your billboard surface a texture atlas like the above by using PaintSurface(), supplying a brush with such a texture.
You should only use EntityTexture() if you're certain that the mesh you're texturing only has one surface, otherwise the other surfaces of the mesh would also have their textures changed.

The actual part of the atlas that is displayed by each billboard is defined by the UV coordinates of the four vertices that constitute the billboard: You can specify UV coordinates for each vertex of a billboard so that they capture the exact rectangular region of the atlas that you want the billboard to display.
Since UV values are always relative (0.0 ~ 1.0), you would calculate them like so:
U = ( pixel_x / atlas_width )
V = ( pixel_y / atlas_height )
;With pixel_x or pixel_y being the pixel coordinates on the atlas that each vertex is placed, and atlas_width and atlas_height being the total dimensions of the atlas texture.

Furthermore, your billboards can represent static elements, such as rocks or trees, or they can also represent animated elements such as characters or special effects.
In the game "Ragnarok Online," the environment is a polygonal mesh and the characters are billboards.
If one or more billboards represent animated elements, you would need to change the UVs of the vertices of these billboards so that they can display different frames of the atlas. To do this, you would need to include those VertexTexCoords() calls in the update loop. Preferably, you would only use these calls on billboards that are actually animated, since these calls are expensive, especially if they're done on a billboard that is not animated.

With this in mind, in the original example on post #1 I have put some calls to VertexColor() that don't need to be in that update loop. Since no billboard is changing in colour (they start with a colour and remain with it), those vertex colour calls are redundant and are just wasting performance.
The appropriate way to use them in this case would be to move them to the billboard creation routine, since the colours of the vertices only need to be set once.
If I wanted the colours of billboards to change with time, however, the VertexColor() calls would be needed inside the update loop.


Rick Nasher(Posted 2014) [#5]
Wow, many thanks for the explanation. Didn't even know about the PaintSurface() command, or these techniques for that matter. Very interesting stuff, bit more low level, but also more (to) control of course.

Don't know where else I would have learned about this though(didn't see any examples uptill now), so again many thanks.


Kryzon(Posted 2014) [#6]
I'm glad.
If you want to make a robust single-surface billboard\particle system, make a thread about it some day and I'll help.


Rick Nasher(Posted 2014) [#7]
Cool. :-)


Kryzon(Posted 2016) [#8]
I realised that you can trim the second use of Sin and Cos, which are computationally expensive, if you understand how affine transformations work.
You only need to calculate Sin and Cos once.

Anyway, this is a more optimised version that does this:




Rick Nasher(Posted 2016) [#9]
Very impressive. Didn't realise it would work this weel with soooo many bilboards at once. Thanks, very useful stuff.


Flanker(Posted 2016) [#10]
I agree, impressive, this could be a nice addition to any single surface particule library written in Blitz3D. Thanks for the input.