Perlin Noise Shader Tutorial

I was roped into writing this post after Sven Bergström put words into my mouth and told people I would write a post on this in a discussion about his excellent Introduction to Shaders blog post, which used the lava from Bombernauts as an example for a vertex shader.

Perlin noise seems tricky when you look it up on the web initially and you get articles like this one or this one that have some quite useful information in them, but drown it out with tons of graphs or mathematical equations.

So, every example I am going to give here will be in the form of a shadertoy shader that you can edit and play with yourself.

PART 1: NOISE

Noise is just a function that spits out a random number based on an input. For 2D noise, the type used for shader effects, the input should be the 2D pixel coordinate you want noise for, and the end result should look like TV static.

Often it’s easiest to just import a texture and use that for your noise, instead of writing a function for it, and the result of that is shown here:
https://www.shadertoy.com/view/XsfXz4

You’ll notice however that textured noise starts to look really blocky when you zoom in. This is mostly fine, because for perlin noise you want it to look BLURRED when it zooms in, but using a texture makes it a bit too blocky.

Here is what it looks like when the noise is done in code instead (code borrowed from another shadertow, listed in the comments of this one): https://www.shadertoy.com/view/4dfXz4

It’s a lot smoother looking when it zooms in.

PART 2: LAYERING

Perlin noise is just averaging a bunch of layers of noise together, with each layer being scaled twice that of the layer before it.

2 layers of perlin noise doesn’t really have much of an effect: https://www.shadertoy.com/view/4sfXz4

But 7 layers does: https://www.shadertoy.com/view/XdXSRN

It doesn’t look quite right though, and it’s because each layer has the same weight. You want the more zoomed in layers to have more of an influence on the final result than the really noisy layers. Here it is with the standard set of weights (each layer has half the weight of the next largest layer): https://www.shadertoy.com/view/4dXSRN

For Bombernauts, I wanted the lava to be less smooth than that, so I chose a different set of weights: https://www.shadertoy.com/view/XsXSRN

PART 3: ANIMATION

When you have a bunch of layers, animating them is really easy, just move each layer in a different direction (add an offset to their input, based on time): https://www.shadertoy.com/view/4sXSRN

And lastly, for comparison, here is the end result using the texture lookup method instead : https://www.shadertoy.com/view/XdfSRN

It’s a lot blockier and uglier.

PART 4: DO IT YOURSELF

Oh whoops, I kinda forgot this was supposed to be a tutorial. Anyway I gave you a bunch of code you can read and play around with here, and that should be more valuable than anything. So go play around with the code and learn things!

(p.s. tomorrow Sven will definitely write a post about… uh… how geometry shaders work or something)

Comments

Early Access

It’s a fairly common question from people when they’ll get to play Bombernauts, and it’s a good question! I really do regard the game as playable and fun right now, and it’s probably a good question, considering it’s probably in a more finished state than a bunch of the other games on Steam Early Access right now.

I do have reservations about early access, because… I have standards I guess? I don’t mean this to shit talk other games on early access, I mean I have a lot of trouble allowing myself to sell an unfinished game, but at the same time, since Bombernauts is multiplayer, I really want to get the community involved as soon as possible.

There are certain things people can extrapolate from an unfinished game, and certain things people are terrible at extrapolating. I think most people can safely imagine how a game would be with more content, but it’s hard to play an unfinished game and imagine how gameplay could change, or graphics could improve (Especially so for a game with a stylized aesthetic instead of realism).

My thought is, people will forgive missing CONTENT in an early access (multiplayer) game, provided there is enough there to hold attention for at least a few hours, if not more if they really enjoy the game. Plus then there’s some obvious stuff to add in regular updates. I can add a couple new powerups, some new levels, a new game mode, additional music, etc and that stuff is really easy for players to parse.

I don’t think people will forgive missing POLISH though. Polish is weird, it’s one of those things which is hard to notice, unless you have a version without polish to compare to. It’s a million little things that add to the feel and character of a game. It’s extremely difficult to actively notice and pay attention to in a game if you aren’t the one who made it, and even harder to predict what kinds of polish could be added to an unfinished game. Hell, I don’t even know. Most of the polish in my games comes from periods where I am unmotivated to work on the big important things in a game, and just invent *something* minor to add to the game to keep myself busy.

First impressions matter too. I don’t want people playing a build of the game I’m not happy with, then being like “cool” and never playing again. ESPECIALLY important with a multiplayer game, where your enjoyment of it is directly proportional to the number of other people playing. If the game improves tenfold from early access to release, the initial players, the people who really believed in the game from the get go, will probably not even notice, or will have burned themselves out on the game playing it in early access. I know I’ve done this to games I love before, spoiling them for myself by playing so much before they’re finished.

The point is, I have a large to-do list of features I need to add, and code things I need to code, to get the game up to standard where I’d be comfortable unleashing it on the world. But I’m working at it.

Also as a side note, there is similar reasoning for why I don’t want to do a Kickstarter too. If you want to support the development of Bombernauts, you can buy my existing products on steam.

Comments

Destruction Effect

Spent the day working on the first draft of dents+scuffs+leakygaskets+smoke+fire destruction effects for the robot. 

Every time he gets hit with a bomb it degrades slightly, if the game goes on long enough he can look really badly damaged.

Its just for visual effect though, there’s no HP or Damage% system in the game (and there never will be, because it’s unnecessary for this game), but I do think it’ll add a lot to the game in the long run.

Comments

Graphical Effects Update

We’ve spent the last week doing a ton of work on the graphical effects in the game, here’s some gifs for you

Explosions look way cooler now

Lava looks way cooler now

There’s still a bunch more to come!

Comments

Variety

I feel the need to talk a bit about variety in a game. This actually isn’t a thing that I’ve solved yet in Bombernauts, and it is perhaps part of the reason why the game is taking so long to be finished.


A simple measure of variety in games could be, how long do you have to play the game before you have seen everything the game has to offer? In some novelty games, you can see everything in minutes (you have to burn the rope, catlateral damage). In most games this usually takes hours to days. In some roguelikes or strategy games, this can take years (spelunky, binding of isaac), and in an extremely small number of games, its possible to never really discover everything in them no matter how long you play for (minecraft, dota).


For the past year I have been adding content to Bombernauts with the goal of increasing the variety in the game. It’s working, based on the above definition of variety at least. I added a lot of powerups, which all stack together with each other making for a massive variety of possible bomb types. I’m about to add a few changes to levels and duels to allow for variety there too. There’s content there. You can play for hours before seeing everything, and I’m still adding more and more content!


But there’s an issue here. The measure of variety I described above is wrong. Or at least, it’s a bit inaccurate. Instead of how long do you have to play before you’ve seen everything, it should be how long do you have to play before you start noticing repetition. By the time someone starts seeing the same (or similar) things happen again, they will FEEL like they’ve seen everything.


So yeah, this is where I’m at. There’s a lot of content now, but the way the items work it is really possible to see all of them with 10 or 15 minutes of play, you can even probably see a bunch of cool combos in that time too. You can’t possibly see all of the effects and details put into them, or learn their consequences and quirks from a gameplay standpoint. There totally is content there for people who play for hours on end, and things to discover and stuff to learn, but I fear right now many people will quit after a couple short games, thinking that they’ve seen everything.


I have a lot of things I’m playing around with to solve this though. A ton of the tricks other games use to get past this (slow unlocking of content over time, tons of levels with vastly different themes to them, even having a story) don’t easily apply to a multiplayer focused game. Anyway, I’ll explain more about some of the solutions I try as I get around to actually trying them. It can be pretty tough at times.


But hey, game design is hard sometimes, otherwise why would people get paid to do it?

Comments

:O

Comments

Distortion

first pass at an explosion distortion effect 

Comments

Amazing bugs

so this bug showed up during testing today after he faceplanted himself into the lava with the luchador mask

Comments

The Crop Circle

I’ve gotten a few questions about the crop circle effect in Bombernauts (also knows as the cutout effect, or the see through walls effect), so I figure I’ll share the technique a bit. It is, unfortunately, not a general-purpose technique, so I’m not going to share code for it (nor would the code be useful to you), but I will share the technique and thought process behind it, and plans for future improvements. 

Here is what the effect looks like in it’s current incarnation. I consider this effect as “not final”, but it’s certainly good enough for now, and it took a LOT of work to get it there.

First of all, to understand the crop circle requires a knowledge of how the level is rendered. The whole level is 1 model. Actually that’s sorta a lie, it’s 5 models, one for each directional face, without any bottom face since you can’t see the bottom of tiles. Here’s what a level looks like when I move its parts around. This lets me set different shader properties for each face separately, such as texture and various fields relating to orientation.

As a result, there’s a few restrictions on what techniques I could use for the crop circle. Transparency is out of the question, since self-transparency is a really tough problem in computer graphics (see: this). In addition I can’t make individual blocks disappear because it’s all one model, and only faces exposed to air are rendered.

Here is a screenshot of the very first iteration of the cutout effect. (Actually I still have a build of this up, here):

The first few prototypes of the game were in an isometric perspective (which was changed very early on, because it is extremely visually confusing). Anyway, I don’t remember exactly the method I was using in this build, but I remember parts of what I tried. There was a massive logical tree in the shader for this, a check if it’s in the “crop circle screen region” (a simple radius check on screen-coordinates), then if it was it does the crop effect. Each texel knows what face its on, where the player is, and its position in the world. I tried a lot of various conditions on these.

Each texel would let itself NOT be cropped if certain conditions were met. A texel on an upward-facing face would always show if it was below the player (in world coordinates). A texel on a front-facing face would always show if it was behind the player. A texel on a left-facing face would always show if it was to the right of the player. Every other pixel would be cropped. I believe there were a few other conditions here too but they aren’t important. Unfortunately, while 2 of these conditions still held true when the game was switched over to a perspective projection, the left-facing face part doesnt hold true anymore. Here’s my comment from the first iteration of the shader that I had comments in:

    //if texel is above character (world) AND texel is IN FRONT of character
     (depth) AND texel is IN FRONT of character (world), crop

It was getting a bit complicated, and every change I made to it was never… good enough. Could fix it in some situations, and not in others.

A few months ago, shortly before recording the trailer actually, I redid the whole effect again. I think it’s up to version 4 now. Here is what the crop looks like, when the entire level is “cropped” (and the outline effect is disabled).

This crop mode right now still lets any pixel through that is below the player by default, but the rest of the confusing conditionals now are gone. Instead, now it’s just checking which side of the face a player is on, and which side the camera is on. A handy diagram here shows what I mean (though, in 2D):

In this diagram, dotproduct(v1, n) and dotproduct(v2, n) will have the same sign if the camera and the player are on the same side of the wall. If they’re on different sides of the wall, they will have different signs. A quick check for this is to multiply them together, same signs makes a positive number and different signs makes a negative number.

If they’re on the same side of the wall, great! the wall CANNOT be blocking the view of the player. Otherwise, the whole wall gets cropped. You’ll notice, regardless of which position on the wall you choose, the math works out the same. So the position I pick is just the texel that is currently being processed in the shader. This is an amazingly simpler method than the craziness I was doing before, though it obviously has a lot of problems still.

Here is a gif of the first pass of this new effect:

It has a lot of the same problems as before, though with a lot less glitchiness in the cropping itself. One of the main things I wanted was to be able to see what was being cropped out of your vision when moving behind something. Games traditionally do this by just making the object transparent, which I’ve explained above why that won’t work. I looked into dithered transparency, but it would have just looked really bad.

So uh, doing the outlines was the first and most obvious attempt at this, and it surprisingly worked really well!

They aren’t a post process effect like outlines are traditionally, they’re actually part of the tilemap, and are generated on the CPU.

The shader knows what outline tiles to use for each main tile, and is only responsible for comping them together with changes in lighting to make it easy to visually process the shape of the landscape. The game actually generates a separate set of tiles for concave and convex edges, as seen here:

So the important thing here is the shader knows already if a texel is an outline or not. Don’t cull it if it’s an outline! And it looks great this way. I am only showing convex edges in this, showing the concave ones too makes it too confusing to look at. Here’s what it looks like with both edges shown, just for comparison:

It’s a bit busy and you lose the ability to clearly see the shape of what’s being masked out.

The other major problem was, if you watch the earlier gif, it was running the crop effect when the player wasn’t being visually obscured by anything. You can see that here:

My solution for now is, I just make the size of the circle dynamically change size when you walk behind walls! It’s surprisingly simple too, I run a raycast from the player to the camera, if it hits a tile, I take the difference between the point where it collides and the player, and make the crop sphere have that for a radius (with reasonable minimums and maximums, and easing). It works pretty well for now. If an object is far in front, the crop circle is bigger. If you’re pressed up against a wall, it’s smaller.

Here’s the gif from the start again, with all the effects in place:

Its not perfect yet. There’s a lot of other effects I want to add. I want to add a shadow effect for when a player is partially obscured by walls (other players would have this effect too, and possibly other in game object). I want to change the calculation of the size of the sphere to take a few more points rather than just the center of the character into consideration. And there’s a ton of other small things that could be polished up with it too, but at this point in time I think it’s “good enough”.

It took a long time to get it there though.

Comments

Gameplay Limits

My game design method usually involves making a prototype, then picking an arbitrary or made up “game design philosophy” that fits the prototype I made, then designing the rest of the game with that philosophy in mind. This method helps enforce a bit of consistency in the design, while giving clear guidelines for how to solve certain design problems.

So for Bombernauts, I have been thinking about a concept of gameplay limits. Anyway, limits are cool. If you frame your game design based on what the player CAN’T do, then what they CAN do is nearly infinite (at least that’s the thought). It doesn’t always work like this in practice, as programming has its own limits, but it helps with design a lot. If someone tries to do X and can’t, is X something I explicitly want to limit?

But this is not actually what I chose as a philosophy for Bombernauts. There’s a bit more to it, regarding HOW things are limited. I see 2 categories: hard and soft. I am unsure if these terms have been used before for game design, as googling that brings up stuff relating to BDSM which I really don’t need in my search history, so if there’s a better term for it please let me know.

Let’s start by explaining “hard limits”, which is what I’m attempting to AVOID in Bombernauts. A hard limit, simply put, makes it extremely clear when the limit is hit, often long before you can hit the limit. The simplest example is game length. Want games to not take longer than 5 minutes? Add a 5 minute timer. You know what the limit is, you know when it’s going to be hit, and there’s not much you can do to stop it. Another example would be say, health. If a player has 100 health, and attacks to 10 damage, they will die in 10 hits. In a vs. game this makes it clear who’s winning or losing at any given time, so statistically the player with less health will lost more often. If it’s 10 to 90, the game is basically already decided. There’s still a chance for a comeback of course, but at that point it’s pretty clear who’s going to win, and you can see the end of the match in sight.

A “soft limit”, on the other hand, emerges naturally from the game mechanics, and does not have a clear boundary that needs to be hit for the limit to take place. A nice example here is score in everyone’s favorite rougelite-like-like-like Spelunky. There is a maximum possible score in Spelunky, but nobody knows exactly what it is (You’d have to check optimal routes for every seed in the game, around 4 billion seeds). If you play Spelunky a lot, you’ll edge ever closer to that max score over time, but will never reach it (and if you do, you’ll never really know you reached it).

Super Smash Bros is another game with a lot of good examples of soft limits. How many hits do you need to land to kill the other player? Well… it varies. You are never a guaranteed 1 hit away from death in Super Smash Bros, though the chance of a single hit killing you goes up over time as you rack up more damage percent on your character. You can even be killed at a very low percent with a well placed attack and ledge grab from your opponent. As a result the game almost always has a bit of tension over who will win and who will lose, even when one player has a large advantage.

As a programming example, here are 2 ways to do “maximum speed”. The hard limit way would be:

    speed += acceleration;
    if(speed > max_speed){
        speed = max_speed;
    }

The soft limit way would be:

    speed += acceleration;
    speed *= friction;

The soft limit way limits velocity because when ((speed+acceleration)*friction == speed), you’ve hit your cap. You can calculate friction needed to reach a certain max speed by solving that equation for friction, with max_speed in place of speed. It works out to be friction = max_speed/(max_speed+acceleration). See the graphs below for an estimate of how these functions look in game. They both limit speed to the same value, but do so in a different way. The hard limit caps out in finite time, which can be good for games where you want tight timings on things. The soft limit never quite reaches its cap, which can be good if you want a really smooth feeling motion, or want to handle situations where the player can end up moving faster than a max speed cause of an external force.

These two kinds of limits exist on a spectrum though, it’s not binary “this is a hard limit” or “this is a soft limit”. The example of HP in a fighting game I used earlier, I categorized it as a hard limit because it clearly limits how many hits you can take before dying, but it still manages to be a soft limit on game length, and with healing moves or wombo combos there can be uncertainty on it.

Bombernauts’ design is about soft limits. If there is a value or a behavior I need to limit, I will attempt to use a soft limit if possible. For example, game length. A lot of people have suggested to me, “hey you could raise the lava after X time to keep games short!” or “hey there could be a sudden death mode after X time when bombs start raining from the sky!”. Both of those are hard limits, and they’re not necessary because game length is already limited! Bombs that you throw destroy the level over time, and there is a limited amount of level to destroy. It can vary depending on the number of players, but there should be no stalemate situations (unless all players stop playing… which can happen in a lot of games really).

Explosion forces vary depending on distance from an explosion, and the radius is invisible, so you don’t get a clear boundary of if you were hit by an explosion or not. This is another soft limit. Get too close and you will be knocked away, too far away and you wont, but the actual crossover point where it’s dangerous is ill-defined.

There is never a current winning player in a single match of Bombernauts, because there is no concept of HP. Even if you die, you can get back into the game for a comeback with a well placed ghost bomb. This degree of uncertainty can make matches really tense, surprising, and fun.

These few mechanics were in from the start of the game… and how I discovered the concept of soft limits. Since then I’ve used that concept in solving a ton of other design problems in the game. Limiting the effectiveness of bomb jumping (while making the shorter jumps easier) was a mix of soft limits (from how much bombs can effect your speed while already moving, and what degree your own bombs stun you for when they push you vertically). Limiting the ability to spam bombs as fast as possible without adding something like a cooldown also involved a soft limit (the game increases a stat which makes you get stunned for longer when you spam bombs a lot, at a certain point your own bombs start stunning you, which prevents you from continually spamming them, though there are ways around this with clever play).

Anyway hope this was informative, and remember: I’m not saying soft limits are the “right” way to do things. Most games have a mix of both, and its up to you to decide which kind of limit to go for in your own games, it’s just something to think about.

- Tyler

Comments