I like writing shaders but i don’t like writing or reading too much code. I like using three’s built in materials as abstractions of real world materials like gold or plastic or rubber, in which case i don’t write any shader code.
Some times though i need to implement an effect that is not part of the lighting system, for which i need shaders. For example, if i want depth peeling, i need a depth peel
stage in addition to clip planes
, transformation
, lighting
etc. In this case, i want to keep the built-in material abstraction and flexibility (ie. use Phong, Lambert, PBR etc) but add my own logic on top of that.
If you ever found yourself looking at the src/renderers/shaders/ShaderLib
folder of three.js and copying code from there into your own files, you might know what i’m talking about.
The idea behind this project is to decouple the various material abstractions from the THREE.WebGLRenderer
. You can make your own SomeMaterial
with the same interface as PhongMaterial
like this:
class MyPhongMaterial extends ChunkMaterial{ //abstraction
constructor(parameters){ // your parameters like color:myColor, shininess:myShininess
const defaultParameters = {
map: null,
normalMap: null,
color, new THREE.Color(1,1,1)
shininess: 1,
awesomeness: 999,
}
const uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib.foo,
THREE.UniformsLib.bar
])
super({
uniforms, //give uniforms to ShaderMaterial
vertexShader, //give templates to ShaderMaterial
fragmentShader, //give templates to ShaderMaterial
defaultParameters, //define the materials interface
parameters, //if any optional parameters are provided use these
})
}
}
ChunkMaterial
then servers as a framework for assembling valid GLSL out of chunks and templates, and wiring the appropriate object properties to uniforms.
In an ideal world this can solve these problems:
- making new materials, or modifying existing ones, “globally” (ie.
PhongMaterial needs a refactor
) all should happen in the sub classes.ChunkMaterial
super class has no idea how many materials you are using and what properties they have. If you want to extend fromMaterial
right now, you have to modifyMaterial
too, in order to include the properties of your new material. - modifying existing materials on the fly should be easier. These chunks are no longer black boxed, and their creation doesn’t have to be deferred. Ie. with
Material
the only way you can access this is throughonBeforeCompile
- reduce the size of your bundle, by making some abstractions. The gain is currently rather minimal, (2x-3x less code per
Material___.js
file) but stuff could be taken out ofWebGLRenderer
Pitfalls:
- getters and setters may have performance issues
- not super easy to ensure that tree shaking is happening
- Can lead to bloat when GLSL is present both in
THREE.ShaderChunk
and this framework’s chunks. This could be mitigated by usingTHREE.ShaderChunk
and only providing overrides or additional chunks.
Would appreciate feedback.