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 :