Scenegraph optimizations

Scenegraph is pretty snappy now, although there are plenty of opportunities left to optimize. Major changes:

* Added `TransformCache` class, which allows `ChainTransform` instances to be re-used across frames. This prevents most of the program recompiling.
* Canvas gets `ndc`, `framebuffer`, and `pixels` entities that are used to represent the coordinate systems it handles.
* Avoid generating throw-away `Variable` instances in `Function.__setitem__`. This was wasting a lot of time.

There is still some cleanup left to do, but once this is merged I think we finally have a usable scenegraph.
SceneCanvas calls it once per draw, so transforms are forgotten if they go through one draw without being used. All of the cases I can think of where this might cause trouble actually need a different solution than just increasing max_age.