preparing big arrays with all the geometry --arrays for vertex attributes (position, normal, UV coordinates), and an array for triangle vertex indices-- and then using these arrays in a single draw call, instead of doing a draw call per particle. This is what batching is.
;Example of a fast alignment of billboards with the camera plane.;;Optimised 03/06/2016;------------------------------------------------------;The amount of single-surface quadrilateral billboards in the scene.Const BILLBOARD_AMOUNT% = 5000Const LARGE_NUMBER% = 10000000 ;Used for setting the cullbox of the single-surface mesh.Const FX_FORCEALPHA% = 32 ;EntityFX flags used with the billboards to enable per-vertex colour and alpha.Const FX_FULLBRIGHT% = 1Const FX_VERTEXCOLOUR% = 2Const BILLBOARD_ROTATION_SPEED# = 2.0 ;Speed with which all billboards are rotated.;Type for a billboard object (a camera-aligned quadricular mesh).;Holds some properties so billboards can be different from one another, like size and rotation.Type TBillboard Field posX#, posY#, posZ# Field roll# Field scaleX# Field scaleY# Field r#, g#, b#, alpha# Field surf% Field vID%[3]End TypeAppTitle("Fast Billboard Alignment Example")Graphics3D(800, 600, 0, 2)Local camera = CreateCamera()MoveEntity(camera, 0, 5, 0);Single surface elements needed:;-------------------------------------------------------------------------;- A mesh. Setting the cullbox to a very large size so it's never culled by the camera (i.e it's always visible).Local billboardMesh = CreateMesh()MeshCullBox(billboardMesh, -LARGE_NUMBER, -LARGE_NUMBER, -LARGE_NUMBER, 2 * LARGE_NUMBER, 2 * LARGE_NUMBER, 2 * LARGE_NUMBER)EntityFX(billboardMesh, FX_FULLBRIGHT + FX_VERTEXCOLOUR + FX_FORCEALPHA);- A surface to hold the billboards (there can be more than one).Local billboardSurface = CreateSurface(billboardMesh);- A simple pivot without modifications. This pivot is used to align the billboards.Local billboardPivot = CreatePivot();-------------------------------------------------------------------------;Populate the scene with billboards.If BILLBOARD_AMOUNT * 4 > 65534 Then RuntimeError "Too many vertices on a single surface."Const MIN_RADIUS# = 30Const MAX_RADIUS# = 200Local angleFor n = 1 To BILLBOARD_AMOUNT ;Create random billboards around the scene. ;The billboards are added to the surface specified by the programmer. angle = Rand(0, 359) addBillboard(billboardSurface, Cos(angle) * Rand(MIN_RADIUS, MAX_RADIUS), Rand(-5, 15), Sin(angle) * Rand(MIN_RADIUS, MAX_RADIUS), Rand(0, 359), Rnd(0.25, 2.0), Rnd(0.25, 2.0))NextMoveMouse(400, 300)HidePointer()Local fastMethod = 1Local fpsTimer = CreateTimer(30)Local deltaCount = 0Local lastDeltaLocal deltaWhile Not (KeyHit(1) Or (KeyDown(56) + KeyDown(62))) WaitTimer(fpsTimer) navigation(camera) ;During the update cycle, align all the billboards with the camera. alignBillboards(camera, billboardPivot) UpdateWorld() RenderWorld() Flip()WendEndFunction navigation(camera) MoveEntity(camera, KeyDown(32) - KeyDown(30), 0, KeyDown(17) - KeyDown(31)) Local mY = MouseYSpeed() If Abs(mY + EntityPitch(camera, True)) > 88.9 Then mY = 0 TurnEntity(camera, mY, -MouseXSpeed(), 0) RotateEntity(camera, EntityPitch(camera, True), EntityYaw(camera, True), 0, True) ;Doesn't let the camera tilt with time. MoveMouse(400, 300) MouseXSpeed() ;Avoids the camera rotating right? I think my mouse is broken.End FunctionFunction addBillboard.TBillboard(surface, x#, y#, z#, roll#, scaleX# = 1.0, scaleY# = 1.0) b.TBillboard = New TBillboard b\surf = surface b\posX = x b\posY = y b\posZ = z b\roll = roll b\scaleX = scaleX b\scaleY = scaleY b\r = Rand(0, 255) ; 0 ~ 255. b\g = Rand(0, 255) ; 0 ~ 255. b\b = Rand(0, 255) ; 0 ~ 255. b\alpha = Rand(20, 100) / 100.0 ; 0.0 ~ 1.0 b\vID[0] = AddVertex(surface, -1, 1, 0) ;Top left. b\vID[1] = AddVertex(surface, 1, 1, 0) ;Top right. b\vID[2] = AddVertex(surface, 1, -1, 0) ;Bottom right. b\vID[3] = AddVertex(surface, -1, -1, 0) ;Bottom left. AddTriangle(surface, b\vID[0], b\vID[1], b\vID[2]) AddTriangle(surface, b\vID[2], b\vID[3], b\vID[0]) Return bEnd FunctionFunction alignBillboards(camera, pivot) ;Retrieve the (normalised) 'up' and 'right' vectors of the camera in world space. ;This is only needed once per frame instead of per billboard as it is usually done. RotateEntity(pivot, EntityPitch(camera, True), EntityYaw(camera, True), 0, True) Local camRightX#, camRightY#, camRightZ# TFormNormal(1, 0, 0, pivot, 0) camRightX = TFormedX() camRightY = TFormedY() camRightZ = TFormedZ() Local camUpX#, camUpY#, camUpZ# TFormNormal(0, 1, 0, pivot, 0) camUpX = TFormedX() camUpY = TFormedY() camUpZ = TFormedZ() Local bCos#, bSin# Local bRightX#, bRightY#, bRightZ# Local bUpX#, bUpY#, bUpZ# ;Update the billboard objects. For b.TBillboard = Each TBillboard ;1) Update the properties of the billboard. b\roll = b\roll + BILLBOARD_ROTATION_SPEED ;b\life, ;b\scale, ;b\alpha etc. ;---------------------------------------------------------------------------------------------- ;2) Update the geometry of the billboard based on the properties and the camera. ;Get the cosine and sine for rotating the "up" and "right" vectors of the billboard. bCos = Cos(b\roll) bSin = Sin(b\roll) ;Right vector. bRightX = ((camRightX * bCos) - (camUpX * bSin)) * b\scaleX bRightY = ((camRightY * bCos) - (camUpY * bSin)) * b\scaleX bRightZ = ((camRightZ * bCos) - (camUpZ * bSin)) * b\scaleX ;Up vector. bUpX = ((camRightX * bSin) + (camUpX * bCos)) * b\scaleY bUpY = ((camRightY * bSin) + (camUpY * bCos)) * b\scaleY bUpZ = ((camRightZ * bSin) + (camUpZ * bCos)) * b\scaleY ;Position and rotation. ;The vertices of the billboard quad are placed based on the sum (or subtraction) of the rotated right and up vectors. VertexCoords(b\surf, b\vID[0], b\posX - bRightX + bUpX, b\posY - bRightY + bUpY, b\posZ - bRightZ + bUpZ) ;Top left. VertexCoords(b\surf, b\vID[1], b\posX + bRightX + bUpX, b\posY + bRightY + bUpY, b\posZ + bRightZ + bUpZ) ;Top right. VertexCoords(b\surf, b\vID[2], b\posX + bRightX - bUpX, b\posY + bRightY - bUpY, b\posZ + bRightZ - bUpZ) ;Bottom right. VertexCoords(b\surf, b\vID[3], b\posX - bRightX - bUpX, b\posY - bRightY - bUpY, b\posZ - bRightZ - bUpZ) ;Bottom left. ;Colour. VertexColor(b\surf, b\vID[0], b\r, b\g, b\b, b\alpha) VertexColor(b\surf, b\vID[1], b\r, b\g, b\b, b\alpha) VertexColor(b\surf, b\vID[2], b\r, b\g, b\b, b\alpha) VertexColor(b\surf, b\vID[3], b\r, b\g, b\b, b\alpha) ;Texture. ;VertexTexCoords(...) ;VertexTexCoords(...) ;VertexTexCoords(...) ;VertexTexCoords(...) ;Etc. NextEnd Function