I am seeking for advices and opinions those badass enough to write their own shaderMaterials might want to share in regards to what dev environment should one adopt to create shaders specifically for three.js.
The tools I found while researching on this topic which seemed the most interresting to me are:
Shdr looks kind of cool. However I would suggest that when you are just starting out, don’t use any tool except for a text editor.
Fancy tools are generally just distractions when you are learning the basics. Get to grips with those first and then see what tools will be useful for your workflow.
I set up a worker thread which poll the shader file and when it detects a change it sends the string to the main thread where it gets compiled. If it is successful also updates the material with the new shader. This setup can refresh the shader from the text editor several times per second, which has helped me learn a few things about writing shaders with a text editor.
It’s super useful when you want to quickly visualize the result of a simple 1-dimensional function. For instance what does sin(tan(x)) look like?
It’s got its own quirks that you need to transpose to GLSL, such as % translates to mod(x, y) and frac(x) translates to fract(x), but I find it very helpful.
I also use a custom language decorations (bracket blocks and such) on top to use shared headers and vertex and fragment in one file, so it’s reasonable to manage instead the need of redundant declaration.
The advantage is not dealing with 2 separate files. For the shared header you don’t have to declare all varyings or uniforms twice, i suggested it on github once:
I’m already using this approach in all my projects, it’s much easier to deal with when you don’t have to maintain declarations twice. Though the code i provided there is only a prototype, i improved it and added more features like async file inclusion.
Wow! This is actually more than compelling! Actually ever since I first heard of the web workers I aimed at using them for my three.js constructions, yet I never knew quite where to start or what were their limits.
I’d like to give them a try for the purpose you are describing. Would you mind explaining a little more in details how exactly you’ve set up your dev environnement so that I can replicate this?
Anyways sir, I find this to be quite classy & stunning!
Keep a list of shaders in some json structure. Which map a shader id to a file url: {“fire_shader”:"./assets/shaders/fire_shader.txt"}
Some other structure maps materials to shaders and yet another one maps models to materials.
When it is time to load a model we traverse this little structure and eventually get to the point where its time for the material to set the shader it fetches the shader from a shader cache using a callback.
If the shader cache dosnt have any fire_shader yet the request to load the file is passed to the worker thread.
The worker thread is a small but rather brutal thing which has an interval loop and a cache which store all the files its been asked to load.
Every frame of the interval loop (i find that about 10 ms per frame is good for stuff like shaders) it loads one of the files in its cache using XHR and compares the result with what it already has cached. (Just compare the string “if (result !== cached) {cache[url] = result; postMessage([url, result])}”)
The main thread now gets the data which triggers the callback chain up to the shader chache. The shader cache attempts to compile the shader using a try catch. If the compilation is successful store the new shader and call the first callback with it.
I use this trick for all sorts of data and find it rather robust and fun to use.
Workers are great for a lot of stuff. Using the SharedBufferArray to create a binary protocol between worker threads and the main rendering thread pretty much allows for any computation to move into a worker thread. Also using SharedBufferArray as attribute buffers for geometry instancing lets you do things like particles and UI rendering in a worker thread. Beware tho that this requires some significant amount of experimentation.