From 4c7c2e863b5e423ef0e398c6823e7f91a6e5e144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petri=20J=C3=A4rvisalo?= Date: Thu, 30 May 2024 22:32:17 +0300 Subject: [PATCH] new effect, occulusion etc... softshadows... --- shader.glsl | 350 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 221 insertions(+), 129 deletions(-) diff --git a/shader.glsl b/shader.glsl index 86e31ad..fbd997e 100644 --- a/shader.glsl +++ b/shader.glsl @@ -4,8 +4,13 @@ uniform float u_time; uniform sampler2D texture_sampler; uniform sampler2D texts; +struct Ray { + vec3 rd; + vec3 dir; +}; + mat2 scale(vec2 scale){ - return mat2(scale.x, 0.0, 0.0, scale.y); + return mat2(1. / scale.x, 0.0, 0.0, 1./scale.y); } //////////////////////////////////////////////////////////////// @@ -595,12 +600,6 @@ mat2 Rot(float a) { return mat2(c, -s, s, c); } -vec3 applyFog(in vec3 color, in float distance) { - float fogAmount = 1.0 - exp(-distance * 0.01); - vec3 fogColor = vec3(0.14, 0.13, 0.31); - return mix( color, fogColor, fogAmount ); -} - float opExtrusion( in vec3 p, in float sdf, in float h ) { vec2 w = vec2( sdf, abs(p.z) - h); @@ -617,90 +616,123 @@ float sdCog2d(vec2 pos) { float sdCog(vec3 pos, float angle) { pos.xy *= Rot(angle); - float d1 = opExtrusion(pos, sdCog2d(pos.xy), 0.15); - float d2 = fCapsule(pos - vec3(0.,0., -0.5), vec3(0., 0.0, 0.), vec3(0., 0., 1.), 0.2); - return 0.8 * fOpDifferenceRound(d1,d2,0.1)-0.02;} + float d1 = opExtrusion(pos, sdCog2d(pos.xy), 0.05); + float d2 = fCapsule(pos, vec3(0., 0.0, 0.), vec3(0., 0., 1.), 0.2); + return 0.8 * fOpDifferenceRound(d1,d2,0.05)-0.003;} float sdHex(vec3 pos, float i, float angle) { vec3 po = pos; - //po.xy *= Rot(angle); - - pR(po.yz, PI/2.); - //float d1 = opExtrusion(pos, sdCog2d(pos.xy), 0.01); - float d1 = fHexagonIncircle(po, vec2(0.5+i, .1)); - float d2 = fHexagonIncircle(po, vec2(0.2+i, .05)); - return 0.9 * fOpGroove(d1,d2, 0.2,0.2); + po.xz *= Rot(angle); + po.yz *= Rot(angle); + pR(po.yz, PI/2.); + + float d1 = fHexagonCircumcircle(po, vec2(0.5+i, .1)); + float d2 = fHexagonCircumcircle(po, vec2(0.2+i, .1)); + return fOpDifferenceRound(d1,d2,0.1); + } - -float model(vec3 pos, float angle) { - - float d = 1e10; - - for (float i = 1.; i < 5.; i++) { - vec3 po = pos; - // pos.z += i*.1; - float a = sdHex(po, i*0.2, angle); - - d = min(d,a); - } - - return d; -} // Scene vec2 mapScene(in vec3 p) { + float mat = 0.; float d = 1e10; - float dGround = p.y + 1.5; - d = min(d, dGround); + //float dGround = p.y + 2.5; + //d = min(d, dGround); vec3 po = p; //po.y += sin(u_time); // pMod3(po, vec3(3.)); - - float c1 = model(po, u_time); - d = min(d, c1); - + po.xy *= scale(vec2(1.3, 1.3)); - /*float c2 = sdCog(p+vec3(0.5, -.87, 0.), -u_time); + const float num = 6.; + for (float i = 1.; i <= num; i++) { + // pos.z += i*.1; + float a = sdHex(po,i*0.35, u_time + abs( 2. + 0.4 * sin(u_time)) * i*3.1415/num); + d = min(d,a); + if (d == a) mat = 1. + mod(i,3.); + } + + /*float c2 = sdCog(p, u_time); d = min(d, c2); - - float c3 = sdCog(p+vec3(0.5, .87, 0.), -u_time); - d = min(d, c3); - */ - float mat = 0.; - - if ( d == c1) mat = 1.; - //if ( d == c2) mat = 2.; + if ( d == c2) mat = 4.; +*/ + // float c3 = fBox(p+vec3(0.5, .87, 0.), vec3(1., 1.,1.)); + // d = min(d, c3); + + + + // if ( d == c1) mat = 1.; + //if ( d == c3) mat = 3.; return vec2(d, mat); } -vec3 castRay(vec3 ro, vec3 rd) { +vec3 castRay(vec3 ro, vec3 rd, inout vec3 pos) { float t = 0.0; float mat = 0.; - float count = 0.; - for(int i=0; i < 100; i++) { - vec3 p = ro + rd * t; - vec2 res = mapScene(p); + float hit = 0.; + for(int i=0; i < 150; i++) { + pos = ro + rd * t; + vec2 res = mapScene(pos); t += res.x; mat = res.y; - count = float(i); - if (t > 40. || res.x < abs(0.001*t) ) break; + if (t > 80.) break; + if (res.x < abs(0.001*t) ) { + hit = 1.; + break; + } + } + if (t > 80.) t = -1.0; + return vec3(t, mat, hit); +} + + +vec3 castReflectedRay(vec3 ro, vec3 rd, vec3 pos) { + float t = 0.0; + float mat = 0.; + float hit = 0.; + for(int i=0; i < 50; i++) { + pos = ro + rd * t; + vec2 res = mapScene(pos); + t += res.x; + mat = res.y; + if (t > 40.) break; + if (res.x < abs(0.001*t) ) { + hit = 1.; + break; + } + } if (t > 40.) t = -1.0; - return vec3(t, mat, count); + return vec3(t, mat, hit); +} + +float softshadow( in vec3 ro, in vec3 rd, float mint, float maxt, float w ) +{ + float res = 1.0; + float t = mint; + for( int i=0; i<40; i++ ) + { + if (t > maxt) break; + float h = mapScene(ro + t*rd).x; + res = min( res, h/(w*t) ); + t += clamp(h, 0.005, 0.50); + if( res < -1.0 || t>maxt ) break; + + } + res = max(res,-1.0); + return 0.25*(1.0+res)*(1.0+res)*(2.0-res); } float castShadow(vec3 ro, vec3 rd) { float res = 1.0; float t = 0.001; - for(int i = 0; i < 100; i++) { - vec3 pos = ro + t* rd; - float h = mapScene(pos).x; + for(int i = 0; i < 40; i++) { + float h = mapScene(ro + t* rd).x; res = min(res, 10.0*h/t); if (abs(h) < (0.001*t) ) break; t += h; @@ -722,67 +754,81 @@ vec3 fresnel( vec3 F0, vec3 h, vec3 l ) { return F0 + ( 1.0 - F0 ) * pow( clamp( 1.0 - dot( h, l ), 0.0, 1.0 ), 5.0 ); } -vec3 addPointLight(vec3 light_pos, vec3 light_color, float shininess, vec3 v, vec3 dir, vec3 n) { +// https://suricrasia.online/blog/shader-functions/ +vec3 eRot(vec3 p, vec3 ax, float ro) { + return mix(dot(ax,p)*ax, p, cos(ro)) + sin(ro)*cross(ax,p); +} + + + +vec3 addPointLight(vec3 light_pos, vec3 light_color, float shininess, vec3 v, vec3 dir, vec3 n, float occ) { vec3 Ks = vec3( .5454 ); vec3 Kd = vec3( 1. ); vec3 ref = reflect( dir, n ); vec3 vl = normalize( v ); vec3 diffuse = Kd * vec3( max( 0.0, dot( vl, n ) ) ); vec3 specular = vec3( max( 0.0, dot( vl, ref ) ) ); - vec3 F = fresnel( Ks, normalize( vl - dir ), vl ); - specular = pow( specular, vec3( shininess ) ); - float shadow = castShadow(v + n*0.02, light_pos); + vec3 F = fresnel( Ks, normalize( vl - dir ), vl )*occ; + float shadow = softshadow(v+n*0.01,light_pos, .01, 30., 18.); + //float shadow = castShadow(v + n*0.02, light_pos); + specular = pow( specular, vec3( shininess ) )*occ; + return light_color * mix( diffuse, specular, F ) * shadow; - return light_color * mix( diffuse, specular, F ); } - + +float getAmbientOcc(vec3 p, vec3 n) { + float occ = 0.; + float weight = 1.; + for (int i = 0; i < 8; i++) { + float len = 0.01 + 0.02 * float(i*i); + float dist = mapScene(p+n*len).x; + occ += (len - dist) * weight; + weight *=0.85; + } + return 1.0 - clamp(0.6 * occ, 0., 1.); +} + vec3 shading(vec3 v, vec3 n, vec3 dir, float material) { float shininess = 1.; - vec3 ref = reflect( dir, n ); - vec3 outMaterial = vec3(0.1529, 0.1529, 0.1529); + float occ = getAmbientOcc(v,n); + vec3 outMaterial = vec3(0.1529, 0.1529, 0.1529); if (material == 0.) { - outMaterial = vec3(0.4, 0.2235, 0.3608); + outMaterial = vec3(0.2863, 0.1059, 0.2431); shininess = 1.5; } else if (material == 1.) { - outMaterial = vec3(0.8784, 0.8784, 0.8784); - shininess = 15.; + outMaterial = vec3(0.3294, 0.0941, 0.6); + shininess = 0.6; } else if (material == 2.) { - outMaterial = vec3(0.0431, 0.2118, 0.4588); + outMaterial = vec3(0.5804, 0.9647, 1.0); shininess = 1.; } else if (material == 3.) { - outMaterial = vec3(0.1569, 0.1922, 0.2549); - shininess = 16.; + outMaterial = vec3(0.0, 0.0, 0.0); + shininess = 100.; + } else if (material == 4.) { + outMaterial = vec3(0.9961, 1.0, 0.9922); + shininess = .3; } vec3 lights = vec3(0.); - lights += addPointLight(vec3( 0.,20., 10. ),vec3(0.38, .54, .54)*2., shininess, v, dir, n); - lights += addPointLight(vec3( 2.0, .0, -10.0 ),vec3(0.22, 0.14, 0.57)*3., shininess, v,dir,n ); + lights += addPointLight(vec3( 0., -40., -1. ),vec3(0.56, 0.44, 0.18)*2., shininess, v, dir, n, occ); + lights += addPointLight(vec3( -20.,4., 10. ),vec3(0.04, 0.2, 0.71)*2., shininess, v, dir, n, occ); + // lights += addPointLight(vec3( 2., -1.0, -1.0 ),vec3(0.12, 0.51, 0.63)*2., shininess, v,dir,n,occ ); - vec3 lightDir = vec3(-2. , 3., -1.); + vec3 lightDir = vec3(0. , 4., 2.); float sun_dif = clamp(dot(n, lightDir), 0., 1.); - float shadow = castShadow(v + n*0.02, lightDir); - lights += vec3(0.0863, 0.102, 0.1059) *sun_dif* shadow; //* mix( vec3(sun_dif), specular, F ) + float shadow = softshadow(v+n*0.01,lightDir, .01, 30., 18.); + lights += vec3(0.6627, 0.7098, 0.8863) * sun_dif*shadow*occ; //* shadow; //* mix( vec3(sun_dif), specular, F ) + - { - vec3 lightDir = vec3(0. , .6, -1.); - float sun_dif = clamp(dot(n, lightDir), 0., 1.); - //lights += vec3(0.1804, 0.3686, 0.5451) * sun_dif; - } - - //vec3 col = mix(vec3(0.051, 0.0118, 0.1216), vec3(0.2471, 0.3216, 0.0471), v.y); - //lights += col * fresnel(vec3(.5),dir, n); // final += texture( iChannel0, ref ).rgb * fresnel( Ks, n, -dir ); // vec3 col = vec3(0.4)* ref.x; - // vec3 col = vec3(0.0588, 0.0588, 0.1216);// - vec3(0.149, 0.0863, 0.2314) * v.x; - // lights += col * fresnel( vec3(.5), ref, -dir ); + float ind = clamp( dot( n, normalize(lightDir*vec3(-1.0,.0,-1.0)) ), 0.0, 1.0 ); + lights += vec3(0.1333, 0.1333, 0.1216) * ind *occ; - //float ind = clamp( dot( n, normalize(lightDir*vec3(-1.0,.0,-1.0)) ), 0.0, 1.0 ); - //lights += vec3(0.2196, 0.2196, 0.2196) * ind; - - return outMaterial * lights; + return outMaterial * max(vec3(0.), lights); } vec3 postProcess(vec3 col) { @@ -794,17 +840,17 @@ vec3 postProcess(vec3 col) { vec2 screenCoord = gl_FragCoord.xy/u_resolution.xy; // Vignette - float radius = 0.9; + float radius = 0.8; float d = smoothstep(radius, radius-0.4, length(screenCoord-vec2(0.5))); - col = mix(col, col * d, 0.6); + col = mix(col, col * d, .9); // Contrast - float constrast = .3; + float constrast = .5; col = mix(col, smoothstep(0.0, 1.0, col), constrast); // Colour mapping - col *= vec3(0.9412, 0.8392, 1.0); + col *= vec3(1.0, 1.0, 1.0); col = pow( col, vec3(1.0/2.2) ); // gamma @@ -820,78 +866,124 @@ vec3 postProcess(vec3 col) { vec3 getCameraRayDir(vec2 uv, vec3 camPos, vec3 camTarget) { // Calculate camera's "orthonormal basis", i.e. its transform matrix components - vec3 camForward = normalize(camTarget - camPos); - vec3 camRight = normalize(cross(vec3(0.0, 1.0, 0.0), camForward)); + vec3 camForward = normalize(camTarget-camPos ); + vec3 camRight = normalize(cross(vec3(.0, 1.0, 0.0), camForward)); vec3 camUp = normalize(cross(camForward, camRight)); - float fov = 1.1; + float fov = 0.7; vec3 vDir = normalize(uv.x * camRight + uv.y * camUp + camForward * fov); return vDir; } -vec3 getCameraFov(vec2 uv, vec3 camPos,vec3 camTarget) { +vec3 getCameraRayDir2(vec2 uv, vec3 camPos, vec3 lookAt, float zoom){ + vec3 f = normalize(lookAt - camPos); + vec3 r = cross(vec3(0.0,1.0,0.0),f); + vec3 u = cross(f,r); + vec3 c=camPos+f*zoom; + vec3 i=c+uv.x*r+uv.y*u; + return normalize(i-camPos); +} + +vec3 getCameraFov(vec2 uv, vec3 camPos, vec3 camTarget) { vec3 camForward = normalize(camTarget-camPos); vec3 camRight = normalize(cross(vec3(0.0, 1.0, 0.0), camForward)); vec3 camUp = normalize(cross(camForward,camRight)); - float fov = 1.1; + float fov = 1.7; // Depth of field - float dof = .1; - vec2 h = vec2( noise(gl_FragCoord.xy, .11), noise(gl_FragCoord.xy, .4)); + float dof = .25; + vec2 h = vec2( noise(gl_FragCoord.xy, .13), noise(gl_FragCoord.xy, .4)); //vec3 h= rnd23(gl_FragCoord.xy); vec3 voff = sqrt(h.x)*(camRight*sin(h.y*6.283)+camUp*cos(h.y*6.283))*dof; - camTarget -=voff; - float focusdistance = 40.2; + // camTarget -=voff; + float focusdistance = 150.2; return normalize(uv.x * camRight + uv.y * camUp + fov * camForward + voff * fov/focusdistance); } -vec3 getSceneColor(vec2 fragCoord) { - +vec3 applyFog(vec3 col, float t, vec3 rd, vec3 lightDir, float b ) { + float fogAmount = 1.0 - exp(-t*b); + float sunAmount = max( dot(rd, lightDir), 0.0 ); + vec3 fogColor = mix( vec3(0.3686, 0.2431, 0.4392), // blue + vec3(0.4, 0.7294, 0.9216), // yellow + pow(sunAmount,8.0) ); + return mix( col, fogColor, fogAmount ); +} + +vec3 render(vec2 uv) { + bool useDof = !true; - //vec2 uv = (2.0 * gl_FragCoord.xy - u_resolution.xy) / u_resolution.y; - vec2 uv = 2.0 * (fragCoord.xy/u_resolution.xy - 0.5); - uv.x *= u_resolution.x/u_resolution.y; // Correct for aspect ratio + //vec2 uv = (2.0 * gl_FragCoord.xy - u_resolution.xy) / u_resolution.y; float angle = -2.4 +u_time*0.4; //angle = 0.; // camera - vec3 camPos = vec3(2.*sin(angle), 1.,-2.*cos(angle)); - vec3 camTarget = vec3(0., 0.0, 0.); - vec3 rayDir; + vec3 camPos = vec3(0., 3., -4.); + vec3 camTarget = vec3(0., 0., 0.); + vec3 rayDir; + if (useDof) { rayDir = getCameraFov(uv, camPos, camTarget); } else { - rayDir = getCameraRayDir(uv, camPos, camTarget); - } - - vec3 col = mix(vec3(0.0824, 0.0275, 0.1882), vec3(0.2471, 0.3216, 0.0471), rayDir.y); + rayDir = getCameraRayDir2(uv, camPos, camTarget, 1.0); + } + vec3 col = vec3(0.051, 0.0667, 0.1529); //vec3 col = vec3(0.0314, 0.0118, 0.1255) + rayDir.y * 0.4; - vec3 t = castRay(camPos, rayDir); + vec3 hitPos = vec3(0.); + + vec3 t = castRay(camPos, rayDir, hitPos); + vec3 rd = rayDir; + + if (t.z > 0.) { + vec3 nor = calcNormal(hitPos); + col = shading(hitPos, nor, rayDir , t.y); + float fogAmount = 0.04; + col = col*exp(-t.x*fogAmount) + applyFog(col, t.x, rd, vec3(0., .3, -1.), fogAmount) * (1.0-exp(-t.x*fogAmount)); + + rayDir = normalize(reflect(rayDir, nor)); + vec3 rayOrigin = hitPos + (rayDir * 0.01); + vec3 t2 = castReflectedRay(rayOrigin, rayDir, hitPos); - vec3 pos = camPos + rayDir * t.x; - if (t.x > 0.) { - vec3 nor = calcNormal(pos); - col = shading(pos, nor, rayDir , t.y); - // apply fog - col = applyFog(col, t.x); + if (t2.z > 0.) { + hitPos = rayOrigin + rayDir * t2.x; + nor = calcNormal(hitPos); + col += 0.1 * shading(hitPos, nor, rayDir , t2.y); + + /* rayDir = normalize(reflect(rayDir, nor)); + rayOrigin = hitPos + (rayDir * 0.01); + vec3 t3 = castReflectedRay(rayOrigin, rayDir, hitPos); + + if (t3.z > 0.) { + hitPos = rayOrigin + rayDir * t3.x; + nor = calcNormal(hitPos); + col += 0.025 * shading(hitPos, nor, rayDir , t3.y); + } */ + } } + // pixelColor*exp(-distance*b) + fogColor*(1.0-exp(-distance*b)); return col; } +vec2 getUV(vec2 offset) { + vec2 uv = 2.0 *((gl_FragCoord.xy + offset*0.5)/u_resolution.xy - 0.5); + uv.x *= u_resolution.x/u_resolution.y; // Correct for aspect ratio + return uv; +} void main() { - vec2 uv = gl_FragCoord.xy; + vec3 finalColor = vec3(0.); - const float AA_SIZE = 4.; + const float AA_SIZE = 1.; float count = 0.0; +/* for (float aaY = 0.0; aaY < AA_SIZE; aaY++) { - for (float aaX = 0.0; aaX < AA_SIZE; aaX++) { - finalColor += getSceneColor(uv + vec2(aaX, aaY) / AA_SIZE); + for (float aaX = 0.0; aaX < AA_SIZE; aaX++) { + finalColor += render(getUV(vec2( aaX, aaY))); count += 1.0; } - } - finalColor /= count; + } + finalColor /= count; */ + finalColor += render(getUV(vec2( 0.,0.))); finalColor = postProcess(finalColor);