Hello everyone!
I have been looking to write some custom materials recently and I felt we were missing something like ThreeJS TSL. So I am very excited to bring you today this new tool, I hope you will like it
Context
I first tried ShaderMaterial
: very flexible, but don’t integrate well with existing BabylonJS features such as shadows and lighting models. Then I went for MaterialPlugin
but it was very hacky and finding the right places to inject the code didn’t feel right.
Thankfully we have NodeMaterial
, which solves all the issues mentionned above! But the visual editor does not scale well for complex shaders in term of readability and refactorings (spaghettis are inevitable)
I then decided to use the code API that solves these issues. Here is for example how we can sample a texture:
const uv = new InputBlock("uv");
uv.setAsAttribute("uv");
const albedoTexture = new TextureBlock("albedoTexture");
albedoTexture.target = NodeMaterialBlockTargets.Fragment;
albedoTexture.convertToLinearSpace = true;
albedoTexture.texture = Textures.CRATE_ALBEDO;
uv.output.connectTo(albedoTexture.uv);
Okay that works, but if you know your way around glsl/wgsl, you know that’s a lot of lines for something that used to be quite simple.
Babylon Shading Language
Enter the new Babylon Shading Language (BSL): a thin wrapper around node material blocks to allow you to write this instead:
const uv = BSL.vertexAttribute("uv");
const albedoTexture = BSL.textureSample(Textures.CRATE_ALBEDO, uv, { convertToLinearSpace: true });
As you can see, the syntax is much closer to glsl/wgsl and it’s much shorter without compromising on expressivity!
I find it much easier to read, write and reason about and you can adopt it incrementally in your projects as it is fully compatible with the native blocks ^^
Here is a Before and After comparison for one of my shaders ^^
Usage
I didn’t wrap all blocks yet, I am wrapping them as I need them but you can also contribute of course!
Let me know what you think!