You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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 the vars 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 the vars of one mesh would not alter the assignment to vars of another, because there would be multiple separate internally-managed vars 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.
The text was updated successfully, but these errors were encountered:
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 :
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:
Context
camera count changed
controller instance changed (redirect)
controller action fired (before, after)
Camera
changed / moved / rotated
World
model added / removed
light added / removed
ambient color changed
Model
camera changed / moved / rotated
mesh changed
sub-model added / removed (sub-models are not implemented at this time, just a separate idea I've been kicking around)
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.The text was updated successfully, but these errors were encountered: