I have written this because I have spent countless hours on Solaris, which was my first demo. It is quite an achievement for me considering the following.
It is written 100% in x86 assembly language, runs on linux and windows and is entirely SOFTWARE rendered.
DirectX was used in the win32 version to access video memory.
Why assembly? For the challenge.
Let’s not forget my fellow Brainstorm comrades that helped for the music and art.
If you want to see what I made in this demo, just delete the ‘data’ folder. The executable will still run. FMOD.dll is always required though.
------------------
The memory manager
My memory manager leaves a very small footprint in terms of code, and it is fairly simple. Using the assembly directive "resb" I allocate a big chunk of RAM to the program. This way I don't have to use OS kernel calls to allocate memory.
The list of nodes is created within that memory block.
Freeing memory is just a matter of flagging the node as unused, and scanning the whole list to merge unused nodes. It's fast and you don't need anything more complex for this kind of project.
------------------
The triangle rasterizer
It's based on Chris Hecker 1995 paper "Perspective texture mapping" and I wrote it first in C. I coded it in assembler after it was fully functionnal. I also have a 3DNOW version which permits me to do the perspective division for every pixel(with "pfrcp", which gives an approximate reciprocal in under 10 cycles). So the 3DNOW version is as fast but more accurate.
------------------
Particle renderer
My particles have their own rendering pipelines, 1 for rotatable and 1 for non-rotatable particles. Since particles always face the camera (in this case), I could optimize that a lot. For non-rotatable particles, it's just a rectangle blitter with selectable combining options(alpha, depth)
------------------
Procedural textures
Textures in the demo except the ones in the /data folder are generated at load time. Texture operations are done on
32bpp 8/8/8/8 packed colors so it's faster.
------------------
Opening and ending credits - Flying text with radial blur
Every mesh in the 3D font is proceduraly generated each frame from splines. This way only the spline control points need to be stored. Those control points were generated with my home made fontmaking tool.
Software radial blur is an effect done in 1 pass, but it trashes the cache completely. That's because the memory is accessed in a very unordered fashion. For the blur value at a pixel to be computed, you need the blur value of a pixel closer to the center. So the pixels are processed from the center point to the screen edges.
------------------
Cube spiral scenes
Not very complex, cubes positions are precomputed with the Lorenz spiral equation. 1st scene has a glow filter applied, 2nd has radial blur.
Glow is done this way. First downsize the color buffer to a reasonable size(512x384 to 128x96 in this case). Then apply a blur pass a number of times, say 3. The blur pass consists of a horizontal pass followed by a vertical pass. It’s much faster than applying a 2d convolution filter. The final image is then resized with filtering and added to the color buffer (all done in 1 operation).
------------------
Electric ball
The lightning that you see here(also appears in another scene) is the effect I am most proud of. I have never seen any good lightning effect in games, it either has rough edges or the entire bolt is made of one texture. Well mine is a triangle strip with a 1D texture applied to it. I use 3D perlin noise to generate the vector of coordinates.
Interpolate in X from [0,0,0] to [1,0,0]. Offset both Y and Z using perlin noise. Then you must realign the coord to the X axis, because the last point you get is really at [1, y, z] but you need it at [1,0,0].
The inner and outer sphere is a real-time tessalated icosahedron, the texture coordinates are displaced with perlin noise.
------------------
morphing mesh
one has radial blur, the other has glow
the plasma in the background is a real-time generated 128x96 3D perlin noise texture that is scaled with bilinear filtering to 512x384. Of course by 3D perlin noise texture I mean a 2D texture generated using a 3D perlin noise function where the 1st and 2nd parameters are the texture coordinates and the 3rd is a time based value.
The morphing mesh is an icosahedron and the vertices are displaced radially with perlin noise.
------------------
tunnel with beam rings
The tunnel mesh is tessalated in real-time. It's a modified torus. The camera position is interpolated along the way. Camera direction is realigned with tunnel by using quaternions.
The tunnel texture is a precomputed procedural cellular texture with bump mapping.
The rings are simple triangle strips textured with a 1D texture.
------------------
wavy water with particle fountain
Mesh is a cylinder with no height and a (almost) null radius at one end, so you get a disk. Vertices position and texture coord are displaced with a sin look-up table. Texture is procedural. The backgroud texture was made by the artist.
------------------
beams with harmonic
The morphing object is a spherical harmonic tessalated in real-time. 2 textures are applied with bilinear filtering. Each straight beam is a pair of quads crossed at a 90 degrees angle and the rotating beams around the harmonics are triangle strips. They are textured with a 1D texture and rendered with additive blending. To make the beam ends look round, I render half a light particle at each end. Radial blur is added but only the rotating beams are taken into account. I wanted to replicate and effect I saw in Discloned by Haujobb.
-------------------
metal balls inside metal cube
This scene uses a technique called the marching cubes algorithm. Explanation for this can be found at Paul Bourkes home page. Here is the link.
http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/index.html
The texture is the same everywhere, and it's mapped using the triangle normals. That's why it looks different on the cube, the normals are almost parallel on each face and so the texture is stretched. There is also 1 ambient light and 1 moving light in the scene. It gives more depth to the objects.
-------------------
lightning rod
Here the camera is only rotating around an axis. Forward movement is simulated by moving the textures on the rod and tunnel.
I've already explained the lightning. The tunnel texture is again a cellular texture with bump mapping. Glow is added to the scene, but before the lightning is rendered.
-------------------
disco ball
Both disco ball use a single texture and it's mapped using the triangle normals.
As you can see, each face is a cube and I was able to speed up the effect by culling the cubes not seen by the camera.
I made the beams appear and disappear smoothly by scaling the beam width and fading the color.
-------------------
wobbly text
The font here is the same as the one used in the credits, I just increased the resolution for the real-time tessalation.
The wobbling effect when the text stops is done with a form of shearing based on a shearing center and direction.
The 3 cubes use one precomputed mesh generated with the marching-cube algorithm. A shattering direction vector is also precomputed for each triangle in the mesh. The shattering effect is time based so I could easily reverse it. The wind effect on the cubes is done by modulating the shearing direction with Perlin noise. Gives a really nice result.
There is also 1 diffuse light and 1 specular light in the scene to give a shiny look.
Perlin noise ROCKS, so use it.
Martin Veilleux / Duffman