Customizing Materials: The Community Ninja Tale
Let me start by wishing you all an amazing year!!!
For my first 2022 post, I wanted to share how much I enjoy being a part of the Babylon community. We sometimes have ideas, actually, let me rephrase that… We most of the times have tons of ideas but not enough times per day to build them all and I love to see the community taking over some of our most humble ones and bringing them to life.
Let’s speak more concretely of one example from last month. Basically, it has been a couple years I discussed with David Catuhe about how great it would be to have material plugins for Babylon, but we unfortunately never found the time to build it despite how great it sounds during our chats. Those plugins could allow shader code injection and modify our default delivered materials in any way allowing quick hacks of the shaders without having to fork Babylon.
Browsing our beloved forum as usual, I came across a feature request to add support for baked animations and to correctly support it, we figured we needed again to introduce new code in all our materials and expand our default shaders. Those ever-expanding materials are beginning to have a huge impact on both our bundle size and runtime performance.
As amazing as it sounds, BrunoBG from the community went from requesting the enhancement to implementing the full feature with some help from Popov72 one of our community ninjas (daddy of some amazing features like WebGPU).
I basically only did a code review and merged the PR. This part on its own is huge as it brought to life for every Babylon user a new amazing tool but even better, during the baked animations development we were able to chat about our new amazing plugin system idea. Not only did BrunoBG deliver a new animation system, but following our conversations he ended up creating a new Github feature request for a better and more customizable material.
From this point it was all more real than ever, and we finally had the missing community push to launch the development, but still no time despite how cool this feature was. Amazingly enough, BrunoBG, yet again, did a first version of the code in a pull request. This was enough to trigger the interest of Popov72 who jumped on the PR and helped to make it on par with all our expectations. As a result, this is now all available to use for the entire community and a major improvement of our next release.
The story is great and show how much impact the community is having on the growth of the framework.
I cannot be thankful enough to be part of such a great team and it is amazing to witness the birth of features totally developed by the community.
Funnily enough, another question on the forum popped up just a couple weeks later: Banding issue with point light. In short, our PBR material suffers from banding artifacts when applied to a homogenous surface in very low light.
It is not easy to catch but basically you can see on the picture lots of circles creating hard steps between each color changes. You can open the associated playground to see it live.
We already use a special dithering trick for one of our materials and as we now have plugins, it was clear that creating a dithering plugin would be the way to go. Before the plugin manager existed, it would have involved a lot of hacked and non-reusable code to do so or a custom fork of Babylon.js.
TIME TO CODE… yes, finally \o/
Creating a plugin is really simple, basically the implementation of a plugin consists of inheriting from our base plugin class and overriding a couple of functions. You can learn more from our documentation.
Above is the simplest definition of a plugin, a couple properties and one shader entry point with the code to inject, that is it, no more hacking required.
Referencing the plugin on a material is also easy peasy:
As you can see in this example, smooth as butter… unfortunately the compression in the article does not do the smoothing justice so you might need to open the playground to see it live.
Now, it would be great to be able to do more and for instance control the current plugin state. As you can read below, the only trick to know is to ensure our materials are flagged as dirty when toggling the plugin state.
At least on this playground, the toggle will help your eyes to fully grasp what we are fixing.
And finally, why not add a uniform to control some of the shader values externally?
You can see the result in the following playground.
Basically, this feature is extremely powerful and can let you modify our default materials/shaders in a lot of ways. This is indeed the ground up of our own internal plugins for PBRMaterials where you could find the most complex usage for them: https://github.com/BabylonJS/Babylon.js/tree/master/src/Materials/PBR.
Finally, I want to thank again to the community for this amazing contribution. and most specifically BrunoBG and Popov72, Also a special mention to the Babylon team for the English review.