Tuesday, February 23, 2010

Starfield


The starfield effect is a popular effect, present in a lot of demos. It's easy to code and optimize.

A starfield effect consists of a lot of 3D points, that are animated and projected. The initial position of the stars is usually random. After projecting each point, you decrement the Z coordinate of the point. If the point goes off-screen, the point needs to be recreated.

To project a 3D point, use this formula:

projected x = x / z
projected y = y / z


Create an array of random points. After projecting each point, decrement its Z coordinate. If Z becomes a negative number, or the projected point goes offscreen, calculate another random point. You should scale/translate the projected point.

When you plot the point you can apply different effects, like antialiased particles, different velocities, motion blur, lines or circles instead of pixels...

Tuesday, February 9, 2010

Metaballs


The metaball effect is a famous demoscene effect. It's a cool effect, and it's easy to optimize.
The theory is pretty simple: for each ball, you evaluate the value of a function for a given point, and add it to a variable. If it's over some threshold, then you can plot that point. The function is usually:

P: center of the metaball
S: screen point

f(S, P) = 1 / (S - P)2
For each metaball add f(S, P) to a variable (P: current ball center)


It's very easy to compute this function for each metaball. Howewer, this function is slow, due to the division. For this reason, you must find an alternate function. Another possible function is:
f(S, P) = (1 - S - P2)2

You can erase the square root, due to this:
sqrt(x)2 = x

So, the final formula is:

r = (Sx - Px)2 + (Sy - Py)2
f(S, P) = (1 - r)2


This formula is faster, but not fast enough. However, there's another trick you could do. Most of the space in the screen won't be covered by the metaballs, so you can change the code to scan for metaballs (each rectangle in the image, for example), instead of scanning each pixel of the screen.

Monday, February 8, 2010

Mandelbrot Fractal - Part 3


In my last post I said I was going to show the fractal with colors, and here it is! In this post I'll describe colors in the Mandelbrot fractal.

In my last post I wrote some pseudocode you could use to draw the fractal. In the pseudocode I told you to count the number of times you use the formulas. That's an index for your pallete. You should be able to implement that easily.

If you draw it, though, you'll notice a problem. You can see "banding" in the fractal. No matter how high your iteration limit is, the banding will still be there. You can fix this by changing your formula. Up until now you were doing something like this:

i: index into pal
cnt: iteration counter

i = (pal_size * cnt) / limit
plot pallete[i]


The algorithm should be similiar to that. To eliminate banding, replace the algorithm to this:

i: index into pal
cnt: iteration counter

(calculate iteration formulas 4 more times)
cnt = cnt + 5 - ( log(log(|z|)) / log(2) )
i = (pal_size * cnt) / limit
plot pallete[i]

If you test it using these formulas, banding should be gone (mostly). Alter your pallete until you get something you like.

Sunday, February 7, 2010

MK-Hextiler


This is MK-Hextiler, an enhanced version of Hextiler (a program we use at NSN). It uses the Agar library.

Thursday, February 4, 2010

Mandelbrot Fractal - Part 2


This is the follow-up to part 1. I'm going to continue the explanation from part 1 and describe some initial pseudocode. Beware: this pseudocode is slow. I'll probably handle optimization in a later post.

In my previous post I gave you two formulas that describe the Mandelbrot set :

|z| > 2
z = z2 + c


I also told you what z and c were (complex numbers), and how c relates to the screen point.

First of all, I'm going to describe 3 basic operations with complex numbers. You'll use these to calculate the formulas.

a and b are complex numbers, where .real is the real part, and .imag is the imaginary part.

(a + b).real = a.real + b.real
(a + b).imag = a.imag + b.imag

(a * b).real = (a.real * b.real) - (b.imag * b.imag)
(a * b).imag = (a.imag * b.real) + (a.real * b.imag)

|a| = sqrt( (a.real * a.real) + (a.imag * a.imag) )

Be careful with multiplication: the imaginary part depends on the original real part. This means, save the real part in a temporary variable! It drove me crazy when I first programmed the fractal.

In my previous post, I told you the Mandelbrot set is evaluated using a iterative process: if the condition (|z| > 2) is false, try again, until the counter reaches the limit, or the condition evaluates to true. That counter is going to be important in the process, since it'll determine the final color for the point. I'll refer to it as i.

Knowing this, we can write down some pseudocode, like this:

i = 0
limit = 20

z.real = 0
z.imag = 0

c.real = x
c.imag = y

while i < limit then
- if sqrt( z.real2 + z.imag2 ) > 2 then
-- plot as white
-- break
- z = z2 + c
- i = i + 1

If you plot that code, using C, you'll notice two things:
  • It's ugly.
  • It's slow.

It should look like the photo, if everything ia correct. The photo fractal uses limit=50. It's ugly, but it changes dramatically when you add color. I'll address that in the next part.

Tuesday, February 2, 2010

Mandelbrot Fractal - Part 1

I'm going to describe the Mandelbrot fractal, the most beautiful fractal that I know. I assume you have experience with complex numbers (addition, multiplication...).


First of all, what is the Mandelbrot fractal? It's a set of points. To draw the fractal, you must plot every point that is in the Mandelbrot set. The Mandelbrot set is defined using this formula :
z = z2 + c
|z| > 2

where z and c are complex numbers and c is the point you are testing, such as : c.real = x, c.imag = y.

If the condition is true, the point is in the set. If it isn't true, you must iterate using the first formula. If, after a maximium number of iterations, the condition is still false, then the point isn't in the set.