diff --git a/base.config b/base.config index d783fbc..e3c7683 100644 --- a/base.config +++ b/base.config @@ -43,11 +43,11 @@ USE_WIDECHAR_TEXTS=1 ########### Time base ########### USE_TIME_DIVIDER_IN_X86_CODE=1 -TIME_DIVIDER=77255.477 +TIME_DIVIDER=94500.000 TIME_BASE=bars AUDIO_DELAY=2048 -PROD_END_TIME=2705728 +PROD_END_TIME=3970880 ########### Final product ########### @@ -61,9 +61,9 @@ QUOTE=\" CRINKLER_ORDERTRIES=4000 -AUDIO_BUFFER_ALLOCATED_LENGTH=2705728 +AUDIO_BUFFER_ALLOCATED_LENGTH=3970880 AUDIO_SAMPLING_RATE=44100 LOOP_END=5.0 LOOP_START=3.0 LOOP_ENABLED=0 -TIME_DIVIDER_INT=77255 +TIME_DIVIDER_INT=94500 diff --git a/minified.config b/minified.config index 517e10c..8882112 100644 --- a/minified.config +++ b/minified.config @@ -10,9 +10,9 @@ include $(PARENT_CONFIG) EXE_LINKER_PROGRAM=Crinkler CRINKLER_ORDERTRIES=4000 SHADER_FILE=shader_minified.h -TIME_UNIFORM_NAME='f' -RESOLUTION_UNIFORM_NAME='v' -TEXTS_UNIFORM_NAME='k' +TIME_UNIFORM_NAME='v' +RESOLUTION_UNIFORM_NAME='y' +TEXTS_UNIFORM_NAME='f' USE_WIDECHAR_TEXTS=1 TIME_DIVIDER=44100.000 TIME_BASE=seconds diff --git a/shader.glsl b/shader.glsl index c7d804d..bae10d4 100644 --- a/shader.glsl +++ b/shader.glsl @@ -1,1007 +1,316 @@ -precision mediump float; uniform vec2 u_resolution; uniform float u_time; uniform sampler2D texture_sampler; uniform sampler2D texts; -struct Ray { - vec3 rd; - vec3 dir; -}; - -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; -} - -mat2 scale(vec2 scale){ - return mat2(1. / scale.x, 0.0, 0.0, 1./scale.y); -} - -//////////////////////////////////////////////////////////////// -// -// HG_SDF -// -// GLSL LIBRARY FOR BUILDING SIGNED DISTANCE BOUNDS -// -// version 2021-07-28 -// -// Check https://mercury.sexy/hg_sdf for updates -// and usage examples. Send feedback to spheretracing@mercury.sexy. -// -// Brought to you by MERCURY https://mercury.sexy/ -// -// -// -// Released dual-licensed under -// Creative Commons Attribution-NonCommercial (CC BY-NC) -// or -// MIT License -// at your choice. -// -// SPDX-License-Identifier: MIT OR CC-BY-NC-4.0 -// -// ///// - - -//////////////////////////////////////////////////////////////// -// -// HELPER FUNCTIONS/MACROS -// -//////////////////////////////////////////////////////////////// - -const float PI = 3.14159265; -const float TAU = (2.*PI); -const float PHI = sqrt(5.)*0.5 + 0.5; - -// Sign function that doesn't return 0 -float sgn(float x) { - return (x < 0. )? -1. : 1.; -} - -vec2 sgn(vec2 v) { - return vec2((v.x<0.)?-1.:1., (v.y<0.)?-1.:1.); -} - -float square (float x) { - return x*x; -} - -vec2 square (vec2 x) { - return x*x; -} - -vec3 square (vec3 x) { - return x*x; -} - -float lengthSqr(vec3 x) { - return dot(x, x); -} - - -// Maximum/minumum elements of a vector -float vmax(vec2 v) { - return max(v.x, v.y); -} - -float vmax(vec3 v) { - return max(max(v.x, v.y), v.z); -} - -float vmax(vec4 v) { - return max(max(v.x, v.y), max(v.z, v.w)); -} - -float vmin(vec2 v) { - return min(v.x, v.y); -} - -float vmin(vec3 v) { - return min(min(v.x, v.y), v.z); -} - -float vmin(vec4 v) { - return min(min(v.x, v.y), min(v.z, v.w)); -} - -//////////////////////////////////////////////////////////////// -// -// PRIMITIVE DISTANCE FUNCTIONS -// -//////////////////////////////////////////////////////////////// -// -// Conventions: -// -// Everything that is a distance function is called fSomething. -// The first argument is always a point in 2 or 3-space called

. -// Unless otherwise noted, (if the object has an intrinsic "up" -// side or direction) the y axis is "up" and the object is -// centered at the origin. -// -//////////////////////////////////////////////////////////////// - -float fSphere(vec3 p, float r) { - return length(p) - r; -} - -// Plane with normal n (n is normalized) at some distance from the origin -float fPlane(vec3 p, vec3 n, float distanceFromOrigin) { - return dot(p, n) + distanceFromOrigin; -} - -// Cheap Box: distance to corners is overestimated -float fBoxCheap(vec3 p, vec3 b) { //cheap box - return vmax(abs(p) - b); -} - -// Box: correct distance to corners -float fBox(vec3 p, vec3 b) { - vec3 d = abs(p) - b; - return length(max(d, vec3(0))) + vmax(min(d, vec3(0))); -} - -// Same as above, but in two dimensions (an endless box) -float fBox2Cheap(vec2 p, vec2 b) { - return vmax(abs(p)-b); -} - -float fBox2(vec2 p, vec2 b) { - vec2 d = abs(p) - b; - return length(max(d, vec2(0.))) + vmax(min(d, vec2(0.))); -} - - -// Endless "corner" -float fCorner (vec2 p) { - return length(max(p, vec2(0.))) + vmax(min(p, vec2(0.))); -} - -// Cylinder standing upright on the xz plane -float fCylinder(vec3 p, float r, float height) { - float d = length(p.xz) - r; - d = max(d, abs(p.y) - height); - return d; -} - -// Capsule: A Cylinder with round caps on both sides -float fCapsule(vec3 p, float r, float c) { - return mix(length(p.xz) - r, length(vec3(p.x, abs(p.y) - c, p.z)) - r, step(c, abs(p.y))); -} - -// Distance to line segment between and , used for fCapsule() version 2below -float fLineSegment(vec3 p, vec3 a, vec3 b) { - vec3 ab = b - a; - float t = clamp( dot(p - a, ab) / dot(ab, ab), 0., 1. ); - return length((ab*t + a) - p); -} - -// Capsule version 2: between two end points and with radius r -float fCapsule(vec3 p, vec3 a, vec3 b, float r) { - return fLineSegment(p, a, b) - r; -} - -// Torus in the XZ-plane -float fTorus(vec3 p, float smallRadius, float largeRadius) { - return length(vec2(length(p.xz) - largeRadius, p.y)) - smallRadius; -} - -// A circle line. Can also be used to make a torus by subtracting the smaller radius of the torus. -float fCircle(vec3 p, float r) { - float l = length(p.xz) - r; - return length(vec2(p.y, l)); -} - -// A circular disc with no thickness (i.e. a cylinder with no height). -// Subtract some value to make a flat disc with rounded edge. -float fDisc(vec3 p, float r) { - float l = length(p.xz) - r; - return l < 0. ? abs(p.y) : length(vec2(p.y, l)); -} - -// Hexagonal prism, circumcircle variant -float fHexagonCircumcircle(vec3 p, vec2 h) { - vec3 q = abs(p); - return max(q.y - h.y, max(q.x*sqrt(3.)*0.5 + q.z*0.5, q.z) - h.x); - //this is mathematically equivalent to this line, but less efficient: - //return max(q.y - h.y, max(dot(vec2(cos(PI/3), sin(PI/3)), q.zx), q.z) - h.x); -} - -// Hexagonal prism, incircle variant -float fHexagonIncircle(vec3 p, vec2 h) { - return fHexagonCircumcircle(p, vec2(h.x*sqrt(3.)*0.5, h.y)); -} - -// Cone with correct distances to tip and base circle. Y is up, 0 is in the middle of the base. -float fCone(vec3 p, float radius, float height) { - vec2 q = vec2(length(p.xz), p.y); - vec2 tip = q - vec2(0, height); - vec2 mantleDir = normalize(vec2(height, radius)); - float mantle = dot(tip, mantleDir); - float d = max(mantle, -q.y); - float projected = dot(tip, vec2(mantleDir.y, -mantleDir.x)); - - // distance to tip - if ((q.y > height) && (projected < 0.)) { - d = max(d, length(tip)); - } - - // distance to base ring - if ((q.x > radius) && (projected > length(vec2(height, radius)))) { - d = max(d, length(q - vec2(radius, 0))); - } - return d; -} - -//////////////////////////////////////////////////////////////// -// -// DOMAIN MANIPULATION OPERATORS -// -//////////////////////////////////////////////////////////////// -// -// Conventions: -// -// Everything that modifies the domain is named pSomething. -// -// Many operate only on a subset of the three dimensions. For those, -// you must choose the dimensions that you want manipulated -// by supplying e.g. or -// -// is always the first argument and modified in place. -// -// Many of the operators partition space into cells. An identifier -// or cell index is returned, if possible. This return value is -// intended to be optionally used e.g. as a random seed to change -// parameters of the distance functions inside the cells. -// -// Unless stated otherwise, for cell index 0,

is unchanged and cells -// are centered on the origin so objects don't have to be moved to fit. -// -// -//////////////////////////////////////////////////////////////// - -// Rotate around a coordinate axis (i.e. in a plane perpendicular to that axis) by angle . -// Read like this: R(p.xz, a) rotates "x towards z". -// This is fast if is a compile-time constant and slower (but still practical) if not. -void pR(inout vec2 p, float a) { - p = cos(a)*p + sin(a)*vec2(p.y, -p.x); -} - -// Shortcut for 45-degrees rotation -void pR45(inout vec2 p) { - p = (p + vec2(p.y, -p.x))*sqrt(0.5); -} - -// Repeat space along one axis. Use like this to repeat along the x axis: -// - using the return value is optional. -float pMod1(inout float p, float size) { - float halfsize = size*0.5; - float c = floor((p + halfsize)/size); - p = mod(p + halfsize, size) - halfsize; - return c; -} - -// Same, but mirror every second cell so they match at the boundaries -float pModMirror1(inout float p, float size) { - float halfsize = size*0.5; - float c = floor((p + halfsize)/size); - p = mod(p + halfsize,size) - halfsize; - p *= mod(c, 2.0)*2. - 1.; - return c; -} - -// Repeat the domain only in positive direction. Everything in the negative half-space is unchanged. -float pModSingle1(inout float p, float size) { - float halfsize = size*0.5; - float c = floor((p + halfsize)/size); - if (p >= 0.) - p = mod(p + halfsize, size) - halfsize; - return c; -} - -// Repeat only a few times: from indices to (similar to above, but more flexible) -float pModInterval1(inout float p, float size, float start, float stop) { - float halfsize = size*0.5; - float c = floor((p + halfsize)/size); - p = mod(p+halfsize, size) - halfsize; - if (c > stop) { //yes, this might not be the best thing numerically. - p += size*(c - stop); - c = stop; - } - if (c = (repetitions/2.)) c = abs(c); - return c; -} - -// Repeat in two dimensions -vec2 pMod2(inout vec2 p, vec2 size) { - vec2 c = floor((p + size*0.5)/size); - p = mod(p + size*0.5,size) - size*0.5; - return c; -} - -// Same, but mirror every second cell so all boundaries match -vec2 pModMirror2(inout vec2 p, vec2 size) { - vec2 halfsize = size*0.5; - vec2 c = floor((p + halfsize)/size); - p = mod(p + halfsize, size) - halfsize; - p *= mod(c,vec2(2.))*2. - vec2(1); - return c; -} - -// Same, but mirror every second cell at the diagonal as well -vec2 pModGrid2(inout vec2 p, vec2 size) { - vec2 c = floor((p + size*0.5)/size); - p = mod(p + size*0.5, size) - size*0.5; - p *= mod(c,vec2(2.))*2. - vec2(1.); - p -= size/2.; - if (p.x > p.y) p.xy = p.yx; - return floor(c/2.); -} - -// Repeat in three dimensions -vec3 pMod3(inout vec3 p, vec3 size) { - vec3 c = floor((p + size*0.5)/size); - p = mod(p + size*0.5, size) - size*0.5; - return c; -} - -// Mirror at an axis-aligned plane which is at a specified distance from the origin. -float pMirror (inout float p, float dist) { - float s = sgn(p); - p = abs(p)-dist; - return s; -} - -// Mirror in both dimensions and at the diagonal, yielding one eighth of the space. -// translate by dist before mirroring. -vec2 pMirrorOctant (inout vec2 p, vec2 dist) { - vec2 s = sgn(p); - pMirror(p.x, dist.x); - pMirror(p.y, dist.y); - if (p.y > p.x) - p.xy = p.yx; - return s; -} - -// Reflect space at a plane -float pReflect(inout vec3 p, vec3 planeNormal, float offset) { - float t = dot(p, planeNormal)+offset; - if (t < 0.) { - p = p - (2.*t)*planeNormal; - } - return sgn(t); -} - - -//////////////////////////////////////////////////////////////// -// -// OBJECT COMBINATION OPERATORS -// -//////////////////////////////////////////////////////////////// -// -// We usually need the following boolean operators to combine two objects: -// Union: OR(a,b) -// Intersection: AND(a,b) -// Difference: AND(a,!b) -// (a and b being the distances to the objects). -// -// The trivial implementations are min(a,b) for union, max(a,b) for intersection -// and max(a,-b) for difference. To combine objects in more interesting ways to -// produce rounded edges, chamfers, stairs, etc. instead of plain sharp edges we -// can use combination operators. It is common to use some kind of "smooth minimum" -// instead of min(), but we don't like that because it does not preserve Lipschitz -// continuity in many cases. -// -// Naming convention: since they return a distance, they are called fOpSomething. -// The different flavours usually implement all the boolean operators above -// and are called fOpUnionRound, fOpIntersectionRound, etc. -// -// The basic idea: Assume the object surfaces intersect at a right angle. The two -// distances and constitute a new local two-dimensional coordinate system -// with the actual intersection as the origin. In this coordinate system, we can -// evaluate any 2D distance function we want in order to shape the edge. -// -// The operators below are just those that we found useful or interesting and should -// be seen as examples. There are infinitely more possible operators. -// -// They are designed to actually produce correct distances or distance bounds, unlike -// popular "smooth minimum" operators, on the condition that the gradients of the two -// SDFs are at right angles. When they are off by more than 30 degrees or so, the -// Lipschitz condition will no longer hold (i.e. you might get artifacts). The worst -// case is parallel surfaces that are close to each other. -// -// Most have a float argument to specify the radius of the feature they represent. -// This should be much smaller than the object size. -// -// Some of them have checks like "if ((-a < r) && (-b < r))" that restrict -// their influence (and computation cost) to a certain area. You might -// want to lift that restriction or enforce it. We have left it as comments -// in some cases. -// -// usage example: -// -// float fTwoBoxes(vec3 p) { -// float box0 = fBox(p, vec3(1)); -// float box1 = fBox(p-vec3(1), vec3(1)); -// return fOpUnionChamfer(box0, box1, 0.2); -// } -// -//////////////////////////////////////////////////////////////// - - -// The "Chamfer" flavour makes a 45-degree chamfered edge (the diagonal of a square of size ): -float fOpUnionChamfer(float a, float b, float r) { - return min(min(a, b), (a - r + b)*sqrt(0.5)); -} - -// Intersection has to deal with what is normally the inside of the resulting object -// when using union, which we normally don't care about too much. Thus, intersection -// implementations sometimes differ from union implementations. -float fOpIntersectionChamfer(float a, float b, float r) { - return max(max(a, b), (a + r + b)*sqrt(0.5)); -} - -// Difference can be built from Intersection or Union: -float fOpDifferenceChamfer (float a, float b, float r) { - return fOpIntersectionChamfer(a, -b, r); -} - -// The "Round" variant uses a quarter-circle to join the two objects smoothly: -float fOpUnionRound(float a, float b, float r) { - vec2 u = max(vec2(r - a,r - b), vec2(0)); - return max(r, min (a, b)) - length(u); -} - -float fOpIntersectionRound(float a, float b, float r) { - vec2 u = max(vec2(r + a,r + b), vec2(0)); - return min(-r, max (a, b)) + length(u); -} - -float fOpDifferenceRound (float a, float b, float r) { - return fOpIntersectionRound(a, -b, r); -} - - -// The "Columns" flavour makes n-1 circular columns at a 45 degree angle: -float fOpUnionColumns(float a, float b, float r, float n) { - if ((a < r) && (b < r)) { - vec2 p = vec2(a, b); - float columnradius = r*sqrt(2.)/((n-1.)*2.+sqrt(2.)); - pR45(p); - p.x -= sqrt(2.)/2.*r; - p.x += columnradius*sqrt(2.); - if (mod(n,2.) == 1.) { - p.y += columnradius; - } - // At this point, we have turned 45 degrees and moved at a point on the - // diagonal that we want to place the columns on. - // Now, repeat the domain along this direction and place a circle. - pMod1(p.y, columnradius*2.); - float result = length(p) - columnradius; - result = min(result, p.x); - result = min(result, a); - return min(result, b); - } else { - return min(a, b); - } -} - -float fOpDifferenceColumns(float a, float b, float r, float n) { - a = -a; - float m = min(a, b); - //avoid the expensive computation where not needed (produces discontinuity though) - if ((a < r) && (b < r)) { - vec2 p = vec2(a, b); - float columnradius = r*sqrt(2.)/n/2.0; - columnradius = r*sqrt(2.)/((n-1.)*2.+sqrt(2.)); - - pR45(p); - p.y += columnradius; - p.x -= sqrt(2.)/2.*r; - p.x += -columnradius*sqrt(2.)/2.; - - if (mod(n,2.) == 1.) { - p.y += columnradius; - } - pMod1(p.y,columnradius*2.); - - float result = -length(p) + columnradius; - result = max(result, p.x); - result = min(result, a); - return -min(result, b); - } else { - return -m; - } -} - -float fOpIntersectionColumns(float a, float b, float r, float n) { - return fOpDifferenceColumns(a,-b,r, n); -} - -// The "Stairs" flavour produces n-1 steps of a staircase: -// much less stupid version by paniq -float fOpUnionStairs(float a, float b, float r, float n) { - float s = r/n; - float u = b-r; - return min(min(a,b), 0.5 * (u + a + abs ((mod (u - a + s, 2. * s)) - s))); -} - -// We can just call Union since stairs are symmetric. -float fOpIntersectionStairs(float a, float b, float r, float n) { - return -fOpUnionStairs(-a, -b, r, n); -} - -float fOpDifferenceStairs(float a, float b, float r, float n) { - return -fOpUnionStairs(-a, b, r, n); -} - - -// Similar to fOpUnionRound, but more lipschitz-y at acute angles -// (and less so at 90 degrees). Useful when fudging around too much -// by MediaMolecule, from Alex Evans' siggraph slides -float fOpUnionSoft(float a, float b, float r) { - float e = max(r - abs(a - b), 0.); - return min(a, b) - e*e*0.25/r; -} - - -// produces a cylindical pipe that runs along the intersection. -// No objects remain, only the pipe. This is not a boolean operator. -float fOpPipe(float a, float b, float r) { - return length(vec2(a, b)) - r; -} - -// first object gets a v-shaped engraving where it intersect the second -float fOpEngrave(float a, float b, float r) { - return max(a, (a + r - abs(b))*sqrt(0.5)); -} - -// first object gets a capenter-style groove cut out -float fOpGroove(float a, float b, float ra, float rb) { - return max(a, min(a + ra, rb - abs(b))); -} - -// first object gets a capenter-style tongue attached -float fOpTongue(float a, float b, float ra, float rb) { - return min(a, max(a - ra, abs(b) - rb)); -} - -//#endSection End of library - -// https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl -// golden_noise -float noise(in vec2 xy, in float seed){ - return fract(tan(distance(xy*PHI, xy)*seed)*xy.x); -} - -vec3 rnd23(vec2 p) -{ - vec3 p3 = fract(p.xyx * vec3(.1031, .1030, .0973)); - p3 += dot(p3, p3.yxz+33.33); - return fract((p3.xxy+p3.yzz)*p3.zyx); -} - -mat2 Rot(float a) { - float s=sin(a), c=cos(a); +// Rotate +mat2 rot2D(float angle) { + float s = sin(angle); + float c = cos(angle); return mat2(c, -s, s, c); } -float opExtrusion( in vec3 p, in float sdf, in float h ) +// Exponential smoothing +float smin( float a, float b, float k ) { - vec2 w = vec2( sdf, abs(p.z) - h); - return min(max(w.x,w.y),0.0) + length(max(w,0.0)); + k *= 1.0; + float r = exp2(-a/k) + exp2(-b/k); + return -k*log2(r); } -float sdCog2d(vec2 pos) { - float r = length(pos)*2.; - float a = atan(pos.y,pos.x); - float f = 1. - smoothstep(-0.2, .8, sin(a * 12.))*0.14; - f = smoothstep(f,f + 2.,r); - return f; -} - -float sdCog(vec3 pos, float angle) { - pos.xy *= Rot(angle); - 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 sdText(vec3 pos, float angle) { - //pos.xy *= Rot(angle); - vec3 color = texture2D(texts, getUV(vec2( 0.,0.))).rgb; - - //gl_FragColor = vec4(vec3(color), 1.); - - //float d1 = opExtrusion(pos, , 0.1); - return 0.; -// return d1; +float smax( float a, float b, float k ) +{ + float h = max(k-abs(a-b),0.0); + return max(a, b) + h*h*0.25/k; } -float sdHex(vec3 pos, float i, float angle) { - vec3 po = pos; +///////////////// +// GEOMETRY // +///////////////// + +float sdBox( in vec2 p, in vec2 r ) +{ + return length( max(abs(p)-r,0.0) ); +} + +float sdBox2(vec3 p, vec3 b) { + vec3 q = abs(p) - b; + return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); +} + +float sdSphere(vec3 p, float r){ + return length(p) -r; +} + +float sdTriPrism( vec3 p, vec2 h, float rot ) +{ + p.xy *= rot2D(rot); + const float k = sqrt(3.0); + h.x *= 0.5*k; + p.xy /= h.x; + p.x = abs(p.x) - 1.0; + p.y = p.y + 1.0/k; + if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0; + p.x -= clamp( p.x, -2.0, 0.0 ); + float d1 = length(p.xy)*sign(-p.y)*h.x; + float d2 = abs(p.z)-h.y; + + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + + +////////////////// +// ANIMATION // +////////////////// + +// Rotate ring with duration d and startTime s +float ringRotateFunc(float d, float s, float timeFact) { + const float TWOPI = 6.28318530718; + float maxCycles = d; + float startTime = s; + float phase = ((u_time * timeFact) - startTime) / TWOPI; + phase = min(phase, maxCycles); +return TWOPI * phase; +} + +// Animate ring movements +vec3 ringAnim( in vec3 p) { + +const float STARTDELAY = 2.0; + +float factor = 9.0+9.0*clamp(sin(ringRotateFunc(2.0, 0.0, 1.0) * 0.05), -0.9, 0.9); + +// delay start +if( u_time >= STARTDELAY ) { +factor = 9.0+9.0*clamp(sin(ringRotateFunc(2.0, 0.0, 1.0) * 0.05), -0.9, 0.9); +p.xy = rot2D(factor) * p.xy; +} + +if(u_time >= 14.0) { +factor = 9.0+9.0*clamp(sin(ringRotateFunc(2.0, 14.0, 1.0) * 0.05), -0.9, 0.9); +p.xy = rot2D(factor * -1.0) * p.xy; +} + +return p; +} + +// Animate prism movements +float prismAnim(in float x, in float delay) { + + +if(u_time >= delay) { +x += (0.045*clamp(sin((ringRotateFunc(2.4, delay*10.0, 10.0) * 0.4)),-0.9, 0.9)); +} + +return x; +} + + +////////////// +// SCENE // +////////////// + +vec2 map( in vec3 p) +{ + // Stargate + + // Ring boxes + const float an = 6.283185/24.0; + float sector = round(atan(p.y,p.x)/an); + float angrot = sector*an; + vec3 q = p; + q.xy = mat2(cos(angrot),-sin(angrot), + sin(angrot), cos(angrot))*q.xy; + float d = sdBox( q.xy - vec2(1.8,0.0), vec2(0.24,0.14) ) - 0.02; + + // Main ring + float d2 = abs(length(p.xy) - 1.8) - 0.2; + d = min(d,d2); + + // Inner ring + float d3 = abs(length(p.xy) - 1.75) - 0.08; + d3 = smax( d3, abs(p.z - 0.1)-0.04, 0.005 ); + d = max(-d3,d); + + // Depth slice rings + d = smax( d, abs(p.z)-0.1, 0.02 ); + + // Prisms + float index = 1.0; + for(int i=0; i<8; i++ ) { - po.xz *= Rot(angle); - po.yz *= Rot(angle); - pR(po.yz, PI/2.); + //vec3 p2 = prismAnim(p); + + float secDist = 6.283185 / 8.0; // sector distance + float angle = ((24.67 / 6.283185 )); // sector size + vec3 q = p; + float rotationIncrement = angle + (index * secDist); - float d1 = fHexagonCircumcircle(po, vec2(0.5+i, .1)); - float d2 = fHexagonCircumcircle(po, vec2(0.2+i, .1)); - return fOpDifferenceRound(d1,d2,0.1); - -} - -// Scene -vec2 mapScene(in vec3 p) { - float mat = 0.; - float d = 1e10; - - //float dGround = p.y + 2.5; - //d = min(d, dGround); - - vec3 po = p; - //po.y += sin(u_time); - // pMod3(po, vec3(3.)); - po.xy *= scale(vec2(1.3, 1.3)); - - 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 = sdText(p, u_time); - //d = min(d, c2); - //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, inout vec3 pos) { - float t = 0.0; - float mat = 0.; - float hit = 0.; - for(int i=0; i < 150; i++) { - pos = ro + rd * t; - vec2 res = mapScene(pos); - t += res.x; - mat = res.y; - 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; + // Nudge first and the last prism out of the ground + if (i == 1) { + rotationIncrement = rotationIncrement + 0.2; } + if (i == 7) { + rotationIncrement = rotationIncrement - 0.2; + } + + float prismSector = round(atan(p.y,p.x)/(rotationIncrement)); + q.xy = rot2D(rotationIncrement) * q.xy; + + // We can now call each prism by it's index + // draw all except the middle bottom prism + if (i > 0) { + q.x = q.x - 1.95; + + if(i == 1) { + q.x = prismAnim(q.x, 13.0); + } + + if(i == 2) { + q.x = prismAnim(q.x, 26.0); + } + + float d4 = sdTriPrism(vec3(q.x, q.y - 0.0 , q.z - 0.0), vec2(0.2,0.2), 0.5) - 0.02; + d = min(d, d4); + } + + index += 1.0; } - if (t > 40.) t = -1.0; - return vec3(t, mat, hit); + + //Rotating glyphs + vec3 p2 = ringAnim(p); + float an2 = (6.283185/32.0); + float sector2 = round((atan(p2.y,p2.x)/an2) ); + float angrot2 = sector2*an2; + vec3 q2 = p2; + q2.xy = rot2D(angrot2)*q2.xy; + float d5 = sdBox2( q2.xyz - vec3(1.75,0.0,0.0), vec3(0.04, 0.14, 0.05) ) - 0.02; + d = min(d, d5); + + + // Gate Base + const float stepHeight = 0.1; + float stepDist = 1.5; + const float stepWidth = 2.0; + + for(int i = 0; i < 4; i++) { + float step = sdBox2(vec3(p.x,p.y+stepDist,p.z), vec3(stepWidth,stepHeight,stepDist)) - 0.05; + d = min(d, step); + stepDist += stepHeight * 2.0; + } + + return vec2( d ); } -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; +//////////////// +// DRAWING // +//////////////// +float rayMarch(vec3 ro, vec3 rd) { + + float t = 0.; // total distance travelled + float d; + // Raymarching + for (int i = 0; i < 80; i++) { + vec3 p = ro + rd * t; // "cast" rays + + d = map(p).x; // Get distance to objects + + + t += d; // "march" the ray + + if (d< .001 || t>100.) break; } - res = max(res,-1.0); - return 0.25*(1.0+res)*(1.0+res)*(2.0-res); + return t; } +vec3 getNormal(vec3 p) { + float d = map(p).x; + vec2 e = vec2(.01, 0); -float castShadow(vec3 ro, vec3 rd) { - float res = 1.0; - float t = 0.001; - 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; - if (t > 20.) break; - } - return clamp(res,0., 1.); -} - -vec3 calcNormal(vec3 pos) { - vec2 e = vec2(.001, 0.); - vec3 n = vec3( mapScene(pos+e.xyy).x - mapScene(pos-e.xyy).x, - mapScene(pos+e.yxy).x - mapScene(pos-e.yxy).x, - mapScene(pos+e.yyx).x - mapScene(pos-e.yyx).x - ); + vec3 n = d - vec3( + map(p-e.xyy).x, + map(p-e.yxy).x, + map(p-e.yyx).x); return normalize(n); } -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 ); +float getLight(vec3 p, vec3 lightPos, float intensity, float shadow) { + vec3 l = normalize(lightPos - p); + vec3 n = getNormal(p); + + float dif = clamp(dot(n, l), 0., intensity); + + // Shadows + float d = rayMarch(p+n*.0025, l); + if(d 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); - - 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; -} - - -void main() +void main( ) { - - vec3 finalColor = vec3(0.); - 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 += render(getUV(vec2( aaX, aaY))); - count += 1.0; + // Initialization + vec2 uv = (gl_FragCoord.xy * 2. - u_resolution.xy) / u_resolution.y; + //vec2 m = iMouse.xy/u_resolution.xy; + + vec3 ro = vec3(0, 2, 3); + //ro.yz *= rot2D(-m.y*3.14+1.); + //ro.xz *= rot2D(-m.x*6.2831); + + //vec3 ro = vec3(0,0,-3); // ray origin + + vec3 rd = GetRayDir(uv, ro, vec3(0, 0., 0.), 1.); // ray direction + vec3 col = vec3(0); // color + + float d = rayMarch(ro, rd); + + if (d < 1000.) + { + // Lighting + vec3 p = ro + rd * d; + + float mat = map(p).y; + // Light 1 + // Light 1 Position + vec3 lightPos1 = vec3( 3, 5, 4); + // Light 1 Arguments + // 1: Ray starting point + // 2: Light position + // 3: Light intensity + // 4: Shadow intensity + float dif = getLight(p, lightPos1, 0.75, 0.2); + // Color for light 1 + col = vec3(dif * vec3(1)); + + // Light 2 + vec3 lightPos2 = vec3( -3, 5, -4); + dif = getLight(p, lightPos2, 0.75, 0.1); + // Color for light 2 + col += vec3(dif * vec3(0.5,0.2,0.1)); + + if(mat==0.){ + col *= vec3(0,0,1); } - } - finalColor /= count; */ - finalColor += render(getUV(vec2( 0.,0.))); - - finalColor = postProcess(finalColor); + else if(mat==1.){ + col *= vec3(0,1,0); + } + else if(mat==2.){ + col *= vec3(1,0,0); + } + } - gl_FragColor = vec4(finalColor, 1.); - -} \ No newline at end of file + gl_FragColor = vec4(col, 1); +} diff --git a/shader_minified.h b/shader_minified.h index b1e807c..0230763 100644 --- a/shader_minified.h +++ b/shader_minified.h @@ -1,228 +1,167 @@ // Generated with Shader Minifier 1.3.6 (https://github.com/laurentlb/Shader_Minifier/) #ifndef SHADER_MINIFIED_H_ # define SHADER_MINIFIED_H_ -# define VAR_texts "k" -# define VAR_texture_sampler "m" -# define VAR_u_resolution "v" -# define VAR_u_time "f" +# define VAR_texts "f" +# define VAR_texture_sampler "x" +# define VAR_u_resolution "y" +# define VAR_u_time "v" const char *__temp_cleaned_shader_glsl = - "uniform vec2 v;" - "uniform float f;" - "uniform sampler2D m,k;struct Ray{vec3 rd;vec3 dir;};" - "vec2 s()" + "uniform vec2 y;" + "uniform float v;" + "uniform sampler2D x,f;" + "mat2 n(float v)" "{" - "vec2 r=2.*((gl_FragCoord.xy+vec2(0)*.5)/v.xy-.5);" - "r.x*=v.x/v.y;" - "return r;" + "float x=sin(v),y=cos(v);" + "return mat2(y,-x,x,y);" "}" - "mat2 n()" + "float n(float v,float x,float y)" "{" - "vec2 v=vec2(1.3);" - "return mat2(1./v.x,0.,0.,1./v.y);" + "float m=max(y-abs(v-x),0.);" + "return max(v,x)+m*m*.25/y;" "}" - "const float i=2.*acos(-1.),c=sqrt(5.)*.5+.5;" - "float n(vec3 v,vec2 x)" + "float n(vec3 v,vec3 y)" "{" - "vec3 f=abs(v);" - "return max(f.y-x.y,max(f.x*sqrt(3.)*.5+f.z*.5,f.z)-x.x);" + "vec3 x=abs(v)-y;" + "return length(max(x,0.))+min(max(x.x,max(x.y,x.z)),0.);" "}" - "void n(inout vec2 v)" + "float s(vec3 v)" "{" - "float f=acos(-1.)/2.;" - "v=cos(f)*v+sin(f)*vec2(v.y,-v.x);" + "vec2 f=vec2(.2);" + "v.xy*=n(.5);" + "const float y=sqrt(3.);" + "f.x*=.5*y;" + "v.xy/=f.x;" + "v.x=abs(v.x)-1.;" + "v.y=v.y+1./y;" + "if(v.x+y*v.y>0.)" + "v.xy=vec2(v.x-y*v.y,-y*v.x-v.y)/2.;" + "v.x-=clamp(v.x,-2.,0.);" + "float x=length(v.xy)*sign(-v.y)*f.x,a=abs(v.z)-f.y;" + "return length(max(vec2(x,a),0.))+min(max(x,a),0.);" "}" - "float s(float v,float f)" + "float s(float x,float y,float m)" "{" - "return min(-.1,max(v,f))+length(max(vec2(.1+v,.1+f),vec2(0)));" + "float f=(v*m-y)/(2.*acos(-1.));" + "f=min(f,x);" + "return 2.*acos(-1.)*f;" "}" - "float t(vec2 v,float f)" + "vec3 m(vec3 y)" "{" - "return fract(tan(distance(v*c,v)*f)*v.x);" + "float x=9.+9.*clamp(sin(s(2.,0.,1.)*.05),-.9,.9);" + "if(v>=2.)" + "x=9.+9.*clamp(sin(s(2.,0.,1.)*.05),-.9,.9),y.xy=n(x)*y.xy;" + "if(v>=14.)" + "x=9.+9.*clamp(sin(s(2.,14.,1.)*.05),-.9,.9),y.xy=n(x*-1.)*y.xy;" + "return y;" "}" - "mat2 s(float v)" + "float m(float x,float y)" "{" - "float f=sin(v),x=cos(v);" - "return mat2(x,-f,f,x);" + "if(v>=y)" + "x+=.045*clamp(sin(s(2.4,y*10.,10.)*.4),-.9,.9);" + "return x;" "}" - "float n(vec3 v,float f,float x)" + "vec2 a(vec3 v)" "{" - "vec3 r=v;" - "r.xz*=s(x);" - "r.yz*=s(x);" - "n(r.yz);" - "float i=n(r,vec2(.5+f,.1)),y=n(r,vec2(.2+f,.1));" - "return s(i,-y);" - "}" - "vec2 t(vec3 v)" - "{" - "float x=0.,r=1e10;" - "vec3 i=v;" - "i.xy*=n();" - "for(float m=1.;m<=6.;m++)" + "float x=round(atan(v.y,v.x)/.261799375)*.261799375;" + "vec3 f=v;" + "f.xy=mat2(cos(x),-sin(x),sin(x),cos(x))*f.xy;" + "float y=length(max(abs(f.xy-vec2(1.8,0))-vec2(.24,.14),0.))-.02;" + "y=min(y,abs(length(v.xy)-1.8)-.2);" + "float i=abs(length(v.xy)-1.75)-.08;" + "i=n(i,abs(v.z-.1)-.04,.005);" + "y=max(-i,y);" + "y=n(y,abs(v.z)-.1,.02);" + "float r=1.;" + "for(int a=0;a<8;a++)" "{" - "float y=n(i,m*.35,f+abs(2.+.4*sin(f))*m*3.1415/6.);" - "r=min(r,y);" - "if(r==y)" - "x=1.+mod(m,3.);" - "}" - "return vec2(r,x);" - "}" - "vec3 s(vec3 v,vec3 f,inout vec3 x)" - "{" - "float r=0.,i=0.,y=0.;" - "for(int m=0;m<150;m++)" - "{" - "x=v+f*r;" - "vec2 n=t(x);" - "r+=n.x;" - "i=n.y;" - "if(r>80.)" - "break;" - "if(n.x0)" "{" - "y=1.;" - "break;" + "c.x=c.x-1.95;" + "if(a==1)" + "c.x=m(c.x,13.);" + "if(a==2)" + "c.x=m(c.x,26.);" + "float l=s(vec3(c))-.02;" + "y=min(y,l);" "}" + "r+=1.;" "}" - "if(r>80.)" - "r=-1.;" - "return vec3(r,i,y);" - "}" - "vec3 t(vec3 v,vec3 f,vec3 x)" - "{" - "float r=0.,i=0.,y=0.;" - "for(int m=0;m<50;m++)" + "vec3 a=m(v);" + "float c=6.283185/32.;" + "vec3 l=a;" + "l.xy=n(round(atan(a.y,a.x)/c)*c)*l.xy;" + "float z=n(l.xyz-vec3(1.75,0,0),vec3(.04,.14,.05))-.02;" + "y=min(y,z);" + "float e=1.5;" + "for(int u=0;u<4;u++)" "{" - "x=v+f*r;" - "vec2 n=t(x);" - "r+=n.x;" - "i=n.y;" - "if(r>40.)" - "break;" - "if(n.x40.)" - "r=-1.;" - "return vec3(r,i,y);" + "return vec2(y);" "}" - "float x(vec3 v,vec3 x)" + "float a(vec3 x,vec3 y)" "{" - "float r=1.,f=.01;" - "for(int i=0;i<40;i++)" + "float f=0.,v;" + "for(int i=0;i<80;i++)" "{" - "if(f>30.)" - "break;" - "float m=t(v+f*x).x;" - "r=min(r,m/(18.*f));" - "f+=clamp(m,.005,.5);" - "if(r<-1.||f>30.)" + "vec3 m=x+y*f;" + "v=a(m).x;" + "f+=v;" + "if(v<.001||f>1e2)" "break;" "}" - "r=max(r,-1.);" - "return.25*(1.+r)*(1.+r)*(2.-r);" + "return f;" "}" - "vec3 x(vec3 v)" + "vec3 h(vec3 v)" "{" - "vec2 f=vec2(.001,0);" - "vec3 r=vec3(t(v+f.xyy).x-t(v-f.xyy).x,t(v+f.yxy).x-t(v-f.yxy).x,t(v+f.yyx).x-t(v-f.yyx).x);" - "return normalize(r);" + "float y=a(v).x;" + "vec2 x=vec2(.01,0);" + "vec3 f=y-vec3(a(v-x.xyy).x,a(v-x.yxy).x,a(v-x.yyx));" + "return normalize(f);" "}" - "vec3 e(vec3 v,vec3 f)" + "float a(vec3 v,vec3 x,float y)" "{" - "vec3 x=vec3(.5454);" - "return x+(1.-x)*pow(clamp(1.-dot(v,f),0.,1.),5.);" + "vec3 f=normalize(x-v),m=h(v);" + "float i=clamp(dot(m,f),0.,.75),c=a(v+m*.0025,f);" + "if(c0.)" - "{" - "vec3 k=x(n);" - "m=e(n,k,i,d.y);" - "m=m*exp(-d.x*.04)+mix(m,mix(vec3(.3686,.2431,.4392),vec3(.4,.7294,.9216),pow(max(dot(c,vec3(0,.3,-1)),0.),8.)),1.-exp(-d.x*.04))*(1.-exp(-d.x*.04));" - "i=normalize(reflect(i,k));" - "vec3 g=n+i*.01,a=t(g,i,n);" - "if(a.z>0.)" - "n=g+i*a.x,k=x(n),m+=.1*e(n,k,i,a.y);" - "}" - "return m;" + "vec3 x=normalize(vec3(0)-y),f=normalize(cross(vec3(0,1,0),x));" + "return normalize(x+v.x*f+v.y*cross(x,f));" "}" "void main()" "{" - "vec3 v=vec3(0);" - "v+=p(s());" - "v=e(v);" - "gl_FragColor=vec4(v,1);" + "vec2 x=(gl_FragCoord.xy*2.-y.xy)/y.y;" + "vec3 v=vec3(0,2,3),f=h(x,v),i=vec3(0);" + "float c=a(v,f);" + "if(c<1e3)" + "{" + "vec3 m=v+f*c;" + "float l=a(m).y,r=a(m,vec3(3,5,4),.2);" + "i=vec3(r*vec3(1));" + "r=a(m,vec3(-3,5,-4),.1);" + "i+=vec3(r*vec3(.5,.2,.1));" + "if(l==0.)" + "i*=vec3(0,0,1);" + "else if(l==1.)" + "i*=vec3(0,1,0);" + "else if(l==2.)" + "i*=vec3(1,0,0);" + "}" + "gl_FragColor=vec4(i,1);" "}"; #endif // SHADER_MINIFIED_H_