codepens/platonics/dist/index.html

339 lines
9.5 KiB
HTML
Raw Normal View History

2023-10-06 23:12:53 +02:00
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - Platonics</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<script id="vertexShader_buffer" type="x-shader/x-vertex">attribute vec4 a_position;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;
void main() {
gl_Position = a_position;
}
</script>
<script id="fragmentShader_under" type="x-shader/x-vertex">
#extension GL_EXT_shader_texture_lod : enable
precision highp float;
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
uniform sampler2D u_noise;
uniform vec2 u_cam;
uniform samplerCube u_environment;
/* Raymarching constants */
/* --------------------- */
const float MAX_TRACE_DISTANCE = 8.; // max trace distance
const float INTERSECTION_PRECISION = 0.001; // precision of the intersection
const int NUM_OF_TRACE_STEPS = 100; // max number of trace steps
const float STEP_MULTIPLIER = .8; // the step mutliplier - ie, how much further to progress on each step
/* Structures */
/* ---------- */
struct Camera {
vec3 ro;
vec3 rd;
vec3 forward;
vec3 right;
vec3 up;
float FOV;
};
struct Surface {
float len;
vec3 position;
vec3 colour;
float id;
float steps;
float AO;
};
struct Model {
float dist;
vec3 colour;
float id;
};
vec2 getScreenSpace() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x);
return uv;
}
float easeInOutCubic(float d) {
if (d < 0.5) return 4. * pow(d, 3.);
return 1. - pow(-2. * d + 2., 3.) * .5;
}
float easeInOutExpo(float k) {
if(k == 0.) return 0.;
if(k == 1.) return 1.;
k *= 2.;
if(k < 1.) return .5 * pow(1024., k - 1.);
return .5 * ( -pow(2., -10. * (k - 1.)) + 2. );
}
/*--------------------------------
/ Modelling
/ -------------------------------- */
float smin(float a, float b, float k) {
float res = exp(-k*a) + exp(-k*b);
return -log(res)/k;
}
mat4 rotationMatrix(vec3 axis, float angle) {
axis = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float oc = 1.0 - c;
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
0.0, 0.0, 0.0, 1.0);
}
float udBox( vec3 p, vec3 b ) {
return length(max(abs(p)-b,0.0));
}
float t = 0.;
Model model(vec3 p) {
float d = length(p) - .2;
// vec3 colour = vec3(1,0,0);
d = 100.;
vec3 colour2 = vec3(0);
vec3 colour1 = vec3(0);
vec3 colour = vec3(1);
vec3 pos1, pos2 = vec3(0,0,0);
vec3 endpos1 = vec3(-.25, 0, 0);
vec3 endpos2 = vec3(.25, 0, 0);
pos1 = mix(vec3(0), endpos1, t);
pos2 = mix(vec3(0), endpos2, t);
vec3 _p = p;
for(float i = 0.; i < 3.; i++) {
vec3 c;
vec3 pos = vec3(0);
if(i == 1.) {
pos = pos1;
c = colour2;
}
if(i == 2.) {
pos = pos2;
c = colour1;
}
p = _p + pos;
float t5 = u_time / 5. * (i + 1.);
p = (rotationMatrix(vec3(cos(t5), sin(t5), .5), u_time / 3. ) * vec4(p, 1.)).xyz;
if(d == 100.) {
d = udBox(p, vec3(.1));
} else {
float d1 = udBox(p, vec3(.1));
float ddiff = (d1 - d)/d1;
d = smin(d, d1, mix(90., 20., t));
colour = mix(c, colour, smoothstep(0., 1., ddiff * .7)); // This mixes the colours together based on the gradient produced by the smin
}
}
return Model(d, colour, 1.);
}
Model map( vec3 p ){
return model(p);
}
Surface calcIntersection( in Camera cam ){
float h = INTERSECTION_PRECISION*2.0;
float rayDepth = 0.0;
float hitDepth = -1.0;
float id = -1.;
float steps = 0.;
float ao = 0.;
vec3 position;
vec3 colour;
for( int i=0; i< NUM_OF_TRACE_STEPS ; i++ ) {
if( abs(h) < INTERSECTION_PRECISION || rayDepth > MAX_TRACE_DISTANCE ) break;
position = cam.ro+cam.rd*rayDepth;
Model m = map( position );
h = m.dist;
rayDepth += h * STEP_MULTIPLIER;
id = m.id;
steps += 1.;
ao += max(h, 0.);
colour = m.colour;
}
if( rayDepth < MAX_TRACE_DISTANCE ) hitDepth = rayDepth;
if( rayDepth >= MAX_TRACE_DISTANCE ) id = -1.0;
return Surface( hitDepth, position, colour, id, steps, ao );
}
Camera getCamera(in vec2 uv, in vec3 pos, in vec3 target) {
vec3 forward = normalize(target - pos);
vec3 right = normalize(vec3(forward.z, 0., -forward.x));
vec3 up = normalize(cross(forward, right));
float FOV = .6;
return Camera(
pos,
normalize(forward + FOV * uv.x * right + FOV * uv.y * up),
forward,
right,
up,
FOV
);
}
float softshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax ) {
float res = 1.0;
float t = mint;
for( int i=0; i<16; i++ ) {
float h = map( ro + rd*t ).dist;
res = min( res, 8.0*h/t );
t += clamp( h, 0.02, 0.10 );
if( h<0.001 || t>tmax ) break;
}
return clamp( res, 0.0, 1.0 );
}
float calcAO( in vec3 pos, in vec3 nor ) {
float occ = 0.0;
float sca = 1.0;
for( int i=0; i<5; i++ )
{
float hr = 0.01 + 0.12*float(i)/4.0;
vec3 aopos = nor * hr + pos;
float dd = map( aopos ).dist;
occ += -(dd-hr)*sca;
sca *= 0.95;
}
return clamp( 1.0 - 3.0*occ, 0.0, 1.0 );
}
// This is here to provide a fallback for devices that don't support GL_EXT_shader_texture_lod
vec4 cubeTexture(samplerCube map, vec3 uv, float lod) {
#ifdef GL_EXT_shader_texture_lod
return textureCubeLodEXT(map, uv, lod);
#endif
return textureCube(map, uv);
}
vec3 shade(Surface surface, vec3 nor, vec3 ref, Camera cam) {
vec3 col = surface.colour;
vec3 pos = surface.position;
vec3 I = normalize(pos - cam.ro);
vec3 R = reflect(I, nor);
vec3 reflection = cubeTexture(u_environment, R, 5.).rgb;
// reflection *= 0.;
// col = reflection;
// lighitng
float occ = 1./surface.AO;
vec3 lig = normalize( vec3(-0.6, 0.7, -0.) );
float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 );
float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
float bac = clamp( dot( nor, normalize(vec3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
// float dom = smoothstep( -0.1, 0.1, ref.y );
float fre = pow( clamp(1.0+dot(nor,cam.rd),0.0,1.0), 2.0 );
float spe = pow(clamp( dot( ref, lig ), 0.0, 1.0 ),4.0);
// dif *= softshadow( pos, lig, 0.02, 2.5 );
//dom *= softshadow( pos, ref, 0.02, 2.5 );
vec3 lin = vec3(0.0);
lin += 1.20*dif*vec3(.95,0.80,0.60);
lin += 1.20*spe*vec3(1.00,0.85,0.55)*dif;
lin += 0.80*amb*vec3(0.50,0.70,.80)*occ;
//lin += 0.30*dom*vec3(0.50,0.70,1.00)*occ;
lin += 0.30*bac*vec3(0.25,0.25,0.25)*occ;
lin += 0.20*fre*vec3(1.00,1.00,1.00)*occ;
col = col*lin;
col += reflection * .5;
return col;
}
// Calculates the normal by taking a very small distance,
// remapping the function, and getting normal for that
vec3 calcNormal( in vec3 pos ){
vec3 eps = vec3( 0.001, 0.0, 0.0 );
vec3 nor = vec3(
map(pos+eps.xyy).dist - map(pos-eps.xyy).dist,
map(pos+eps.yxy).dist - map(pos-eps.yxy).dist,
map(pos+eps.yyx).dist - map(pos-eps.yyx).dist );
return normalize(nor);
}
vec3 render(Surface surface, Camera cam, vec2 uv) {
vec3 colour = vec3(.4,.4,.45);
vec3 colourB = vec3(.1, .1, .1);
colour = mix(colourB, colour, smoothstep(1., 0., (length(uv) - surface.steps/100.) * (1.+smoothstep(-1., -1.5, -abs(cam.ro.z))*.5)));
// colour = mix(vec3(.5,0,.3), vec3(0,.5,0), smoothstep(-1., -1.5, cam.ro.z))+surface.steps/100.;
// colour -= texture2D(u_noise, uv).rgb;
if (surface.id == 1.){
vec3 surfaceNormal = calcNormal( surface.position );
vec3 ref = reflect(cam.rd, surfaceNormal);
colour = surfaceNormal;
colour = shade(surface, surfaceNormal, ref, cam);
}
return colour;
}
void main() {
vec2 uv = getScreenSpace();
t = easeInOutExpo( smoothstep(0., 1., sin(u_time * .25) * 2.) );
float camd = mix(.8, 1.5, t);
float c = cos(u_cam.x);
float s = sin(u_cam.x);
mat3 xrot = mat3(
c, 0, s,
0, 1, 0,
-s, 0, c
);
// c = cos(u_cam.y);
// s = sin(u_cam.y);
// mat3 yrot = mat3(
// 1, 0, 0,
// 0, c, -s,
// 0, s, c
// );
// xrot *= yrot;
vec3 campos = vec3( 0, 0, camd ) * xrot;
// campos += vec3( 0, cos(u_cam.y)*camd, sin(u_cam.y)*camd );
// Camera cam = getCamera(uv, mix(vec3(0,0,-.8), vec3(0,0,-1.5), t), vec3(0));
// Camera cam = getCamera(uv, vec3(0.,0.,1.25), vec3(0, 0, 0));
Camera cam = getCamera(uv, campos, vec3(0));
Surface surface = calcIntersection(cam);
gl_FragColor = vec4(render(surface, cam, uv), 1.);
// gl_FragColor = vec4(vec3(surface.steps/100.), 1.);
}
</script>
<!-- partial -->
<script type="module" src="./script.js"></script>
</body>
</html>