Crafting the On-chain SVG Little Martians
When Vanessa Rosa first showed me the real-world ceramics that helped inspire the story of “Little Martians & The Human Memorial Monument”, I knew this would be a fun challenge to create on-chain SVG versions of them. This article goes delves into how the on-chain Little Martians are crafted using SVG from code directly embedded in the smart contracts.
It went from this inspiration:
To this:
In order to display these NFTs, they are all generated directly from the smart contract. No additional server required. There are also various randomized components involved that change the pattern of each Little Martian into unique configurations.
In order to retrieve this image, you start by calling the generateImage() method in the smart contract along with an existing token id. This token id is randomly generated at mint by hashing together the timestamp of the block + the address of the owner.
Here, you can see the SVG being pulled directly from the smart contract.
Recreating the Little Martians
The first step was to get some custom shells made. Vanessa set out to illustrate 10 different shell designs that were saved in SVG.
These are saved as SVG paths. The ceramic shell on the right is translated into the following:
All the numbers are points in this illustration. The only problem is: this is a lot of text to store on Ethereum. Each shell was around 2-3kb. A smart contract, when you deploy it, regardless of how much computation it does, is not allowed to go beyond 24kb. This isn’t technically a restriction, as you can deploy multiple smart contracts to account for this limitation. In addition, some SVG projects also chooses to store the string containing the SVG not as smart contact storage, but as contract bytecode (which to me, feels like an awkward hack).
For context, projects like Shields deployed their 1mb of SVG for 27 ETH (!). Cyberbrokers spent 78 ETH to uploaded 13.2mb of SVG. Regardless, with development and resource constraints, I opted to stick with using in-contract storage (as it’s traditionally done) vs contract bytecode.
So, I downsampled the paths a bit using an online SVG editor and took out some superfluous points. This allowed us to store all 10 ceramics in one smart contract (along with all the computation necessary to generate it).
Instead of the static SVG from projects like Shields or Cyberbrokers, however, the Little Martians require dynamic and interesting patterns. Thus, instead of storing large amounts of SVG, we could merely generate them randomly, on-chain.
One such useful tool in SVG is the usage of filters. It allows you to generate patterns in SVG and manipulate them. A perfect tool to generate random patterns that resemble the original ceramics that Vanessa made.
Filters & Layers!
The patterns comprise of various layers. Let’s dissect a Little Martian to show how the layers combine to create it.
There’s 6 primary layers: the ceramic shell, a background blur, a cross-hatch/stepping layer, a primary background pattern, a primary foreground pattern, and the face outline.
The ceramic shell is the external contours of the Little Martian.
The background blur gives a smoother texture to the Little Martian. A coin flip is first done to determine if the background is white/gray or black. If it’s white, the blur doesn’t add to the texture. However, if it’s black, the blur adds a background shade of gray cloudy texture to the Little Martian.
The random variables here influence how large the blobs of gray clouds are, as well as the seed for it.
The next layer attempts to add some rougher texture to the Little Martian. It aims to add what looks like “steps” or a “cross-hatch” to the ceramic. The random variables here influences the degree of how intricate the steps are (2 variables), a seed, and the scale (which changes how “deep” the steps are with regards to the specular lighting being cast onto the steps).
Then, it adds a full colour spectrum “turbulence” layer. This SVG tool allows you to generate a random pattern using Perlin noise. It automatically also generates with full colour. The random variables here include two variables related to the complexity of the Perlin noise as well as a seed.
The final layer is another Perlin noise turbulence layer, but this time it also attempts to colour shift. It’s the same as the previous layer (2 variables for the noise + one variable for the seed), but also adds 7 new random variables related to the colour. There are 3 colour offsets according to RGB colour wheel that’s altered by whether the offset occurs or not. If it does, there’s a random variable that determines how much the colour is shifted. And then, finally, an alpha channel determining the intensity of the colour shift.
In total, there’s over 20+ random variables of different scales changing the patterns of each Little Martian. As you can also see in the code, there’s other fixed variables that also affect the filters, including specular lighting and Gaussian blur.
A lot of tweaking and experimentation was involved to ensure that random variables that were chosen would create interesting Little Martians.
Here’s another example:
… and the 4 primary layers.
If you enjoyed this, please support the story by reading it here. If you want to own a Little Martian, you can mint one here until 16 May! We hope that more of them can find a home.