content/hifi-content/samuel/pokestop.fs
2022-02-14 02:04:11 +01:00

311 lines
No EOL
12 KiB
GLSL

// Based on https://www.shadertoy.com/view/Xt33D8
//
// Created by Sam Gondelman on 7/22/2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Math constants
const float PI = 3.14159265359;
const float EPS = 0.0001;
const float FLT_MAX = 1.0 / 0.000000000001; // hacky but GLSL doesn't have a FLT_MAX by default
// Raymarching constants
const float TMAX = 100.0;
const int MAX_STEPS = 100;
const float DIST_THRESHOLD = 0.00001;
// Timer uniforms
uniform float cubeTime = 0.0;
uniform float growTime = 0.0;
uniform float distTime = 0.0;
// Other constants/helpers
const vec3 UP = vec3(0.0, 1.0, 0.0);
#define clamp01(a) clamp(a, 0.0, 1.0)
struct Ray {
vec3 src;
vec3 dir;
float t;
vec3 pos;
vec3 nor;
int matID;
int iter;
};
// GLSL default parameters don't seem to work so this is for any call to map
// where you don't actually care about the material of what you hit
int junkMatID;
// Primitives
float plane(vec3 p, float y) {
return p.y - y;
}
float box(vec3 p, vec3 dim) {
vec3 d = abs(p) - dim;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float cylinder(vec3 p, float r, float h) {
vec2 d = abs(vec2(length(p.xz),p.y)) - vec2(r, h);
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float cone(vec3 p, float r, float h) {
float d1 = -p.y - h;
float q = p.y - h;
float si = 0.5*r/h;
float d2 = max(sqrt(dot(p.xz,p.xz)*(1.0-si*si)) + q*si, q);
return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);
}
// CSG operations
float intersectionDist(float d1, float d2) {
return max(d1, d2);
}
float subtractionDist(float d1, float d2) {
return max(d1, -d2);
}
// Transformations
vec3 rX(vec3 p, float a) {
float c = cos(radians(a));
float s = sin(radians(a));
vec3 q = p;
p.y = c * q.y - s * q.z;
p.z = s * q.y + c * q.z;
return p;
}
vec3 rY(vec3 p, float a) {
float c = cos(radians(a));
float s = sin(radians(a));
vec3 q = p;
p.x = c * q.x + s * q.z;
p.z = -s * q.x + c * q.z;
return p;
}
void propose(inout float val, inout int matID, float proposedVal, int proposedMatID) {
if (proposedVal < val) {
val = proposedVal;
matID = proposedMatID;
}
}
float map(vec3 p, inout int matID) {
float res = FLT_MAX;
propose(res, matID, cylinder(p, 1.0, 0.05), 2);
float height = 4.0;
float heightOffset = 0.05 * cos(1.1 * iGlobalTime);
propose(res, matID, cylinder(p - vec3(0, height/2.0, 0), 0.05, height/2.0), 2);
propose(res, matID, box(p - vec3(0, height, 0), vec3(1.0, 0.05, 1.0)), 2);
const float CUBE_GROW_TIME = 0.25;
float cubeRatio = 1.0 - cubeTime/CUBE_GROW_TIME;
propose(res, matID, box(rY(rX(p - vec3(0, (1.75 + heightOffset) * height, 0),
45.0 + iGlobalTime * 20.0), 45.0 + iGlobalTime * 20.0),
vec3(0.75*cubeRatio)), 2);
const float GROW_TIME = 0.5;
float ratio = growTime/GROW_TIME;
float outerRing = subtractionDist(
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 360.0 * ratio),
90.0),
ratio*2.5, 0.05),
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 360.0 * ratio),
90.0),
ratio*2.1, 0.1));
propose(res, matID, outerRing, 2);
float outerRing2 = subtractionDist(
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 - 360.0 * ratio),
90.0),
ratio*2.4, 0.1),
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 - 360.0 * ratio),
90.0),
ratio*2.2, 0.15));
propose(res, matID, outerRing2, 2);
float smallRing1 = subtractionDist(
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 360.0 * ratio),
90.0),
ratio*2.875, 0.125),
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 360.0 * ratio),
90.0),
ratio*2.725, 0.15));
float t1 = iGlobalTime / 5.0;
float angle1 = 110.0 + 150.0 * abs(cos(5.0*t1)*cos(t1) + sin(2.0*t1)*cos(0.5*t1))/ 2.0;
float cone1 = cone(rX(p - vec3(0, (1.0 + heightOffset) * height, 0) - vec3(0, 0.75 * height, 0),
angle1),
1.0, 0.75*height);
float plane1 = plane(rX(p - vec3(0, (1.0 + heightOffset) * height, 0) - vec3(0, 0.75 * height, 0.0), angle1), 0.0);
//propose(res, matID, intersectionDist(cone1, plane1), 2);
propose(res, matID, intersectionDist(smallRing1, intersectionDist(cone1, plane1)), 2);
float smallRing2 = subtractionDist(
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 360.0 * ratio),
90.0),
ratio*1.875, 0.125),
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 360.0 * ratio),
90.0),
ratio*1.725, 0.15));
float t2 = iGlobalTime / 6.5;
float angle2 = -110.0 + 230.0 * abs(cos(2.0*t2)*cos(4.5*t2) + sin(2.25*t2)*cos(0.25*t2) + 0.5)/ 2.0;
float cone2 = cone(rX(p - vec3(0, (1.0 + heightOffset) * height, 0) - vec3(0, 0.75 * height, 0),
angle2),
1.0, 0.75*height);
float plane2 = plane(rX(p - vec3(0, (1.0 + heightOffset) * height, 0) - vec3(0, 0.75 * height, 0.0), angle2), 0.0);
//propose(res, matID, intersectionDist(cone2, plane2), 2);
propose(res, matID, intersectionDist(smallRing2, intersectionDist(cone2, plane2)), 2);
float ballBottom = subtractionDist(
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 180.0 * ratio),
90.0),
ratio*1.5, 0.05),
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 + 180.0 * ratio),
90.0),
ratio*0.725, 0.1));
propose(res, matID, intersectionDist(ballBottom, plane(p, (1.75 + heightOffset) * height - 0.1)), 2);
float ballTop = subtractionDist(
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 - 180.0 * ratio),
90.0),
ratio*1.5, 0.05),
cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 - 180.0 * ratio),
90.0),
ratio*0.725, 0.1));
propose(res, matID, intersectionDist(ballTop, -plane(p, (1.75 + heightOffset) * height + 0.1)), 2);
const float ROT_STEP = 1.5;
const float ROT_REST = 1.0;
float rotOffset = 180.0 * sin(PI / 2.0 * min(ROT_STEP, mod(distTime, ROT_STEP + ROT_REST)) / ROT_STEP);
if (mod(floor(distTime / (ROT_STEP + ROT_REST)), 3.0) < 2.0) {
rotOffset = 180.0 + rotOffset;
} else {
rotOffset = 360.0 - 2.0 * rotOffset;
}
propose(res, matID, cylinder(rX(rY(p - vec3(0, (1.75 + heightOffset) * height, 0),
90.0 - 720.0 * ratio + rotOffset),
90.0),
ratio*0.5, 0.05), 2);
return res;
}
// Lighting
float directionalLightDiffuse(vec3 nor, vec3 ldir) {
return clamp01(dot(nor, -ldir));
}
vec3 LIGHT_DIR = vec3(-0.577);
vec3 computeColor(Ray ray) {
vec3 col = vec3(0.0);
// Default lighting
float sunLight = directionalLightDiffuse(ray.nor, LIGHT_DIR);
// Switch on matID
// a return -> different/no lighting
// no return -> default lighting
if (ray.matID == 2) {
col = vec3(0.345, 1.0, 1.0);
col = mix(vec3(0.133, 0.294, 0.784), col, sunLight);
} else {
discard;
}
return col;
}
vec3 calculateNormal(vec3 pos) {
const vec3 e = vec3(EPS, 0.0, 0.0);
float p = map(pos, junkMatID);
return normalize(vec3(map(pos + e.xyy, junkMatID) - p,
map(pos + e.yxy, junkMatID) - p,
map(pos + e.yyx, junkMatID) - p));
}
vec3 render(inout Ray ray) {
float h = 1.0;
float t = 0.0;
for(int i = 0; i < MAX_STEPS; i++) {
h = map(ray.src + t*ray.dir, ray.matID);
t += h;
ray.iter = i;
if (t > TMAX || h < DIST_THRESHOLD) break;
}
ray.t = t;
ray.pos = ray.src + ray.t*ray.dir;
ray.nor = calculateNormal(ray.pos);
int missed = int(step(TMAX, ray.t));
ray.matID = (1- missed) * ray.matID;
ray.nor *= float(1-missed);
return computeColor(ray);
}
vec4 getProceduralColor() {
Ray ray;
ray.pos = vec3(0.0);
ray.nor = vec3(0.0);
ray.matID = 0;
ray.t = 0.0;
vec3 worldEye = getEyeWorldPos();
// this will make it movable, scalable, and rotatable
vec3 ro = _position.xyz;
vec3 eye = (inverse(iWorldOrientation) * (worldEye - iWorldPosition)) / iWorldScale;
//vec3 ro = iWorldOrientation * (_position.xyz * iWorldScale) + iWorldPosition; // world position of the current fragment
//vec3 eye = worldEye;
// fit the map function inside a unit cube
ro.x *= 5.4150;
ro.y *= 10.1727;
ro.z *= 5.4150;
ro.x += 0.0;
ro.y += 5.0139;
ro.z += 0.0;
eye.x *= 5.4150;
eye.y *= 10.1727;
eye.z *= 5.4150;
eye.x += 0.0;
eye.y += 5.0139;
eye.z += 0.0;
vec3 rd = normalize(ro - eye); // ray from camera eye to ro
ray.src = eye;
ray.dir = rd;
return vec4(render(ray), 1.0);
}
float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) {
vec4 color = getProceduralColor();
diffuse = color.rgb;
specular = color.rgb;
shininess = 0.5;
return 1.0;
}