Updated 2015-05-22 13:35:10 by dbohdan

Have you heard about glslsandox website ?

It shows (using WebGL) what can be done with pixel shaders.

There are some really impressive ones ...

Here is a small Tcl script using the tcl3d package that can be used to try the shaders of glslsandox

You only need to replace the pixel shader code to try another one ...

Hope you'll enjoy !
#! /bin/sh
# next line restarts using tclsh \
    exec tclsh85 "$0" ${1+"$@"}

package require tcl3d

proc mkshader {type src} {
    set sh [glCreateShader $type]
    tcl3dOglShaderSource $sh $src
    glCompileShader $sh
    puts "compilation report : [tcl3dOglGetShaderState $sh $::GL_COMPILE_STATUS] [tcl3dOglGetShaderInfoLog $sh]"
    return $sh
}

proc mkprogram {v f} {
    set p [glCreateProgram]
    glAttachShader $p $v
    glAttachShader $p $f
    glLinkProgram $p
    puts "link report : [tcl3dOglGetProgramState $p $::GL_LINK_STATUS] [tcl3dOglGetProgramInfoLog $p]"
    return $p
}

proc createcb { toglwin } {
    glClearColor 0.0 0.0 0.0 0.0
    glShadeModel $::GL_SMOOTH

    set v [mkshader  $::GL_VERTEX_SHADER {
        void main() {
            gl_Position = ftransform();
        }
    }]
    
    # --- replace the code below to try another shader
    set f [mkshader $::GL_FRAGMENT_SHADER {
        #ifdef GL_ES
        precision mediump float;
        #endif

        uniform float time;
        //uniform vec2 mouse;
        //uniform vec2 resolution;

        float lengthsq(vec2 p) { return dot(p, p); }

        float noise(vec2 p){
            return fract(sin(fract(sin(p.x) * (43.13311)) + p.y) * 31.001);
        }


        float worley(vec2 p) {        
          // Initialise distance to a large value
          float d = 20.0;
          for (int xo = -2; xo <= 2; xo++) {
            for (int yo = -2; yo <= 2; yo++) {
              // Test all surrounding cells to see if distance is smaller.
              vec2 test_cell = floor(p) + vec2(xo, yo);
              // Update distance if smaller.
              float n0 = noise(test_cell);
              float n1 = noise(test_cell + vec2(134.0,8413.0));
                                                                                
              float ox = mix( n0, n1, sin(time) );
              float oy = mix( n0, n1, cos(time) );
                                                                                
              vec2 c = test_cell + vec2(ox,oy);
              d = min(d, lengthsq(p - c));
            }
          }
          return d;
        }

        void main() {
            vec2 uv = gl_FragCoord.xy;
            float t = 0.9 * worley(gl_FragCoord.xy / 20.0);
            gl_FragColor = vec4(vec3(t,sqrt(t),t), 1.0);
        }
    }]


    set p [mkprogram $v $f]
    
    glUseProgram $p

    set ::uloc_time       [glGetUniformLocation $p "time"]
    set ::uloc_mouse      [glGetUniformLocation $p "mouse"]
    set ::uloc_resolution [glGetUniformLocation $p "resolution"]
}

proc displaycb { toglwin } {
    incr ::time
    glUniform1f $::uloc_time [expr {0.05*$::time}]
    
    glClear $::GL_COLOR_BUFFER_BIT

    glLoadIdentity
    glBegin GL_QUADS
    glVertex2f -1 -1
    glVertex2f -1  1
    glVertex2f  1  1
    glVertex2f  1  -1
    glEnd
    
    $toglwin swapbuffers
}

proc reshapecb { toglwin { w -1 } { h -1 } } {
    set w [$toglwin width]
    set h [$toglwin height]
    glUniform2f $::uloc_resolution $w $h
    glViewport 0 0 $w $h
}

proc Animate {} {
    .w postredisplay
    set ::animateId [after 40 ::Animate]
}

proc StartAnimation {} {
    puts "starting animation"
    if { ! [info exists ::animateId] } {
        Animate
    }
}

proc StopAnimation {} {
    if { [info exists ::animateId] } {
        after cancel $::animateId 
        unset ::animateId
    }
}


togl .w -w 640 -h 480 -double true -createproc createcb -displayproc displaycb -reshapeproc reshapecb
pack .w -expand 1 -fill both
bind .w <Key-Escape> exit
bind .w <Motion> {
    glUniform2f $::uloc_mouse %x %y
}

wm protocol . WM_DELETE_WINDOW exit
StartAnimation

Here are two screenshots made using the above program and 2 different shaders :

See also  edit