Introduction:
The fifth edition of Lovebyte was held on the weekend of 15-16th February 2025 on Discord and Twitch. This year, the theme is Blind Date, which ment that all competitions entries were shown anonymously. The party was a blas and the competitions were of high quality with many new demoscene productions released!
We weren't able to join a lot of competitions, but I am happy with the 2 intros that we were able to deliver.
Mesa (128 Bytes, MicroW8):
The first intro we developed for Lovebyte 2025 is Mesa for the MicroW8. After having gained some experience with raymarching in 128 bytes with intros like Atlantis Rising and Apoptosis, I was looking for ways to up scene complexity the visual quality, which i think we were able to do with this production.
Visuals:
As I mentioned in an earlier blogpost as well: When trying to attempt raymarching in smaller sizes, you usually only have a few choices in terms of geometry: Cylinder (usually the cheapest option in terms of size), Sphere or a gyroid type of distance function. As I already used th cylinder in Silos (2022), a clipped inverse-sphere in Microlair (2022), and experimented with a gyroid shape in Apoptosis (2023), so for this intro i wanted to see if a more complex SDF could be done in this size.
The plan was to start of with a raymarching loop that is drawing simple swirling path, given that:
u = z * raydirection_x
v = z * raydirection_y
w = cos(z+t)
We can now calculate te distance to the path using:
d1 = abs(u + w) - 1.0
d2 = abs(v - 1.0)
distance = max(d1,d2);
Swirling pathway
Adding structures:
Next up was adding a repeated structure to the outer edges to give the whole pathway a world to live in. Given that the swirling path is already taking up a bunch of instructions to generate, this ment that the outer structure needed to be simple but effective. So i ended up with the simplest cosgrid I could think of, reusing the cos(z+t) value from the path.
d3 = (cos(u)+cos(v)+w)
distance = min(max(d1,d2),d3)
One of the simplest repeated structures I could find
Polishing the look:
From here I went about coloring, texturing and polishing the overall look of the intro, as well as introducing some progression to the intro. Given the overall look of the intro I went with the brown tones for colors and added some texturing by calculating the color based on hitpoint Z deformed with a scaled cosine of the vertical hitpoint which will give it that ribbed structure.
Because the SDF was already a combination of 3 distances, there wasn't any room to do proper 'scene fading', so after some experimentation a camera motion was added that would start from the side 'mountains' and slowly reveal the swirling path, before getting back and ending in the side of the mountainranges again after about a minute or so.
Final polish of the overall look came in the form of adding a bit of float-noise to get rid of the crude 16-color ramp and texture, as well as using the same float-noise for our ray origin-z value, which adds a very crude and subtle form of extra depth to the overall image.
Optimisations:
So here are the different optimisations tactics i used on the intro to get everything within the size limit:
* Have a single label to jump to with branch_if for all 3 loops (x,y,z).
* Both the x and y loops use a modulo structure to automatically reset the value. ( branch_if x:=(x+1)#%320:drawloop;
)
* Both the x and y loops have the same iteration counter ( 320
), so technically its overdrawing.
* Using the same divider (also 320, but converted int to float) for extracting u,v ray directions from the x,y loop.
* If possible use as few different float values as possible.
* If possible use as few different i32 values as possible.
* If possible use 'intvalue as f32' to represent float values.
* Use inline variables/code as much as possible.
* Don't initialise any variables unless you really have to.
Audio:
This intro uses the bare minimum audio I could muster in such a small size. This was done by mashing the MicroW8 soundregisters (located at 80 and up in memory) with different values.
These can either be based of a variable or calculation or in this case a constant as i was looking for a single note sound. After a process of trial and error I landed on this low humming sound that I think worked well with the intro.
somevar?80 = constantvalue;
Fractured (32 Byte Intro, DOS):
For this intro I wanted to create a fully animated proper fractal (with smooth animation and a proper iteration loop), instead of using dodgy exit-conditions for the fractal-ish shape i've done in Blake32 back in 2021. Unfortunately, trying to get there took me 4 years, with the first versions being closer to 64 bytes than 32 bytes.
Sculpting away (2021-2022):
After starting the intro in 2021, i continued to work on and off the intro, i was able to shave bytes off one at a time, shrinking down from 50+ bytes down to 42, one or 2 bytes at a time, coming back to the intro every few weeks or months. After 2 years I had a version of the effect working in 36 bytes with movement, as well as a seperate still image of the fractal in 32 bytes.
Deadlocked (2023-2024):
It was at this point where it seemed i was stuck, and after trying to get back to it (sometimes with some variations in 35 bytes that broke other stuff) it really seemed i was stuck on it. When no further progress was made for another year I slowly began to loose faith in the project. I even considered just including the static fractal version in one of my tiny intro albums and be done with it.
Static Fractal (2023)
Breakthrough (Christmas 2024):
Then during the christmas holiday season of 2024 i was finally able to get a breakthrough of 2 more bytes, bringing the then 35 byte version of the intro down to 33 bytes by using a different/branchless way of handling color incremention. The downside was that i had lost the grayscale colorscheme. However the very next day i found a combination of loop iterations and color-increment value that would give me the grayscale colorscheme back using the new method.
Almost there (January 2025):
Success! I was now down to 33 bytes and had regained hope that the last byte would be found eventually. About a week later after a rubberducking session with blossom, we found a way to not use cx for the iteration loopcounter as it needed to stay at 255 for the adc [si],cl trick to work. But this ment that we had to free up another register.
This came in the form of freeing up the bx register from LES AX,[BX] MOV AH,0xCC
by doing the LES BP,[BX] at the start of the code and just using setting AH
to 0xCD
and leaving the lower part of ax set to the color, resulting in a skewed display, which after messing a bit with the shape wasn't too bad/distraction for this fractal (if you didn't know the display is actually skewed).
Freeing up BX register ment we could just do a regular DEC BX
and condition check instead of using loop
in conjunction with CX. And with this the intro finally reached its 32 byte size-target!
Final selection:
Once the target size was reached, i made a couple of slight variations for final selection. I narrowed down 6 candidates to 4 to 2 and finally selected the one i felt had good movement and worked well with the slanted screen setup.
Sourcecode:
Here is the fully commented sourcecode for the intro:
Ofcourse once the intro was finished every step above seems like an obvious choice in hindsight, but it took me a lot of effort to finally get there and get the code this clean. I hope the above code can help people understand the mechanics of the effect.
Bonus release: Entropy (16 Bytes, DOS):
Lovebyte's 8 and 16 byte intro showcase is always a good avenue to support the party and release some of my smaller works, in this case: entropy reduction trainer (shortened to entropy),
This effect started as a textmode fire effect (complete with pc speaker fire crackling), but then I decided it would look nicer and look a bit cleaner with just the blue tints. Fortunately 16 bytes is quite comfortable size for textmode based effects. You dont need to spend 4 bytes on graphics mode setup, so there is plenty of room to experiment with a typical small sized automaton effect like this.
Bonus release: Crawler (16 Bytes, ZX Spectrum):
Another entry for the 16 byte intro showcase comes in the form of this ZX Spectrum intro. I wanted to try more smaller sized effects that alter both the colormap at $5800 as well as the screen's pixeldata at $4000 and this intro is a nice example of that.
Conclusion:
While i didn't compete in a lot of categories this year, I am happy with the intros that we were able to deliver. I think that Mesa turned out pretty well for its size and I think its the most polished 128 byte raymarcher I've done thusfar. Also I'm super stoked that I was finally able to complete and release Fractured after working on it for so long.
For more information about all the Lovebyte 2025 releases, you can find them at demozoo
- Enjoy!