Lost in Parallel Universe

My rejected project — Lost in Parallel Universe
Some CG loop NFTs that I’ve made.
  1. I didn’t do enough research on who was going to judge my project. It was an amateur mistake. When I started the project, I thought I would just make the project I like and kept pushing the quality of it, then I would get a chance. That’s completely wrong. You will never be able to sell a pair of shoes to those who were asking for a pair of gloves, no matter how good a shoe maker you are. Know your target audience, ALWAYS. Here is the official list of their Cruation Board. Stop writing your codes and learn what your audience wants. It is not about making art that you like, it is about making commercial art that sells.
  2. I naively thought that making a real-time visual project would gain any advantage for my application. By sacrificing image quality to achieve some real-time effects such as smoke simulation to run in 60fps was a stupid idea. The visual quality may looks great in my line of work in the web advertising industry, however it won’t cut it in front of the Cruation Board who value quality of the image over all those smart tricks that I have done to get my project running at 60fps. I was convinced that when the art committee saw this fully interactive experience, they would be impressed. So, within those 2–3 months of production time, I kept on working on the performance optimisation and adding features such as accelerometer navigation for mobile devices but I was totally detached from the reality that the members in the Cruation Board are not someone working in our industry who would appreciate these sort of details. So, if you do 3D scene graph like I do, forget about real-time rendering, you should go for an offline rendering approach such as this in-browser path tracing test that I have made recently.
  3. I wasted so much time to do the optimisation and adding details and features. Basically after 2 weeks of development, my project got to the level of pretty much 80% of what I submitted in the final version. If what I did in the early stage didn’t fit what the Cruation Board wanted, I don’t think that the extra 20% would make any difference. Instead I should have explored different art styles and tried producing as many as diverse projects as possible and hoping one of them will be chosen by the Cruation Board.
The high fidelity in-browser path tracing generative visual test that I’ve made.
  1. It can run Blender project in the backend and generate Cycle/Eevee render outputs. Using blockchain token to generate the seed random values in Python and artists can create generative artwork in codes or leveraging the Geometry Nodes to create something far more interesting artwork.
  2. Same for Houdini artists. If the platform can run the HDA created by the artists, the creativities are limitless. For rendering, Mantra and Karma would be enough but it may take forever to generate the final image to reupload to OpenSea. Otoy RenderToken can be a good option via a generated orbx file.
  3. If real-time rendering is not a critical thing, there is no reason not to be able to run scripts in Python directly in the backend. It can also open the door to generative AI artwork. How amazing it can potentially be?

Project Breakdown

Since I’ve already spent countless hours on this project, I would like to share some cool tricks and ideas that I’ve learn in this project in case any creative coders are interested.

Nebula Sky

From the beginning I knew that I want my artwork to have strong contrast and with a night time set up. It was an obvious choice to create a starry night using a nebula skybox. But like what I said, in ArtBlocks, you can’t really import image as texture, so I had to create it procedurally. The skybox comes in 3 parts:

  1. The galaxy looking nebula: It was created by multiple octaves of simplex noise. I also used the similar technique to add the 2 colours gradient to make it looks a bit more interesting.
  2. The small stars: If you used the similar high octave simplex technique but use a super high level of pow() to clamp down the brightness and ramp up the contrast, you can get some small noisy grain-liked stars.
  3. The dynamic blinky stars: Adding some dynamic stars which will blink over time can add some subtle details to the composition. I’ve only used 1024 but it is already pretty convincing imo.


The story behind my project is that in the future time, people are lost in another parallel universe. People need to harness energy from the ground in order to survive. But you are not alone. The centre piece of the visual is the energy beam, to show that there are other people living in the parallel universe, I decided to created some neighbours.

Realtime Volumetric Smoke

The fluid simulation was borrowed by this amazing project. However, I want some 3D smoke instead. The idea was to take the 2D fluid simulation as 2D height field and ray march it. But if I just ray march the 2D height field, it will obviously look so 2D. The hack is to cache the previous simulation over several frames to create this fake 3D volumetric simulation so that the lower level of the smoke will return the more current results and the higher level of the smoke will return the older results.

The 2D fluid simulation with history

Main Visuals

In my project there are 4 different main visuals: Particles and Wires, Geometric Shapes, Rings and Grid Blocks

Particles and Wires

It is the classic curl noise simulation with wires and instanced based geometric shapes. There are 3 different particles shapes I’ve used in this experience: Spheres, Pyramid and Rectangle Blocks.

Geometric shapes

This is a fairly simple effects. It mix and match different geometric shapes which spins among the light beam up to the sky. To make the visual look a bit more interesting, I created a pattern generator which generate various seamless patterns through the canvas APIs and pass the 3 different patterns to the shaders via the texture with RGB channels.

Geometric Shapes Main visual with different patterns
Random seamless patterns used for the Geometric Shapes main visual

Grid Rings

Rings is probably the easiest one however, the simplicity leaves this visual with some empty space to breath unlike the other complex main visual systems.

Grid Blocks

This is actually a pretty interesting main visual. I simply did some KDTree-like splitting on a 2D square to get some interesting grids. Then for each grid, I created N x 3D shapes among the Y-axis(up) with random height values and then I normalise the height across different grid so that I can create a Y-axis loopable animation without any overlapping. By moving the shapes vertically and scale them by time, I created this unique blocks shape grid system.

Side Visuals

In order to create enough variety and improve the overall composition. Some supported side visuals are needed to fill up some empty spaces.


This is a pretty expensive side visual. To render this crystal refraction correctly, I had to do a multi-pass rendering as following:

  1. Sort the instances from back to front
  2. Before each render of the crystal instance, cache the viewport and blur it.
  3. Render the crystal with specular light only with some generative FBM noise as imperfection. Then sample the blurry viewport cache with RGB offset based on the surface normal to create that fake crystal look.

Light Props

This is a classic CG mograph kind of side visuals. There are 3 different types of light props as following:

Geometric Shapes

Like the Geometric Shapes of the main visual, but it provides some variety of chaos to the overall composition. In my option, this side visual is a bit chaotic, however I asked around and some of them like this sort of dynamic high energy visuals.

Different geometric Shapes coming from the door or from the ground to support the main visual.


There are some other small details such as rains, distance field based water ripples, imperfect ground reflection etc.

File Size Optimisation

If you are working on a ArtBlocks project, you want to watch your file size because it can cost artists a lot of cash for the gas fee. So here are some tricks that I’ve learnt to reduce the file size:

  1. In my project, I used Viteas the bundler and it is built on top of ESBuild which is super fast and it can produce very clean pre-minified codes. Choosing a good bundler helps a lot to produce smaller file size project down the line.
  2. You need to lose your classes. You shouldn’t create a class for anything you don’t instantiated as it will create a lot of necessary `this` and public function or property names that are not minifier friendly.
  3. You may want to leak some variables to global.
  4. You may want to hash your depended library. For example, do a forIn loop with the THREE.js and hash the function and property names with lesser characters.
  5. If you do shader scripting, you should macro everything. For example, use U1 u_fooand U2 u_bar instead of uniform float u_foo and uniform vec2 u_bar. Then you can quantise the attribute, uniform, varying ids through simple regular expressions. Of course, you need to minify your shader using tools like GLSLX.
  6. Last but not least, JSCrunch. It is a crazy script that can convert your codes into ascii string and using an eval() in runtime to compile the JavaScript for execution. I didn’t use it in my application online as I am using Netlify and JSCrunch build time is super long. I tested it locally, I can crunch my final script from 60KB down to 37KB!!

My Little Storybook

This is a Webby winning interactive story about a bird family crossing the river. It is how we reimagine children books can be done these days leveraging the immersive Web technology.


A high fidelity web based automobile visualisation. We tried to visualise one of our interpretations about the contrast of motion and style on the web.

Infinite Passerella

An infinite fashion show running 24/7 in the virtual space. You don’t need a ticket to the Fashion Week, you just need to click the link below.

Abduction 🛸

A little toy game we’ve created that you can control an UFO to abduct a hundred of thousands of people within the browser



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Edan Kwan

Edan Kwan


Not an Artist | Dad of 2 | Founder and Creative Dev Intern at Lusion | 香港人