Introduction
Toy Town Thiebaud is a static image generator written in p5.js that takes the extreme perspective and landscapes of the paintings of California by Wayne Thiebaud as inspiration. The generator can be set to a full random mode where the landscape can vary as well as the roads and buildings upon them as it will use a perlin noise seed for the terrain generation. The roads are generated differently and are applied via a texture to the terrain, after having been used to alter the heightmap of the terrain itself to accommodate flat roads. The buildings are then a class that spawns at a given position in relation to where the roads are.
Concept and Background Research
My first idea for the project was to take pollution data and map out a landscape based on this, however I wasn’t able to find the sort of dataset I was hoping for. Over the Christmas period, a painter whose landscapes I have long admired, Wayne Thiebaud, sadly passed away and so I decided to turn my project into a purely generative landscape project with his work as the inspiration.
Wayne Thiebaud, Road Through, 1983
The intent was to recreate Thiebaud’s penchant for depictions of elevation changes as near sheer vertical drops, lending to roads being black strips running the height of his paintings, and farmland running along slopes standing out at the near horizontal. Town buildings in his paintings often stand stretched to meet the inclines of the roads they sit on.
There is a love affair with colour, highly saturated tones fill his canvases with warm light, yellows and greens dominate the space, contrasted by the blue shadows and lighter, endless skies.
Wayne Thiebaud, Hill Street (Day City), 1981
My work has often been about landscape, and Thiebaud’s near surreal, almost flattened spaces were my jumping off point for this project.
Technical Implementation
My initial move was to make the basic terrain, using the technique I learned from Daniel Shiffman in a previous project. (Shiffman 2016)
Onto this I started to try and develop an algorithm for creating rivers on the surface, using each given point’s lowest neighbour.
I switched to using a random lower neighbour which gave more satisfying results
I attempted to recreate Sebastian Lague’s hydraulic erosion algorithm in p5, as it was initially written in c#. (Lague 2019)
The first step was to increase the resolution of my noise generation.
I played around with the idea of drawing the landscape with the stroke rather than the light information
After spending some time working on my port of Lague’s algorithm, I could see that something was occurring, but I wasn’t able to accurately recreate his results so I abandoned it at this juncture.
At this point, I had changed my project to generating Thiebaud inspired landscapes, and I began work on a road generating system.
Here a line is drawn where each road would spawn, following the displacement of the map.
Checking that my algorithm was affecting the height of the displacement where the roads were placed as I was having trouble seeing the effect, because I wasn’t adjusting the normals, likely.
I spent time trying to make a modular road building system, but then pivoted to creating a set of beginShape(Quad_Strip) objects coloured appropriately.
Jumping ahead, I abandoned creating individual shapes for the roads as it led to clipping through the landscape.
Instead I generated the roads as a texture map along with the grass so that it would conform properly, and occasionally distort with the landscape.
I also created a class for my building objects to generate them along the edges of the road.
Picking lighting colours using Thiebaud paintings to get a white balance.
Created the flow field sky from the Tyler Hobbs tutorial on flow fields. (Hobbs 2020)
The colouring is dictated by a set of lerps between yellows, reds and blues, combined with an additive algorithm found on github. (Delcros 2015)
Trouble with creating the grass
Test with grass working. A simple randomly placed vertical line taking the colour of the pixel it sits on.
Put all together
An example of my road generator maps. I added in a random quad tile generation tool to simulate the different colours of ground Thiebaud might use when colouring farmland for instance.
The full “Toy-Town” look with the grass very bright, but without the normals adjusted for the roads to be flat.
Select Renders:
Picking an angle is difficult as it runs too slow for easyCam and a couple of the functions are currently written in such a way that they would break or perform unnecessary extra calculations if looped. As such the project was designed to produce the following view, but extra renders of the external “Island” view with full randomness on the landscape are included here.
Reflection and Future Development
This project was utterly absorbing, despite the constant five minute waits for a render to load, or not in many cases. Throughout the course of making it I found many errors in incorrect type of object leading to NaN errors or undefined, and the process of solving them helped me learn loads about how JavaScript defines and works with objects, and handles arrays and functions (Thanks to W3 schools). There was lots of vector maths involved, which was rewarding when it went right.
Although I am very happy with how this project has turned out, there are lots of obvious areas it could be further developed. I didn’t include a blur in the farm graphics object because I know that blurring takes ages, from when I have used the example algorithm on the subject, but it would soften the distinctions between different areas. On the external views, you can clearly see there are occasional polygons that appear massive and block parts of the canvas. My distancing algorithm between buildings doesn’t work properly. Road intersections could do with a look over to try and create more realistic areas there and the road generator itself gets confused as to what angle to create a road at sometimes.
Introduction of a modular building system using realistic models would be a bonus, and perhaps using a post-processing algorithm on the image to create a more painterly look could be an interesting avenue to explore. Introduction of trees, hedgerows, fencing and other small props of semi-urban life. Cars, even, and perhaps try to run it in real-time by writing it for Unity or Unreal and making use of the engines to handle some of the more computationally complex elements.
However, before I get carried away, improvements in efficiency in how the code works would be the best place to start.
References
Ashkenas, Jeremy. 2021. Underscore.Js (version v1.13.2). JavaScript. DocumentCloud.
Delcros, Jordan. 2015. “Combine Two RGBA Colors With Javascript”. Gist. https://gist.github.com/JordanDelcros/518396da1c13f75ee057.
Hobbs, Tyler. 2020. “Flow Fields — Tyler Hobbs”. TYLER HOBBS. https://tylerxhobbs.com/essays/2020/flow-fields.
Lague, Sebastian. 2019. “Github – Seblague/Hydraulic-Erosion”. Github. https://github.com/SebLague/Hydraulic-Erosion.
Shiffman, Daniel. 2016. “3D Terrain Generation With Perlin Noise In Processing”. The Coding Train. https://thecodingtrain.com/CodingChallenges/011-perlinnoiseterrain.html.
Thiebaud, Wayne. 1983. Road Through. Oil on Canvas. New York: Aquavella Galleries.
Thiebaud, Wayne. 1981. Hill Street (Day City). Oil on Canvas. Private Collection.
Categories: Uncategorized