frankiezafe.net & org . LABO . Resources . First shaders in blender game engine

Video

Blender project

blender GUI for this project

How does it works?

There are 3 passes to achieve the work.

The pyhton script [ jump to code > simple.py ] change the value shared with the shaders.
Tips uniform float myValue in the shader code correspond to root["myValue"] in the python script, simple and magic!

Note: the video is not to be trusted > the screen capture is running at 30fps and lag from time to time. 
The rendering is made at 60fps, so the glitches are much more important when you see the app running.

Download blender project and the GLSL files here.

simple.py

import bge, random, mathutils

root = bge.logic.getCurrentScene().objects["root"]
cam = bge.logic.getCurrentScene().objects[ "Camera" ]
clight = bge.logic.getCurrentScene().objects[ "Camlight" ]

if "cam_rot" not in root:
    root["cam_rot"] = mathutils.Euler( (0,0,0), 'XYZ' )
    root["cam_pos"] = mathutils.Vector( cam.worldPosition )
    root["cam_ori"] = mathutils.Matrix( cam.worldOrientation )
    root["clight_pos"] = mathutils.Vector( clight.worldPosition )
    root["cam_ori"] = mathutils.Matrix( cam.worldOrientation )
    root["clight_ori"] = mathutils.Matrix( clight.worldOrientation )
    root["glitchspeed"] = -1
    
root["percentage"] = random.random()
root["timer"] = random.random() * 1000
# root["xmin"] = random.random() * 0.5
# root["xmax"] = 0.5 + random.random() * 0.5
ty1 = 0.2 + random.random() * 0.7
ty2 = random.random() * 0.25
root["ymin"] += ( ( ty1 - ty2 ) - root["ymin"] ) * 0.1
root["ymax"] += ( ( ty1 + ty2 ) - root["ymax"] ) * 0.1

newd = random.random() * 0.1
root["glitchdecal"] += ( newd - root["glitchdecal"] ) * 0.01
root["glitchdecalstart"] = 0.2 + random.random() * 0.2
root["glitchdecalend"] = 0.6 + random.random() * 0.2


root["glitchd"] += 0.0008 * root["glitchspeed"]
if root["glitchd"] > 0.17 :
    root["glitchd"] = 0.17
    root["glitchspeed"] *= -1
elif root["glitchd"] < 0.03 :
    root["glitchd"] = 0.03
    root["glitchspeed"] *= -1

root["cam_rot"].y += 0.003
root["cam_rot"].z += 0.002

np = mathutils.Vector( root["cam_pos"] )
np.rotate( root["cam_rot"] )
cam.worldPosition = np
np = mathutils.Matrix( root["cam_ori"] )
np.rotate( root["cam_rot"] )
cam.worldOrientation = np

np = mathutils.Vector( root["clight_pos"] )
np.rotate( root["cam_rot"] )
clight.worldPosition = np
np = mathutils.Matrix( root["clight_ori"] )
np.rotate( root["cam_rot"] )
clight.worldOrientation = np

# cube = bge.logic.getCurrentScene().objects[ "Cube.006" ]
# cube.worldPosition.x += 1 - random.random() * 2

simple.glsl

uniform sampler2D bgl_RenderedTexture;
uniform sampler2D bgl_DepthTexture;
uniform float percentage;
uniform float timer;
uniform float xmin;
uniform float xmax;
uniform float ymin;
uniform float ymax;

void main(void) {
    
    // using depth
    vec4 dc = texture2D(bgl_DepthTexture, gl_TexCoord[0].st);
    
    float x = gl_TexCoord[0].st.x;
    float y = gl_TexCoord[0].st.y;
    if (
        // x >= xmin && x <= xmax &&
        y >= ymin && y <= ymax
        )
    {
    // NOISE
        float noiseR = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer)) * 43758.5453));
        float noiseG =     (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer*2)) * 43758.5453));
        float noiseB =     (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer*3)) * 43758.5453));
        
        vec4 noise = vec4( noiseR, noiseG, noiseB, 1.0 );
        float range = ( ymax - ymin ) * 0.5;
        range = ( y - ( ymin + range ) ) / range;
        if ( range < 0 ) { range *= -1; }
        gl_FragColor = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st) + ( noise * percentage );

    // INVERT COLORS
    /*
    vec4 invert = 1.0 - texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
    vec4 color = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
    gl_FragColor = mix(color, invert, percentage);
    gl_FragColor.a = 1.0;
    */
    } else {
        gl_FragColor = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
    }
}

depth-glitch.glsl

uniform sampler2D bgl_RenderedTexture;
uniform sampler2D bgl_DepthTexture;
uniform float timer;
uniform float glitchd;
uniform float glitchspan;

vec3 convertRGBtoHSV(vec3 rgbColor) {
    float r = rgbColor[0];
    float g = rgbColor[1];
    float b = rgbColor[2];
    float colorMax = max(max(r,g), b);
    float colorMin = min(min(r,g), b);
    float delta = colorMax - colorMin;
    float h = 0.0;
    float s = 0.0;
    float v = colorMax;
    vec3 hsv = vec3(0.0);
    if (colorMax != 0.0) {
     s = (colorMax - colorMin ) / colorMax;
    }
    if (delta != 0.0) {
        if (r == colorMax) {
            h = (g - b) / delta;
        } else if (g == colorMax) {        
            h = 2.0 + (b - r) / delta;
        } else {    
            h = 4.0 + (r - g) / delta;
        }
        h *= 60.0;
        if (h < 0.0) {
            h += 360.0;
        }
    }
    hsv[0] = h;
    hsv[1] = s;
    hsv[2] = v;
    return hsv;
}

void main(void) {
    
    // using depth
    vec4 dc = texture2D(bgl_DepthTexture, gl_TexCoord[0].st);
    float depth = ( 1.000 - ( (dc.r + dc.g + dc.b) / 3.0 ) ) * 16.000;
    
    // validation
    // vec4 rgba = vec4( depth, depth, depth, 1.0);
    // gl_FragColor = rgba;
    
    vec4 rgba = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
    
    // noise on black zones
    vec3 hsv = convertRGBtoHSV( (vec3) rgba );
    if ( hsv[ 2 ] < 0.2 ) {
        float noiseAmount = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer)) * 43758.5453)) * 0.6;
        vec4 noiseColor = vec4( noiseAmount, noiseAmount, noiseAmount, 1.0 );
        rgba += ( noiseColor * noiseAmount * ( 1 - ( hsv[ 2 ] / 0.2 ) ) );
    }
    
    // red laser
    if ( depth > 0 && depth > glitchd - glitchspan && depth < glitchd + glitchspan ) {
        float d = ( ( depth - glitchd ) / glitchspan );
        if ( d < 0 ) {
            d *= -1;
        }
        d = 1-d;
        float redamount = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer)) * 43758.5453)) * d;
        // vec4 noiseColor = vec4( noiseAmount, 0.5, 0.5, 1.0 );
        rgba[ 0 ] += redamount;
        
    } else if ( depth == 0 || depth == 0.1 ) {
        
        rgba = vec4( 0, 0, 0, 1.0);
        /*
        // get symetric color
        float r = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer)) * 43758.5453)) * 1000;
        if ( r < 250 ) {
            rgba = texture2D(bgl_RenderedTexture, vec2( 1 - gl_TexCoord[0].st.x, gl_TexCoord[0].st.y * 0.5) );
        } else if ( r < 500 ) {
            rgba = texture2D(bgl_RenderedTexture, vec2( 1 - gl_TexCoord[0].st.x, 1 - gl_TexCoord[0].st.y ) );
        } else if ( r < 750 ) {
            rgba = texture2D(bgl_RenderedTexture, vec2( gl_TexCoord[0].st.x, 1 - gl_TexCoord[0].st.y ) );
        } else {
            rgba = vec4( 0, 0, 0, 1.0);
        }
        */
        
    }
    
    
    gl_FragColor = rgba;
    
}

decal-glitch.glsl

uniform sampler2D bgl_RenderedTexture;
uniform float glitchdecal;
uniform float glitchdecalstart;
uniform float glitchdecalend;

void main(void) {
    
    float x = gl_TexCoord[0].st.x;
    float y = gl_TexCoord[0].st.y;
    
    if ( y > glitchdecalstart && y < glitchdecalend ) {
        
        float decalx = x + glitchdecal;
        if ( decalx < 0 ) { decalx = 0; }
        else if ( decalx > 1 ) { decalx = 1; }
        
        gl_FragColor = texture2D(bgl_RenderedTexture, vec2( decalx, y ) );
                
    } else {
    
        gl_FragColor = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
    
    }
    
}