Baseteroid is a game in a non-Euclidean space and written using only a fragment shader with a ShaderToy service. The game is heavily inspired by a popular arcade game "Asteroid", released in November 1979.
You can play out game without downloading it it on the shadertoy service here.
The development stages are the following:
- Stage 1: Create a base game with raymarcher as renderer
[current stage]
- Stage 2: Add a black hole visualization which will warp the space around it.
- Stage 3: Add black hole affected physics, which will change the gameplay
- Create a raymarcher
- Handle player input
- Give player inertia and movement
- Make asteroids randomly spawn
See render.glsl and main.glsl.
Ray marching - is a class of rendering methods for 3D computer graphics where rays are traversed iteratively, effectively dividing each ray into smaller ray segments, sampling some function at each step.
In a shader, it is basically launching a ray for each texel, and calculating the distance to hit object for each of those rays.
Raymarching "marches" using circles, at each iteration taking the smallest distance to any object.
Whether a circle collides with some object is determined by the signed distance functions for those respective objects.
Lighting is also made with raymarching from object to light source and looking whether we have hit the light source or if there is something in the way.
Here is an example of a simple Raymarcher we wrote for this project:
The game is written obviously in 3D, but it is entirely top-down, as in Asteroid but all the render is in 3D. So far it has a ship with inertia and asteroid spawning.
Here is how the game looks after the first development stage:
- Collisions and shooting system
- Life System
- Black hole light bending
- Custom asteroid sdf
The player can collide using the sphere to sphere intersection, with the collision results being stored in texels at runtime.
You can also shoot by pressing "E"
(or also "SPACE"
if you are on ShaderToy). The projectile will
destroy the upcoming asteroids.
The Player has 3 lifes, and the amount of lifes is represented by the color of the player and his projectiles:
green
, yellow
and red
respectively.
You lose lifes after a collision with an asteroid, after which you have a few seconds of cooldown protection
. After you use all your lifes you will get a GAME OVER
screen and the
game will restart.
At the center of the screen there is the black hole, that visually
bends the world around it. Here is how it works:
The black hole is positioned slightly above the player and the asteroids, that allows it to bend the rays going from the camera to the playing field. Also this allows us to precompute the entirely of ray travel path for layers that do not contain moving objects and that's like most of the ray path. The precompute allows us to achieve 60 FPS
even on wealer machines.
Here is how it looks:
The default sphere as asteroid is a bit boring and unrealistic, right?
Well, yes, but it's fast in computing, so if we want to make a fast custom object that resembles an asteroid we will need to forget about hash fucntions and random noise and make it using simple unions and intersections of primitive shapes.
Hence, after a ton of trial and error we decided to take a union of 2 rounded cubes and call it a day:) Here it is in action:
There is also an option to turn a sphere back on by setting #define POTATO 0
in this file.
Also go ahead, set #define SUS 1
here, see what happens >:)