Later I realized there are two kinds of shaders, vertex shader and fragment shader.
In order to put them into single @shader() together, I borrowed the idea of the CSS syntax,
that is, to group them with the syntax of CSS selectors.
This also extends well while adding textures.
Multiple textures can be identified by their prefixes.
If there's no fragment group I'll treat the whole as fragment shader,
which makes the code much simpler.
Code inside Custom Properties
The length of the shader code increases easily so it's a good idea to place it to somewhere else.
Using CSS Custom properties is an option.
Since css-doodle supports writing rules in ordinary CSS files,
the code can be breakdown into smaller parts and join them together with var().
However, the values of custom property will be serialized by the CSS parser. All the numbers like 3.0
will be transformed to integer 3, which makes the shader code fails to compile.
A workaround is to write 3. instead of 3.0.
The implementation is quite straightforward.
Parse code inside @shader() to read fragment/vertex shader and textures.
Transform textures into images before passing them to WebGL.
Handle shader compiling and linking.
Output the canvas as image data in the end.
So there's a basic example, fill the color of each pixel based on its coordinates.