8Bit Color Replacer

GTR

New Member
Tutorial Author
Joined
Sep 23, 2020
Hello, this time i will share another nice shader , if you want use old console or computer palette try this shader;

Credit: Based on shader from Coldberg NESIFY;
https://www.shadertoy.com/view/MdfXDH

Brigthness is set by default to 1.0, pixelsize(dither) set to 0.005;
Live example here use num_keys to change fx, key_num0 is reset fx;
Image from www freewallpaper, sfx from abandonware

http://gigatron3k.free.fr/html5/CX/8bitcolors/CerberusGame.html

Pics : no fx Cpc-464 C-64 and so on
1601129199741.png
1601129268673.png
1601129341501.png

Include palettes :
TWOBGS ,
BW
EGA
CPC
CGA
GAMEBOY
TELETEXT
VIC-20
C-64

I am now reading documentation so the source code is documented a bit;

8bitcolors.cxs file :

Cerberus X:
' Cerberus X - 8Bit console color replacer
'
' V1.0 GTR 2020
' Brightness and pixel dither is set by default lazy :)
'


Strict

Import mojo2

'Our custom shader
Class ConsoleShader Extends Shader

    Private
    Global _instance:ConsoleShader

    Method New()
        Build(LoadString("8bitcolors.glsl"))
    End

    ' this method must be implemented as it sets valid/default material parameters
    ' When texture is used in shader this code is needed , when not used easy way is used !
    ' see Cerberus shader conversion tutorial
    '
    Method OnInitMaterial:Void( myMaterial:Material )
       'store uniforms to material include texture image Sampler2D
        myMaterial.SetTexture("Texture",Texture.White())
        
          myMaterial.SetScalar("nofx",1.0)
         myMaterial.SetScalar("pixelsize",0.005)
        myMaterial.SetScalar("BRIGHTNESS",1.0)
        myMaterial.SetScalar("TWOBGS",1.0)
        myMaterial.SetScalar("BW",0.0)
        myMaterial.SetScalar("EGA",0.0)
        myMaterial.SetScalar("CPC",0.0)
        myMaterial.SetScalar("CGA",0.0)
        myMaterial.SetScalar("GAMEBOY",0.0)
        myMaterial.SetScalar("TELETEXT",0.0)
        myMaterial.SetScalar("VIC20",0.0)
        myMaterial.SetScalar("C64",0.0)
      
      
    End
  
    Function Instance:ConsoleShader()
        If Not _instance _instance = New ConsoleShader()
        Return _instance
    End
      
End


Class ConsoleEffect

    Private
    Global _canvas:Canvas
    Field _material:Material 
  
    Method New()

        ' ensure there is a single instance of the canvas
        If Not _canvas _canvas = New Canvas()
        _material = New Material(ConsoleShader.Instance())
    End

    Method SetNofx:Void( value:Float )
          _material.SetScalar("nofx", value)
    End

    Method SetPixSize:Void( value:Float )
          _material.SetScalar("pixelsize", value)
    End
    Method SetBrightness:Void( value:Float )
          _material.SetScalar("BRIGHTNESS", value)
    End
  
    Method SetTwoBgs:Void( value:Float )
          _material.SetScalar("TWOBGS", value)
    End
    Method SetBw:Void( value:Float )
          _material.SetScalar("BW", value)
    End
    Method SetEga:Void( value:Float )
          _material.SetScalar("EGA", value)
    End
    Method SetCpc:Void( value:Float )
          _material.SetScalar("CPC", value)
    End
    Method SetCga:Void( value:Float )
          _material.SetScalar("CGA", value)
    End
  
    Method SetGameBoy:Void( value:Float )
          _material.SetScalar("GAMEBOY", value)
    End
    Method SetTeletext:Void( value:Float )
          _material.SetScalar("TELETEXT", value)
    End
    Method SetVic20:Void( value:Float )
          _material.SetScalar("VIC20", value)
    End
    Method SetC64:Void( value:Float )
          _material.SetScalar("C64", value)
    End
      
    Method Render:Void(source:Image, target:Image )
  
        _material.SetTexture("Texture", source.Material.ColorTexture)
        _canvas.SetRenderTarget(target)
        _canvas.SetViewport(0, 0, target.Width(), target.Height())
        _canvas.SetProjection2d(0, target.Width(), 0, target.Height())
        _canvas.DrawRect(0, 0, target.Width(), target.Height(), _material)
        _canvas.Flush()
    End
  
End

Class MyApp Extends App

    Field sourceImage:Image
    Field targetImage:Image
    Field myCanvas:Canvas
    Field effect:ConsoleEffect   ' call methods and all function inside like effect.SetNoFx etc
  
    ' uniform float to write in shader parameters
    '
    Field nofx:Float = 1.0       ' no fx orignal image
    Field pixsize:Float = 0.005  ' fake dithering default value
    Field brigtness:Float = 1.0  ' default brigthness
      
    Field twobgs:Float = 0.0
    Field bw:Float = 0.0
    Field ega:Float = 0.0
    Field cpc:Float = 0.0
    Field cga:Float = 0.0
    Field gameboy:Float = 0.0
    Field teletext:Float = 0.0   
    Field vic20:Float = 0.0
    Field c64:Float = 0.0
  
   ' Field sfx:Sound
  
    Method OnCreate:Int()
     '   sfx = LoadSound("ast.mp3")           ' sound or sfx
        sourceImage = Image.Load("fwp.jpg")  ' Image: free wallpaper from www   your logo here ;
        targetImage = New Image(800, 600)    ' image size
        effect = New ConsoleEffect()         ' effect.method()
        myCanvas = New Canvas()              ' canvas
     '   PlaySound(sfx,1,1)                   ' play sfx
        Return 0                             ' return something 0 = ok;
    End
  
    ' reset all fx here
    Method ResetFx:Int()
            nofx    = 0.0
            twobgs  = 0.0
            bw      = 0.0
            ega     = 0.0
            cpc     = 0.0
            cga     = 0.0
            gameboy = 0.0
            teletext= 0.0
            vic20   = 0.0
            c64     = 0.0
      
         Return 0
      
    End
  
    Method OnUpdate:Int()
      
        ' infinite timer unused here this shader is not animated
        ' timer =   Millisecs()/1000.0
              
      
        If KeyHit( KEY_NUM1 )
            ResetFx()
            bw   = 1.0
          
        Endif
        If KeyHit( KEY_NUM2 )
            ResetFx()
            twobgs  = 1.0
        Endif
        If KeyHit( KEY_NUM3 )
            ResetFx()
            ega     = 1.0
        Endif
        If KeyHit( KEY_NUM4 )
            ResetFx()
            cpc     = 1.0
        Endif
        If KeyHit( KEY_NUM5 )
            ResetFx()
            cga     = 1.0
        Endif
        If KeyHit( KEY_NUM6 )
            ResetFx()
            gameboy = 1.0
        Endif
        If KeyHit( KEY_NUM7 )
            ResetFx()
            teletext  = 1.0
        Endif
        If KeyHit( KEY_NUM8 )
            ResetFx()
            vic20   = 1.0
        Endif
        If KeyHit( KEY_NUM9 )
            ResetFx()
            c64     = 1.0
        Endif
      
      
      
        If KeyHit( KEY_NUM0 )
            ResetFx()
            nofx = 1.0
        Endif 
      
              
        Return 0
    End
  
  
    Method OnRender:Int()
        ' call method inside ConsoleEffect to write uniforms params all are float SetScalar used,
        ' vector not used here but in future like color vec3/4 or position x,y vec2;
        '
        effect.SetNofx(nofx)
        effect.SetPixSize(pixsize)
        effect.SetBrightness(brigtness)
      
        effect.SetTwoBgs(twobgs)
        effect.SetBw(bw)
        effect.SetGameBoy(gameboy)
        effect.SetEga(ega)
        effect.SetCpc(cpc)
        effect.SetCga(cga)
        effect.SetTeletext(teletext)
        effect.SetVic20(vic20)
        effect.SetC64(c64)
        ' use default canvas color , use red color after for text
        myCanvas.SetColor(1.0,1.0,1.0)
        effect.Render(sourceImage, targetImage)
        myCanvas.Clear()
        myCanvas.DrawImage(targetImage, 320, 240, 0, 0.7, 0.7)
        myCanvas.SetColor(1.0,1.0,1.0) ' red color for text
        myCanvas.DrawText("8Bit Color Replacer V1.0" , DeviceWidth()/2+40,460, 1.0)
        myCanvas.DrawText("KEYS : 0/1/2/3/4/5/7/8/9" , DeviceWidth()/2+80,10, 2.0)
      
        If bw      = 1.0 myCanvas.DrawText("Black & White" , DeviceWidth()/2-220,460, 1.0)
        If twobgs  = 1.0 myCanvas.DrawText("Two Bgs" ,       DeviceWidth()/2-220,460, 1.0)
        If gameboy = 1.0 myCanvas.DrawText("GameBoy" ,       DeviceWidth()/2-220,460, 1.0)
        If ega     = 1.0 myCanvas.DrawText("EGA" ,           DeviceWidth()/2-220,460, 1.0)
        If cga     = 1.0 myCanvas.DrawText("CGA" ,           DeviceWidth()/2-220,460, 1.0)
        If cpc     = 1.0 myCanvas.DrawText("CPC-464" ,       DeviceWidth()/2-220,460, 1.0)
        If teletext= 1.0 myCanvas.DrawText("Teletext" ,      DeviceWidth()/2-220,460, 1.0)
        If vic20   = 1.0 myCanvas.DrawText("Vic-20" ,        DeviceWidth()/2-220,460, 1.0)
        If c64     = 1.0 myCanvas.DrawText("C-64" ,          DeviceWidth()/2-220,460, 1.0)
      
        myCanvas.Flush()
        Return 0
    End
  
End


Function Main:Int()
    New MyApp()
    Return 0
End
8bitcolors.data drawer contain 8bitcolors.glsl ;

Cerberus X:
#ifdef GL_ES
precision mediump float;
#endif

uniform sampler2D Texture;

//uniform float timer;
uniform float nofx;
uniform float pixelsize;
uniform float BRIGHTNESS;
uniform float TWOBGS;
uniform float BW;
uniform float EGA;
uniform float CPC;
uniform float CGA;
uniform float GAMEBOY;
uniform float TELETEXT;
uniform float VIC20;
uniform float C64;


vec3 find_closest (in vec3 ref) { 
    vec3 old = vec3 (100.0*255.0,100.0*255.0,100.0*255.0);     
    #define TRY_COLOR(new) old = mix (new, old, step (length (old-ref), length (new-ref))); 

    if(TWOBGS==1.0){
    TRY_COLOR (vec3 (000.0, 000.0, 000.0));
    TRY_COLOR (vec3 (103.0, 103.0, 103.0));
    TRY_COLOR (vec3 (184.0, 184.0, 184.0)); 
    TRY_COLOR (vec3 (255.0, 255.0, 255.0)); 
    }
  
    if(BW==1.0){
    TRY_COLOR (vec3 (000.0, 000.0, 000.0));
    TRY_COLOR (vec3 (255.0, 255.0, 255.0)); 
    }
      
    if(TELETEXT==1.0){
    TRY_COLOR (vec3 (000.0, 000.0, 000.0));
    TRY_COLOR (vec3 (255.0, 000.0, 000.0));
    TRY_COLOR (vec3 (000.0, 255.0, 000.0));
    TRY_COLOR (vec3 (000.0, 000.0, 255.0));
    TRY_COLOR (vec3 (000.0, 255.0, 255.0));
    TRY_COLOR (vec3 (255.0, 000.0, 255.0));
    TRY_COLOR (vec3 (255.0, 255.0, 000.0));
    TRY_COLOR (vec3 (255.0, 255.0, 255.0)); 
    }
      
    if(GAMEBOY==1.0){
    TRY_COLOR (vec3 (156.0, 189.0, 015.0));
    TRY_COLOR (vec3 (140.0, 173.0, 015.0));
    TRY_COLOR (vec3 (048.0, 098.0, 048.0));
    TRY_COLOR (vec3 (000.0, 000.0, 000.0)); // (015.0, 056.0, 015.0));
    }
  
    if(EGA==1.0){
    TRY_COLOR (vec3 (000.0,000.0,000.0));
    TRY_COLOR (vec3 (255.0,255.0,255.0));
    TRY_COLOR (vec3 (255.0,  0.0,  0.0));
    TRY_COLOR (vec3 (  0.0,255.0,  0.0));
    TRY_COLOR (vec3 (  0.0,  0.0,255.0));
    TRY_COLOR (vec3 (255.0,255.0,  0.0));
    TRY_COLOR (vec3  (  0.0,255.0,255.0));
    TRY_COLOR (vec3 (255.0,  0.0,255.0));
    TRY_COLOR (vec3 (128.0,  0.0,  0.0));
    TRY_COLOR (vec3 (  0.0,128.0,  0.0));
    TRY_COLOR (vec3 (  0.0,  0.0,128.0));
    TRY_COLOR (vec3 (128.0,128.0,  0.0));
    TRY_COLOR (vec3 (  0.0,128.0,128.0));
    TRY_COLOR (vec3 (128.0,  0.0,128.0));
    TRY_COLOR (vec3 (128.0,128.0,128.0));
    TRY_COLOR (vec3 (255.0,128.0,128.0));
    }
  
    if(CGA==1.0){
    TRY_COLOR (vec3 (000.0,000.0,000.0));
    TRY_COLOR (vec3 (000.0,170.0,170.0));
    TRY_COLOR (vec3 (170.0,000.0,170.0));
    TRY_COLOR (vec3 (170.0,170.0,170.0));
    }
  
    if(CPC==1.0){
    TRY_COLOR ( vec3(000.0,000.0,000.0));
    TRY_COLOR ( vec3(000.0,000.0,128.0));
    TRY_COLOR ( vec3(000.0,000.0,255.0));
    TRY_COLOR ( vec3(128.0,000.0,000.0));
    TRY_COLOR ( vec3(128.0,000.0,128.0));
    TRY_COLOR ( vec3(128.0,000.0,255.0));
    TRY_COLOR ( vec3(255.0,000.0,000.0));
    TRY_COLOR ( vec3(255.0,000.0,128.0));
    TRY_COLOR ( vec3(255.0,000.0,255.0));
    TRY_COLOR ( vec3(000.0,128.0,000.0));
    TRY_COLOR ( vec3(000.0,128.0,128.0));
    TRY_COLOR ( vec3(000.0,128.0,255.0));
    TRY_COLOR ( vec3(128.0,128.0,000.0));
    TRY_COLOR ( vec3(128.0,128.0,128.0));
    TRY_COLOR ( vec3(128.0,128.0,255.0));
    TRY_COLOR ( vec3(255.0,128.0,000.0));
    TRY_COLOR ( vec3(255.0,128.0,128.0));
    TRY_COLOR ( vec3(255.0,128.0,255.0));
    TRY_COLOR ( vec3(000.0,255.0,000.0));
    TRY_COLOR ( vec3(000.0,255.0,128.0));
    TRY_COLOR ( vec3(000.0,255.0,255.0));
    TRY_COLOR ( vec3(128.0,255.0,000.0));
    TRY_COLOR ( vec3(128.0,255.0,128.0));
    TRY_COLOR ( vec3(128.0,255.0,255.0));
    TRY_COLOR ( vec3(255.0,255.0,000.0));
    TRY_COLOR ( vec3(255.0,255.0,128.0));
    TRY_COLOR ( vec3(255.0,255.0,255.0));
    }
  
    if(VIC20==1.0){
    TRY_COLOR (vec3(000.0,000.0,000.0));
    TRY_COLOR (vec3(255.0,255.0,255.0));
    TRY_COLOR (vec3(168.0,115.0,074.0));
    TRY_COLOR (vec3(233.0,178.0,135.0));
    TRY_COLOR (vec3(119.0,045.0,038.0));
    TRY_COLOR (vec3(182.0,104.0,098.0));
    TRY_COLOR (vec3(133.0,212.0,220.0));
    TRY_COLOR (vec3(197.0,255.0,255.0));
    TRY_COLOR (vec3(168.0,095.0,180.0));
    TRY_COLOR (vec3(233.0,157.0,245.0));
    TRY_COLOR (vec3(085.0,158.0,074.0));
    TRY_COLOR (vec3(146.0,223.0,135.0));
    TRY_COLOR (vec3(066.0,052.0,139.0));
    TRY_COLOR (vec3(126.0,112.0,202.0));
    TRY_COLOR (vec3(189.0,204.0,113.0));
    TRY_COLOR (vec3(255.0,255.0,176.0));
    }
    if(C64==1.0){
    TRY_COLOR (vec3(0.0, 0.0,0.0));
    TRY_COLOR (vec3(098.0,098.0,098.0));
    TRY_COLOR (vec3(137.0,137.0,137.0));
    TRY_COLOR (vec3(173.0,173.0,173.0));
    TRY_COLOR (vec3(255.0,255.0,255.0));
    TRY_COLOR (vec3(159.0,078.0,068.0));
    TRY_COLOR (vec3(203.0,126.0,117.0));
    TRY_COLOR (vec3(109.0,084.0,018.0));
    TRY_COLOR (vec3(161.0,104.0,060.0));
    TRY_COLOR (vec3(201.0,212.0,135.0));
    TRY_COLOR (vec3(154.0,226.0,155.0));
    TRY_COLOR (vec3(092.0,171.0,094.0));
    TRY_COLOR (vec3(106.0,191.0,198.0));
    TRY_COLOR (vec3(136.0,126.0,203.0));
    TRY_COLOR (vec3(080.0,069.0,155.0));
    TRY_COLOR (vec3(160.0,087.0,163.0));
    }
  
  
  
    return old ;
}




vec3 dither (vec3 color, vec2 uv) { 
    color *= 255.0 * BRIGHTNESS; 
  
    color = find_closest (clamp (color, 0.0, 255.0));
    return color / 255.0;
}


void shader(){

    //convert clip position to valid tex coords

     //vec2 uv = (b3d_ClipPosition.st/b3d_ClipPosition.w)*0.5+0.5;
     vec2 uv = b3d_Texcoord0  ;
  
     uv = uv - mod(uv, pixelsize); // pixelsize 0.005
    
     vec3 tc = texture2D(Texture,uv).xyz;
  
     if(nofx==1.0)
         b3d_FragColor =  vec4 (tc,1.0);
     else   
      
     b3d_FragColor =  vec4 (dither (tc, uv.xy),1.0);     
    
  
}
Don't forget you need texture like image.png or jpeg like descripted in the source code;
If you need help feel free to contact me;

Regards
 
Last edited:
Top Bottom