Custom Shaders in q5.js WebGPU
Create advanced visual effects in q5.js
Shaders can make a square wobble, a video do somersaults, and a squiggle…
…turn into a moving tapestry!
While shader programming presents a steep learning curve, its fundamental role in computer graphics, from visual effects to simulations and compositing, makes it worth introducing in game design and computer arts courses. Early exposure helps students grasp the power and utility of shaders. Hence, q5 now provides a big sandbox for WGSL shader creation.
If you’re unfamiliar with shader programming, be sure to read my guide on Custom Shaders in q5 WebGPU.
Check out the new shaders reference page!
https://q5js.org/learn/#shadersSection
In p5.js, `createShader` requires full vertex and fragment shader code. While applying shaders to a `plane` (a special rectangle) is straightforward, it's not so clear how to affect all the other things p5 can render: images, video, and text. Also any uniform data added to the shader must be specified by the user, adding to the amount of boilerplate needed.
Last summer, Dave Pragurek, inspired by luma web library’s shader hooks, added a new and improved way for users to make shaders by modifying p5’s base material shader. This in turn, inspired my work on a new system for custom shader support in q5.
My aim was to lower the barrier of entry to WGSL shader programming without revoking much low-level control. Rather than opting for a lot of intermediary interfaces or making a high-level superset of WGSL, my aim was tighter integration of custom shaders within q5.
Recognizing that users often merely want to customize the fragment stage, q5’s `createShader` function doesn't require full shaders. Instead it’s flexible, accepting vertex and/or fragment functions as a single string. The user’s code overrides the respective function(s) in a copy of the default shader. I also wrapped complex calculations in helper functions, so users can make changes without needing to understand how the whole shader is implemented. Users can copy/paste the `vertexMain` and/or `fragMain` functions from a default shader or use the examples from the docs as starter code.
If you’re wondering how this works, like all my other work on q5, the custom shader system is open source under the LGPL. I was able to implement it in less than 100 lines of code. WebGPU’s structure requires that q5 not only create new shader modules but also new pipelines, which are clones the default pipelines.
https://github.com/q5js/q5.js/blob/main/src/q5-webgpu-shaders.js
I’d appreciate any feedback on this, as I’m certainly not a shader programming expert.
As always, thanks for reading and stay tuned. Next week I’ll be announcing the official release of q5’s WebGPU renderer in q5.js version 3 beta!



