Summary
Rendering and performance improvements
In the process of upgrading an internal game project to the latest series of Indigo, a number of performance gaps and rendering issues were identified, particularly on Windows using hardware we don't test on very often. This work effort was primarily about resolving those issues.
On one test rig, our game has gone from ~30 FPS to >200 FPS with these rendering pipeline changes. With this kind of work it is always a possibility that we'll introduce regressions, please report if you see anything anomalous.
New Primitive: Quad
How do you draw a box and fill it with a colour?
Well, until now, the answer has been to use Shape.Box. The problem with using a Shape is that all of the shapes share a common drawing method (in order to keep them all looking stylistically the same) called SDFs, and the problem with SDF's is that they are subject to floating point rounding errors.
The other way to do it was with a BlankEntity and a custom shader - but that seems like rather hard work for such a simple task!
Quad is a new primitive that allows you to draw pixel perfect boxes (handy for progress bars and the like). You can fill a quad with a solid colour, or a linear or radial gradient. You can also specific the radius of each corner, if you like.
Improved Aseprite importing
We've had support for importing Aseprite for many years, but only in a particular and limited format. An attempt has been made a better support Aseprite's two JSON formats.
Bug fixes
FrameRatePolicy
There was a nasty bug where setting the FrameRatePolicy actually affected the frame rate. i.e. setting an unlimited frame rate policy on a 60Hz monitor would give you 60 FPS, but setting a frame rate policy of 60 FPS exactly on the same system might result in a lower actual rate.
This happened during the work of moving control over frame rates from Indigo to Tyrian, and has now been resolved, or at least, greatly improved.
Clip rounding errors
Under certain circumstances, and on particular GPU hardware where underlying implementations of certain functions differ, Clip shaders would suffer a rounding error resulting in a bad modulo function. This has been resolved.
In addition, Ultraviolet will now error if you try and use invalid modulo operation argument type combinations, and correctly renders modulo operations for different flavours of GLSL.
Breaking changes
BlankEntity constructors
There was previously a constructor for BlankEntity that allowed you to make one in an invalid state (size = 0,0), which has now been removed. You must now provide a size for your entity, so if you choose to set it to zero, that's on you!
FPSCounter constructors
FPSCounter had some work done to it in the last release, and here the work continues. In the process of fixing a bug, the main constructor which used to take an AssetName, now requires a function where you explain how to make the material for the Text instance RGBA => Material. While I was there, I also re-ordered the arguments to make them more sensible. They'd evolved organically for a few years and since I was breaking the API anyway, now seemed the time to rationalise.
If you really want the old behaviour, there is an FPSCounter.tinted(..) constructor you can use.
Actor's now have View types
Note that this change does not affect
Performers, the opinionated cousins ofActors.
Previously, an Actor's present function always returned Outcome[Batch[SceneNode]]. This worked ok for simple use cases, but Actors often benefit from being rendered via clones, and this type signature doesn't permit that or any other more advanced rendering strategy.
Actors now return an Outcome[ViewType] where ViewType is parameterised and can be literally anything, such as CloneBatchData. The only hard requirement to make this work is that ActorPool now cannot be constructed 'empty' anymore. You must always at minimum provide a function of Batch[ViewType] => SceneUpdateFragment.
If you want the old behaviour, all you have to do is set the ViewType to be Batch[SceneNode], and provide a function Batch[Batch[SceneNode]] => SceneUpdateFragment, something like:
actors => SceneUpdateFragment(
LayerKey("layer a") -> Layer.Content(actors.flatten)
)What's Changed
- WebGL 2.0 renderer optimisations, improvements, and bug fixes by @davesmith00000 in #265
- FIXED #254: Removed invalid BlankEntity constructor by @davesmith00000 in #266
- Fpscounter improvements by @davesmith00000 in #269
- Fixing the frame rate policy bug by @davesmith00000 in #270
- FIXED #264: Actors use custom view types by @davesmith00000 in #272
- FIXED #253: Add math functions to Magnification type by @davesmith00000 in #271
- FIXED #252: Drawing with Quads by @davesmith00000 in #275
- FIXED #273: Remove redundant shaderId overrides by @davesmith00000 in #276
- FIXED #277: Added 'classic' FPSCounter constructors by @davesmith00000 in #280
- FIXED #279: Clip frame shader rounding errors by @davesmith00000 in #281
- FIXED #278: UV modules bugs with Int / mixed types by @davesmith00000 in #282
- Aseprite support improvements by @davesmith00000 in #221
Full Changelog: v0.30.0-M5-PREVIEW...v0.30.0-M6