Skip to content

Instantly share code, notes, and snippets.

@antoineMoPa
Created May 11, 2022 05:34
Show Gist options
  • Save antoineMoPa/2fc2d61cd7dcef182ff4e8bd735f6a4b to your computer and use it in GitHub Desktop.
Save antoineMoPa/2fc2d61cd7dcef182ff4e8bd735f6a4b to your computer and use it in GitHub Desktop.
#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