Since that post I have made some pretty major updates to the backing renderer to increase performance. There's still quite a bit left that can be tweaked, but at this point I'm much more confident in the overall performance of the engine but wanted to outline a few of the changes made to the system and the current results.
First, I was previously using render.RenderImage, that basically just displays a textured quad on the screen with immediate mode rendering. This has been changed to rely on render.shape.Shape class that allows any OpenGL shape to be represented with vertices with triangles, quads, etc. The new Shape class also automatically detects whether VBO is supported and will use that if available over immediate mode. I plan to add additional support for GLSL in the future, but at the moment my focus is the best compatibility and working upwards.
Next, I created a new ui.Box class that represents a modifiable, texturable box on the screen. Previously the cubes being displayed were represented by six distinct RenderImages backed against the same texture.
Finally, I've added the ComponentInstance class I mentioned in my last post to allow instancing rather than creating completely new cubes each time.
The results of these changes were a pretty good bump in performance:
Now, keep in mind that framerates are not linear, so this is a pretty substantial improvement over the 38fps I was previously getting.
To prove this I added a few more boxes to the scene (1600 to be exact) to get my framerate back into the 30s:
The new source code looks a bit different from the previous stress test, but pretty easy to read I think:
package org.sgine.ui import org.sgine.core.Resource import org.sgine.easing.Elastic import org.sgine.effect._ import org.sgine.property.animate.EasingNumericAnimator import org.sgine.property.animate.LinearNumericAnimator import org.sgine.render.Debug import org.sgine.render.RenderSettings import org.sgine.render.StandardDisplay import org.sgine.ui.ext.AdvancedComponent import scala.math._ object TestStressBoxes extends StandardDisplay with Debug { override val settings = RenderSettings.High def setup() = { var box: Box = null for (row <- 0 until 40) { for (column <- 0 until 40) { val y = (row * 30.0) - 350.0 val z = (column * 90.0) - 1800.0 if ((row == 0) && (column == 0)) { box = createBox(y, z, 0.05) } else { createInstance(box, y, z, 0.05) } } } } def createBox(y: Double, z: Double, scale: Double) = { val box = new Box() box.scale.set(scale) box.location.set(0.0, y, z) box.source := Resource("sgine_256.png") animate(box) box.update(0.0) scene += box box } def createInstance(component: Component, y: Double, z: Double, scale: Double) = { val instance = ComponentInstance(component) instance.scale.set(scale) instance.location.set(0.0, y, z) animate(instance) instance.update(0.0) scene += instance instance } private def animate(component: AdvancedComponent) = { component.rotation.x.animator = new LinearNumericAnimator(2.0) component.rotation.y.animator = new LinearNumericAnimator(2.0) component.rotation.z.animator = new LinearNumericAnimator(2.0) component.location.x.animator = new EasingNumericAnimator(Elastic.easeInOut, 3.0) component.rotation.x := Double.MaxValue component.rotation.y := Double.MaxValue component.rotation.z := Double.MaxValue // Move the cube back and forth perpetually on the x-axis val me0 = new PauseEffect(random * 2.0 + 0.5) val me1 = new PropertyChangeEffect(component.location.x, -400.0) val me2 = new PropertyChangeEffect(component.location.x, 400.0) val move = new CompositeEffect(me0, me1, me2) move.repeat = -1 move.start() } }
This could be cleaned up more, but should give you an idea of how simple it is to fill a scene up with boxes. :) I'd like to make one last note on this test that you can't see unless you actually run it. The previous test took around 20 seconds to asynchronously fully load all cubes on the screen. Since I'm using ComponentInstance that time has dropped to about one second to fully load on the screen. This is a drastic improvement in scene load-time. Now it's time to get back to work on functionality.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.