You can think of this lib as some kind of Tilemap for Starling : it renders lots of quads/images in a single DisplayObject with far better performance than regular Starling Quad/Image classes.
You are currently limited to 16383 quads per MassiveDisplay instance (I’m gonna remove that limit)
It’s available on haxelib : haxelib install massive-starling
I believe this lib has lots of potential and can be useful to many devs using Starling : feedback is warmly welcome !
Current version is 1.0.0-alpha, it should be pretty stable : only known issue is an error occuring with ParticleEmitter when building to cpp. It’s my first time with @:generic, I’ll welcome any help with that issue : the haxe part works fine, the error occurs when building the c++ source files
@Bink Thanks ! I’d love to get some feedback, good or bad
Massive was updated to 1.0.0-alpha.1 on github and haxelib
MassiveDisplay now has a renderMode property which is expecting values from MassiveRenderMode
Default renderMode is either MassiveRenderMode.FLOAT32ARRAY (non-flash targets) or MassiveRenderMode.BYTEARRAY_DOMAIN_MEMORY (flash/air target)
MassiveDisplay now has a colorMode property which is expecting values from MassiveColorMode. There is a new mode called REGULAR, which stores vertex color over 4 bytes. This prevents some cool color effects when setting color values higher than 1.0, but brings a small performance improvement (about 5-10% except with Vector render mode on flash/air target, where it’s slower)
Default colorMode is MassiveColorMode.EXTENDED
Note that there is an issue with MassiveColorMode.REGULAR which happens on Firefox but not on Chrome on my system : when using that color mode with FLOAT32ARRAY or VECTOR render modes quads with a blue color value over 0.5 appear all blue. I’ll have to look into it a bit more.
MassiveDisplay instances now share program, except when you set a custom one
MassiveDisplay index buffer creation was optimized
MassiveDisplay’s renderData and updateExactBounds methods were finalized
MassiveDisplay and DisplayData : colorAlpha, colorRed etc were renamed to simply alpha, red etc to avoid Starling’s Tween considering them as Ints
MassiveDisplay and DisplayData now have a color property (Int)
MassiveDisplay was reworked to be more flexible : setting rendering-related values after adding it to Stage could result in errors or weird results, this is no longer the case.
All demos were updated with those changes, particle editor demo now lets you set renderMode and colorMode
Massive was updated to 1.0.0-alpha.2 on github and haxelib
MassiveDisplay can now render an unlimited amount of quads, the 16K limit was removed. MassiveDisplay will make 1 draw call per 16383 quads
bufferSize and numBuffers properties were removed from MassiveDisplay
MassiveDisplay now has a maxQuads property (default 16383) which determines buffer size and how many buffers will be used (1 VertexBuffer3D for 16383 quads)
MassiveDisplay now has an autoUpdateBounds property (default false) : when set to true, bounds data is stored during rendering and exact bounds are calculated right after. When false you can call writeBoundsData() and then updateExactBounds()
MassiveDemo now has a button to toggle autoUpdateBounds
When I started removing the 16K limit I had worse performance at first, because I was using only one VertexBuffer3D : it turns out you have to upload a VertexBuffer3D only once per frame for best performance.
I’m really happy with the state of Massive now ! Next is multitexturing, I hope it won’t lower performance too much
No update yet, but a preview of the multitexturing feature MassiveDemo
Multitexturing is fully working with up to 16 textures on a single MassiveDisplay instance : it could go even higher if you GPU can handle it !
In baseline profile the shader can only handle 5 textures though
Performance is a bit lower when multitexturing is on, but still excellent
I duplicated and colorized the zombi atlas to have 16 of them : every zombi with a different color comes from a different atlas. The demo will automatically select as many atlases as possible.
This is far beyond my expectations to be honest : when I started working on Massive I never thought it would go that far That makes me want to do some kind of “Vampire Survivor” demo… but that’ll have to wait
Alpha3 update will require a small change on haxe-Starling in order to be able to set the ignoreLimits parameter when calling the AGALMiniAssembler’s assemble function
EDIT : replaced the preview link with the regular demo link
Massive was updated to 1.0.0-alpha.3 on github and haxelib
MassiveDisplay can now have up to 16 different textures (only 5 if profile is baseline, because of AGAL 1 limitations)
You have to call MassiveDisplay.init() once, after Starling is started. This lets Massive check for baseline profile and max textures (on non-flash targets : on flash I don’t know how to get this info and max textures is set to 16 if not baseline
MassiveDisplay now has functions to add/remove/get/set textures
added documentation
If you wanna try this version you will have to use the 2.8 branch on my fork, to get the ignoreLimits parameter and the new MultiTextureStyleGitHub - MatseFR/starling at v2.8 · GitHub
I’m waiting for Daniel to merge my PR on the as3 version before I push those on the haxe version
I also released the as3 version of Massive
While doing this I discovered that running starling from haxe on air target results in much better performance than running it from as3 : on the Massive demo with haxe I have 60fps when displaying 4000 classic MovieClips while I only have 20 fps with as3. To get down to 20 fps with haxe I have to display 16 000 classic MovieClips (!)
I was totally expecting the haxe version to be faster because the compiler is such a beast, but not by that much !
For anyone interested the MassiveDemo was updated with a revised version of MultiTextureStyle (that Massive doesn’t use : it only applies to the UI and classic starling clips)
You can clearly see the draw calls changing when enabling/disabling MultiTextureStyle or setting its maxTextures
Massive was updated to 1.0.0-alpha.4 on github and haxelib
DisplayData (base class for QuadData and ImageData) now has skewX and skewY properties
DisplayData’s rotation, scaleX, scaleY, skewX and skewY are now inlined get/set with a “dirty” system : MassiveLayer now use that to know if it needs to recalculate vertices positions, which are stored and re-used when nothing changed. This opens the way for very efficient vertex animations, which I plan to add in “soon”
MassiveDisplay now has a colorOffsetMode property, which takes values from the ColorOffsetMode class (default NONE). Color offset can occur at the MassiveDisplay level, affecting all displayed content, and/or at the “object” (ImageData/QuadData) level.
MassiveColorMode was renamed to ColorMode and has an additionnal DISPLAY value which enables color only at the display level
Program (shader) creation code had a rewrite and is now optimized for every case (color, color offset and texture(s)). Created programs are stored in a cache and reused untill MassiveDisplay.clearProgramCache() is called
ParticleSystem and ParticleSystemOptions have new settings to make use of skew and color offset. Several presets in the particle editor demo have been updated to use those.
ParticleSystem and ParticleSystemOptions have a new emitterMode property which takes values from the EmitterMode class : default is STREAM which is what we had already, and the other one is BURST, which comes with a few additionnal properties : numBursts (how many bursts before stopping, 0 = infinite), burstDuration (for how long the system emits particles for a single burst, 0 = instant), burstInterval (how much time between two bursts) and burstIntervalVariance
About color offset
Color multiplies with texel color, while color offset adds or substracts. If you have a black pixel and want to colorize it red color won’t work because the RGB values are zero, and the multiplied result will still be zero. Color offset will color it red because it adds to that zero value.
You can use the particle editor demo to play around with color offset
ColorOffsetMode has 4 possible values :
DISPLAY enables color offset on the MassiveDisplay object, affecting all displayed content in the same way. You can then control color offset using the redOffset, greenOffset, blueOffset and alphaOffset properties.
OBJECT enables color offset for “display objects” (ImageData and QuadData). You can control color offset individually for each object using the redOffset, greenOffset, blueOffset and alphaOffset properties.
DISPLAY_AND_OBJECT enables color offset for both
NONE disables color offset entirely
You can use any combination of colorMode and colorOffsetMode : for example you could have colorMode set to ColorMode.NONE, which will still display textures, and colorOffsetMode set to ColorOffsetMode.OBJECT if all you want is color offset (to make an enemy blink red when taking damage for example)
Remember that colorMode and colorOffsetMode (as well as using multiple textures) affects the Program (shader) complexity so for best performance you should use the minimum settings that you need.
An interesting side effect of color offset is that you can use negative alphaOffset values to achieve the exact same result as BlendMode.ADD but with more control : setting alphaOffset to -1.0 is like 100% ADD, while -0.5 is 50% ADD
I think this only works with textures that have premultiplied alpha, which is typically the case anyway.
You can see this in action by launching the ParticleEditor and load the animated fx, ghost donut or star geyser preset
Massive was updated to 1.0.0-alpha.6 on github and haxelib (there was an alpha 5 but I realized it had a stupid error)
Many things changed with quite a few added features, I’m now pretty happy with where this is going and think I’m getting close to a “final” version
MassiveLayer no longer exists : it is replaced with MixedContainer and ImgContainer, both extending ContainerBase. I removed the type parameters for now, they might come back later but ContainerBase is relatively easy to extend if you really want a container with a specific type. ParticleSystem is also a container now.
MixedContainer lets you add containers or display objects while ImgContainer only takes display objects. ImgContainer is slightly faster since it doesn’t have to check if an added object is a container or not.
containers have color and color offset vars which apply to all objects inside them. A container inside a container is affected by its parent(s) position, color and color offset. I will consider adding scale and rotation properties to containers.
ImageData no longer exists : it is replaced with Img, Clip and EventClip. QuadData no longer exists, period. If you want a simple color quad you’ll have to create a tiny white texture to use with Img and set its color.
Img extends QuadBase and is a simple textured quad (equivalent to a Starling Image)
Clip extends Img and can play animations (using the new Animation class)
EventClip extends Clip and can dispatch animation events
VertexPositionData is a new class that stores custom vertex positions, when a QuadBase (Img, Clip, EventClip) object has its vertexPosition property set the container it belongs to will use that when rendering. It will also use scaleX/scaleY but ignore rotation and skewX/skewY. It can be inverted on X and Y axis.
VertexColorData is a new class that stores individual colors for each vertex, when a QuadBase object has its vertexColor and/or vertexColorOffset properties set the container it belongs to will use that when rendering instead of regular color/colorOffset values. It can be inverted on X and Y axis
Animator is now an object which can be added to a Juggler and handles animating clips and particles, as well as advancing particle systems. You can add single clips to it or arrays/vectors, if you add an array/vector you can then set its content as you like, meaning you can add/remove tons of clips without needing to call any add or remove function. It can animate clips in a very basic (faster) way, where it won’t skip frames if framerate is low with addBasicClip and addBasicClipList. Otherwise it’ll skip frames if needed with addClip/addEventClip and addClipList/addEventClipList, and EventClip will still dispatch events for skipped frames
Animation is a new class for clip animations, it contains one or more AnimationFrame objects. Animation frames store Frame and optionnally VertexPositionData and VertexColorData (color and/or color offset). It can also store events and event parameters, but those will only work when the animation is played by an EventClip object. Note that a single Animation object can be used by as many Clip or EventClip objects as you want.
AnimationCollection is a new class that stores animations and lets you retrieve them with their ID, it can be used with Clip’s animationCollection property to take advantage of Animation’s nextAnimationID and/or to use Clip’s playWithID function
AnimUtils is a new class with helper functions to create animations, including vertex position and vertex color animations.
ParticleSystem now has an animator property which you can set and the system will register itself and its particles to it
ParticleSystemOptions now doesn’t export all settings unless they are required, resulting in smaller particle configuration file size (and faster parsing I guess)
I’m probably forgetting a few things but that’s most of the changes
Next is gonna be (bitmap) text ! I also want to try adding a few built-in “filters”
EDIT : forgot to mention demos have been updated, with MassiveDemo illustrating some of the new stuff like vertex position / color / color offset animation
Here are the links again for convenience :