Open sinisterchipmunk opened 11 years ago
This looks great ! (except the first line) I can't really be constructive, not knowing much about how jax and others handle GLSL, but I see the point of event-based assigning.
What event do you think of ? I could only come up with :
Model Camera
Context Active Camera
For this to work, I think there need to be plenty of hooks for event listeners throughout Jax. Fortunately, a lot of these are already in place, though they may need some tweaking. We also would need to make triggering custom events much easier to do, so people can trigger changes based on things we can't foresee. I'm thinking of something like jQuery's trigger(evtName[, evtData])
method available to all Jax objects.
Some built-in events off the top of my head:
I'm sure there are many more to be considered, but that's the list of what strikes me as immediately obvious.
This is only a thought and I have no clue what the actual implementation would look like.
I have never been happy with the way Jax assigns uniform variables and attributes to the shaders. It is pretty easy for a developer (and we've come a long way toward making it as simple as possible), but there are significant performance penalties coming from the current approach.
Currently, all variables are assigned to each shader in use, every frame. This results in a predictably huge amount of time wasted on redundant assignments. Since
Jax.Material#setVariables
is called so many times, there is also significant CPU waste in the form of recalculating intermediate variables on the JavaScript side.(Note: I haven't done any profiling. These are just my observations when looking at the way the code works.)
I'd like to try to remove as much of this overhead as possible. My proposal is to make changes event-based, so that they are only assigned when some dependent attribute is modified.
We'd leave the
Jax.Material#setVariables
method in place as it exists today. This way, legacy code would not be broken, and variables could still be recalculated every frame if needed.This proposal comes in the form of an additional hook method (here called
register
), which would become the new "best practice" for shader variable assignment.It could look something like this:
Fringe benefits include less internal reliance on the matrix stack, and consequently less matrix concatenation on the CPU. We'd let the dependent matrices be calculated on the GPU, which is pretty much always faster than on the CPU, and I would be willing to bet that since the matrix calculations would usually be based on uniforms, they'd be very well optimized.
The
vars
object would be a collection of variables with the same API as today, but would not function as we know them today. Today, an assignment to thevars
object is essentially global to the shader. The above model wouldn't quite work, otherwise a change based on any mesh using this material, would make the same change for all meshes using this material -- not what we want. So instead,vars
would have to be managed, at a minimum, per-mesh: an assignment to thevars
of one mesh would not alter the assignment tovars
of another, because there would be multiple separate internally-managedvars
objects. Thus, there would be a multitude of event listeners, each operating on various different meshes as materials are added to them.We could also implement an
unregister
method for unhooking events when materials are removed. This would give the developer greater control, but I'd also be in fan of somehow being aware of which event listeners were registered by which materials on which meshes; and then Jax could just unregister all listeners when a material is removed from a mesh. This would nearly always be the expected result, after all.