512 • 826 • 2701


Cloud Lightning Shader in GLSL

This was a part of a larger skydome shader for an art test completed in UDK. I recreated the cloud lightning portion in GLSL based on what I had set up in UDK's node based material editor. The lightning effect is driven by a single texture map containing the masked off areas and an assortment of sin waves.

Vertex Program:

void main(void)
   //I need 3 texture coordinates to keep one non-moving and two
   //moving in opposing directions
   gl_TexCoord[0] = gl_MultiTexCoord0;
   gl_TexCoord[1] = gl_MultiTexCoord0;
   gl_TexCoord[2] = gl_MultiTexCoord0;
   gl_Position = ftransform();

Fragment Program:

uniform sampler2D maskTexture;
uniform float time;
uniform vec4 highlightColor;
uniform vec4 shadowColor;
uniform vec4 lighteningColor;
uniform float brightnessBoost;

void main(void)
   //2 Masks are panning across eachother and being multiplied creating randomly positioned lightening highlights.
   //These highlights are then multiplied by a non-moving mask that gives definition to the illuminated cloud shapes. 
   vec2 vMask = vec2(gl_TexCoord[1].s + time * 0.5, gl_TexCoord[1].t + time * 0.2);
   vec2 hMask = vec2(gl_TexCoord[2].s - time * 0.15, gl_TexCoord[2].t - time * 0.2);
   vec4 cloudMask = texture2D(maskTexture, gl_TexCoord[0].st);
   vec4 vPanningMask = texture2D(maskTexture, vMask);
   vec4 hPanningMask = texture2D(maskTexture, hMask);
   //Faked random intervals are created using sin waves multiplied together.
   float flash;
   float flash_0;
   float flash_1;
   float flash_2;
   float flash_3;
   flash_0 = sin(time) + 0.7;
   flash_1 = sin(20.0 * time) + 1.8;
   flash_2 = sin(2.85 * time) + 0.9;
   flash_3 = sin(5.18 * time) + 1.7;
   //The sin waves are all multiplied then masked off by the 3 masks. A float is then multiplied by the clamped result to give it a boost.
   flash = clamp(flash_0 * flash_1 * flash_2 * flash_3 * cloudMask.w * vPanningMask.z * hPanningMask.y, 0.0, 8.0) * brightnessBoost;
   //For the purposes of this example I just colorized the red channel from the texture and added the finished lightening flashes.
   gl_FragColor = mix(shadowColor, highlightColor, cloudMask.x) + flash * lighteningColor;

Cloud Mask Texture:



Custom Color and Detail Shader

For this shader I set out to utilize four channel maps to minimize the number of texture maps involved for isolating parts of the model. In this example I stayed with diffuse only; Though it would not be difficult to expand this shader to include other important maps like normal and spec. Additional maps, like normal and spec, would also have the advantage of bringing in more black and white maps through their alpha channels.

Four Channel Mask Map:

All four channels come in with the texture sample and then are split into their individual components and added to a small constant number. This keeps the color selection from reaching pure black which darkens out all of the detail in the diffuse completely. These channels are multiplied by an exposed color parameter. These color parameter can be changed through code directly or connected through code to GUI elements for color pickers in game.


Nothing too fancy here; Just a diffuse map with an alpha channel for the mowhawk. All of the individual channels from the mask map areas that were tinted are multiplied with the diffuse then added together bringing the brightness back to an acceptable level.

Detail Map:

This map input could be set up differently to accomodate blending other than multiply. I chose multiply because it works well for the tattoos. Alternately, you could subtract out the diffuse information on a given area then use that masked off area on an additional map to replace areas on a texture using addition. The mask for this operation could easily be placed in the additional detail diffuse map you are adding.