Have you heard about http://glslsandbox.com%|%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 http://glslsandbox.com%|%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 exit bind .w { 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 : [http://img15.hostingpics.net/pics/434638bubbles.png] [http://img15.hostingpics.net/pics/939312lightning.png] ** See also ** * [Functional imaging] <>Tcl3D | Graphics