CalvinCreator
Forums Newbie
Posts: 9
|
|
« on: April 20, 2017, 12:28:13 AM » |
|
I am interested in learning how to implement the Triangle Inequality Average Coloring algorithm. However, I can only find information on it in Jussi Härkönen's master's thesis, which I don't have the math to understand, or in the Ultra Fractal formula database, and while I have tried to understand what is going on I am very unfamiliar with the libraries used. How does the Triangle Inequality Average Coloring algorithm work? Pheudo code would be much appreciated, or even just a paragraph or two of description! *EDIT* I have also found a JavaScript implementation here: http://jsfiddle.net/LMNu9/5/ but it's just so much gibberish to me because I have no familiarity with JavaScript or languages like it. Thank you very much!
|
|
|
Logged
|
|
|
|
Softology
|
|
« Reply #1 on: April 20, 2017, 01:38:23 AM » |
|
Maybe this code will help (if you are more familiar with C based GLSL shader code)? This is for a basic power 2 Mandelbrot with TIA coloring. #version 400
uniform vec2 resolution; uniform vec3 palette[256]; uniform double xmin; uniform double xmax; uniform double ymin; uniform double ymax; uniform double bailout; uniform int maxiters; uniform int samplepixels;
double sqrsamplepixels=double(samplepixels*samplepixels); double bailout_squared=double(bailout*bailout); double magnitude,r1,r2,g1,g2,b1,b2,tweenval; double realiters; vec4 finalcol,col; int superx,supery; double stepx=(xmax-xmin)/resolution.x/samplepixels; double stepy=(ymax-ymin)/resolution.y/samplepixels; int colval,colval1,colval2; dvec2 z,c; //triangle inequality average coloring double sum,sum2,ac,il,lp,az2,lowbound,f,index,tr,ti; int mandelbrotPower; double rval,gval,bval,rval1,gval1,bval1,rval2,gval2,bval2;
void main(void) { sum=0; sum2=0; ac=0; il=0; lp=0; mandelbrotPower=2;
finalcol=vec4(0,0,0,0); for (supery=0;supery<samplepixels;supery++) { for (superx=0;superx<samplepixels;superx++) { c.x = xmin+gl_FragCoord.x/resolution.x*(xmax-xmin)+(stepx*superx); c.y = ymin+gl_FragCoord.y/resolution.y*(ymax-ymin)+(stepy*supery); int i; z = dvec2(0.0,0.0);
//triangle inequality average coloring sum = 0; sum2 = 0; ac = sqrt(c.x * c.x + c.y * c.y); il = 1.0 / log(mandelbrotPower); lp = log(float(log(float(bailout)) / mandelbrotPower)); az2 = 0.0; lowbound = 0.0; f = 0.0; index = 0.0;
for(i=0; i<maxiters; i++) { //START OF FRACTAL FORMULA double x = (z.x * z.x - z.y * z.y) + c.x; double y = (z.y * z.x + z.x * z.y) + c.y; //END OF FRACTAL FORMULA magnitude=(x * x + y * y); if(magnitude>bailout_squared) break; z.x = x; z.y = y;
//triangle inequality average sum2=sum; if ((i!=0)&&(i!=maxiters-1)) { tr=z.x-c.x; ti=z.y-c.y; az2=sqrt(tr * tr + ti * ti); lowbound=abs(az2 - ac); sum+=((sqrt(z.x * z.x + z.y * z.y)-lowbound)/(az2+ac-lowbound)); }
}
if (i==maxiters) { col=vec4(0.0,0.0,0.0,1.0); } else { //triangle inequality average sum=sum/i; sum2=sum2/(i-1.0); f=il*lp - il*log(log(float(length(z)))); index=sum2+(sum-sum2)*(f+1.0); realiters=255*index; colval1= int(mod(realiters,255)); colval2=int(mod((colval1+1),255)); tweenval=fract(realiters); if (colval1<0) { colval1=colval1+255; } if (colval2<0) { colval2=colval2+255; } rval1 =palette[colval1].r; gval1 =palette[colval1].g; bval1 =palette[colval1].b; rval2 =palette[colval2].r; gval2 =palette[colval2].g; bval2 =palette[colval2].b; rval =rval1 +((rval2 - rval1)*tweenval); gval =gval1 +((gval2 - gval1)*tweenval); bval =bval1 +((bval2 - bval1)*tweenval); col=vec4(rval,gval,bval,1.0); } finalcol+=col; } } gl_FragColor = vec4(finalcol/sqrsamplepixels); }
|
|
« Last Edit: April 20, 2017, 01:48:01 AM by Softology »
|
Logged
|
|
|
|
Adam Majewski
|
|
« Reply #2 on: April 20, 2017, 02:49:22 PM » |
|
|
|
« Last Edit: April 21, 2017, 09:48:35 PM by Adam Majewski, Reason: new link »
|
Logged
|
|
|
|
CalvinCreator
Forums Newbie
Posts: 9
|
|
« Reply #3 on: April 21, 2017, 03:19:22 AM » |
|
Softology, can you describe how it works qualitatively? That would be wonderful! If you don't have the time, could you tell me what samplepixels is and what the fract method does? Are supery and superx the current x and y pixels? Is the mod method modulus or floor modulus? Finally, is c the complex number represented by the coordinates of the point being examined, and do these lines: c.x = xmin+gl_FragCoord.x/resolution.x*(xmax-xmin)+(stepx*superx); c.y = ymin+gl_FragCoord.y/resolution.y*(ymax-ymin)+(stepy*supery); convert the screen coordinates into real world coordinates?
Adam Majewski, I actually mentioned one of your sources already as unintelligible to me, and your second source mentions Triangle Inequality in passing only, pointing out that one of the fractal images was created using that method. Thanks, however.
|
|
|
Logged
|
|
|
|
Softology
|
|
« Reply #4 on: April 21, 2017, 06:33:00 AM » |
|
Fract returns the fractional part of a number, ie fract(1.23) returns 0.23. Mod is modulus. See here for the official GLSL language spec https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.20.pdfThe c.x and c.y calculate the real and imaginary parts of the complex C in Z=Z^2+C But yes, they convert the pixel location onto the complex plane. Samplepixels supports calculating mutliple values per pixel. Here is the code without supersampling to make it (maybe?) easier to follow. #version 400
uniform vec2 resolution; uniform vec3 palette[256]; uniform double xmin; uniform double xmax; uniform double ymin; uniform double ymax; uniform double bailout; uniform int maxiters;
double bailout_squared=double(bailout*bailout); double magnitude,r1,r2,g1,g2,b1,b2,tweenval; double realiters; vec4 finalcol,col; int superx,supery; double stepx=(xmax-xmin)/resolution.x; double stepy=(ymax-ymin)/resolution.y; int colval,colval1,colval2; dvec2 z,c; //triangle inequality average coloring double sum,sum2,ac,il,lp,az2,lowbound,f,index,tr,ti; int mandelbrotPower; double rval,gval,bval,rval1,gval1,bval1,rval2,gval2,bval2;
void main(void) { sum=0; sum2=0; ac=0; il=0; lp=0; mandelbrotPower=2;
finalcol=vec4(0,0,0,0); c.x = xmin+gl_FragCoord.x/resolution.x*(xmax-xmin); c.y = ymin+gl_FragCoord.y/resolution.y*(ymax-ymin); int i; z = dvec2(0.0,0.0);
//triangle inequality average coloring sum = 0; sum2 = 0; ac = sqrt(c.x * c.x + c.y * c.y); il = 1.0 / log(mandelbrotPower); lp = log(float(log(float(bailout)) / mandelbrotPower)); az2 = 0.0; lowbound = 0.0; f = 0.0; index = 0.0;
for(i=0; i<maxiters; i++) { //START OF FRACTAL FORMULA double x = (z.x * z.x - z.y * z.y) + c.x; double y = (z.y * z.x + z.x * z.y) + c.y; //END OF FRACTAL FORMULA magnitude=(x * x + y * y); if(magnitude>bailout_squared) break; z.x = x; z.y = y;
//tia sum2=sum; if ((i!=0)&&(i!=maxiters-1)) { tr=z.x-c.x; ti=z.y-c.y; az2=sqrt(tr * tr + ti * ti); lowbound=abs(az2 - ac); sum+=((sqrt(z.x * z.x + z.y * z.y)-lowbound)/(az2+ac-lowbound)); }
}
if (i==maxiters) { col=vec4(0.0,0.0,0.0,1.0); } else { //triangle inequality average sum=sum/i; sum2=sum2/(i-1.0); f=il*lp - il*log(log(float(length(z)))); index=sum2+(sum-sum2)*(f+1.0); realiters=255*index; colval1= int(mod(realiters,255)); colval2=int(mod((colval1+1),255)); tweenval=fract(realiters); if (colval1<0) { colval1=colval1+255; } if (colval2<0) { colval2=colval2+255; } rval1 =palette[colval1].r; gval1 =palette[colval1].g; bval1 =palette[colval1].b; rval2 =palette[colval2].r; gval2 =palette[colval2].g; bval2 =palette[colval2].b; rval =rval1 +((rval2 - rval1)*tweenval); gval =gval1 +((gval2 - gval1)*tweenval); bval =bval1 +((bval2 - bval1)*tweenval); col=vec4(rval,gval,bval,1.0); } gl_FragColor = vec4(col); }
What language are you using to write the code? If you can get a basic Mandelbrot renderer going first then adding TIA functionality should not be that difficult.
|
|
|
Logged
|
|
|
|
xenodreambuie
|
|
« Reply #5 on: April 21, 2017, 10:38:23 AM » |
|
Here's some general explanation. The triangle inequality is basically a cheap way to calculate an angle. TIA is averaging the angle over all iterations to get a smooth result. So there is some initialization and some calculations per iteration to do the sum. It has to store the sum at the previous iteration before adding the next one so you can interpolate between them to get a continuous function between iteration bands (in the same way that continuous potential is usually interpolated). This interpolation is done after the iterations bail out.
|
|
|
Logged
|
|
|
|
CalvinCreator
Forums Newbie
Posts: 9
|
|
« Reply #6 on: April 21, 2017, 02:24:53 PM » |
|
Thank you both very much! The code is much more understandable without the supersampling(it's probably rather obvious that I had never heard of it before) and the qualitative description is great. Thank you!
|
|
|
Logged
|
|
|
|
superheal
|
|
« Reply #7 on: April 21, 2017, 04:15:40 PM » |
|
I tried to reproduce the result but I got this http://imgur.com/a/JCyPdthere are discontinuities between the bailout bands, anyone knows what might causing this?
|
|
|
Logged
|
|
|
|
superheal
|
|
« Reply #8 on: April 21, 2017, 04:34:32 PM » |
|
Nevermind I changed the smoothing method, to general smoothing that uses the current and previous value of z and got it to work. http://imgur.com/a/Ex7wx
|
|
|
Logged
|
|
|
|
Adam Majewski
|
|
« Reply #9 on: April 21, 2017, 06:00:49 PM » |
|
How do you run this code ? ( gcc, fragmentarium, shadertoy ? ) It is fragment or vertex shader ?
|
|
« Last Edit: April 23, 2017, 12:17:10 PM by Adam Majewski, Reason: ext »
|
Logged
|
|
|
|
Adam Majewski
|
|
« Reply #10 on: April 21, 2017, 06:16:00 PM » |
|
How do you run this code ? ( gcc, fragmentarium, shadertoy ? )
can you post the code ?
|
|
|
Logged
|
|
|
|
CalvinCreator
Forums Newbie
Posts: 9
|
|
« Reply #11 on: April 21, 2017, 10:59:41 PM » |
|
I turned the GLSL code into a java program that I have been executing, although I am not sure I did it correctly. When I set the bailout value too high (over 10^5) the value of z becomes NaN as far as Java is concerned so the algorithm breaks. I would think this is because the number is too big, but I'm not getting an error so I don't know. Even when it doesn't work, when the bailout value is close to the limit I get color bands like this: http://imgur.com/a/yeU2LWhen I make the bailout lower, like 10^3, it looks like this: http://imgur.com/a/odP3iThere are two things I see wrong with this: a, my understanding is the Triangle Inequality Average Coloring works best with high bailout values--I believe 10^20 is recommended and b, the second option looks the same regardless of whether or not I use the calculated fractional value to interpolate between the two colors. Any ideas?
|
|
|
Logged
|
|
|
|
CalvinCreator
Forums Newbie
Posts: 9
|
|
« Reply #12 on: April 22, 2017, 12:35:53 AM » |
|
Additionally, when I zoom in a lot all contrast disappears. I seems most of my color palette is not being used, or not being used often. Why is this? http://imgur.com/a/wwfhM
|
|
|
Logged
|
|
|
|
|
Softology
|
|
« Reply #14 on: April 25, 2017, 10:59:12 PM » |
|
my understanding is the Triangle Inequality Average Coloring works best with high bailout values--I believe 10^20 is recommended
I use 800,000 as a bailout. It seems to stop the iteration banding and image corruption. Some areas do lack details when using TIA. A more busy palette can help, ie one with bands of shaded colors rather than a simple single shade from blue to white.
|
|
|
Logged
|
|
|
|
|