Help
underconstruction.gif
When you first visited Bauble, you were greeted by an interactive tutorial. You can restore it by deleting your script (just clear out the text field) and then refreshing the page. Make sure to save a backup of your script if you've done something interesting!
Some general notes:
- Argument order is usually not significant; only the types of values are significant. Argument order is significant when a function takes multiple arguments of the same type, such as
torus
-- the major radius must come before the minor radius. - Probably the most useful functions in order are
move
,union
,rotate
, the shape primitives,color
, andshade
.
All of the examples on this page are interactive. To prevent annoying scroll hijacking, you have to click on a canvas to focus it before you can zoom.
Function reference
- Shapes
- Spatial operations
move
rotate
scale
offset
onion
distort
mirror
reflect
mirror-plane
mirror-space
symmetry
flip
twist
swirl
bend
map-distance
- Hybrid spatial/surface operations
- Repetition
- Operations on color
- Meta-operations
- General helpers
- GLSL functions ported to Janet
- Janet functions ported to GLSL
- Functions that are the same
- Color constants
Shapes
A quick list of all shape primitives:
sphere
sphere
is the simplest of all primitives. It has only one parameter: the radius.
box
box
can take a single float
dimension or a vec3
.
The dimensions you supply to box
are twice the size that the box appears. Think of them like a radius: a box of "width 50" will range from p.x = -50
to p.x = 50
.
:r
to round the edges.
cylinder
The second argument is twice the height of the cylinder, which is centered at the origin.
:r
to round the edges.
ellipsoid
Not an exact distance field! This is an approximation that produces better results than scaling a sphere, but that is still only an approximation.
line
The two vec3
arguments are the start and end points. An optional float
argument is the radius of the line (default 0
).
torus
half-space
This one is very hard to show with images, because it just looks like a flat-colored plane of infinite extent. Instead, it's easier to understand when used as an input to a boolean operation:
The first argument is a signed axis, and the second optional argument is the position along that axis.
cone
Unlike most other shapes, which are centered at the origin, the cone rests at the origin, and the height you pass it is the cone's actual height, not one half of its height. It's still the extent of the cone in a single axis, like other shapes, but unlike most shapes the cone does not extend in both directions.
:r
to round the edges.
ground
ground
should not be used in actual art, but it's useful for debugging. It's kind of a "(half-space :-y)
that you can see through," so that you can add a ground to see shadows, and still move the camera around to view the underside of your shape.
It is not an actual distance field (the distance depends on the position of the camera), so it will not work well with morphs, boolean operations, or ambient occlusion. It's really just for quickly looking at shadows.
Spatial operations
move
Can take a vec3
elements or named :x
, :y
, and :z
float arguments. You can mix and match these forms, and the computed sum will be used.
move
is also a great way to distort shapes.
rotate
Takes named :x
, :y
, and :z
arguments; the final rotation is the combination of each rotation in order. There is no vector form because the order of the rotations is significant: (rotate :x 1 :y 1)
is not the same as (rotate :y 1 :y x)
.
You can also pass :pivot
, with a vec3
that will form the point around which rotation happens.
You can also optionally supply scale arguments, which will multiply the rotations following that scale argument by a fixed amount. Valid scales are :pi
, :tau
, or :deg
. You can change scale mid-rotation, for example by saying (rotate :deg :x 45 :tau :y 0.125)
. This is equivalent to (rotate :x tau/8 :y tau/8)
.
scale
Can take a single float
, a vec3
, or named :x
:y
:z
parameters. Like move
, you can mix and match these forms and the final product will be used as the scale factor for each axis.
If you scale by different amounts across different axes, the distance field produced will be an underestimate. This means that Bauble can still raymarch it accurately without the use of slow
, but soft shadows and boolean operations will be inaccurate.
offset
Name will probably change.
Good way to apply texture to a shape, although if your expression is expensive you should use bounded-offset
instead.
onion
float
argument is half of the thickness. The shape will be both inset and outset by this amount.
distort
This allows you to supply an arbitrary expression that will replace p
. You can use this to deform space in ways that are not possible with any of the built-in operators.
This is by its nature a bizarre operation that can be used to do anything, including implement any of the other spatial distortion operations, so examples are not very informative.
mirror
Interior distances will have discontinuities when a shape crosses the axis.
You can specify multiple axes to mirror along. The optional :r
argument makes this a smooth mirror.
reflect
Like mirror, but doesn't create a copy. Can take multiple axes.
mirror-plane
TODO
mirror-space
TODO
symmetry
It's hard to describe this one. It mirrors space across every axis and also flips it across every axis of rotation. You end up with only a tiny sliver of useful space that you can put a shape in, so it's only really suitable for abstract things.
flip
Rotates the shape 90° around a signed axis (so :x
rotates counter-clockwise, :-x
rotates clockwise). More efficient than rotate
.
twist
float
argument is the rate of rotation, in radians per unit distance.
This is equivalent to a rotation around an axis that varies with p.(axis)
, but it might be slightly more efficent.
Does not produce a correct distance field.
swirl
float
argument is the rate of rotation, in radians per unit distance.
This is equivalent to a rotation around an axis that varies with (length p.(other axes))
, but it might be slightly more efficent.
Does not produce a correct distance field.
bend
This operation is weird and hard to explain and I will probably get rid of it.
Does not produce a correct distance field.
map-distance
Apply a function to a shape's distance field. Can be used to do weird things. Many operations, like offset
or slow
, are simple transformations on the underlying distance field. For example, offset
:
Hybrid spatial/surface operations
The boolean operations union
, intersect
, and subtract
can all take an optional :r
value, but note that this will make color calculations slower: all surfaces will be evaluated, even those that do not contribute at all to the final result. When used without :r
, or with an :r
value of 0
(as evaluated on the CPU -- any symbolic expression will cause Bauble to take the slow branch), only the one relevant surface will be evaluated.
Because of this, you should prefer to apply surfaces after smooth boolean operations, unless of course you are relying on the surface blending. Even if it's the same surface, Bauble will still evaluate it multiple times! (This is a fixable deficiency in Bauble but it is the way that it is right now.)
union
Union produces a correct distance field unless shapes overlap, in which case the interior distance field will be discontinuous.
intersect
Does not produce a correct distance field.
subtract
Does not produce a correct distance field.
morph
Produces incorrect distance fields when the amount is outside of the range [0, 1]
.
Repetition
tile
Tile divides space into rectangular regions.
The vec3
argument determines the size of each tile, with 0
meaning that no repetition takes place in that direction. By default the shape will be repeatedly infinitely in every direction, but the optional argument :limit
will clamp the repetition.
:limit
must be a tuple of three positive integers; you cannot write a dynamic expression for :limit
.
If you provide a function argument instead of a shape, your function will be called with an expression for the current index of the tiling. This allows you to produce different objects at each instance of the tiling. The index will always be a vec3
, even if you are not repeating in all three directions.
Indexes are integers, so the index of the element at the origin is [0 0 0]
, the index to the right of that is [1 0 0]
, etc.
You can also provide a shape and a function, in which case the shape will be passed as the first argument to your function. By appropriating a little bit of Janet convention, we call this argument $
, for $hape
. This is useful for fitting tile
into a pipeline:
Asymmetry
The way tile
works is that, for each step of the raymarch, it computes the current "slice" of space. Then it evaluates only that one slice, and returns the nearest distance.
This means that, if the actual nearest shape is in a different tile than the current one, this will produce an invalid distance field.
Here you can see lots of artifacts around the edges of the boxes, where rays overshoot their targets. The solution to this problem, if you want to tile an asymmetric shape, is to first duplicate the shape a small number of times (with union
) and then to tile that array of shapes with overlap.
A future version of Bauble will have a helper to make this more convenient.
radial
Similar to tile
, but repeats radially. Requires an axis and a count. Can optionally take a number that will determine how far to outset the shape before repeating it (default 0
).
Like tile
you can supply a mapping function (with a shape) or a producing function (without a shape). The index will be an integer in the range [0, count)
. As with tile
, only a fraction of space is considered at once, so asymmetric shapes will produce invalid distance fields.
Operations on color
shade
fresnel
cel?
resurface
map-color
color
Meta-operations
bound
bounded
bounded-offset
slow
pivot
General helpers
fork
spoon
remap+
(andsin+
,cos+
,perlin+
)hsv
hsl
rgb
hex-rgb
pi
,pi/2
,pi/3
, etctau
,tau/2
,tau/3
, etcdeg
tau*
,pi*
,tau/
,pi/
ss
hash
functionsperlin
GLSL functions ported to Janet
sign
clamp
step
(note: argument order reversed)smoothstep
distance
dot
mix
min
(note: overloaded better)max
(note: overloaded better)fract
normalize
sqrt
length
/vec-length
pow
(note: overloaded better)
Janet functions ported to GLSL
sum
product
atan2
(note: safer thanatan
)
Functions that are the same
sin
cos
abs
round
floor
ceil
atan
mod
Color constants
(def red (hsv (/ 0 6) 0.98 1))
(def orange (hsv (/ 0.25 6) 0.98 1))
(def yellow (hsv (/ 1 6) 0.98 1))
(def green (hsv (/ 2 6) 0.98 1))
(def cyan (hsv (/ 3 6) 0.98 1))
(def sky (hsv (/ 3.5 6) 0.98 1))
(def blue (hsv (/ 4 6) 0.98 1))
(def purple (hsv (/ 4.5 6) 0.98 1))
(def magenta (hsv (/ 5 6) 0.98 1))
(def hot-pink (hsv (/ 5.5 6) 0.98 1))
(def white [1 1 1])
(def light-gray [0.75 0.75 0.75])
(def gray [0.5 0.5 0.5])
(def dark-gray [0.25 0.25 0.25])
(def black [0.03 0.03 0.03])