Wooscript Extensions

Please note that this article is kept for archive purposes only, Wooscript has moved on a long way since this was written!

I’ve been busily working away on Wooscript for the last few days and have added a few more basic functions to let me get on with building more interesting scenes.

To start with I’ve been adding some more primitive types. Up to now I’ve had the intrinsic rule “box” for adding a cube onto the object. This does allow you to have a lot of fun, but the raytracer already supports a bunch of other object types, and sphere primitives are the most obvious next step. So I’ve added a new intrinsic rule called “sphere”. Here’s a quick example of a tower of spheres…

rule main{
repeat(r1, 10)
}

rule r1 {
call(sphere)
adjust(y, +1)
}
10 spheres

Tower of spheres

Another common thing you need for more complicated fractals is the ability to pick between two different rules to give an object randomness. To do this I’ve added a new calling type called “branch”. This function takes a list of rules, with weightings, and then randomly executes one of them. Here’s a quick example with the tower of spheres now randomly picking a sphere or a cube.

rule main{
repeat(r1, 10)
}

rule r1 {
branch(sphere, 1, box, 1)
adjust(y, +1)
}
10 objects in a tower

Tower of 10 random objects

Next up I’ve added the ability to set various material parameters for the objects as they’re added into the scene. The basic stuff is “diff” for diffuse colour, “spec” for specular colour, “emi” for emissive colour and “power” for specular power. I’ll be adding glossiness etc. when I get round to it. For now here’s an example of a tower of spheres where each one is a random colour.

rule main{
repeat(r1, 10)
}

rule r1 {
branch(red, 1, green, 1, blue, 1)
call(sphere)
adjust(y, +1)
}

rule red {
adjust(diff, =1, =0, =0)
}

rule green {
adjust(diff, =0, =1, =0)
}

rule blue {
adjust(diff, =0, =0, =1)
}
random colour spheres

Tower of random colours

Emissive light is kind of fun and lets you get some interesting renders. Here’s the basic 10 element tower with the emissive colour set instead of the diffuse colour.

rule main{
repeat(r1, 10)
}

rule r1 {
branch(red, 1, green, 1, blue, 1)
call(sphere)
adjust(y, +1)
}

rule red {
adjust(emi, =1, =0.01, =0.01)
}

rule green {
adjust(emi, =0.01, =1, =0.01)
}

rule blue {
adjust(emi, =0.01, =0.01, =1)
}
emissive object test

Emissive tower

This is interesting, but ultimately expensive to render. I needed 500 samples per pixel for the pathtracer to pick up this grainy amount of light. The WooTracer does support spherical lights too, so I’ve added that as an instrinsic rule “spherelight” and that gives a much smoother result.

spherical light sources

Tower of spherical lights

This renders significantly faster and only requires 60 samples per pixel to give these results. There will come a point where having hundreds of lights will be more expensive, but for now I’ll leave the option of picking an explicit light type as well as setting up emissive surface colours.

There is one final thing that has had me doing a lot of pondering recently. Initially I created the wooscript language so that the “state” of the rendering engine was rolled back as each rule finished. i.e. if I call three different rules that each instantiate a random line of cubes, the start point will be the same for each one unless I change it explicitly.

rule main{
call(r1)
adjust(ry, +120)
call(r1)
adjust(ry, +120)
call(r1)
}

rule r1 {
adjust(rx, +45)
call(r2)
}

rule r2 {
call(box)
adjust(y, +0.4:0.6)
adjust(rx, -2:3)
call(r2)
}
Cube stems

Three “stems” of cubes

This is cool, but if I want to add a sphere at the end of each stem I have a problem. The method that added each box is recursive, there’s no way in the language to specify that on the last recursion (i.e. adding the end of the stem) it should add a sphere instead. The StructureSynth language gets round this using an elegant syntax of r2 > r3 where the “>” indicates that the r3 rule should be run on the last recursion.

This is pretty sweet but it’s a bit against the principals I’ve been using for WooScript where I’m generally trying to be quite clear about what the language does and minimising magic syntax to things like number ranges. So I pondered this for some time, scratched my chin a bit, had a few beers, and eventually decided that the nicest solution is to make the state control explicit to the developer. Instead of winding back the state after each rule, the state is now left where it was after the rule ran. This allows us to easily chain recursive functions together. If we want to return the state to an earlier position then we use push() to store the state, and pop() to restore it.

This changes the stem code (and some previous examples) so that it now looks like this. Note that I’ve rolled up the 120 degree rotations to set up each stem into the r1 rule. This is possible to do because I can choose where to push the stack inside this rule.

rule main{
repeat(r1, 3)
}

rule r1 {
adjust(ry, +120)
push()
adjust(rx, +45)
call(r2)
pop()
}

rule r2 {
call(box)
adjust(y, +0.4:0.6)
adjust(rx, -2:3)
call(r2)
}

Given this new way of working with the state I can now add a squashed sphere onto the end of each stem to give a very simple fractal flower.

rule main{
adjust(recursions, =15)
adjust(diff, =0.5, =1, =0.5)
repeat(r1, 3)
}

rule r1 {
adjust(ry, +120)
push()
adjust(rx, +45)
call(r2)
adjust(scale, =3, =1, =3)
adjust(diff, =1, =0.5, =0.2)
call(sphere)
pop()
}

rule r2 {
call(box)
adjust(y, +0.4:0.6)
adjust(rx, -0:3)
call(r2)
}
Simple fractal flower

Simple fractal flower

I’m working on some more fractal geometry stuff which I’ll hopefully have an article on in the near future.

In the meantime I’ll leave you with the featured render which uses a number of the language extensions documented above.

raytraced image of procedural object with area light sources

Spherical light with procedural “ribs”

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Spam Protection *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>