REM 'On the Salt Lake' by Sebastien Durand, https://www.shadertoy.com/view/fsXcR8
     REM Adapted for BBCSDL by Richard Russell, http://www.rtrussell.co.uk, 30-Dec-2023

     REM Initialise window:
     
ScrW% = 640
     ScrH% = 480
     VDU 23,22,ScrW%;ScrH%;16,20,16,0

     REM Install libraries:
     
INSTALL @lib$ + "shaderlib"

     REM Create arrays and structures:
     
DIM Vertex$(100), Fragment$(1000), Float{0%,1%}

     REM Fill vertex and fragment shader arrays from DATA statements:
     
PROC_readshader(Vertex$())
     PROC_readshader(Fragment$())

     REM Initialise window and get its size:
     
ON MOVE IF @msg% <> 5 RETURN ELSE PROCcleanup
     VDU 26

     REM Ensure cleanup on exit:
     
ON CLOSE PROCcleanup : QUIT
     ON ERROR PROC
cleanup : IF ERR=17 CHAIN @lib$+"../examples/tools/touchide" ELSE MODE 3 : PRINT REPORT$ : END

     PRINT
"Compiling shaders, please wait..."
     *REFRESH

     REM Initialise shader library:
     
PROC_shaderinit(oVertex%, oFragment%)

     REM Compile shaders:
     
PROC_compileshader(oVertex%, Vertex$(), "Vertex")
     PROC_compileshader(oFragment%, Fragment$(), "Fragment")

     REM Link and use shaders:
     
oProgram% = FN_useshaders(oVertex%, oFragment%)
     SYS `glGetUniformLocation`, oProgram%, "iTime",       @memhdc% TO pTime%
     SYS `glGetUniformLocation`, oProgram%, "iMouse",      @memhdc% TO pMouse%
     SYS `glGetUniformLocation`, oProgram%, "iResolution", @memhdc% TO pResolution%
     SYS `glGetUniformLocation`, oProgram%, "iChannel0",   @memhdc% TO pChannel0%
     SYS `glGetUniformLocation`, oProgram%, "iChannel1",   @memhdc% TO pChannel1%

     REM Load and bind texture to uniform:
     
SYS `glUniform1i`, pChannel0%, 0, @memhdc%
     SYS `glActiveTexture`, GL_TEXTURE0, @memhdc%
     Texture% = FN_loadtexture1(@dir$ + "hiker.png")
     IF Texture% = 0 ERROR 100, "Couldn't load hiker.png"
     SYS `glUniform1i`, pChannel1%, 1, @memhdc%
     SYS `glActiveTexture`, GL_TEXTURE0 + 1, @memhdc%
     Texture% = FN_loadtexture1(@dir$ + "hiker.bmp")
     IF Texture% = 0 ERROR 100, "Couldn't load hiker.bmp"

     REM Render:
     
REPEAT
       MOUSE
X%,Y%,B%
       Float.0% = FN_f4(TIME/100)
       SYS `glUniform1fv`, pTime%, 1, Float{}, @memhdc%
       Float.0% = FN_f4(X% / 2) : Float.1% = FN_f4(Y%*2)
       SYS `glUniform2fv`, pMouse%, 1, Float{}, @memhdc%
       Float.0% = FN_f4(@size.x%) : Float.1% = FN_f4(@size.y%)
       SYS `glUniform2fv`, pResolution%, 1, Float{}, @memhdc%
       PROC_render
     UNTIL FALSE
     END

     
DEF PROCcleanup
     ON ERROR OFF
     
Texture% += 0 : IF Texture% SYS `glDeleteTextures`, 1, ^Texture%
     oProgram% += 0 : oVertex% += 0 : oFragment% += 0
     PROC_shaderexit(oProgram%, oVertex%, oFragment%)
     *REFRESH ON
     ENDPROC

     
REM Vertex shader with animation code:
     
DATA "attribute vec4 vPosition;"
     
DATA "uniform float iTime;"
     
DATA "uniform sampler2D iChannel1;"
     
DATA "varying vec3 shoulder1, elbow1, wrist1, head, shoulder2, elbow2, wrist2;"
     
DATA "varying vec3 foot1, ankle1, knee1, hip1, foot2, ankle2, knee2, hip2;"
     
DATA "varying mat2 rot, rot1, rot2;"
     
DATA "float gTime;"

     
DATA "// Interpolate pos of articulations"
     
DATA "vec3 getPos(int n, float it, float z) {"
     
DATA "vec3 p = texture2D(iChannel1, vec2((it+0.5)/16.0, (float(n)+0.5)/8.0)).rgb * 255.0;"
     
DATA "return .02*vec3(p.x+floor(gTime/8.)*168., 150.-p.y, p.z*z);"
     
DATA "}"


     
DATA "void main()"
     
DATA "{"
     
DATA "// Animation"
     
DATA "gTime = iTime * 6.0;"
     
DATA "float it = (gTime - 8.0 * floor(gTime / 8.0));"
     
DATA "float dz = 1.;"

     
DATA "head = getPos(0, it, dz);"

     
DATA "shoulder1 = getPos(1, it, -dz);"
     
DATA "elbow1 = getPos(2, it, -dz);"
     
DATA "wrist1 = getPos(3, it, -dz);"

     
DATA "foot1 = getPos(7, it, dz);"
     
DATA "ankle1 = getPos(6, it, dz);"
     
DATA "knee1 = getPos(5, it, dz);"
     
DATA "hip1 = getPos(4, it, dz);"

     
DATA "it = (gTime + 4.0 - 8.0 * floor((gTime + 4.0) / 8.0));"

     
DATA "shoulder2 = getPos(1, it, dz);"
     
DATA "elbow2 = getPos(2, it, dz);"
     
DATA "wrist2 = getPos(3, it, dz);"

     
DATA "foot2 = getPos(7, it, -dz);"
     
DATA "ankle2 = getPos(6, it, -dz);"
     
DATA "knee2 = getPos(5, it, -dz);"
     
DATA "hip2 = getPos(4, it, -dz);"

     
DATA "float dx = it >= 4. ? -85.*.02 : 85.*.02;"
     
DATA "foot2.x += dx;"
     
DATA "ankle2.x += dx;"
     
DATA "knee2.x += dx;"
     
DATA "hip2.x += dx;"

     
DATA "shoulder2.x += dx;"
     
DATA "elbow2.x += dx;"
     
DATA "wrist2.x += dx;"

     
DATA "float a = -1.5708*.4;"
     
DATA "rot = mat2(cos(a), sin(a), -sin(a), cos(a));"

     
DATA "a = .2*cos(.4*iTime) + .3*cos(.05*iTime);"
     
DATA "rot1 = mat2(cos(a), sin(a), -sin(a), cos(a));"

     
DATA "a = .5*cos(.5*3.141592*gTime);"
     
DATA "a = a*a;"
     
DATA "rot2 = mat2(cos(a), sin(a), -sin(a), cos(a));"

     
DATA "gl_Position = vPosition ;"
     
DATA "}"
     
DATA ""

     
REM Fragment shader from https://www.shadertoy.com/view/fsXcR8
     
DATA "uniform float iTime;"
     
DATA "uniform vec2 iMouse;"
     
DATA "uniform vec2 iResolution;"
     
DATA "uniform sampler2D iChannel0;"

     
DATA "//-----------------------------------------------------"
     
DATA "// Created by sebastien durand - 2021"
     
DATA "// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License."
     
DATA "// Inspired by nguyen nhut work https://twitter.com/nguyenhut_art"
     
DATA "//-----------------------------------------------------"

     
DATA "#define PI 3.14159265"

     
DATA "#define WITH_AO"

     
DATA "#define ZERO 0"

     
DATA "#define GROUND 0."
     
DATA "#define SKIN 1."
     
DATA "#define SHOES1 2."
     
DATA "#define SHOES2 2.5"
     
DATA "#define SHORT 3."
     
DATA "#define BAG 4."
     
DATA "#define SHIRT 5."
     
DATA "#define BED 7."
     
DATA "#define METAL 8."

     
DATA "#define WITH_SPIRAL"

     
DATA "float gTime;"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//    Animation"
     
DATA "//---------------------------------------------------------------------"

     
DATA "varying vec3 shoulder1, elbow1, wrist1, head, shoulder2, elbow2, wrist2;"
     
DATA "varying vec3 foot1, ankle1, knee1, hip1, foot2, ankle2, knee2, hip2;"
     
DATA "varying mat2 rot, rot1, rot2;"

     
DATA "#define U(a,b) (a.x*b.y-b.x*a.y)"

     
DATA "float smin(float a, float b, float k){"
     
DATA "float h = clamp(.5+.5*(b-a)/k, 0., 1.);"
     
DATA "return mix(b,a,h)-k*h*(1.-h);"
     
DATA "}"

     
DATA "vec2 min2(vec2 a, vec2 b) {"
     
DATA "return a.x<b.x ? a : b;"
     
DATA "}"

     
DATA "#ifdef WITH_SPIRAL"
     
DATA "float sdSpiral(vec3 p, vec2 sz){"
     
DATA "float m = PI*sz.x,"
     
DATA "d = length(p.xy) + atan(-p.y,p.x)*sz.x*.5;"
     
DATA "d -= m*clamp(d/m+0.5,1.,4.);"
     
DATA "return max(abs(d)-sz.x/1.3, abs(p.z)-sz.y);"
     
DATA "}"
     
DATA "#endif"

     
DATA "// Distance to Bezier"
     
DATA "// inspired by [iq:https://www.shadertoy.com/view/ldj3Wh]"
     
DATA "// calculate distance to 2D bezier curve on xy but without forgeting the z component of p"
     
DATA "// total distance is corrected using pytagore just before return"
     
DATA "vec2 sdBezier(vec2 m, vec2 n, vec2 o, vec3 p) {"
     
DATA "vec2 q = p.xy;"
     
DATA "m-= q; n-= q; o-= q;"
     
DATA "float x = U(m, o), y = 2. * U(n, m), z = 2. * U(o, n);"
     
DATA "vec2 i = o - m, j = o - n, k = n - m,"
     
DATA "s = 2. * (x * i + y * j + z * k),"
     
DATA "r = m + (y * z - x * x) * vec2(s.y, -s.x) / dot(s, s);"
     
DATA "float t = clamp((U(r, i) + 2. * U(k, r)) / (x + x + y + z), 0.,1.); // parametric position on curve"
     
DATA "r = m + t * (k + k + t * (j - k)); // distance on 2D xy space"
     
DATA "return vec2(sqrt(dot(r, r) + p.z * p.z), t); // distance on 3D space"
     
DATA "}"

     
DATA "//-----------------------------------------------------------------------------------"
     
DATA "// iq - https://www.shadertoy.com/view/ldj3Wh"
     
DATA "vec2 sdBezier(in vec3 p,in vec3 b0,in vec3 b1,in vec3 b2 ) {"
     
DATA "b0 -= p; b1 -= p; b2 -= p;"
     
DATA "vec3 b01 = cross(b0,b1), b12 = cross(b1,b2), b20 = cross(b2,b0),"
     
DATA "n =  b01+b12+b20;"
     
DATA "float a = -dot(b20,n), b = -dot(b01,n), d = -dot(b12,n), m = -dot(n,n);"
     
DATA "vec3  g =  (d-b)*b1 + (b+a*.5)*b2 + (-d-a*.5)*b0;"
     
DATA "float t = clamp((a*.5+b-.5*(a*a*.25-b*d)*dot(g,b0-2.*b1+b2)/dot(g,g))/m, 0., 1.);"
     
DATA "return vec2(length(mix(mix(b0,b1,t), mix(b1,b2,t),t)),t);"
     
DATA "}"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//    HASH functions (iq)"
     
DATA "//---------------------------------------------------------------------"

     
DATA "vec2 hash22(vec2 p) {"
     
DATA "p = fract(p * vec2(5.3983, 5.4427));"
     
DATA "p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));"
     
DATA "return fract(vec2(p.x * p.y * 95.4337, p.x * p.y * 97.597));"
     
DATA "}"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//   Modeling Primitives"
     
DATA "//   [Inigo Quilez] http://iquilezles.org/www/articles/distfunctions/distfunctions.htm"
     
DATA "//---------------------------------------------------------------------"

     
DATA "float sdCap(vec3 p, vec3 a, vec3 b) {"
     
DATA "vec3 pa = p - a, ba = b - a;"
     
DATA "float h = clamp( dot(pa,ba)/dot(ba,ba), 0., 1. );"
     
DATA "return length( pa - ba*h );"
     
DATA "}"

     
DATA "float sdCap2(vec3 p, vec3 a, vec3 b, float r1, float r2) {"
     
DATA "vec3 pa = p - a, ba = b - a;"
     
DATA "float h = clamp(dot(pa,ba)/dot(ba,ba), 0., 1. );"
     
DATA "return length( pa - ba*h ) - mix(r1,r2,h);"
     
DATA "}"

     
DATA "float udRoundBox( vec3 p, vec3 b, float r ) {"
     
DATA "return length(max(abs(p)-b,0.))-r;"
     
DATA "}"

     
DATA "float sdCappedCylinder(vec3 p, vec2 h ) {"
     
DATA "vec2 d = abs(vec2(length(p.xz),p.y)) - h;"
     
DATA "return min(max(d.x,d.y),0.) + length(max(d,0.));"
     
DATA "}"

     
DATA "// approximated"
     
DATA "float sdEllipsoid( in vec3 p, in vec3 r ) {"
     
DATA "float k0 = length(p/r);"
     
DATA "return k0*(k0-1.)/length(p/(r*r));"
     
DATA "}"

     
DATA "float sdEar(in vec3 p) {"
     
DATA "vec3 p_ear = 1.5*p;"
     
DATA "float d = max(-sdEllipsoid(p_ear-vec3(.005,.015,.02), vec3(.07,.1,.07)),"
     
DATA "sdEllipsoid(p_ear, vec3(.08,.12,.09)));"
     
DATA "d = max(p_ear.z, d);"
     
DATA "d = smin(d, sdEllipsoid(p_ear+vec3(.035,.045,.01), vec3(.04,.04,.018)), .01);"
     
DATA "return d/1.5;"
     
DATA "}"


     
DATA "mat3 baseArm1, baseArm2, baseBag, baseFoot1, baseFoot2;"

     
DATA "vec2 sdMan(in vec3 pos){"
     
DATA "vec3 p0 = pos;"
     
DATA "vec2 res = vec2(999,0);"

     
DATA "// Legs"
     
DATA "float dSkin = min("
     
DATA "min(sdCap(pos, ankle1, knee1),"
     
DATA "sdCap(pos, knee1, hip1)),"
     
DATA "min(sdCap(pos, ankle2, knee2),"
     
DATA "sdCap(pos, knee2, hip2)))-.1;"

     
DATA "// Foot1 flat part - vector base linked to leg 1"
     
DATA "float dShoes1 = max(sdCap(pos, foot1, ankle1) - .15, -dot((pos-ankle1)*baseFoot1-vec3(0,0,-.13), vec3(0,0,1)));"

     
DATA "// Leg 2"
     
DATA "float dShoes2 = max(sdCap(pos, foot2, ankle2) - .15, -dot((pos-ankle2)*baseFoot2-vec3(0,0,-.13), vec3(0,0,1)));"

     
DATA "vec3 ep0 = mix(shoulder1,shoulder2,.5),"
     
DATA "ha0 = mix(hip1,hip2,.5);"

     
DATA "// Head"
     
DATA "vec3 h1 = vec3(0,.17,0), h2 = vec3(.02,-.11,0),"
     
DATA "h = mix(h1,h2,.2);"
     
DATA "dSkin = min(dSkin, sdCap(pos, head - h, head - h2)-.25);"

     
DATA "vec3 posHead = pos-head;"
     
DATA "posHead.xz *= rot1;"
     
DATA "vec3 posEar = posHead;"
     
DATA "posEar.z = abs(posEar.z);"
     
DATA "posEar-=vec3(0.,-.08,.29);"
     
DATA "posEar.zx *= rot;"

     
DATA "// ear / noze"
     
DATA "dSkin = smin(dSkin, min(sdEar(posEar.zyx),"
     
DATA "sdCap(posHead, - mix(h1,h2,.4), - mix(h1,h2,.4) + vec3(.28,0,0))- .04),.02);"
     
DATA "// Torso"
     
DATA "vec3 a = mix(ha0,ep0,.15), b = mix(ha0,ep0,.78);"

     
DATA "// Neck"
     
DATA "float dNeck = sdCap(pos, ep0-vec3(.08,0,0), head-vec3(.08,.1,0))- .1;"
     
DATA "dSkin = smin(dSkin, dNeck,.06);"

     
DATA "float dTorso = smin(sdCap(pos,shoulder1,shoulder2)-.11, sdCap2(pos, a, b, .23,.28),.095);"
     
DATA "dSkin = min(dSkin, dTorso);"

     
DATA "dTorso = smin(dTorso, sdCap(pos, shoulder1, mix(shoulder1,elbow1,.3))- .1,.05);"

     
DATA "// Arm 1"
     
DATA "dSkin = smin(dSkin, sdCap(pos, shoulder1, elbow1)- .1,.05);"
     
DATA "dSkin = min(dSkin, sdCap2(pos, elbow1, wrist1-.05*normalize(wrist1-elbow1), .1, .08));"

     
DATA "vec3 p2 = (pos-wrist1)*baseArm1; // change to hand base"
     
DATA "float d2 = sdCap(p2,vec3(-.1,.12,.04),vec3(-.04,.18,.06))-.05;"
     
DATA "p2.z -= 1.5*p2.x*p2.x;"
     
DATA "d2 = min(d2,sdEllipsoid(p2-vec3(.02,.05,0), vec3(.17,.14,.07)));"

     
DATA "// Arm 2"
     
DATA "dTorso = smin(dTorso, sdCap(pos, shoulder2, mix(shoulder2,elbow2,.3))- .1,.05);"
     
DATA "dSkin = smin(dSkin, sdCap2(pos, shoulder2, elbow2, .11,.1),.05);"
     
DATA "dSkin = min(dSkin, sdCap2(pos, elbow2, wrist2-.105*normalize(wrist2-elbow2), .1, .08));"

     
DATA "p2 = (pos - wrist2)*baseArm2; // change to hand base"
     
DATA "d2 = min(d2,sdCap(p2,vec3(-.1,.12,.04),vec3(-.04,.18,.06))-.05);"
     
DATA "p2.z -= 1.5*p2.x*p2.x;"
     
DATA "d2 = min(d2,sdEllipsoid(p2-vec3(.02,.05,0), vec3(.17,.14,.07)));"

     
DATA "dSkin = smin(d2, dSkin, .1);"

     
DATA "// Short"
     
DATA "float dShort = min(sdCap(pos, hip1, mix(hip1,knee1,.7)),"
     
DATA "sdCap(pos, hip2, mix(hip2,knee2,.7)))-.14;"
     
DATA "dShort = min(dShort, smin(dShort, sdEllipsoid(pos-ha0-vec3(.01,.06,0),vec3(.23,.3,.3)), .05));"

     
DATA "// Belt"
     
DATA "vec3 p3 = p0;"
     
DATA "p3.y -= ha0.y+.2;"
     
DATA "float dBelt = max(max(min(dTorso-.05,dShort-.02), p3.y), -p3.y-.16);"
     
DATA "dShoes1 = min(dShoes1, dBelt);"

     
DATA "float dMetal = mix(dBelt,sdCappedCylinder((p0-ha0-vec3(.2,.11,0)).zxy, vec2(.07,.14)),.5);"
     
DATA "float dNeck2 = length(pos - ep0)-.25;"
     
DATA "dTorso = max(max(dTorso-.03, -dNeck2), -dSkin + .005);"
     
DATA "dTorso = max(dTorso, -pos.y + a.y);"

     
DATA "pos.x += .2;"
     
DATA "pos = pos - ep0;"
     
DATA "pos *= baseBag;"
     
DATA "vec3 pos0 = pos;"

     
DATA "// Backpack"
     
DATA "float ta = cos(2.8+.25*PI*gTime);"

     
DATA "// Water"
     
DATA "vec3 p = pos - vec3(-.50,-.5,-.4);"
     
DATA "p.xy *= rot2;"
     
DATA "dMetal = min(dMetal, min(sdCap(p,vec3(0), vec3(0,-.4-.04*ta,-.04*ta))- .1,"
     
DATA "sdCap(p,vec3(0,.1,.01*ta), vec3(0,.15,.015*ta))-.07));"
     
DATA "pos.z = abs(pos.z);"
     
DATA "float dPack = sdBezier(pos, vec3(-.2,.2,.17),vec3(.9,.2,.36),vec3(-.2,-.6,.3)).x-.04;"

     
DATA "dPack = mix(dPack, dTorso,.2);"

     
DATA "pos = pos0;"

     
DATA "float ta2 = cos(2.5+.25*PI*gTime);"
     
DATA "pos.y += .15*ta2*ta2;"
     
DATA "pos.z += .06*ta2*ta2*ta2;"
     
DATA "#ifdef WITH_SPIRAL"
     
DATA "float dBed = sdSpiral(pos-vec3(-.35-.14,.5-.16,0), vec2(.015,.5));"
     
DATA "#else"
     
DATA "float dBed = sdCappedCylinder(pos.yzx+vec3(-.35,0,.5), vec2(.2,.5));"
     
DATA "#endif"

     
DATA "dPack = min(dPack, sdCappedCylinder(pos-vec3(-.75,.23,.26), vec2(.05,.03)));"
     
DATA "pos.z = abs(pos.z);"
     
DATA "dPack = min(dPack, sdCappedCylinder(pos.yzx-vec3(.35,.25,-.5), vec2(.22,.05)));"
     
DATA "dPack = min(dPack, udRoundBox(pos0-vec3(-.33,-.25,-.35), vec3(.08,.1,.1),.04));"
     
DATA "dPack = smin(dPack, udRoundBox(pos0-vec3(-.33,-.2,0), vec3(.1,.3,.2), .15), .12);"

     
DATA "// Little box"
     
DATA "dBed = min(dBed, udRoundBox(pos0-vec3(-.33,-.1,-.35), vec3(.08,.1,.1),.0));"

     
DATA "// Cap"
     
DATA "pos = posHead + h2;"
     
DATA "float d = pos.x*.2-pos.y+.15*cos(5.*pos.z)-.12;"
     
DATA "float dHat = max(sdCap(pos, vec3(0), vec3(.2,0,0))-.27, -d);"
     
DATA "dHat = min(dHat, mix(dSkin, sdCappedCylinder(pos, vec2(.25,.23)),.4)-.01);"
     
DATA "dHat = max(dHat, d-.02);"
     
DATA "dPack = min(dPack, dHat);"

     
DATA "// Asssociate distance to materials"
     
DATA "res = min2(res, vec2(dTorso, SHIRT));"
     
DATA "res = min2(res, vec2(dShort, SHORT));"
     
DATA "res = min2(res, vec2(dShoes1, SHOES1));"
     
DATA "res = min2(res, vec2(dShoes2, SHOES2));"
     
DATA "res = min2(res, vec2(dSkin, SKIN));"
     
DATA "res = min2(res, vec2(dMetal, METAL));"
     
DATA "res = min2(res, vec2(dPack, BAG));"
     
DATA "res = min2(res, vec2(dBed, BED));"

     
DATA "// Distance field is not precise for cap and hands"
     
DATA "res.x *= .8;"
     
DATA "return res;"
     
DATA "}"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//   Ray marching scene if ray intersect bbox"
     
DATA "//---------------------------------------------------------------------"

     
DATA "vec2 Trace( in vec3 ro, in vec3 rd) {"
     
DATA "vec2 res = vec2(999,0);"
     
DATA "float t = .5;"
     
DATA "for( int i=ZERO; i<128; i++ ) {"
     
DATA "vec2 h = sdMan( ro+rd*t);"
     
DATA "if( abs(h.x)<.0005*t ) {"
     
DATA "res = vec2(t,h.y);"
     
DATA "break;"
     
DATA "}"
     
DATA "t += h.x;"
     
DATA "if (t >= 100.0) break;"
     
DATA "}"
     
DATA "return res;"
     
DATA "}"

     
DATA "//------------------------------------------------------------------------"
     
DATA "// [Shane] - Desert Canyon - https://www.shadertoy.com/view/Xs33Df"
     
DATA "//------------------------------------------------------------------------"
     
DATA "// Tri-Planar blending function. Based on an old Nvidia writeup:"
     
DATA "// GPU Gems 3 - Ryan Geiss: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html"
     
DATA "float tex3D(sampler2D tex, in vec3 p, in vec3 n){"
     
DATA "n = max(n*n, .001);"
     
DATA "n /= (n.x + n.y + n.z );"
     
DATA "return (texture2D(tex, p.yz)*n.x + texture2D(tex, p.zx)*n.y + texture2D(tex, p.xy)*n.z).x;"
     
DATA "}"

     
DATA "// Texture bump mapping. Four tri-planar lookups, or 12 texture lookups in total."
     
DATA "vec3 doBumpMap( sampler2D tex, in vec3 p, in vec3 n, float k){"
     
DATA "const float ep = .001;"
     
DATA "vec3 grad = vec3( tex3D(tex, vec3(p.x-ep, p.y, p.z), n),"
     
DATA "tex3D(tex, vec3(p.x, p.y-ep, p.z), n),"
     
DATA "tex3D(tex, vec3(p.x, p.y, p.z-ep), n));"
     
DATA "grad = (grad - tex3D(tex, p, n))/ep;"
     
DATA "grad -= n*dot(n, grad);"
     
DATA "return normalize(n + grad*k);"
     
DATA "}"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//   Ambiant occlusion"
     
DATA "//---------------------------------------------------------------------"

     
DATA "#ifdef WITH_AO"
     
DATA "float calcAO( in vec3 pos, in vec3 nor ){"
     
DATA "float dd, hr, sca = 1., totao = 0.;"
     
DATA "vec3 aopos;"
     
DATA "for( int aoi=ZERO; aoi<5; aoi++ ) {"
     
DATA "hr = .01 + .05*float(aoi);"
     
DATA "aopos = nor * hr + pos;"
     
DATA "totao += -(sdMan(aopos).x-hr)*sca;"
     
DATA "sca *= .75;"
     
DATA "}"
     
DATA "return clamp(1. - 4.*totao, 0., 1.);"
     
DATA "}"
     
DATA "#endif"

     
DATA "float textureInvader(vec2 uv) {"
     
DATA "float y = 7.-floor((uv.y)*16.+4.);"
     
DATA "if (y<0. || y>7.) return 0.;"
     
DATA "float x = floor((abs(uv.x))*16.),"
     
DATA "v=y>6.5? 6.:y>5.5? 40.:y>4.5? 47.:y>3.5?63.:"
     
DATA "y>2.5? 27.:y>1.5? 15.:y>0.5? 4.:8.;"
     
DATA "return floor(mod(v/pow(2.,x), 2.0)) == 0. ? 0.: 1.;"
     
DATA "}"

     
DATA "vec3 doColor(in vec3 p, in vec3 rd, in vec3 n, in vec2 res){"
     
DATA "// sky dome"
     
DATA "vec3 skyColor =  .5*vec3(.5, .6, .9),"
     
DATA "col = skyColor - max(rd.y,0.)*.5;"

     
DATA "float ss = .5, sp = 0.;"
     
DATA "if (res.y == GROUND) {"
     
DATA "col = .7+ .5 *vec3(texture2D(iChannel0,.1*p.zx).x)+p.y;"
     
DATA "col.r *= .8;"
     
DATA "n = doBumpMap(iChannel0, .1*p, n, .002);"
     
DATA "ss = 0.;"
     
DATA "sp = .3;"
     
DATA "} else"
     
DATA "if (res.y == SHOES1) {"
     
DATA "sp = .1;"
     
DATA "vec3 pFoot = (p-ankle1)*baseFoot1;"
     
DATA "col = mix(vec3(.1,.1,0), vec3(0,0,.1), smoothstep(-.1,-.09,pFoot.z));"
     
DATA "} else if (res.y == SHOES2) {"
     
DATA "col = vec3(0,0,.1);"
     
DATA "sp = .1;"
     
DATA "vec3 pFoot = (p-ankle2)*baseFoot2;"
     
DATA "col = mix(vec3(.1,.1,0), vec3(0,0,.1), smoothstep(-.1,-.09,pFoot.z));"
     
DATA "} else if (res.y == SKIN) {"
     
DATA "col = vec3(222,177,144)/255.;"
     
DATA "ss = 1.;"
     
DATA "sp = .1;"
     
DATA "if (p.x>head.x) {"
     
DATA "// Draw simple face"
     
DATA "vec3 phead = (p - head);"
     
DATA "phead.xz *= rot1;"
     
DATA "vec2 p2 = phead.zy;"
     
DATA "p2.x = abs(p2.x);"
     
DATA "float d = length(p2-vec2(.1,0))-.02;"
     
DATA "d = min(d, max(length(p2-vec2(0.,-.18))-.05, -length(p2-vec2(0.,-.14))+.07));"
     
DATA "col = mix(vec3(0), col, smoothstep(.0,.01,d));"
     
DATA "}"
     
DATA "} else if (res.y == METAL) {"
     
DATA "col = vec3(.8,.9,1.);"
     
DATA "sp = 2.;"
     
DATA "} else if (res.y == SHORT) {"
     
DATA "col = vec3(.35,.7,.85);"
     
DATA "} else if (res.y == BAG) {"
     
DATA "// vec3 ep0 = mix(shoulder1,shoulder2,.5);"
     
DATA "// p.x += .2;"
     
DATA "// p -= ep0;"
     
DATA "col = vec3(.3,.5,.2);"
     
DATA "// nor = doBumpMap(iChannel0, .1*(p*baseBag), nor, .002);"
     
DATA "sp = .1;"
     
DATA "} else if (res.y == SHIRT) {"
     
DATA "col = vec3(.3,.4,.5);"
     
DATA "vec2 p2 = p.zy;"
     
DATA "p2.y -= mix(mix(shoulder2,shoulder1,.5),"
     
DATA "mix(hip2,hip1,.5),.5).y;"
     
DATA "col *= 1.-.5*textureInvader(p2*1.9-vec2(0,.3));"
     
DATA "ss = .2;"
     
DATA "} else if (res.y == BED) {"
     
DATA "col = vec3(1.,.5,.01);"
     
DATA "ss = 1.;"
     
DATA "sp = .3;"
     
DATA "}"
     
DATA "else {"
     
DATA "return col;"
     
DATA "}"
     
DATA "vec2 d = vec2(res.x, res.y);"
     
DATA "vec3 ld = -normalize(vec3(50,100,-100)-p);"
     
DATA "// IQ sss version"
     
DATA "float sss = ss*0.2*clamp(0.5+0.5*dot(ld,n),0.0,1.0)*(2.0+dot(rd,n));"
     
DATA "vec3 r = reflect(rd,n);"
     
DATA "float diff = max(0.,dot(n,ld)),"
     
DATA "amb = dot(n,ld)*.45+.55,"
     
DATA "spec = pow(max(0.,dot(r,ld)),40.),"
     
DATA "fres = pow(abs(.7+dot(rd,n)),3.);"
     
DATA "#ifdef WITH_AO"
     
DATA "float ao = calcAO(p, n);"
     
DATA "#endif"
     
DATA "// lighting"
     
DATA "col = col*mix(1.2*vec3(.25,.08,.13),vec3(.984,.996,.804), mix(amb,diff,.75)) +"
     
DATA "spec*sp+fres*mix(col,vec3(1),.7)*.4;"
     
DATA "// kind of sub surface scatering"
     
DATA "col += sss*vec3(1.,.3,.2);"
     
DATA "// sky light reflected from the ground"
     
DATA "col += max(0.,dot(vec3(0,-1,0), n))*.1*skyColor;"
     
DATA "// ambiant occusion"
     
DATA "#ifdef WITH_AO"
     
DATA "col *= mix(ao,1.,.5);"
     
DATA "#endif"
     
DATA "// fade in distance"
     
DATA "return mix( col, skyColor, smoothstep(30.,100., res.x) );"
     
DATA "}"


     
DATA "//---------------------------------------------------------------------"
     
DATA "//   Calculate normal"
     
DATA "//---------------------------------------------------------------------"
     
DATA "vec3 normal(in vec3 pos, vec3 rd, float t ) {"
     
DATA "vec3 n = vec3(0);"
     
DATA "float a = 0.0, b = 0.0, c = 1.0;"
     
DATA "for (int i = ZERO; i < 4; i++) {"
     
DATA "vec3 e = .5773*(2.*vec3(c, b, a)-1.);"
     
DATA "n += e*sdMan(pos+.002*e).x;"
     
DATA "a = 1.0 - a; if (a == 0.0) b = 1.0 - b; else c = 1.0 - c;"
     
DATA "}"
     
DATA "return normalize(n - max(0., dot(n,rd ))*rd);"
     
DATA "}"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//   Camera"
     
DATA "//---------------------------------------------------------------------"

     
DATA "mat3 setCamera( in vec3 ro, in vec3 ta, in float r) {"
     
DATA "vec3 w = normalize(ta-ro),"
     
DATA "p = vec3(sin(r), cos(r),0.),"
     
DATA "u = normalize( cross(w,p) ),"
     
DATA "v = normalize( cross(u,w) );"
     
DATA "return mat3( u, v, w );"
     
DATA "}"

     
DATA "//---------------------------------------------------------------------"
     
DATA "//   Entry point"
     
DATA "//---------------------------------------------------------------------"
     
DATA "//#define iTime (iTime + 250.) // Direct to big Bone"
     
DATA "void main() {"
     
DATA "gTime = iTime * 6.0;"

     
DATA "vec3 v1 = normalize(wrist1-elbow1),"
     
DATA "v0 = normalize(wrist1-shoulder1),"
     
DATA "v3 = normalize(cross(v1,v0)),"
     
DATA "v2 = cross(v1,v3);"
     
DATA "baseArm1 = mat3(v0,v2,-v3);"

     
DATA "v1 = normalize(wrist2-elbow2),"
     
DATA "v0 = normalize(wrist2-shoulder2),"
     
DATA "v3 = normalize(cross(v1,v0)),"
     
DATA "v2 = cross(v1,v3);"
     
DATA "baseArm2 = mat3(v0,v2,v3);"

     
DATA "v1 = normalize(shoulder1-shoulder2);"
     
DATA "v0 = normalize(mix(hip1,hip2,.5)-mix(shoulder1,shoulder2,.5));"
     
DATA "v2 = normalize(cross(v1,v0));"
     
DATA "v3 = normalize(cross(v1,v2));"
     
DATA "baseBag = mat3(-v2,v3,v1);"

     
DATA "v2 = normalize(knee1 - ankle1);"
     
DATA "v1 = normalize(ankle1 - foot1-v2*.1);"
     
DATA "v3 = cross(v1,v2);"
     
DATA "baseFoot1 = mat3(v1,v3,-cross(v1,v3));"

     
DATA "v2 = normalize(knee2 - ankle2);"
     
DATA "v1 = normalize(ankle2 - foot2-v2*.1);"
     
DATA "v3 = cross(v1,v2);"
     
DATA "baseFoot2 = mat3(v1,v3,-cross(v1,v3));"

     
DATA "// ------------------------------------"

     
DATA "// Screen"
     
DATA "vec2 q = gl_FragCoord.xy/iResolution.xy,"
     
DATA "m = iMouse.xy/iResolution.xy - .5,"
     
DATA "p = -1.+2.*q;"
     
DATA "p.x *= iResolution.x/iResolution.y;"

     
DATA "// Camera"
     
DATA "vec3 ro = vec3( hip1.x+12.*cos(PI*(m.x)),"
     
DATA "3.+5.*(m.y), hip1.z+12.*sin(PI*(m.x)));"
     
DATA "vec3 ta = hip1;"
     
DATA "ta.x +=1.2;"
     
DATA "ta.y = 1.2;"
     
DATA "mat3 ca = setCamera(ro, ta, 0.);"
     
DATA "vec3 rd = ca * normalize(vec3(p.xy,4.5) );"

     
DATA "// Ray intersection with scene"
     
DATA "vec2 res = Trace(ro, rd);"
     
DATA "if (rd.y >= 0.) {"
     
DATA "res = min2(res, vec2(999.,100.));"
     
DATA "} else {"
     
DATA "res = min2(res, vec2(-ro.y / rd.y,GROUND));"
     
DATA "}"

     
DATA "// Rendering"
     
DATA "vec3 pos = ro + rd*res.x;"
     
DATA "vec3 n = pos.y<.02 ? vec3(0,1,0) : normal(pos, rd, res.x);"
     
DATA "vec3 col = doColor(pos, rd, n, res);"
     
DATA "col = pow( col, vec3(.4545) ); // Gamma"
     
DATA "col *= pow(16.*q.x*q.y*(1.-q.x)*(1.-q.y), .1); // Vigneting"

     
DATA "gl_FragColor = vec4(col,1);"
     
DATA "}"
     
DATA ""