BROKEN_FIELD is a tiny shader toy inspired by Bytebeat music. BROKEN_FIELD can be used to create or procedurally generate tiny, interactive art programs. The textbox above defines a simple per-pixel shader. The output of the shader is then displayed on the canvas on the right. For each pixel, the program is expected to output an integer. The value of the integer, modulo 256, determines the brightness of the corresponding outputted pixel.
As an example, suppose we have the following program: sx * sy
. This program is run for each
pixel of the output canvas. Hence, for the pixel at coordinates (50, 30)
, the output of the program
is 50 * 30 = 1500 mod 256 = 220 = 0xDC
. By default, this gives that particular pixel the hex color
0x00DC00
. This process is repeated for every pixel, which forms the final output image.
Note that these programs are just fragments of GLSL inserted into a GLSL shader. Hence, all of the GLSL functions are available. See below for some technical details.
#00FF00
).735
and the wrap value is 32
, then the value is constrained to
rem_euclid(735, 32) = 31
. Defaults to 256
.
256 x 512
, then all screenshots and videos will have
an output resolution of 256 x 512
). Very large canvas sizes may not work properly or consume a
large amount of memory. Defaults to 1024 x 1024
.
You can take a screenshot of the current canvas by using the "Take Screenshot" button or clicking on the canvas. This will take a picture of the canvas as a PNG and is shown in the small square below the canvas.
You can also record a video of the current canvas by pressing "R". Press "R" again to stop the recording. Holding "Shift" while starting the recording will reset the current frame time to zero (or whatever the starting frame time is set to), allowing you to capture the start of the shader. This will export a WebM.
Finally, you can also record a GIF using the "Record GIF" button. The "Manual Recording" input textboxes will
determine which values of t
will be shown in the exported GIF. Important! Large
resolutions and long GIFs will take a long time to render and will have a large file size. You may want to use a
site like ezgif to reduce the file size of the GIF.
t
- time - Equals the current frame. The rate at which this value increases (or
decreases) can be controlled with the "Time Scale" slider.sx
- screen x-coordinate - Equals the x-coordinate of the pixel. Note that the
x-coordinate increases in the rightwards direction.sy
- screen y-coordinate - Equals the y-coordinate of the pixel. Note that the
y-coordinate increases in the upwards direction.mx
- mouse x-coordinate - Equals the x-coordinate of the mouse. Note that the
x-coordinate increases in the rightwards direction.my
- mouse y-coordinate - Equals the y-coordinate of the mouse. Note that the
y-coordinate increases in the upwards direction.kx
- keyboard x-coordinate - Increased by one by pressing right and decreased by
one by pressing left.ky
- keyboard y-coordinate - Increased by one by pressing up and decreased by one
by pressing down.You can append _f
to any of these variables to get a float-valued verison of the variable. For
example, t_f
is equal to the current frame value, but as a float.
All of this stuff is just a GLSL fragment shader under the hood. Specifically, it's this shader:
In the shader above, ${bytebeat}
is substituted with whatever you type into the textarea.
(The vertext shader is extremely boring. it is literally this four-line shader:
A typical program consists of just a GLSL expression. However, BROKEN_FIELD also supports declaring variables. This is done in typeical GLSL syntax. For example, here is a program using variables:
int foo = sy * sx; int bar = 56 ^ mx; foo * t + barA few extensions to this syntax are provided via the Internal Parser. First, declarations may be elided. If this is done, BROKEN_FIELD will attempt to infer a reasonable type for the variable. Second, types may be automatically coerced using
int()
,
float()
, bool()
and so on. This is only done if the program does
not already compile as normal GLSL. In otherwords, treating the input as GLSL code is
prefered over the Internal Parser when possible. Please note that the Internal Parser probably
isn't perfect and doesn't understand all of the possible constructs you can do in GLSL, so
there's a good chance it won't work if you use something really tricky with it.
You can see what shader code is actually running under the Shader Information dropdown, which also shows whether or not the code is treated as raw GLSL or was internally parsed.