Feline
|
|
« on: July 29, 2012, 02:36:27 AM » |
|
Very brief intro by way of a caveat: I'm a physicist, not a mathematician. I understand and appreciate the mathematical exposition on syntopia's blog, but I tinker with all this to make pretty pictures; and as long as a DE does that for me, I couldn't care less whether it is entirely mathematically sound. I am beholden to mathematical correctness in my work life; in my free time I want to be allowed to play around. I've been collecting (and wanted to post somewhere for a while) a variety of notes on Fragmentarium, and just to finally kick that off, this post.
Having said that, here's what I can discern about the two power functions in the default Mandelbulb distance estimator in Fragmentarium.
The shader will use the one or the other, depending on the state of the "AlternateVersion" checkbox. Fire it up, select the Mandelbulb Tab and toggle it on or off a couple times to remind yourself how they're different.
Next, click the little arrow that allows you to change the value of the "Power" slider by one, such that power=9.000 then toggle the "AlternateVersion" checkbox again.
Surprised?
The two versions of the power function are identical to each other, for integer values of power = (n*4+1) = 1,5,9,13,17... For other values (including fractional values) the difference between them is merely a phase angle in theta (the "latitude" of the Mandelbulb). To see how that works, make the following small additions to the DE:
1) Somewhere at the beginning add a line that says
#define PI 3.14159265
(this is just for convenience - I have that in my "MathUtils", it is a riddle to me why this isn't standard).
2) right before the line that goes void powN1(... add the following line, which will give you an additional slider that you can use to add a phase angle to theta:
uniform float ExtraQ; slider[-2,0,2]
3) Lastly, add the value of the slider to theta at the end of the first line of code in the function as follows:
float theta = acos(z.z/r)+ExtraQ*PI/power;
(The part before the plus sign is already there, just add the stuff at the end).
That's it: hit the "Build" button, make sure "AlternateVersion" is NOT checked and slowly slide the new "ExtraQ" slider a little left-and-right to get a feeling for the kinds of things you can do with it.
Now it gets interesting: Change the "Power" slider to any value you like (can be a fractional value) then set the "ExtraQ" slider to the value (1-Power)/2 (*).
(* If that doesn't fit into the slider range, you're allowed to add integer multiples of 2 to the value. Since the whole thing gets multiplied by pi and phases of 2pi are identical to phases of zero).
Toggle the "AlternateVersion" checkbox and you'll notice that the two versions are identical.
Finally: since that term is the only difference between the two versions, you can modify the line that defines theta one more time like this:
float theta = acos(z.z/r)-AlternateVersion*((1-Power)/2*PI/Power);
remove the line that defines ExtraQ (unless you'd like to keep it around for other effects) and replace the whole chunk down in the DE that goes like this:
if (AlternateVersion) { powN2(z,r,dr); } else { powN1(z,r,dr); }
With the single line
powN1(z,r,dr);
This avoids a conditional in the main DE loop, which is almost always a speed gain in GPU calculations since GPUs are notoriously bad at branch predictions.
Footnotes: - There is an obvious analog phase "ExtraP" that one could add to Phi, but that is not terribly useful. Think about it, then try it. - Extend your "Power" slider to go from [-4.,8.,18] and verify that Power=-3 satisfies the condition above, where ExtraQ=0 yields the same result for both versions. Incidentily this'll unlock a number of interesting shapes for negative powers. Unfortunately the DE will blow up for those in various places, unless you make a couple other modifications. (in another post, maybe.)
|