Shadertoy to CX conversion

GTR

New Member
Tutorial Author
Joined
Sep 23, 2020
Hello,

This is my first tutorial here. We are going to sloooowly convert basic Shadertoy shader to CX.
When you are in shadertoy.com and start new shader you have exactly this.
On the left the quad or screen space containing compiled result of the code in the right.
1600970614182.png
1600968997582.png


All test are made for HTML5 export, i have not windows, ios, or android and just discovered Cerberus X yesterday.

To convert this shader for CX we have 2 solution.

1- Minimum conversion method.
2- Write entire shader for CX.

For lazy coder like me we are exploring the first method.

Let's begin.
Run Cerberus X and ....
1 - Create new drawer rename it shader
2 - Create New file called shader.cxs
3 - Copy this code inside the shader.cxs file

Cerberus X:
' Cerberus X - Shadertoy Default Shader
'
' Gtr V1.0 2020


Strict

Import mojo2


Class MyShader Extends Shader

    Method New()
        Build(LoadString("shader.glsl"))
    End

    Method OnInitMaterial:Void( myMaterial:Material )
    'write uniform
     myMaterial.SetScalar("timer", 0)

    End
      
End


Class MyApp Extends App

    Field shaderMaterial:Material = New Material(New MyShader())
    Field myCanvas:Canvas
    Field timer:Float = 0.0
    Field tx:String =" "
      
    Method OnCreate:Int()
  
        myCanvas = New Canvas()
    
        Return 0
    End

    Method OnUpdate:Int()
        ' infinite timer
        timer =   Millisecs()/1000.0
            
        Return 0
    End
  
    Method OnRender:Int()
        shaderMaterial.SetScalar("timer", timer)
        myCanvas.DrawRect(0, 0, 800, 600, shaderMaterial)
        'myCanvas.DrawText(Millisecs()/10000.0, 0,0) ' force screen update
         myCanvas.DrawText(tx, 0,0)
        myCanvas.Flush()
  
        Return 0
    End

End


Function Main:Int()
    New MyApp()
    Return 0
End
4 - Create data file inside shader drawer : shader.data
5- Create textfile and rename it shader.glsl
6 - inside shader.glsl copy this shader code.

Cerberus X:
// Shadertoy default Shader ; Gtr 2020
// Basic way to convert shader for CX

uniform sampler2D ColorTexture;

uniform float timer;   // we are using this uniform in shader.cxs  "timer" to modfy color

// Shadertoy Emulation     #define is used to emulate iTime and iResolution for CX ... iTime become 'timer' will used on CX
#define iTime timer          
#define iResolution b3d_Texcoord0    // iResolution become  b3d_Texcoord0 on CX

// Shadertoy Shader without modification

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));

    // Output to screen
    fragColor = vec4(col,1.0);
}
// End Shadertoy shader


// CX shader , just call mainImage(out, in)  function


void shader(){


    mainImage(b3d_FragColor, b3d_Texcoord0.xy);


}
7- Save all and Run build and Run;
8- Have fun
 

Attachments

Last edited:

GTR

New Member
Tutorial Author
Joined
Sep 23, 2020
Finally if you are not lazy and write this shader for CX shader the code is like so;

Cerberus X:
// Shadertoy default Shader ; Gtr 2020
 
uniform float timer;

void shader(){

    vec2 uv = b3d_Texcoord0.xy;

    vec3 col = 0.5 + 0.5*cos(timer+uv.xyx+vec3(0,2,4));

    b3d_FragColor=vec4( col,1.0 );

}
Enjoy and best regards
 
Last edited:

GTR

New Member
Tutorial Author
Joined
Sep 23, 2020
If you also want to convert Seascape shader TDM;
Keep shader.cxs and replace shader.glsl with this code

1600973453526.png

Cerberus X:
// Shadertoy seascape Shader from TDM ; Gtr 2020
//

/*
* "Seascape" by Alexander Alekseev aka TDM - 2014
* License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
* Contact: tdmaav@gmail.com
*/

uniform float timer;
// Shadertoy Emulation     #define is used to emulate iTime and iResolution for CX ... iTime become 'timer' will used on CX
#define iTime timer        
#define iResolution b3d_Texcoord0    // iResolution become  b3d_Texcoord0 on CX

const int NUM_STEPS = 8;
const float PI         = 3.141592;
const float EPSILON    = 1e-3;
#define EPSILON_NRM (0.1 / iResolution.x)


// sea
const int ITER_GEOMETRY = 3;
const int ITER_FRAGMENT = 5;
const float SEA_HEIGHT = 0.6;
const float SEA_CHOPPY = 4.0;
const float SEA_SPEED = 0.8;
const float SEA_FREQ = 0.16;
const vec3 SEA_BASE = vec3(0.0,0.09,0.18);
const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6)*0.6;
#define SEA_TIME (1.0 + iTime * SEA_SPEED)
const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);

// math
mat3 fromEuler(vec3 ang) {
    vec2 a1 = vec2(sin(ang.x),cos(ang.x));
    vec2 a2 = vec2(sin(ang.y),cos(ang.y));
    vec2 a3 = vec2(sin(ang.z),cos(ang.z));
    mat3 m;
    m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
    m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
    m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
    return m;
}
float hash( vec2 p ) {
    float h = dot(p,vec2(127.1,311.7));  
    return fract(sin(h)*43758.5453123);
}
float noise( in vec2 p ) {
    vec2 i = floor( p );
    vec2 f = fract( p );  
    vec2 u = f*f*(3.0-2.0*f);
    return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
                     hash( i + vec2(1.0,0.0) ), u.x),
                mix( hash( i + vec2(0.0,1.0) ),
                     hash( i + vec2(1.0,1.0) ), u.x), u.y);
}

// lighting
float diffuse(vec3 n,vec3 l,float p) {
    return pow(dot(n,l) * 0.4 + 0.6,p);
}
float specular(vec3 n,vec3 l,vec3 e,float s) {  
    float nrm = (s + 8.0) / (PI * 8.0);
    return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
}

// sky
vec3 getSkyColor(vec3 e) {
    e.y = (max(e.y,0.0)*0.8+0.2)*0.8;
    return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4) * 1.1;
}

// sea
float sea_octave(vec2 uv, float choppy) {
    uv += noise(uv);      
    vec2 wv = 1.0-abs(sin(uv));
    vec2 swv = abs(cos(uv));  
    wv = mix(wv,swv,wv);
    return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}

float map(vec3 p) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
   
    float d, h = 0.0;  
    for(int i = 0; i < ITER_GEOMETRY; i++) {      
        d = sea_octave((uv+SEA_TIME)*freq,choppy);
        d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp;      
        uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}

float map_detailed(vec3 p) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
   
    float d, h = 0.0;  
    for(int i = 0; i < ITER_FRAGMENT; i++) {      
        d = sea_octave((uv+SEA_TIME)*freq,choppy);
        d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp;      
        uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}

vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
    float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0);
    fresnel = pow(fresnel,3.0) * 0.5;
       
    vec3 reflected = getSkyColor(reflect(eye,n));  
    vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
   
    vec3 color = mix(refracted,reflected,fresnel);
   
    float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
    color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
   
    color += vec3(specular(n,l,eye,60.0));
   
    return color;
}

// tracing
vec3 getNormal(vec3 p, float eps) {
    vec3 n;
    n.y = map_detailed(p);  
    n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
    n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
    n.y = eps;
    return normalize(n);
}

float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
    float tm = 0.0;
    float tx = 1000.0;  
    float hx = map(ori + dir * tx);
    if(hx > 0.0) return tx;  
    float hm = map(ori + dir * tm);  
    float tmid = 0.0;
    for(int i = 0; i < NUM_STEPS; i++) {
        tmid = mix(tm,tx, hm/(hm-hx));                  
        p = ori + dir * tmid;                  
        float hmid = map(p);
        if(hmid < 0.0) {
            tx = tmid;
            hx = hmid;
        } else {
            tm = tmid;
            hm = hmid;
        }
    }
    return tmid;
}

vec3 getPixel(in vec2 coord, float time) {  
    vec2 uv = coord / iResolution.xy;
    uv = uv * 2.0 - 1.0;
    uv.x *= iResolution.x / iResolution.y;  
       
    // ray
    vec3 ang = vec3(sin(timer*3.0)*0.1,sin(time)*0.2+0.3,timer);  
    vec3 ori = vec3(0.0,3.5,timer*5.0);
    vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.14;
    dir = normalize(dir) * fromEuler(ang);
   
    // tracing
    vec3 p;
    heightMapTracing(ori,dir,p);
    vec3 dist = p - ori;
    vec3 n = getNormal(p, dot(dist,dist) * 0.0001);  // EPSILON_NRM replaced by 0.0001
    vec3 light = normalize(vec3(0.0,1.0,0.8));
           
    // color
    return mix(
        getSkyColor(dir),
        getSeaColor(p,n,light,dir,dist),
        pow(smoothstep(0.0,-0.02,dir.y),0.2));
}

// main
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    
    vec3 color = getPixel(fragCoord, timer);
    
    // post
    fragColor = vec4(pow(color,vec3(0.65)), 1.0);
}

void shader(){

    mainImage(b3d_FragColor, 1.-b3d_Texcoord0.xy);

}
 
Top Bottom