Broken screen shader (do u wanna play a game)

Posted on

It is not kind of very optimized shader, sometimes I  simply want to show how to combine different simple effects to create big one.

And because Halloween is very soon) I found movie with famous mask, but even after adding voice to it (btw I have no idea what this guy is saying) – it is not scary yet.

Now I want to make effect like broken screen with flicks, kind of noise and color, maybe texture of glass and result should be like this:

Seems it is more dramatic now.

So, our steps again:
1) Make broken video effect
2) Distort the video
3) Make this effects animated without external code

Only FLSL.

Here is our raw texture for experiments

Halloween Pumpkin

At first we design the main effect. I wanna base it on checkerboard:

   const float step = 50; 

    float2 newUV = (floor(iUV0 * step) / step);
    
    float k = newUV.x*step+newUV.y*step;
    k = floor(k);
    k = k-floor(k/2)*2; 
    
    output fragment = sampler2D( texture, iUV0 )*k;
checkerboard
checkerboard

 

Of course, we need to decrease extremely uniform of this pattern, so we need to make changes with newUV value

   const float step = 50; 

    float2 uv_steps = float2(step, step-step*iUV0.y);
    float2 newUV = (floor(iUV0 * uv_steps) / uv_steps);
    
    float k = newUV.x*step+newUV.y*step;
    k = floor(k);
    k = k-floor(k/2)*2; 
    
    output fragment = sampler2D( texture, iUV0 )*k;
distorted checkerboard
distorted checkerboard

Ook, much better.

Obviously, the center of image should be more opened – to see our scary guy. Because k is our parameter to show or not pixel, we will use sine with it.

   const float d = 3;
    float k = newUV.x*step+newUV.y*step;
    k = floor(k);
    k = k-floor(k/d)*d; 
    k+= (sin(newUV.y*PI)>0.7);

Broken effect is pretty good now.

opened center of image with sine
opened center of image with sine

Now it is time to make some distortion: bend our image and scale it a little:

   float2 finUV = iUV0+float2(sin(iUV0.y*PI/2)/10,0);
    finUV*=0.9;
    output fragment = sampler2D( texture, finUV );

And we need to break up RGB color channels.

   float4 tex1 = sampler2D( texture, finUV );
    float4 tex2 = sampler2D( texture, finUV+float2(0.003,0) );
    
    output fragment = float4(tex1.r,tex2.g,tex1.b,1);

Hah, looks like stereo effect.

 

So, we need to combine broken effect and distortion:

Our bend code result (finUV) will be as input for broken effect.

   float2 finUV = iUV0+float2(sin(iUV0.y*PI/2)/10,0);
    finUV*=0.9;
    
    float2 uv_steps = float2(step, step-step*finUV.y);
    float2 newUV = (floor(finUV * uv_steps) / uv_steps);

For output we will use result of bearing up channels (combination of tex1 and tex2). And then we will use modificator k from broken effect result

   float4 tex1 = sampler2D( texture, finUV );
    float4 tex2 = sampler2D( texture, finUV+float2(0.003,0) );
    
    output fragment = float4(tex1.r,tex2.g,tex1.b,1)*(k>0);

final static result

What about animation? We need some modificator, based on TIME, that will look and randomized.

   float t = sin(0+time.x*7)+cos(time.y*5+PI/3);
    float int = (t>0.3)*(t<0.7)+0.5*(t>=0.7);

After this calculations int will be either 0.0 or 0.5 or 1.0. Very useful to make three levels of this effect: 0 – no effect, 0.5 – only distortion, 1 – with broken screen.

Look to final code for usage.

Finally, we will place broken glass texture with screen method.

Do not forget to place “use namespace flare.blendMode” at header of shader

   output fragment = screen(tex_glass,tex_final);

Final code:

To use video in shader (until Flare3D is not support swf version 26 (player 15)) – check out this sample. It’s pretty easy.


use namespace flare;
use namespace flare.transforms;
use namespace flare.filters;
use namespace flare.blendMode;

sampler2D texture;
sampler2D glass;

param TIME time;



technique main
{
    output vertex = transform();
    float t = sin(0+time.x*7)+cos(time.y*5+PI/3);
    float int = (t&gt;0.3)*(t&lt;0.7)+0.5*(t&gt;=0.7);
    
    float2 finUV = iUV0+float2(sin(iUV0.y*PI/2)/10,0)*int;
    
    finUV*=0.9+(1-int)/10;
    
    const float step = 50; 
    float2 uv_steps = float2(step, step-step*iUV0.y);
    float2 newUV = (floor(finUV * uv_steps) / uv_steps);
    
    float k = floor(newUV.x*step+newUV.y*step);
    const float d = 3;
    k = k-floor(k/d)*d; 
    k+= (sin(newUV.y*PI)&gt;0.7);

    float4 tex_glass = sampler2D( glass, iUV0 );
    
    
    float4 tex1 = sampler2D( texture, finUV );
    float4 tex2 = sampler2D( texture, finUV+float2(0.003,0)*k*int );
    
    float4 tex_final = float4(tex1.r,tex2.g,tex1.b,1);
    tex_final*=((k+1-int)&gt;0);
    tex_final*=(1-(float4(0.7,0.6,0.2,1)-float4(0.9,0.0,0.0,1)*t)*int);
    
    output fragment = screen(tex_glass,tex_final);
}

 

Leave a Reply