Created
May 11, 2022 05:34
-
-
Save antoineMoPa/2fc2d61cd7dcef182ff4e8bd735f6a4b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #version 300 es | |
| #define PI 3.14159265359 | |
| #define PI2 6.28318530718 | |
| precision highp float; | |
| uniform float time; | |
| uniform float iGlobalTime; | |
| in vec2 UV; | |
| out vec4 out_color; | |
| uniform vec3 iResolution; | |
| #define FACE_MATERIAL 0 | |
| #define HAT_MATERIAL 1 | |
| #define EYE_MATERIAL 2 | |
| vec2 hat1(vec3 pos){ | |
| pos.xyz -= vec3(0.0,0.15,0.0); | |
| if (pos.y < -0.7) { | |
| return vec2(1e10, float(HAT_MATERIAL)); | |
| } | |
| pos.y += 0.02 * cos(pos.x * 10.0); | |
| pos.y += 0.04 * cos(pos.x * 2.0); | |
| pos.xz *= 1.0 - 0.7 * (-pos.y - 0.0); | |
| float f = length(pos.xz) - 0.3; | |
| float verticalConstraint = abs(pos.y + 0.10) - 0.18; | |
| f = max(f, verticalConstraint); | |
| return vec2(f, float(HAT_MATERIAL)); | |
| } | |
| vec2 hat2(vec3 pos){ | |
| pos.xyz -= vec3(0.0,-0.3,0.0); | |
| pos.y += 0.01 * cos(pos.x * 10.0); | |
| pos.y += 0.5 * cos(pos.x * 2.4) * pos.y; | |
| float r = length(pos.xz); | |
| float f = max(r - 0.7, 0.0); | |
| pos.y -= 0.5 * pow(1.1 * r, 2.0) + 0.4 * (2.0 * pow(1.0 - clamp(r, 0.3, 1.0), 5.0)); | |
| float verticalConstraint = max(abs(pos.y) - 0.003, 0.0); | |
| f = max(f, verticalConstraint); | |
| return vec2(f, HAT_MATERIAL); | |
| } | |
| void hat_Material(inout vec4 col, vec3 p, float AOLight, vec3 r, float t) { | |
| vec4 hat = vec4(0.0); | |
| // Fog function | |
| hat.rgb = 0.7 * vec3(0.25,0.13,0.04); | |
| hat.rgb *= 0.6; | |
| col = hat; | |
| col *= 0.2 + AOLight * 1.0; | |
| col.a += 2.0/t; | |
| col = clamp(col, vec4(0.0), vec4(1.0)); | |
| } | |
| vec2 wire(vec3 pos){ | |
| // This part has to match hat2 | |
| pos.xyz -= vec3(0.0,-0.3,0.0); | |
| pos.y += 0.01 * cos(pos.x * 10.0); | |
| pos.y += 0.5 * cos(pos.x * 2.4) * pos.y; | |
| float r = length(pos.xz); | |
| pos.y -= 0.5 * pow(1.1 * r, 2.0) + 0.4 * (2.0 * pow(1.0 - clamp(r, 0.3, 1.0), 5.0)); | |
| float a = atan(pos.z, pos.x); | |
| float offsetNormal = 0.001 - 0.013 * sin(a * 30.0); | |
| float offsetUp = 0.001 + 0.014 * cos(a * 30.0); | |
| float wireDistNormal = abs(r - 0.7 + offsetNormal); | |
| float wireDistUp = abs(pos.y + offsetUp); | |
| float wireDist = max(length(vec2(wireDistNormal, wireDistUp)) - 0.004,0.0); | |
| return vec2(wireDist, HAT_MATERIAL); | |
| } | |
| vec2 face(vec3 p){ | |
| p.y += 0.4; | |
| // Distored position | |
| vec3 dp = p * vec3(1.2,0.6,1.2); | |
| float dSphere = length(dp) - 0.43; | |
| // p.z *= 3.0 + 3.0 * abs(cos(10.0 * p.y)); | |
| // p.x *= 0.4 + 0.9 * cos(p.y * 10.0); | |
| vec3 q = abs(p * vec3(1.0,0.8,1.0)) - 0.14; | |
| float dBox = length(max(q, 0.0)) - 0.1; | |
| return vec2(dBox * 0.7 + dSphere, FACE_MATERIAL); | |
| } | |
| void face_Material(inout vec4 col, vec3 p, float AOLight, vec3 r, float t) { | |
| vec4 faceCol = vec4(0.8, 0.65, 0.46, 1.0); | |
| faceCol.rgb *= 0.6 + 0.3 * pow(AOLight, 0.7); | |
| // SubSurface Estimation 1: | |
| // high res texture + low res texture mixed together, but | |
| // Low Res has more red channel impact | |
| float lf = 200.0; | |
| float hf = lf * 4.0; | |
| float a = atan(p.x, p.z); | |
| float h = p.y; | |
| float highRes = 0.2 * abs(cos(h * hf) * cos(a * hf)); | |
| float lowRes = abs(cos(h * lf)); | |
| float blendFactor = 0.14; | |
| faceCol.rgb *= (1.0 - blendFactor) + blendFactor/2.0 * highRes; | |
| faceCol.rgb += blendFactor/2.0 * lowRes * vec3(1.0, 0.1, 0.1); | |
| // SubSurface Estimation 2: | |
| // Thin parts let more lights come through, and mostly red | |
| // Depth estimation | |
| // Using a point far, hopefully at the other side | |
| // (considering object size << 300.0 * length from p to o) | |
| vec3 p1 = p; | |
| vec3 p2 = 0.3 * normalize(r) + p1; | |
| float sdfP2 = face(p2).x; | |
| float dp2p1 = length(p2 - p1); | |
| float depth = dp2p1 - sdfP2; | |
| faceCol.rgb = clamp(faceCol.rgb, 0.0, 1.0); | |
| float ao = 2.0 * pow(clamp(1.0 - depth/0.3, 0.0, 1.0), 2.0); | |
| faceCol.r += ao * 1.0; | |
| faceCol.g += ao * 0.5; | |
| faceCol.b += ao * 0.5; | |
| col = faceCol * faceCol.a; | |
| } | |
| void eye_Material(inout vec4 col, vec3 p, float AOLight, vec3 r, float t) { | |
| } | |
| vec2 eyeLeft(vec3 p){ | |
| p.x += 0.11; | |
| p.z += 0.3; | |
| p.y += 0.37; | |
| p.z *= 2.5; | |
| float d = length(p) - 0.07; | |
| return vec2(d, float(EYE_MATERIAL)); | |
| } | |
| vec2 eyeRight(vec3 p){ | |
| p.x -= 0.11; | |
| p.z += 0.3; | |
| p.y += 0.37; | |
| p.z *= 2.5; | |
| float d = length(p) - 0.07; | |
| return vec2(d, float(EYE_MATERIAL)); | |
| } | |
| vec3 DISTANCE_FROM_ALL_OBJECTS(vec3 p) { | |
| vec2 distances_and_materials[] = vec2[]( | |
| hat1(p), | |
| hat2(p), | |
| wire(p), | |
| face(p), | |
| eyeLeft(p), | |
| eyeRight(p) | |
| ); | |
| float curr_min = 10e3; | |
| float d; | |
| float curr_min_index = -1.0; | |
| float curr_min_material = -1.0; | |
| for(int i = 0; i < distances_and_materials.length(); i++) { | |
| vec2 current = distances_and_materials[i]; | |
| d = current.x; | |
| if (d < curr_min) { | |
| curr_min = d; | |
| curr_min_material = current.y; | |
| curr_min_index = float(i); | |
| } | |
| } | |
| return vec3(curr_min, curr_min_index, curr_min_material); | |
| } | |
| vec3 randomize(vec3 p) { | |
| float s = 1.0 * mod((cos(p.x * 1120.0 + p.y * 1100.0 + p.z * 1022.0)), 1.0); | |
| p.x += 0.2 * mod(s + 1.0, 1.0) - 0.5; | |
| p.y += 0.2 * mod(s + 2.0, 1.0) - 0.5; | |
| p.z += 0.2 * mod(s + 3.0, 1.0) - 0.5; | |
| return p; | |
| } | |
| #define MAX_ITERATIONS 130 | |
| #define MARCH_SPEED 0.27 | |
| vec3 worldTransform(vec3 p) { | |
| p.y += 0.0; | |
| vec2 offset = vec2(0.0, 0.0); | |
| p.xz -= vec2(offset); | |
| float a = atan(p.z, p.x); | |
| float l = length(p.xz); | |
| a -= 0.0; | |
| a += time * 6.2832; | |
| p.x = l * cos(a); | |
| p.z = l * sin(a); | |
| p.xz += vec2(offset); | |
| return p; | |
| } | |
| /* Walk the ray through the scene */ | |
| vec4 trace(vec3 o, vec3 r){ | |
| vec3 p; | |
| float t = 0.0; | |
| float d; | |
| int i = 0; | |
| vec3 result; | |
| for(; i < MAX_ITERATIONS; i++){ | |
| p = o + r * t; | |
| vec3 noise = vec3( | |
| cos(p.x * 300333.0 + float(i)) + cos(p.y * 10000.0), | |
| cos(p.y * 33020.0 + float(i)) * cos(p.y * 2e3), | |
| cos(p.z * 33000.0 + float(i)) + cos(p.z * 2e5) | |
| ); | |
| // Noise reduces banding artifacts | |
| p.xyz += noise * 0.0002; | |
| result = DISTANCE_FROM_ALL_OBJECTS(p); | |
| d = result.x; | |
| t += MARCH_SPEED * d; | |
| if(d < 0.002){ | |
| break; | |
| } | |
| } | |
| int material = int(result.z); | |
| vec4 col = vec4(0.0); | |
| float AOLight = 1.0 / (float(i)/float(MAX_ITERATIONS)); | |
| switch (material) { | |
| case HAT_MATERIAL: | |
| hat_Material(col, p, AOLight, r, t); | |
| break; | |
| case FACE_MATERIAL: | |
| face_Material(col, p, AOLight, r, t); | |
| break; | |
| case EYE_MATERIAL: | |
| eye_Material(col, p, AOLight, r, t); | |
| break; | |
| } | |
| return col; | |
| } | |
| void mainImage( out vec4 fragColor, in vec2 fragCoord ) | |
| { | |
| vec2 uv = fragCoord.xy / iResolution.xy; | |
| float ratio = iResolution.x / iResolution.y; | |
| uv.x *= ratio; | |
| vec4 col = vec4(1.0); | |
| vec2 pos = uv - vec2(0.5 * ratio, 0.5); | |
| // Create ray (with position and origin) | |
| vec3 r,o; | |
| float a = time * 6.2832; | |
| mat2 rotation_xz = mat2( | |
| cos(a), -sin(a), | |
| sin(a), cos(a) | |
| ); | |
| r = normalize(vec3(pos, 1.0)); | |
| o = vec3(0.0, -0.4, -2.0); | |
| r.xz = rotation_xz * r.xz; | |
| o.xz = rotation_xz * o.xz; | |
| col = trace(o, r); | |
| fragColor = col; | |
| } | |
| void main(){ | |
| vec2 uv = UV.xy * iResolution.xy; | |
| vec4 col; | |
| mainImage(col, uv); | |
| col.rgba += 1.0 * (1.0 - col.a); | |
| out_color = col; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment