@@ -82,6 +82,12 @@ vec3 safe_normalize(vec3 t) {
8282 }
8383 return normalize (t);
8484}
85+ vec4 safe_normalize(vec4 t) {
86+ if (length (t) < 0.000001 ) {
87+ return vec4 (0.0 , 0.0 , 0.0 , 1.0 );
88+ }
89+ return normalize (t);
90+ }
8591
8692float getAngle(vec2 s) {
8793 float theta = 0.0 ;
@@ -112,11 +118,17 @@ float boundReflect(float x, float b) {
112118 }
113119}
114120
121+ mat3 frame_constant_mandelbulb_colorRotato;
122+ mat3 frame_constant_klein_colorRotato;
123+ mat3 frame_constant_quaternion_colorRotato;
124+ vec4 frame_constant_quaternion_q;
125+ vec4 frame_constant_quaternion_c;
126+
115127vec4 orbitTrap;
116128float distanceEstimator(vec3 t) {
117129 orbitTrap = vec4 (1.0 , 1.0 , 1.0 , 1.0 );
118130
119- // Mandelbox
131+ // Mandelbox.
120132 if (runtime.distance_estimator_id == 1 ) {
121133 const int maxIterations = 5 ;
122134 const float reScale = 4.8 ;
@@ -152,7 +164,7 @@ float distanceEstimator(vec3 t) {
152164 }
153165 return (length (s)- BVR)/ abs (DEfactor) / reScale;
154166 }
155- // Mandelbulb
167+ // Mandelbulb.
156168 else if (runtime.distance_estimator_id == 2 ) {
157169 const int maxIterations = 3 ;
158170 const float reScale = 1.85 ;
@@ -162,8 +174,6 @@ float distanceEstimator(vec3 t) {
162174 float dr = 1.0 ;
163175 float r = 0.0 ;
164176
165- mat3 colorRotato = buildRot3(safe_normalize(push.smooth_mids.xyz), 0.325 * push.time);
166-
167177 for (int i = 0 ; i < maxIterations; i++ ) {
168178 r = length (s);
169179 const float b = 1.5 ;
@@ -180,10 +190,11 @@ float distanceEstimator(vec3 t) {
180190 s = r* vec3 (sin (theta)* cos (phi), sin (theta)* sin (phi), cos (theta));
181191 s += t;
182192
183- orbitTrap.xyz = min (orbitTrap.xyz, abs ((s - (push.reactive_high.xyz + push.reactive_bass.xyz)/ 2.0 ) * colorRotato )/ 1.25 );
193+ orbitTrap.xyz = min (orbitTrap.xyz, abs ((s - (push.reactive_high.xyz + push.reactive_bass.xyz)/ 2.0 ) * frame_constant_mandelbulb_colorRotato )/ 1.25 );
184194 }
185195 return min (0.5 * log (r)* r/ dr, 3.5 ) / reScale;
186196 }
197+ // Klein-inspired.
187198 else if (runtime.distance_estimator_id == 3 ) {
188199 const int maxIterations = 3 ;
189200 const float reScale = 0.8 ;
@@ -197,8 +208,6 @@ float distanceEstimator(vec3 t) {
197208 float st = sin (theta);
198209 mat2 rotato = mat2 (ct, st, - st, ct);
199210
200- mat3 colorRotato = buildRot3(safe_normalize(push.smooth_mids.xyz), 0.15 * push.time);
201-
202211 for (int i = 0 ; i < maxIterations; i++ ) {
203212 if (i == 2 ) {
204213 s.xy *= rotato;
@@ -212,7 +221,7 @@ float distanceEstimator(vec3 t) {
212221 s *= k;
213222 scale *= k;
214223
215- orbitTrap.xyz = min (orbitTrap.xyz, abs ((s - (push.reactive_high.xyz + push.reactive_bass.xyz)/ 2.0 ) * colorRotato ));
224+ orbitTrap.xyz = min (orbitTrap.xyz, abs ((s - (push.reactive_high.xyz + push.reactive_bass.xyz)/ 2.0 ) * frame_constant_klein_colorRotato ));
216225 }
217226
218227 return max ((0.25 * abs (s.z)/ scale)/ reScale, length (t/ reScale)- 0.62 );
@@ -257,10 +266,11 @@ float distanceEstimator(vec3 t) {
257266 }
258267 return d/ reScale;
259268 }
269+ // Sierpiński-inspired.
260270 else if (runtime.distance_estimator_id == 5 ) {
261271 const int maxIterations = 8 ;
262272 const float scale = 2.0 ;
263- const float reScale = 1.4 ;
273+ const float reScale = 1.375 ;
264274
265275 t *= reScale;
266276 vec3 s = t;
@@ -296,47 +306,61 @@ float distanceEstimator(vec3 t) {
296306 // Quaternion Julia.
297307 else if (runtime.distance_estimator_id == 6 ) {
298308 const int maxIterations = 6 ;
299- const float reScale = 2.25 ;
309+ const float reScale = 1.85 ;
300310 t *= reScale;
301- float power = 3.0 ;
311+ float power = 4.0 + sin (0.025 * push.time);
312+
302313 // Store the running derivative as a quaternion.
303314 float dr = 1.0 ;
304315 float r = 0.0 ;
305316
306- mat3 colorRotato = buildRot3(safe_normalize(push.smooth_mids.xyz), 0.325 * push.time);
307-
308317 // Create a quaternion from the position.
309- // vec4 s = vec4(t, 0.25*sqrt(dot(push.smooth_bass, push.smooth_mids) + dot(push.smooth_bass, push.smooth_high) + dot(push.smooth_mids, push.smooth_high)));
310318 vec4 s = vec4 (0.0 , t);
311- vec4 q = normalize (multiplyQuaternions(multiplyQuaternions(push.smooth_bass, push.smooth_mids), push.smooth_high));
312- vec4 c = 0.75 * q;
313319
314320 for (int i = 0 ; i < maxIterations; i++ ) {
315321 r = length (s);
316322 const float b = 1.5 ;
317323 if (r > b) break ;
318324
319- // Get the derivative, 2*s*ds .
320- dr = length (q) * power* pow (r, power- 1.0 )* dr;
325+ // Get the derivative.
326+ dr = power* pow (r, power- 1.0 )* dr;
321327
322- // s = s*s + c; using quaternion algebra.
323- s = multiplyQuaternions(s, vec4 (2.0 * s.xyz* s.w, s.w* s.w - dot (s.xyz, s.xyz)));
324- s = multiplyQuaternions(q, s) + c;
328+ // s = q*s^p + c; using quaternion algebra.
329+ float phi = acos (s.w/ r);
330+ s = pow (r, power)* vec4 (cos (power* phi), sin (power* phi)* s.xyz/ length (s.xyz));
331+ s = multiplyQuaternions(frame_constant_quaternion_q, s) + frame_constant_quaternion_c;
325332
326- orbitTrap.xyz = min (orbitTrap.xyz, abs ((s.xyz - (push.reactive_high.xyz + push.reactive_bass.xyz)/ 2.0 ) * colorRotato) / 1.25 );
333+ orbitTrap.xyz = min (orbitTrap.xyz, abs ((s.xyz - (push.reactive_high.xyz + push.reactive_bass.xyz)/ 2.0 ) * frame_constant_quaternion_colorRotato) / 3.5 );
327334 }
328- orbitTrap = 0.95 * sqrt (orbitTrap);
335+ orbitTrap.xyz = sqrt (sqrt ( orbitTrap.xyz) );
329336 return min (log (r)* r/ dr, 3.5 ) / reScale;
330337 }
331338
332339 // If no fractal is selected, then escape to infinity.
333340 return 1024.0 ;
334341}
335342
343+ void setFrameConstants() {
344+ // Mandelbulb.
345+ if (runtime.distance_estimator_id == 2 ) {
346+ frame_constant_mandelbulb_colorRotato = buildRot3(safe_normalize(push.smooth_mids.xyz), 0.325 * push.time);
347+ }
348+ // Klein-inspired.
349+ else if (runtime.distance_estimator_id == 3 ) {
350+ frame_constant_klein_colorRotato = buildRot3(safe_normalize(push.smooth_mids.xyz), 0.15 * push.time);
351+ }
352+ // Quaternion Julia.
353+ else if (runtime.distance_estimator_id == 6 ) {
354+ frame_constant_quaternion_colorRotato = buildRot3(safe_normalize(push.smooth_mids.xyz), 0.1 * push.time);
355+ frame_constant_quaternion_q = safe_normalize(multiplyQuaternions(multiplyQuaternions(push.smooth_high, push.smooth_bass), push.smooth_mids));
356+ frame_constant_quaternion_c = 0.615 * multiplyQuaternions(frame_constant_quaternion_q, safe_normalize(multiplyQuaternions(multiplyQuaternions(push.smooth_bass, push.smooth_mids), push.smooth_high)));
357+ }
358+ }
359+
336360const float maxBrightness = 1.6 ;
337361const float maxBrightnessR2 = maxBrightness* maxBrightness;
338362vec3 scaleColor(float distanceRatio, float iterationRatio, vec3 col) {
339- col *= pow (1.0 - distanceRatio, 1.2 ) * pow (1.0 - iterationRatio, 2 .75 );
363+ col *= pow (1.0 - distanceRatio, 1.2 ) * pow (1.0 - iterationRatio, runtime.distance_estimator_id != 6 ? 2.75 : 1 .75 );
340364 if (dot (col, col) > maxBrightnessR2) {
341365 col = maxBrightness* normalize (col);
342366 }
@@ -349,8 +373,12 @@ vec3 castRay(vec3 position, vec3 direction, float fovX, float fovY, out float tr
349373 const float maxDistance = 32.0 ;
350374 const float hitDistance = epsilon;
351375 float minTravel = 0.3 ;
376+
377+ // Set the values that will be constant for this frame between distance estimator calls.
378+ setFrameConstants();
379+
352380 if (runtime.distance_estimator_id == 1 ) {
353- minTravel = minTravel + max (0.0 , - 0.75 * cos (0.03 * push.time));
381+ minTravel += max (0.0 , - 0.75 * cos (0.03 * push.time));
354382 }
355383
356384 float lastDistance = maxDistance;
@@ -371,12 +399,12 @@ vec3 castRay(vec3 position, vec3 direction, float fovX, float fovY, out float tr
371399 travel += dist;
372400 if (travel >= maxDistance) {
373401 if (! runtime.render_particles) {
374- vec3 unmodDirection = normalize (vec3 (coord.x* fovX, coord.y* fovY, 1.0 ));
402+ vec3 unmodDirection = normalize (vec3 (coord.x* fovX, coord.y* fovY, - 1.0 ));
375403 unmodDirection = rotateByQuaternion(unmodDirection, push.quaternion);
376404
377405 vec3 sinDir = sin (100.0 * unmodDirection);
378406 vec3 base = vec3 (exp (- 2.9 * length (sin (pi * push.reactive_bass.xyz + 1.0 ) - sinDir)), exp (- 2.9 * length (sin (e * push.reactive_mids.xyz + 1.3 ) - sinDir)), exp (- 2.9 * length (sin (9.6 * push.reactive_high.xyz + 117.69420 ) - sinDir)));
379- return (runtime.distance_estimator_id == 0 ? 0.8 : 0.575 ) * base;
407+ return (runtime.distance_estimator_id == 0 ? 0.8 : 0.55 ) * base;
380408 }
381409 break ;
382410 }
@@ -425,4 +453,4 @@ void main(void) {
425453 }
426454
427455 fragColor = vec4 (tFragColor, 1.0 );
428- }
456+ }
0 commit comments