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); }