Home > Development, OpenGL, Programming > RainSaver Tech

RainSaver Tech

RainSaver is a screensaver for Windows that I made, which warps the desktop as if it were a liquid with raindrops hitting the surface. Here’s a little bit more in-depth information about how the tech behind that works. I used OpenGL for this project, so everything will be from that perspective, but I imagine the same techniques could also be applied in a Direct3D approach.

The first step is to grab an image of the screen to load into video memory as an OpenGL texture, which I won’t go into a whole lot of detail on, except to say that it involves a handy function called BitBlt. Next, I generate a “drop” texture. The drop texture is basically a normal map, where different colors indicate different normals. These colors are later used in the fragment shader to decide how much, and in which direction, to warp the final image. To actually generate it, I set the colors based on sine waves of the coordinates of the pixel relative to the center of the texture, and the alpha based on a sine wave of the distance from the center, setting negative alpha values to 0. It ends up looking a little like this:

// for each pixel in the 256x256 buffer
	dist = sqrt((float)((y-128)*(y-128) + (x-128)*(x-128)));
	dropBuffer[y][x][0] = 128+(x-128)*(sin(dist/2.0f));
	dropBuffer[y][x][1] = 128+(y-128)*(sin(dist/2.0f));
	dropBuffer[y][x][2] = 255;
	// remove inner ring(s)
	if (dist < 90)
		dropBuffer[y][x][3] = 0;
		dropBuffer[y][x][3] = pow(MAX(0.0f, sin(dist/8.0f)), 12)*255.0f;

There’s also a wavy texture that is generated from cosine and sine waves of x and y coordinates, respectively, and smoothed noise for alpha values.

New raindrops are randomly created every so often, and existing ones expand over time. All existing drops are drawn into a frame buffer object (FBO), along with the wavy texture over the whole screen. Finally, a full screen quad is drawn with multitexturing, using the desktop texture and the FBO distortion texture, and the fragment shader takes it from there, using the final colors in the distortion texture as normals to determine distortion and shading. The GLSL for the warping alters the texture coordinates, like so:

vec2 coords = gl_TexCoord[0].st;
coords.s = coords.s + (change.r*2.0 - 1.0)/40.0;
coords.t = coords.t + (change.g*2.0 - 1.0)/40.0;
  1. April 23, 2010 at 2:07 pm

    Wow, this is pretty awesome.

    My only question, since you’re using GLSL, would it be possible to get this working on multi-monitor setups? 🙂

    • April 23, 2010 at 5:35 pm

      So far, no. The current version of SDL does not support multiple monitor displays (at least, not when I made this). I would like to find a way to do that, though, because that seems to be the most asked for feature.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: