The old surfaces problem

Blitz3D Forums/Blitz3D Programming/The old surfaces problem

gburgess(Posted 2005) [#1]
We all know Blitz can't handle too many surfaces without starting to grind.

Every now and again, this becomes a real pain. The bottleneck in my game at the moment is caused by the graphics. In language made to deal with 3d, this is a real bummer.

The problem is only partly to do with particles. I can't really use a single-surface system, because I have some nice effects going on with my particles splashing into water or kicking up dust on terrain, and I'd like to keep that level of visual interactivity. I'm prepared to pay the price of having to be careful how often I use them.

However, I also have a lot of shots flying around in the air. The game, "Drop Fighter" puts the player in the seat of an advanced air and space fighter, and often there are both allied and enemy units battling around you. This creates a metric buttload of weapons fire flying through the air. I've managed to optimise the crap out of the collision detection, and I'm pretty satisfied with how it stacks up in a heavy combat situation. However, I'm starting to notice a slight amount of slowdown which is being caused during rendering, and it happens when there's a lot of shots in the air. Obviously, one shot = one surface. So, I was wondering...

1) Is the problem ever going to be fixed (or is it even fixable), or is it one of those things that's a side effect of the architecture of the engine?
2) Using HideEntity for stuff that's offscreen... will that help alleviate the problem, or does Blitz automatically remove stuff offscreen from the renderworld job?
3) Any other tips, aside from single-surfacing, on squeezing the most performance out of this situation?


KuRiX(Posted 2005) [#2]
1) This is not really a problem to be fixed, is a limitation.
2) HideEntity is very slow.
3) I think you can use single surfacing. Asign a pivot to every quad in the single surface so you can interact with ground, water, etc!


Beaker(Posted 2005) [#3]
Since when did HideEntity become slow?


John Pickford(Posted 2005) [#4]
It isn't.


Ross C(Posted 2005) [#5]
Yeah, hide entity is instantous, or as quick as. And changing your particles to single surface, you won't loss any degree of creative freedom. It just requires a bit more work.


gburgess(Posted 2005) [#6]
So what's the verdict, does hiding offscreen entities help? Do offscreen entities count in the surface count, and does hiding them while offscreen make them not count?

Yeah, I've looked at single surface for the particles, but it seems to be a bit of a nightmare for me. I see what you're saying about using pivots, but there seems to be other pitfalls with that technique. While I'm sure they're all fixable, it would take a large cunk of time, and wouldn't alleviate the problem of multiple shots flying through the air adding to the surface count.


slenkar(Posted 2005) [#7]
try entityalpha,0


Danny(Posted 2005) [#8]
Blitz does it's own 'off screen' optimalisations for sure (check the rendered poly count). Trying to do it myself I've never been able to actually make it faster using hideEntity() (after checking they are in view ofcourse).

I must add that was in a time that I didn't have a proper 3d card (was software only), but now I do and might give different results.

0.2


KuRiX(Posted 2005) [#9]
I had heard that hideentity was slow. Sorry if not.

The problems with a Single Surface are two:

1 - You can't hide one single quad to gain speed. In a surface, you render the whole surface or you render nothing.

2 - I have noticed some slowdown when using it with letters to make phrases, because you need to change every time every single quad to contain the letter you need (with texture vertex coords).

Of course it is more difficult to implement than sprites, but the gain in speed is very good! I suggest you to download some samples from the code archives and change them to fit your needs.

Good Luck!


gburgess(Posted 2005) [#10]
Okay, well, I wrote a single surface particle system, just so people would stop asking me to. It wasn't as hard as I thought, but I'm pretty disappointed with the performance. It certainly renders faster, but it takes longer to calculate. Overall, the system is very fast with few particles, and very slow with more than 100-200, which overall works out poorer than the old multi-surface system. I'm using two triangles per particle, maybe I should try it with just one bigger tri? Would remove an addvertex and an addtriangle from the cycle, I guess.

Also, there were all kinds of problems with the sea effect I had going on. The plane got transparent near the landmasses, which I thought was pretty neat and was very proud of the effect. That had to go to stop the party's flickering.

All in all, this single surface stuff isn't as awesome as everyone makes it out to be, unless I've made a giant gaffe somewhere that's eating up the speed.


KuRiX(Posted 2005) [#11]
Post some code about the particle position calculation, perhaps you are making innecesary maths...


Ross C(Posted 2005) [#12]
Yea, 200 particles being slow, shouldn't really happen. the maths involved ian't that intense...


Beaker(Posted 2005) [#13]
Always use 2 triangles for particles (unless they are triangle shaped and you fill that shape).


gburgess(Posted 2005) [#14]
Maybe it's something I'm doing elsewhere, I dunno. Well here it is, anyway. This is the new, single-poly version I just finished. Each particle is a polygon big enough to fit one non-repeating version of the texture, hence the UV value of 1.5, to allow the polygon to be big enough to not cut off the sprite. This seems to work fine, Beaker, I can't think of a reason not to do it.

ppsrf%=GetSurface(doparty\parent,1)
PositionEntity doparty\modelhandle,doparty\xpos,doparty\ypos,doparty\zpos
PointEntity doparty\modelhandle,maincam,doparty\angle
TurnEntity doparty\modelhandle,0,180,0

TFormPoint 0-(doparty\size*0.375),0-(doparty\size*0.375),0,doparty\modelhandle,doparty\parent
blx#=TFormedX():bly#=TFormedY():blz#=TFormedZ()
TFormPoint 0-(doparty\size*0.375),(0+(doparty\size*0.375))*2,0,doparty\modelhandle,doparty\parent
tlx#=TFormedX():tly#=TFormedY():tlz#=TFormedZ()
TFormPoint (0+(doparty\size*0.375))*2,0-(doparty\size*0.375),0,doparty\modelhandle,doparty\parent
brx#=TFormedX():bry#=TFormedY():brz#=TFormedZ()
		
v1=AddVertex(ppsrf%,blx#,bly#,blz#,0,0,0)
v2=AddVertex(ppsrf%,tlx#,tly#,tlz#,0,1.5,0)
v3=AddVertex(ppsrf%,brx#,bry#,brz#,1.5,0,0)

VertexColor(ppsrf%,v1,255,255,255,doparty\alpha#)
VertexColor(ppsrf%,v2,255,255,255,doparty\alpha#)
VertexColor(ppsrf%,v3,255,255,255,doparty\alpha#)

AddTriangle(ppsrf%,v1,v2,v3)


The first part positions the null object. It's flipped 180 degrees so the polys are facing the right way.

Obviously, this code is called per-particle. The \parent field refers to the handle of the parent object housing the particles, what's normally called an "emitter" I guess. I don't quite follow the emitter philosophy, but each local explosion and effect has one or two of these parents, basically one for each particle type involved in the effect.

ppsrf% is the surface of the parent object that the polys are being added to, cleared every frame.

TFormPoint is used to find the four corners to join together for each party.

Thanks for the help, guys.


Beaker(Posted 2005) [#15]
A single triangle has much more overdraw than 2 triangles making a quad (if the image is roughly square or circular). Think about it. You will notice greater slowdown as each particle gets closer to the screen.


gburgess(Posted 2005) [#16]
Yeah, that makes sense, but it's still more efficient with a single triangle. At least, so far.

Yeah, you're looking at twice as much polygon area, but don't fully transparent parts of the poly render quicker? That's a question, 'cos I don't know.

Nevertheless, halving the number of actual polygons does the following:

-Reduces the number of AddVertex calls by 25% each cycle.
-Reduces the number of AddTriangle calls by 50% each cycle.
-Reduces the number of TFormPoint calls by 25% each cycle.

The improvement from the reduced meshwork and calculations seem to be outweighing the extra time needed to render the polygons.

As each particle gets closer to the screen, the amount actually visible is the same, the transparent area is bigger, yes, but it's 100% invisible. I would guess this is quicker than if the tri was semitransparent all the way through.


BIG BUG(Posted 2005) [#17]
ppsrf% is the surface of the parent object that the polys are being added to, cleared every frame.


You delete and rebuild your Mesh every frame? Don't!
That tricky part of singlesurface is to build the mesh only once(e.g. with 400 quads, every quad get referenced by a type). Then just grab those quads you need and move the others out of sight.


Ross C(Posted 2005) [#18]
Yep, don't clear and rebuild your surface :o)


TartanTangerine (was Indiepath)(Posted 2005) [#19]
Don't clear and rebuild

I don't see any noticable difference in speed by rebuilding the mesh.


joncom2000(Posted 2005) [#20]
don't clear and rebuild

How can you generate new and delete old particles if you don't clear the surface ?
Surely the number of particles your drawing isn't constant for every type of effect you would use particles for ?


mrtricks(Posted 2005) [#21]
But clearing and rebuilding a mesh takes a lot of processing power. Set up the mesh during initialisation and position the verts of those not needed in any one frame outside the clipping range of the camera. If you have a particular location for hidden verts, it's easy then to check if they're in use or not when you need a new one. They'll still render, but it's still quicker than creating a new mesh every frame.

Think of it like Dimming an Array. You create the 1000 (or however many) items at startup, then use them as needed, then ignore/put away once not needed.

Or, to be poncey, think of it like actors in a stage play. They're all hired before the show opens. When the character walks offstage, the producers don't shoot him and then quickly hire a new actor just before the character's next scene - they just hide him in the green room. Better for everyone :)


John Pickford(Posted 2005) [#22]
In my stuff I don't rebuild the mesh but I know Anthony Flack is building each time for Cletus and he reckons its faster. I've been meaning to redo my stuff on the strength of that anticipating a speed up.


Beaker(Posted 2005) [#23]
In my (and others) tests from long ago, it was about the same speed for both.

The main bottleneck for both is transfering the vert data to the gfx card, and both have the same amount of work here.


joncom2000(Posted 2005) [#24]
Thanks for the explaination mrtricks, but I personally have found moving the vert's around in a mesh using the vertexcoords command slower than rebuilding the mesh. Perhaps there are cases for both methods depending on the amount you have to move.