This one was more a matter of gathering up and updating other people's work, but I think that's still a valuable result... I was enjoying generating shapes with distance fields, but was interested in finding more efficient ways of displaying those shapes than raymarching, so before long I started reading up on the Marching Tetrahedra algorithm. I tried porting Paul Bourke's implementation to WebGL, but the way it was written didn't have consistent winding on the polygons, which would have hurt performance. With a bit of help from Paul and some various other implementations that had been done, I sorted out the winding issue, and also added normal generation based on the techniques typically used in raymarching. I don't think anything in this demo is strictly unique to it, but given how hard it can be to find clear concise demos of the Marching Tetrahedra, I hope that this one will be a helpful example.
When I was first putting this portfolio page together, I wanted something interesting and unique but relatively simple in implementation to have as a page element. I settled on the idea of allowing different tiling wave patterns to interact via CSS blend modes to produce a non-repeating, ever-shifting background image. I went through a few different iterations before settling on the version to use.
I'm really interested in the different ways that rooms and buildings of different shapes "feel", when you're in them... I wanted a way to explore that, and to see what kinds of spaces other people would create if they had a simple tool for doing so.
This tool is still EXTREMELY early -- there's no way to paint the walls, let alone save or share your work -- but I might as well at least show what I have so far!
You can edit the map in the following ways:
- Right-click on a wall to create a portal
- Right-click a portal to link it to another portal
- Right-click in empty space to create a new room
- Left-click+drag on a room's corner to move it
- Left-click+drag on a portal's edge to resize it
Probably my most complex ShaderToy to date, in several ways!
This shader started as an experiment to recreate the kinds of scanline-interrupt tricks that the game Earthbound did to make its warpy-looking battle backgrounds... It came together fairly quickly, mostly through guesswork -- those backgrounds are real clever effects, but they're still based on fairly simple formulas. I still don't know if I've got it *exactly* right, as I just eyeballed it, but it looks close enough and was just for fun anyway. ;) I also threw in the initial battle swirl, which was another fun bit of math to get right... (That was done by a completely different method on the SNES of course; research the SNES window masks if you're curious...)
Then I decided, why not add a couple of simple characters, and the UI... That went relatively quickly, but was a fun little exercise in materials and shapes and such... and once it was implemented, I realised I could pop the background onto a cylinder and load the whole scene in VR, have a view of what it might have felt like to be 'in' those surreal spaces during the battles :P
And then I said, well, I've done everything else, I might as well see if I can rig up some audio from the game..! This turned out to be what might actually be the most complex part of the whole shader, in the end. :P Working from a track-by-track isolation of the original game's "Kraken Of The Sea" song (thanks to the channels being mutable in emulators), I did my best to reproduce it by ear as hand-written FM synthesis... I'm fairly proud of the result, considering that I'd only ever worked with FM synth once before, on my 'Midnight Snow' shader (and that hadn't involved drums)... The one place that I had to 'cheat' instead of working by ear was with the instrument that starts the song, and sweeps its timbre as it goes up and down the octaves. I tried several experiments involving a simple band-pass implementation, and frankly got *very* close on some of them, but I just couldn't manage to get the boops right in the lower ranges, so I gave in and looked at the waveform of a recording, and saw that it was a sine wave enveloped by a saw wave... which I think I never would have thought to try, being so new to all this.
After all that, I thought I was finally done with it. But then a few months later, ShaderToy announced its latest contest, whose theme was "Your Favorite Movie/Game Moment"... and I couldn't resist the urge to revamp it into a fuller version :P
I added another raymarched scene, of the viewer encountering a UFO in a cave (finally a proper first half for the swirly transition to be superimposed on! :P), which wasn't too hard... except that the song that I had in mind for it involves a TON of precise glissandos, which, as it turns out, are FAR FAR harder to implement in a stateless environment than I thought...! I won't get into it all here, but suffice to say the naive implementation basically pulls the rug out from under the sine wave as you're scaling it... I had encountered that before on previous projects, but my workaround back then only had a controlled result on one end, while the other end flew off to infinity... to make Earthbound's spooky cave music work, I needed a scaling sine wave that started at one specific frequency, stopped at another, and never popped in the middle. Solving this literally ate up an entire day of the project (but it was an awful lot of fun).
The other addition from my original version was the one thing that I wanted to add all along, but just seemed too messy... Bitmapped text on the battle interface windows! It turns out I was right about it being messy. :P In the end, I wound up using three different methods for printing it...
The characters' names and health numbers, being monospaced, were stored as individual bitfields (encoded in sequences of ints), chosen based on their grid position. (Ironically, the version of GLSL used on ShaderToy lacks any bitmask features, so I wound up having to hardcode a table of powers of two and do all kinds of division to unpack the values again...! A performance hit, but worth it for reasons that will become clear later...)
The status text, on the other hand, was dynamically-spaced, and I didn't feel like writing a function that would iterate over all the letters to find out which letter a given pixel would display... so, I just stored the entire message as a giant bitmap. :P I did use a *slightly* similar process, though -- the bitmap is stored as indexed columns, since so many of the columns would be repeated anyway (in repeated letters, and even inside letters themselves, i.e. symmetry)... Then, the correct column is just picked from the stored list for each pixel.
Lastly, the HP/PP label text was simple enough (and repetitive enough) that I just wrote a function that manually determined if the pixel should be lit or not with if-statements.
And with that it was done, and I sent it off into the contest, and it was ignored, oh well. :p I had fun, though!
I was looking for a twitter bot idea that was small enough to not be a huge time investment... and I was also looking for a project that would let me sketch out lots of small programs on various themes as I thought of them... the result was this, a bot that would receive a tweet, animate it in some dynamic way, and tweet back the result as an animated gif!
The plan was that I could come up with new ways of animating the text whenever I had an idea, and then swap out which style the bot would use every week or so. (You could also send these animated messages to other users -- a potentially fraught idea, but I figured I could implement blacklists or whitelists if it became necessary...)
The bot works perfectly, and actually ran for a day or so off my personal PC, but eventually I decided I should get it a permanent home, and... never quite got around to doing so...! I might revive it one of these days, it is an awfully fun idea.
I started getting into raymarched distance-field rendering around the same time that I started getting into VR, and unfortunately despite the similar medium, the two hobbies didn't mesh very well, purely for reasons of performance... But I realised, if only parts of the scene really required raymarching to render, a lot of performance could be saved by drawing the rest of the world as cheaper polygons! Here's my demo of performing raymarching on the surface of a 'bounding mesh', inside an otherwise polygonal scene, as opposed to the usual shadertoy-style 'screen-sized quad' approach.
It's worth mentioning, by now this demo has been dragged forwards through a few different updates to the WebVR spec, and while at the moment it's still working, it probably doesn't represent a great example of how things should be done any more (especially where threeJS is involved). I might remake it more cleanly someday, but for now at least it's viewable.
This was about the time when I discovered ShaderToy, and learned that raytracing (which I had always liked the idea of from afar) was nowhere near as hard as I'd always assumed -- and that contemporary PC hardware was actually finally in a position to do actually interesting things with it in real-time! I spent a while hard-coding scenes on ShaderToy, and loving the way I could use code to iterate and expand on whatever I designed -- but the tradeoff was a lack of the simplicity and immediacy you can get in traditional, mouse-driven modeling software. So I decided to see what I could accomplish in making one for distance fields!
Obviously this program was never really finished, it's missing simple things like rotation, not to mention the mouse controls which were the entire point of the project in the first place... But I still like to use it as an example to show off how easily distance fields can create the kinds of smooth, fluid three-dimensional shapes that hardly anything else can create in real-time like this.
Based on videos I saw, of someone drawing with their fingers in sand on a potter's wheel. Touch+hold on the yellow circle to leave a trail as it spins; see what interesting patterns you can come up with! (Should be multi-touch compatible on phones/tablets!)
A game I designed at Fidel Studios, which was sold to King Dot Com. Unfortunately it looks like none of the copies that they put online are still working; luckily I still had a self-contained copy lying around from one of my older portfolios! At one point it was also ported to iOS, but apparently it's no longer available on the app store...
The art was made by my coworkers, but the animations (all dynamic and code-driven) were done by me.
The idea was to make a more strategic match-3 game... I always found it frustrating in those games to have nearly a perfect setup for a huge combo, but to be unable to nudge it into occurring! In this game, you have many more options for manipulating the board, but only a limited number of turns to get everything done in -- it's up to you to decide what opportunities are worth investing a few turns into rather than cashing in the smaller, more immediately available matches elsewhere on the screen...
A few points that aren't mentioned in the (rather slight) help screen:
- Unlike most match-3 games, you're free to swap lanterns even if doing so doesn't form a match -- but bear in mind, you're still using up one turn each time you do so!
- When lanterns explode, they light the lanterns adjacent to them; these lit lanterns are worth more points when you later explode them.
- Don't overlook that you're getting one 'power coin' for each move that you make -- using a power does NOT cost a move to do, so making full use of your coins before the round ends is crucial to getting a good score!
- Have a look at the achievements screen for a sense of what kinds of things should be possible with all the powers at your disposal...
With Flash set to be disabled in all browsers within a matter of years, it's quite possible that this game won't be playable on this page for much longer; the embedded SWF should be self-contained enough to download and run in a standalone desktop Flash Player application with any luck, though!
I saw videos of people doing video projections on their windows for halloween, and I thought, that seems like a waste -- why not have it be something totally dynamic? And so Skully was born!
Developed as my first and only project in Microsoft's ill-fated XNA, Skully is puppeteered entirely with an Xbox controller -- we shone a projector on a sheet hanging in the window, and ran a mic to an amp (with plenty of spooky reverb of course!)
I've had plenty of plans to create some sort of modern follow-up ever since, including one prototype driven by a Wii remote, but none of them have ever gotten off the ground so far.
The announcement of official ports of Cave Story put an end to my homebrew version, but it wasn't the end of my involvement with the game -- I wound up getting asked to do the promotional website for the official Wii release.
I put together a site that recreated some of the interesting environments from the game, complete with dynamic elements in each... (I resisted the urge to include the now-iconic outdoor scenes, since I thought they were a surprise worth preserving for the player.... only to find that the Wii version used one as the title screen anyway...!)
One interesting idea I came up with for the site, that I still haven't seen anyone else do, is that the wallpapers available to each user were given out based on their IP address, meaning you would have to pass the site around to your friends and trade wallpapers with them in order to see them all!
Eventually, the plan was for all the assets to be replaced with their higher-resolution equivalents once the port's new assets were revealed, but somehow we never got around to finishing the site I guess...
The coolest band that never quite went anywhere. (Which I just happened to play in.)
I was having a lot of fun prototyping stuff in Flash in my spare time at school, and so around a kitchen table we threw together every idea we thought our website should have, and I threw in as many of them as I could (some scanned directly from that paper!) Personal favourites include the ducks wandering everywhere for no reason (shoo them away with your cursor if they're a pest) and the fact that you can click+drag the letters in our logo to anagram us whatever new band name you'd like.
(Please note, the emails on the 'contact' page no longer work, as we've since surrendered the domain to the band mentioned on the landing page...)
Back before it got picked up officially, I got Pixel's permission to try porting Cave Story to Nintendo handhelds. I only got so far before real life got in the way, and before long the rights were bought up for an official port which scuttled my work, but it was a fun experience at least!
You can see the last demos for each platform here...
An old school assignment that I'm still pretty fond of; basically a simple clone of Um Jammer Lammy.
Drag the characters into the 'computer' and 'player' slots to begin (the assignment required it :p), then use the keyboard to repeat whatever the computer player does.
If the computer seems to be out of sync with the background music, just reload the page; this is an old Flash bug that still hasn't been fixed, apparently...