Josip Å tajdohar

Raymarched walking animation:


                uniform sampler2D tDiffuse;
                uniform float iTime;
                uniform vec2 iResolution;
                uniform vec2 iMouse;
                varying vec2 sv;
                
                //https://www.xvideos.com/video52507323/great_ass_walking
                // Good reference video for a walking ass, shaking of the ass while walking
                #define MAX_STEPS 200; //Dosnt work, rewrite manualy
                #define SURFACE_DIST 0.0001;
                #define MAX_DIST 5.0;
                #define MIN_DIST 0.2;
                #define pi acos(-1.)
                #define TAU 2.0 * pi
                #define time  5.5 * iTime
                #define s1 sin(time)
                #define s2 sin(time + pi)
                #define c1 cos(time)
                
                #define walking1 sign(s1)* pow(abs(s1), 0.6)
                #define walking2 sign(s2)* pow(abs(s2), 0.6)
                #define floorTime floor(0.5 + time/pi)
                #define walking3 (2.0 * floorTime + sign(c1)*sign(s1)*abs(s1))
                #define shakeCount 15.5
                #define shakeFrec 0.5
                #define shakePartLeft (pi + shakeCount * fract(shakeFrec * time/pi + 0.5*pi)) //pi + ???
                #define shakePartRight (pi + shakeCount * fract(shakeFrec * time/pi + pi))
                #define shakingStabilityLeft (0.5 * sign(c1)*pow(abs(c1), 0.1) + 0.5)
                #define shakingStabilityRight (0.5 * sign(s1)*pow(abs(s1), 0.1) + 0.5)
                #define shakefuncLeft sin(shakePartLeft)/shakePartLeft// * shakingStabilityLeft
                #define shakefuncRight sin(shakePartRight)/shakePartRight
                
                #define skinCol1 vec3(232.0,204.0,185.0) / 255.0
                #define skinCol2 vec3(238.0, 195.0, 186.0) / 255.0
                #define skinCol3 vec3(212.0, 174.0, 146.0) / 255.0
                #define skinCol4 vec3(175.0, 133.0, 105.0) / 255.0
                
                #define subsurface_scale 1.4
                #define subsurface_frequency 800.2
                
                #define skin_scale 0.3
                #define skin_frequency 580.0
                
                #define base_skin_amt .83
                
                #define subsurface_color1 vec3(0.639, 0.058, 0)
                #define subsurface_color2 vec3(0.400, 0.168, 0.05)
                #define subsurface_color3 vec3(0.556, 0.118, 0.12)
                #define subsurface_color4 vec3(0.639, 0.058, 0.25)
                #define subsurface_color5 vec3(0.639, 0.058, 0.25)
                
                #define surface_col 0.9 * vec3(1.0, 1.0, 1.0)
                #define base_skin_color mix(skinCol2, skinCol4, 0.5)
                
                vec2 hash( vec2 p ) // replace this by something better
                {
                    p = vec2( dot(p,vec2(127.1,311.7)),
                              dot(p,vec2(269.5,183.3)) );
                
                    return -1.0 + 2.0*fract(sin(p)*43758.5453123);
                }
                
                float hash13(vec3 p)
                {
                    p = fract(p * vec3(3.131, 5.411, 4.321));
                    p += dot(p.yzx, p + 51.23);
                    return fract(p.x*p.y*p.z);
                }
                
                vec3 hash33(vec3 p)
                {
                    p = fract(p * vec3(3.131, 5.411, 4.321));
                    p.xy += dot(p.yzx, p + 51.23);
                    p.z = dot(p.xy, vec2(2.13, 5.21));
                    return fract(p*p);
                }
                
                float noise( in vec2 p )
                {
                    const float K1 = 0.366025404; // (sqrt(3)-1)/2;
                    const float K2 = 0.211324865; // (3-sqrt(3))/6;
                
                    vec2 i = floor( p + (p.x+p.y)*K1 );
                    
                    vec2 a = p - i + (i.x+i.y)*K2;
                    vec2 o = step(a.yx,a.xy);    
                    vec2 b = a - o + K2;
                    vec2 c = a - 1.0 + 2.0*K2;
                
                    vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
                
                    vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
                
                    return dot( n, vec3(70.0) );
                    
                }
                
                float n_noise(in vec2 p)
                {
                    return 0.5 + 0.5 * noise(p);
                }
                
                mat2 Rot(float a)
                {
                  float s = sin(a);
                  float c = cos(a);
                  return mat2(c, -s, s, c);
                }
                
                float smoothAbs( float x, float n )
                {
                  return sqrt(x*x+n);
                }
                
                float sdSphere( vec3 p, float s )
                {
                   return length(p)-s;
                }
                
                float sdFold(vec2 p, vec2 a, vec2 b)
                {
                    vec2 pa = p-a, ba = b-a;
                    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
                    return length( pa - ba * h );
                }
                
                float sdEllipsoid( vec3 p, vec3 r )
                {
                  float k0 = length(p/r);
                  float k1 = length(p/(r*r));
                  return k0*(k0-1.0)/k1;
                }
                
                float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
                {
                  vec3 pa = p - a, ba = b - a;
                  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
                  return length( pa - ba*h ) - r;
                }
                
                
                float smoothMin( float d1, float d2, float k ) 
                {
                    float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
                    return mix( d2, d1, h ) - k*h*(1.0-h); 
                }
                
                // float sinc( float x, float k )
                // {
                //     float a = pi*((k*x-1.0);
                //     return sin(a)/a;
                // }
                
                ///sign(sin(x)) * pow(abs(sin(x)), 0.3)
                float map( in vec3 pos)
                {
                    //x mirroring coord
                    vec3 posAbsX = pos;
                    posAbsX.x = smoothAbs(posAbsX.x, 0.0001);
                
                    float walkingPosLeft = 0.1 + walking1;
                    float walkingPosRight = 0.1 + walking2;
                
                    // ass
                    float assMod = 1.15 + 0.15 * smoothstep(-0.0, -0.25, posAbsX.y);
                    vec3 assSizeMod =  vec3(assMod,1.0,assMod);
                    vec3 assSizeModLeft = assSizeMod * (1.0 + 0.05 * walkingPosLeft);
                    vec3 assSizeModRight = assSizeMod* (1.0 + 0.05 * walkingPosRight);
                
                    float shakeAmp = 0.12 * smoothstep(0.15, -0.15, posAbsX.y);
                    float assOffsetLeft = 0.12 - shakeAmp * shakefuncLeft;//sin(shakePart)/shakePart;// + 0.0 *  shakePart; 
                    vec3 assCenLeft = vec3(assOffsetLeft, 0.0, -0.07);
                    vec3 assDimLeft = assSizeModLeft * vec3(0.15, 0.25, 0.2);
                    float assLeft = sdEllipsoid(pos - assCenLeft, assDimLeft);
                
                    float assOffsetRight = 0.12 - shakeAmp * shakefuncRight;
                    vec3 assCenRight = vec3(-assOffsetRight, 0.0, -0.07);
                    vec3 assDimRight = assSizeModRight * vec3(0.15, 0.25, 0.2);
                    float assRight = sdEllipsoid(pos - assCenRight, assDimRight);
                
                    float ass = smoothMin(assLeft, assRight, 0.01);
                
                    // back
                    vec3 backCen = vec3(0.08, 0.0, 0.0);
                    vec3 backA = vec3(0.0, 0.0, 0.0);
                    vec3 backB = vec3(0.0, 0.8, 0.0);
                    float backThickness = 0.15 + 0.24 * smoothstep(0.3, 1.5, posAbsX.y);
                    float back = sdCapsule(posAbsX - backCen, backA, backB, backThickness);
                
                    // belley
                
                    vec3 belleyCen = vec3(0.0, 0.35, 0.05);
                    vec3 belleyDim = vec3(0.14, 0.25, 0.1);
                    float belley = sdEllipsoid(pos - belleyCen, belleyDim);
                    back = smoothMin(back, belley, 0.08);
                
                    // legs
                    vec3 leftLegCen = vec3(-0.16, 0.0, 0.0);
                    vec3 rightLegCen = vec3(0.16, 0.0, 0.0);
                
                    float legOffsetAmp = 0.3;
                    float moveLegLeft = legOffsetAmp * walkingPosLeft;
                    float moveLegRight = legOffsetAmp * walkingPosRight;
                
                    vec3 legLeftA = vec3(0.0, -0.1, 0.0);
                    vec3 legLeftB = vec3(0.0, -0.8, moveLegLeft);
                
                    vec3 legRightA = vec3(0.0, -0.1, 0.0);
                    vec3 legRightB = vec3(0.0, -0.8, moveLegRight);
                
                    float legThickness = 0.125 + 0.04 * smoothstep(-0.6, -0.25 , posAbsX.y) + 0.00 * smoothstep(-0.3, -0.1, posAbsX.y) * smoothstep(0.18, .8, posAbsX.x);
                
                    float leftLeg = sdCapsule(pos - leftLegCen, legLeftA, legLeftB, legThickness);
                    float rightLeg = sdCapsule(pos - rightLegCen, legRightA, legRightB, legThickness);
                
                    float legs = min(leftLeg, rightLeg);
                    
                    return smoothMin(smoothMin(ass, back, 0.08), legs, 0.08);
                }
                
                // --- analytically box-filtered checkerboard ---
                float checkersTextureGradBox( in vec2 p, in vec2 ddx, in vec2 ddy, float f)
                {
                    p *= f;
                    // filter kernel
                    vec2 w = max(abs(ddx), abs(ddy)) + 0.1;  
                    // analytical integral (box filter)
                    vec2 i = 2.0*(abs(fract((p-0.5*w)/2.0)-0.5)-abs(fract((p+0.5*w)/2.0)-0.5))/w;
                    // xor pattern
                    return 0.5 - 0.5*i.x*i.y;                  
                }
                
                //https://www.shadertoy.com/view/XlcSz2
                // --- unfiltered checkerboard ---
                float checkersTexture( in vec2 p , float f)
                {
                    vec2 q = floor(p * f);
                    return mod( q.x+q.y, 2.0 );            // xor pattern
                }
                
                vec2 texCoords( in vec3 pos)
                {
                    vec4 sc0 = vec4( 0.0, 0.0, 0.0, 1.0);
                    vec3 q = normalize( pos - sc0.xyz);
                    return vec2( atan(q.x,q.z), acos(q.y )) * sc0.w;
                }
                
                vec2 texCoords2(in vec3 pos)
                {
                   return vec2(pos.x, pos.y);
                }
                
                vec3 SkinCol(vec2 uv)
                {
                    float subsurface_radius = subsurface_scale / 2.0;
                  
                    float subsurface_distance = n_noise(uv * subsurface_frequency);
                    float subsurface = 1.0 - min(1.0, subsurface_distance / subsurface_radius);
                    
                    float skin_value = n_noise(uv * skin_frequency) * skin_scale;
                
                    vec3 col = subsurface_color5 * subsurface;
                    col = mix(col, base_skin_color, base_skin_amt);    
                    col  = mix(col, surface_col, skin_value);
                    // float subsurface_radious = subsurface_scale * 0.5;
                    // vec3 col = vec3(1.0);
                    return col;
                }
                
                vec3 DebugUV(vec2 uv)
                {
                    vec3 col = vec3(uv.x,uv.y, 0.0);
                    //col = vec3(0.5);
                    if((uv.x < 0.05 && uv.x > -0.05) || (uv.x > 0.95 && uv.x < 1.05) || (uv.y < 0.05 && uv.y > -0.05) || (uv.y > 0.95 && uv.y < 1.05))
                    {
                        col = vec3(1,1,1);
                    }
                    return col;
                }
                
                float hair(vec3 p, vec3 i, float t)
                {
                    float h = hash13(i);
                    float dir = dot(p , hash33(i) * 2. - 1.);
                    return sin(dir * (5. + sin(h * 431.52) * 3.) + t);
                }
                
                const vec2 o = vec2(1.,0.);
                
                float hairNoise(vec3 p, float t)
                {
                    vec3 i = floor(p);
                    vec3 f = smoothstep(0.,1.,p-i);
                    return 
                        mix(
                            mix(
                                mix(hair(p,i,t),hair(p,i+o.xyy,t),f.x),
                                mix(hair(p,i+o.yxy,t),hair(p,i+o.xxy,t),f.x),
                                f.y),
                            mix(
                                mix(hair(p,i+o.yyx,t),hair(p,i+o.xyx,t),f.x),
                                mix(hair(p,i+o.yxx,t),hair(p,i+o.xxx,t),f.x),
                                f.y),
                            f.z);
                }
                
                float fbmCarpet(vec3 p, float t)
                {
                    float res = 0.;
                    float noiseMod = 0.0;
                    for (float i = 1.; i < 3.; i += 1.0)
                    {
                        noiseMod += i;
                        res += hairNoise(p*noiseMod,t*noiseMod) / noiseMod;
                    }
                    return res * .25 + .5;
                }
                
                vec3 GroundCol(vec2 uv)
                {
                    //uv.x -= 3.2 * sv.y;
                    vec3 p = vec3(uv * 8., .125);  
                
                    float noise = fbmCarpet(p,  .5);
                    
                    vec3 col = mix(vec3(0.01), vec3(.3, .2, .5), noise);
                    
                    //col = DebugUV(uv);
                    return col;
                }
                
                //https://www.shadertoy.com/view/MdlXz8
                vec3 WallCol(vec2 uv)
                {
                    vec2 p = mod(uv*TAU, TAU)-250.0;
                    vec2 i = vec2(p);
                    float c = 1.0;
                    float inten = .005;
                
                    for (int n = 0; n < 5; n++) 
                    {
                        float t = 0.05 * time * (1.0 - (3.5 / float(n+1)));
                        i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
                        c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
                    }
                    c /= 5.0;
                    c = 1.17-pow(c, 1.4);
                    vec3 col = vec3(pow(abs(c), 8.0));
                    col = clamp(col + vec3(0.0, 0.35, 0.5), 0.0, 1.0);
                    return col;
                }
                
                vec3 BackgroundCol(vec2 uv)
                {
                    uv.xy += vec2(1.25,-0.2); 
                    uv.y /= 0.6 * pow(abs(uv.x), mix(0.45, 2.35, step(uv.x,0.0)));
                    uv.x /= mix(0.6, 0.5, step(uv.x,0.0)) * pow(abs(uv.x), 0.45);
                
                    vec2 sv = uv;
                    
                    vec2 groundUV = uv;
                    groundUV *= 10.;
                    //TODO: solve singularity on the ground. aspect ratio 10 : 2
                    groundUV.x -= mix(5.2, -2.2, step(groundUV.x, 0.0)) * sv.y;
                    groundUV.x -= sign(groundUV.x) * 0.5 * walking3;
                
                    uv *= 10.;
                    uv.x -= sign(uv.x) * 0.5 * walking3;
                
                    vec3 col = WallCol( 0.1 * uv);
                    vec3 groundCol = GroundCol(groundUV);
                    col = mix(col, groundCol, step(sv.y, -0.8));
                
                    return col;
                }
                
                float castRay( in vec3 ro, in vec3 rd)
                {
                    float tmin = MIN_DIST;
                    float tmax = MAX_DIST;
                    float surfDistMin = SURFACE_DIST;
                    
                    float t = tmin;
                    for( int i=0; i<100; i++ )
                    {
                        float h = map( ro+rd*t);
                        //abs increases stability non euklidian mapping after the reymarch steps into
                        //the sdf. the "* t" increases the mistake for farther objects.
                        if( abs(h)<surfDistMin * t  && t<tmax ) break;
                        t += 0.99 * h;
                    }
                    
                    return t;
                }
                
                
                vec3 calcNormal( in vec3 pos)
                {
                    vec2 e = vec2(0.0005,0.0);
                    return normalize( vec3( 
                        map( pos + e.xyy) - map( pos - e.xyy),
                        map( pos + e.yxy) - map( pos - e.yxy),
                        map( pos + e.yyx) - map( pos - e.yyx) ) );
                }
                
                float getLight(vec3 pos, vec3 lightPos)
                {
                    vec3 lightDir = normalize(lightPos - pos);
                    vec3 normal = calcNormal(pos);
                    float diffuseLight = clamp(dot(normal, lightDir), 0. , 1.);
                    
                    float surfDistMin = SURFACE_DIST;
                    //shadows
                    //raymarch to light pos if hit its shadow
                    float distToHit = castRay(pos + normal * surfDistMin, lightDir);
                    //if distToHit less then lightPos - pos then dif *= 0.1;
                    diffuseLight = mix(diffuseLight, 0.5 * diffuseLight, step(distToHit, length(lightPos - pos)));
                    return  diffuseLight;
                }
                
                //Returns the RayDirection for a pixel given the ray origin, the look at vector and a zoom factor.
                vec3 cameraRayDirection(vec2 uv, vec3 rayOrigin, vec3 lookAt, float zoom)
                {
                    vec3 forwardDir = normalize(lookAt - rayOrigin);
                    vec3 rightDir = normalize(cross(vec3(0, 1, 0), forwardDir));
                    vec3 upDir = cross(forwardDir, rightDir);
                    vec3 centerOfScreen = rayOrigin + forwardDir * zoom;
                    vec3 intersectionOfScreen = centerOfScreen + uv.x * rightDir + uv.y * upDir;
                    
                    return intersectionOfScreen - rayOrigin;
                }
                
                vec3 render(vec2 uv)
                {
                    vec3 rayOrigin = normalize(vec3(-1.4, -0.6, -2.5));
                    //rayOrigin = normalize(vec3(-1.0, - 1.0, -2.5));
                    //rayOrigin = normalize(vec3(0.0, 0.0, -1.0)); //look from back
                    // rayOrigin.yz *= Rot( -iMouse.y * pi + 1.0);
                    // rayOrigin.xz *= Rot( -iMouse.x * 2.0 * pi + pi); 
                    vec3 lookAt = vec3(0, 0, 0);
                    vec3 lightPos = vec3(-5.0, 6.0, -5.0);
                    
                    vec3 rayDirection = cameraRayDirection(uv, rayOrigin, lookAt, 1.);
                    
                    float dist = castRay(rayOrigin, rayDirection);
                    vec3 pos = rayOrigin + rayDirection * dist;
                
                    float light = getLight(pos, lightPos);
                
                    vec2 uvw = texCoords2(pos);
                    vec3 foldCol = vec3(0.1, 0.1, 0.1);
                    vec3 skinColor = SkinCol(uvw);
                    float fold = max(sdFold(pos.zy, vec2(-0.0, -0.0), vec2(-1.0, -0.9)), sdSphere(pos+vec3(0.0,0.2,0.2), 0.2));
                    float foldFact = step(fold, 0.003);
                
                    vec3 lightCol = light * skinColor;
                    float maxDist = MAX_DIST;
                    //dist negative for to far fields
                  
                    vec3 background = BackgroundCol(uv);
                
                    vec3 finalCol = mix(lightCol, background, step(maxDist, dist));;
                    return finalCol;
                }
                
                void main()
                {
                    // Normalized pixel coordinates (from 0 to 1)
                    vec2 uv = (sv - 0.5) * iResolution.xy / iResolution.y;
                    vec2 uvVig = sv;
                    // Time varying pixel color
                    vec3 col = render(uv);
                    uvVig.xy *= 1.0 - uvVig.yx;
                    float vig = uvVig.x*uvVig.y * 15.0; // multiply with sth for intensity    
                    vig = pow(vig, 0.25); // change pow for modifying the extend of the  vignette
                    
                    gl_FragColor = vec4(col * vig ,1.0);
                }