cbuchner1
|
|
« Reply #540 on: November 19, 2009, 09:30:48 PM » |
|
I've tried power of 27, but that starts looking more and more like a ball.
So here's a power of 5, rendered on my GPU in phong shading.
|
|
|
|
fractalrebel
|
|
« Reply #541 on: November 19, 2009, 10:05:18 PM » |
|
Something doesn't look quite right here. Maybe it's your rotation angle(s), but I don't think so. Here is my version of z^5 + c:
|
|
|
Logged
|
|
|
|
David Makin
|
|
« Reply #542 on: November 19, 2009, 10:24:53 PM » |
|
I've tried power of 27, but that starts looking more and more like a ball.
So here's a power of 5, rendered on my GPU in phong shading.
Looks like gross over-stepping in the ray-marching ?
|
|
|
Logged
|
|
|
|
cbuchner1
|
|
« Reply #543 on: November 19, 2009, 10:28:03 PM » |
|
Hmm, so far my power 8 looked pretty much like anyone else's. Here's my entire distance estimator in plain CUDA-C. A float3 is a vector with elements .x, .y, and .z. x is the float3 vector with the current coordinate on the ray (elements x.x, x.y, x.z) - poor naming, I know. I am using the trigonometric version (polar coordinates mostly). Let me know if something smells fishy. float R = sqrtf(x.x*x.x + x.y*x.y + x.z*x.z); float th = atan2(x.y, x.x); float ph = atan2(x.z, sqrtf(x.x*x.x + x.y*x.y));
float3 dz; const float c = 1.0f; dz.x = 1.0f; dz.y = 0.0f; dz.z = 0.0f; float ph_dz = 0.0f; float th_dz = 0.0f; float R_dz = 1.0f;
const float sq_threshold = 4.0f; // divergence threshold
// Iterate to compute the distance estimator. int i = m_max_iterations;
const float p = power; // power of fractal while( i-- ) { // derivative dz.x = p*powf(R, p-1.0f) * R_dz*cosf(ph_dz+(p-1.0f)*ph)*cos(th_dz+(p-1.0f)*th)+c; dz.y = p*powf(R, p-1.0f) * R_dz*cosf(ph_dz+(p-1.0f)*ph)*sin(th_dz+(p-1.0f)*th); dz.z = p*powf(R, p-1.0f) * R_dz*sinf(ph_dz+(p-1.0f)*ph ); R_dz = sqrtf(dz.x*dz.x + dz.y*dz.y + dz.z*dz.z); th_dz = atan2(dz.y, dz.x); ph_dz = acos(dz.z/R_dz); // new x,y,z coordinate x.x = powf(R, p) * cosf(p*ph)*cos(p*th) + x.x; x.y = powf(R, p) * cosf(p*ph)*sin(p*th) + x.y; x.z = powf(R, p) * sinf(p*ph) + x.z;
R = sqrtf(x.x*x.x + x.y*x.y + x.z*x.z); th = atan2(x.y, x.x); ph = atan2(x.z, sqrtf(x.x*x.x + x.y*x.y));
// Stop when we know the point diverges. if( R > sq_threshold ) break; } return 0.5 * R * logf(R)/R_dz;
|
|
« Last Edit: November 19, 2009, 10:34:22 PM by cbuchner1 »
|
Logged
|
|
|
|
David Makin
|
|
« Reply #544 on: November 19, 2009, 10:52:20 PM » |
|
Hmm, so far my power 8 looked pretty much like anyone else's. Here's my entire distance estimator in plain CUDA-C. A float3 is a vector with elements .x, .y, and .z. x is the float3 vector with the current coordinate on the ray (elements x.x, x.y, x.z) - poor naming, I know. I am using the trigonometric version (polar coordinates mostly). Let me know if something smells fishy.
This is wrong: ph_dz = acos(dz.z/R_dz); Change to: ph_dz = asin(dz.z/R_dz); Also this is correct: ph = atan2(x.z, sqrtf(x.x*x.x + x.y*x.y)); but this is quicker: ph = asin(x.z, R); Also it's not causing the main problem but the distance estimate will be considerably more accurate if you increase the allowed bailout to say 11 or more (I have testing R^2 against 128 as the minimum option in my UF formula). In addition, although I don't know CUDA, I'd guess that precomputing the sines and cosines will be considerably faster than calling sin() and cos() twice with the same argument - also does CUDA not have a sincos() function ?
|
|
« Last Edit: November 19, 2009, 11:01:16 PM by David Makin »
|
Logged
|
|
|
|
cbuchner1
|
|
« Reply #545 on: November 19, 2009, 11:17:02 PM » |
|
Thanks for the corrections. My power 5 looks less mutant now. And some other weird effects (such as banding effects in flat surface regions) are gone. In addition to the errors you found, I was not adding a constant c vector in each iteration - instead I was adding the current x vector in some kind of recursive feedback loop. I am surprised it even gave sane images. Here's the cleaned up code where I also renamed x to z. float R = sqrtf(z.x*z.x + z.y*z.y + z.z*z.z); float th = atan2(z.y, z.x); float ph = asinf(z.z / R);
float3 dz; const float3 c = z; float ph_dz = 0.0f; float th_dz = 0.0f; float R_dz = 1.0f;
const float sq_threshold = 4.0f; // divergence threshold
// Iterate to compute the distance estimator. int i = m_max_iterations;
const float p = power; // power of fractal while( i-- ) { // derivative dz.x = p*powf(R, p-1.0f) * R_dz*cosf(ph_dz+(p-1.0f)*ph)*cos(th_dz+(p-1.0f)*th)+1.0f; dz.y = p*powf(R, p-1.0f) * R_dz*cosf(ph_dz+(p-1.0f)*ph)*sin(th_dz+(p-1.0f)*th); dz.z = p*powf(R, p-1.0f) * R_dz*sinf(ph_dz+(p-1.0f)*ph ); R_dz = sqrtf(dz.x*dz.x + dz.y*dz.y + dz.z*dz.z); th_dz = atan2(dz.y, dz.x); ph_dz = asinf(dz.z/R_dz); // new x,y,z coordinate z.x = powf(R, p) * cosf(p*ph)*cos(p*th) + c.x; z.y = powf(R, p) * cosf(p*ph)*sin(p*th) + c.y; z.z = powf(R, p) * sinf(p*ph) + c.z;
R = sqrtf(z.x*z.x + z.y*z.y + z.z*z.z); th = atan2(z.y, z.x); ph = asinf(z.z / R);
// Stop when we know the point diverges. if( R > sq_threshold ) break; } return 0.5 * R * logf(R)/R_dz;
And finally after optimization (sincosf etc...) the computation part looks like this:
// derivative dz iteration float pP_ = p*powf(R, p-1.0f); float c1, s1; sincosf(ph_dz+(p-1.0f)*ph, &s1, &c1); float s1_, c1_; sincosf(th_dz+(p-1.0f)*th, &s1_, &c1_); dz.x = pP_ * R_dz*c1*c1_+1.0f; dz.y = pP_ * R_dz*c1*s1_; dz.z = pP_ * R_dz*s1; // polar coordinates of derivative dz R_dz = sqrtf(dz.x*dz.x + dz.y*dz.y + dz.z*dz.z); th_dz = atan2(dz.y, dz.x); ph_dz = asinf(dz.z /R_dz); // z iteration float P_ = powf(R, p); float s2,c2; sincosf(p*ph, &s2, &c2); float s2_, c2_; sincosf(p*th, &s2_, &c2_); z.x = P_ * c2*c2_ + c.x; z.y = P_ * c2*s2_ + c.y; z.z = P_ * s2 + c.z;
// polar coordinates of z R = sqrtf(z.x*z.x + z.y*z.y + z.z*z.z); th = atan2(z.y, z.x); ph = asinf(z.z / R);
|
|
« Last Edit: November 19, 2009, 11:33:59 PM by cbuchner1 »
|
Logged
|
|
|
|
David Makin
|
|
« Reply #546 on: November 19, 2009, 11:19:42 PM » |
|
|
|
|
Logged
|
|
|
|
shanest
Guest
|
|
« Reply #547 on: November 19, 2009, 11:22:26 PM » |
|
Hello,
I just found this thread in the last couple of days because of the publicity of twinbee's Mandelbulb article.
At anyrate, I'd love to get in and dabble with this stuff myself. I have pretty strong background in both Math and programming, but haven't experimented with fractals since playing around in Mathematica 5 years ago and have never done much graphics-based programming.
What is the best way to get started with this? In particular, how would I write something like twinbee's custom raymarcher? Those images are absolutely beautiful.
In general, I'd prefer to know of solutions that are free/open-source and cross-platform (Linux is my standard OS) besides Xaos. I'm not adverse to trying to write something on my own, but basically just want to get exploring in the easiest way possible.
The easiest free route to anything fractal where you want to write your own formulas is probably ChaosPro: http://www.chaospro.de/Though as with Ultra Fractal this will not produce the fastest possible routines since that's always going to be better coded directly in C/C++ etc. or better still for a GPU (if you've got good cooling) If you want to try in ChaosPro my UF formula here: http://www.fractalgallery.co.uk/MMFWip3D.zipincludes many of the formulas discussed in this thread using basic Phong rendering and is fairly easily adaptable to work in ChaosPro - just remove all references to the use of the fBm (to get the formula from the zip, download & install the trial version of UF5, run it and "Update Public Formulas" from the Options menu, unzip the above file, copy all the text from the txt file and then paste into the open fractal window in UF5. Then when the parameter file has pasted click on the edit formula button (top right) and you then have the text source for the UF fornula which you can transfer/adapt to ChaosPro. Arrgh - apologies, I missed that you said "cross-platform" and Linux For now, I'm running UF5 under WINE and it appears to work well. I can't, however, figure out how to get your 3D code or the 3DRaytracerFormula plugin. I've updated the public forums, but if I paste the text into the "Open Fractal" window, the program just crashes on me. What's the easiest way to get your renderer up and running? I'd love to explore this construction and make some changes myself.
|
|
|
Logged
|
|
|
|
David Makin
|
|
« Reply #548 on: November 19, 2009, 11:33:28 PM » |
|
In addition to the errors you found, I was not adding a constant c vector in each iteration - instead I was adding the current x vector in some kind of recursive feedback loop. I am surprised it even gave sane images.
I missed that (I never thought to check the constant), glad it seems to be fixed now. Another point - if you make the +1.0f in the iterated derivative into a passed parameter of either 0 or 1 then you have a routine that works for Mandelbrots (1) or Julias (0). I don't suppose an ATI X600 or even an ATI X1900XT are CUDA-enabled ?
|
|
« Last Edit: November 19, 2009, 11:41:49 PM by David Makin »
|
Logged
|
|
|
|
|
|