Performance
The process of rendering can be divided into several passes:
- declare tree of objects in Calcit-js
- collect points and attributes into typed arrays(via twgl.js)
- build WebGL program from shaders
- call WebGL APIs to paint(via twgl.js)
- optionally, extra framebuffers are used for bloom effect(via twgl.js)
Not all passes need to be re-computed when new frames are painted. In WebGL, we may put parameters that controls how object change in "uniforms", reuse shader programs and "attibutes". That means, when only last 2 steps need to be re-computed for new frames. When you are controlling the camera and the canvas being redrew, normally attributes do not need to be re-computed.
For imperative or OO programs, we may cache arrays for attributes directly. However in tree-shape DSLs, we need to cache them with some tricks. Caclit uses memoizations like in Clojure with the library memof.
; storing 1 item of caches for function
memof.once/memof1-call add3 1 2 3
; storing items of caches of a function by a given key, pass nil to skip
memof.once/memof1-call-by |a-unique-key add3 1 2 3
and each Triadica component is currently a function.
Uniforms
An extra field of injecting uniforms is provided called get-uniforms
:
object $ {} (:draw-mode :triangles)
:vertex-shader $ inline-shader "\"spin-city.vert"
:fragment-shader $ inline-shader "\"spin-city.frag"
:attributes attributes
:get-uniforms $ fn ()
js-object
:citySpin $ :spin-city @*dirty-uniforms
in the function, dirty tricks can be used to access mutable states.