How expensive is the billboard transform?

I’m currently using a simple model for the projectiles in my program. I have a way to replace them with a simple image that looks similiar but uses 2 billboard transforms.

My question is that I have had hundreds of projectiles in my program with the simple models, if I go with billboards will it slow everything down?

Do you want to use a billboard because you think a billboard will look better?

With hundreds of projectiles, the fastest way is to create 50 projectiles at a time, and parent them to a RigidBodyCombiner. When one isn’t in use, move it out of sight, don’t remove it from the combiner. Removing it from the combiner requires the combiner to recompute, whereas merely moving it out of sight is mere animation. You can set the scale to zero — that counts as animation.

That way, what you’re basically doing is animating one complex model with 50 “limbs”, instead of creating and destroying individual projectiles.

You know, I bet you could do the same with billboards. I haven’t tested this, but you could probably create 50 billboards at a time, under a rigid body combiner. You could probably stick billboard effects on those billboards, and it would probably work just fine.

Another approach to render lots of “billboarded” polygons, if each billboard object is just a single textured polygon, is to use the GeomPoints object, as described the manual page, with setRenderModePerspective() and MPointSprite in effect. This is the way the SpriteParticleRenderer works to render hundreds or thousands of billboarded sprites.

David

I have tried to render lots of billboards using this technique, but I run into a problem when rendering the result.

When viewing the .egg file below (e.g. with pview.exe) the sprites are at first rendered with “thickness” 1, and after rotating around a few seconds (random mouse movements) suddenly the “real” thickness is applied (the sprites get bigger).

Is this a bug, or am I doing something wrong here? Maybe I forgot to set some parameters. I am using the default Panda3D 1.4.1 distribution for Windows.

PS: This also happens if I use a GeomVertexWriter and then use setRenderModeThickness and setRenderModePerspective for the created NodePath.

enn0x

<CoordinateSystem> { Z-Up }

<VertexPool> test {
  <Vertex> 0 {
    -29.0051 39.5694 0.245445
  }
  <Vertex> 1 {
    -24.4634 -16.365 0.892678
  }
  <Vertex> 2 {
    -15.898 44.3481 0.716794
  }
  <Vertex> 3 {
    -21.1664 -43.8205 0.710566
  }
}
<PointLight> {
  <Scalar> thick { 30 }
  <Scalar> perspective { 1 }
  <VertexRef> { 0 <Ref> { test } }
}
<PointLight> {
  <Scalar> thick { 30 }
  <Scalar> perspective { 1 }
  <VertexRef> { 1 <Ref> { test } }
}
<PointLight> {
  <Scalar> thick { 30 }
  <Scalar> perspective { 1 }
  <VertexRef> { 2 <Ref> { test } }
}
<PointLight> {
  <Scalar> thick { 30 }
  <Scalar> perspective { 1 }
  <VertexRef> { 3 <Ref> { test } }
}

The .egg file was created with this script:

from pandac.PandaModules import EggData
from pandac.PandaModules import EggPoint
from pandac.PandaModules import EggVertex
from pandac.PandaModules import EggVertexPool
from pandac.PandaModules import Filename
from pandac.PandaModules import Point3D

import random

vp = EggVertexPool( 'test' )

data = EggData( )
data.setCoordinateSystem( 1 ) # CS_zup_right
data.addChild( vp )

for i in range( 200 ):
    x = random.uniform( -50, 50 )
    y = random.uniform( -50, 50 )
    z = random.uniform( -1, 1 )

    vertex = EggVertex( )
    vertex.setPos( Point3D( x, y, z ) )
    vp.addVertex( vertex )

    p = EggPoint( )
    p.setPerspective( True )
    p.setThick( 10.0 )
    p.addVertex( vertex )
    data.addChild( p )

data.writeEgg( Filename( 'test.egg' ) )

Could be a driver issue. I’ve run into several driver issues related to this perspective-sprite extension.

Try setting:
hardware-point-sprites 0

in your Config.prc, to do the computation on the CPU. This is not quite as fast, but still much faster than the corresponding billboard x n computation.

David

Setting hardware-point-sprites to 0 solves the issue. So far I don’t see much performance loss. Thanks a lot for the workaround.

enn0x

I hit it too eventually, and I’m very happy ! :smiley: :smiley: :smiley:
… since I realized how to fix it without “hardware-point-sprites 0”, but my question is : if I do the following way, is it still done by hardware ?

If textured, it’s upside down, so I have to flip it myself, and the flipping fixed the problem.

my case :

LS=LineSegs()
LS.setColor(1,1,1,1)
LS.setThickness(25)
LS.moveTo(0,0,0)
point=render.attachNewNode(LS.create())
tex=loader.loadTexture('maps/lilsmiley.rgba')
TS=TextureStage.getDefault()
point.setTexGen(TS,TexGenAttrib.MPointSprite)
point.setTexture(tex)
point.setTexScale(TS,1,-1)
point.setTransparency(TransparencyAttrib.MAlpha)
point.setRenderModePerspective(1,1)

yours :

test=loader.loadModel('test')
test.reparentTo(render)
TS=TextureStage.getDefault()
test.setTexGen(TS,TexGenAttrib.MPointSprite)
test.setTexScale(TS,1,-1)

camera.setPos(250,-40,0)
camera.lookAt(test)
mat=Mat4(camera.getMat())
mat.invertInPlace()
base.mouseInterfaceNode.setMat(mat)

Loading like this (with flipped texture) seems to fix it for me too, but there is almost no performance difference between disabling hardware sprites and flipping texture. Thanks for the alternate solution :slight_smile:

import direct.directbase.DirectStart
from pandac.PandaModules import TextureStage

np = loader.loadModel( 'test.egg' )
np.reparentTo( render )
np.setTexScale( TextureStage.getDefault( ), -1, 1 ) 

run( )

enn0x

Note that as soon as you call setTexScale() it forces it to render in software again. The OpenGL sprite texture extension is really insanely limited. If you want to render it in hardware, you have to paint your texture upside-down.

David

yes, I already realized it and had my tex flipped.
Thanks for your clarification, David. :slight_smile: