http://glsl.heroku.com/e#19378.0

precision highp float;
uniform vec2 resolution;
uniform float time;
uniform vec2 mouse;

float hash11(float p) {
    return fract(sin(p)*45768.23);
}

float hash21(vec2 p) {
    return fract(sin(p.x * 15.23 + p.y * 32.12) * 45768.23);
}

float hash31(vec3 p) {
    return fract(sin(p.x *15.23 + p.y * 35.87 + p.z * 75.53) * 45768.23);
}

vec2 hash22(vec2 p) {
    mat2 m = mat2(15.23, 32.12, 71.23, 152.31);
    return fract(sin(m*p)*45768.23);
}

vec3 hash33(vec3 p) {
    mat3 m = mat3(15.23, 35.11, 70.24, 151.22, 301.11 , 612.23, 1345.17, 2678.98, 5371.13);
    return fract(sin(m*p)*45768.23);
}

float value_noise(vec3 p) {
    vec3 g = floor(p);
    vec3 f = fract(p);
    float fbl = hash31(g + vec3(0.0, 0.0, 0.0));
    float fbr = hash31(g + vec3(1.0, 0.0, 0.0));
    float ftl = hash31(g + vec3(0.0, 1.0, 0.0));
    float ftr = hash31(g + vec3(1.0, 1.0, 0.0));
    float bbl = hash31(g + vec3(0.0, 0.0, 1.0));
    float bbr = hash31(g + vec3(1.0, 0.0, 1.0));
    float btl = hash31(g + vec3(0.0, 1.0, 1.0));
    float btr = hash31(g + vec3(1.0, 1.0, 1.0));
    
    float fb = mix(fbl, fbr, f.x);
    float ft = mix(ftl, ftr, f.x);
    float fres = mix(fb, ft, f.y);
    float bb = mix(bbl, bbr, f.x);
    float bt = mix(btl, btr, f.x);
    float bres = mix(bb, bt, f.y);
    
    float res = mix(fres, bres, f.z);
    return res;
}

float sdPlane(in vec3 p) {
    return p.y + value_noise(p);
    // return p.y;
}

float sdSphere(in vec3 p, in float r) {
    return length(p) - r;
}

float map(in vec3 p) {
    float d = sdPlane(p);
    d = min(d, sdSphere(p - vec3(0.0, 0.25, 0.0), 0.25)); // find surface compare 
    return d;
}

vec3 calcNormal(in vec3 p) {
    // calculate all surface`s normal
    vec3 e = vec3(0.001, 0.0, 0.0);
    vec3 nor = vec3(
        map(p + e.xyy) - map(p - e.xyy),
        map(p + e.yxy) - map(p - e.yxy),
        map(p + e.yyx) - map(p - e.yyx)
    );
    return normalize(nor);
}

float castRay(in vec3 cameraPosition, in vec3 renderVector, in float maxt) {
    // find surface
    float precis = 0.001;
    float h = precis * 2.0;
    float t = 0.0;
    for(int i = 0; i < 60; i++) {
        if(abs(h) < precis || t > maxt) continue;
        h = map(cameraPosition + renderVector * t);
        t += h;
    }
    return t;
}

float softshadow(in vec3 cameraPosition, in vec3 renderVector, in float mint, in float maxt, in float k) {
    float sh = 1.0;
    float t = mint;
    float h = 0.0;
    for(int i = 0; i < 30; i++) {
        if(t > maxt) continue;
        h = map(cameraPosition + renderVector * t);
        sh = min(sh, k * h / t);
        t += h;
    }
    return sh;
}

vec3 render(in vec3 cameraPosition, in vec3 renderVector) {
    vec3 col = vec3(1.0);
    float distanceFromCamera = castRay(cameraPosition, renderVector, 20.0); // distance camera to target
    vec3 pos = cameraPosition + renderVector * distanceFromCamera; //surface`s point?
    vec3 nor = calcNormal(pos); // calculate all surface`s normal
    vec3 lig = normalize(vec3(-0.4, 0.7, 0.5)); // light`s vector
    float dif = clamp(dot(lig, nor), 0.0, 1.0); // light`s strenght -> color
    float spec = pow(clamp(dot(reflect(renderVector, nor), lig), 0.0, 1.0), 16.0);
    float sh = softshadow(pos, lig, 0.02, 20.0, 7.0);
    col = col * (dif + spec) * sh;
    return col;
}

void main() {
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    vec2 p = uv * 2.0 - 1.0;
    p.x *= resolution.x / resolution.y;
    // vec3 cameraPosition = vec3(1.0, 1.0, 3.0); //camera ray origin
    vec3 cameraPosition = vec3( mouse.x*4.0, 1.0, 3.0); //camera ray origin
    vec3 targetOrigin = vec3(0.0, 0.0, 0.0); //target
    vec3 eyeToTarget = normalize(targetOrigin - cameraPosition); //eye to target vector
    vec3 upVector = vec3(0.0, 1.0, 0.0); //up vector
    vec3 targetUpVector = normalize(cross(eyeToTarget, upVector)); // target`s right coorenderVector 
    vec3 targetRightVector = normalize(cross(targetUpVector, eyeToTarget)); // target`s up coorenderVector  
    vec3 renderVector = normalize(p.x * targetUpVector + p.y * targetRightVector + mouse.y*2.5 * eyeToTarget); //viewer`s vector
    vec3 col = render(cameraPosition, renderVector);
    
    gl_FragColor = vec4(col, 1.0);
}
Tags : #shader