. Features
. Gallery
. Download
. Documentation
. Resources
. Mailing Lists
. Programs
. Feature Voting
. Wishlist
. Theory
. Tutorials
. Formula DB
. Contact
Release 4.0

ChaosPro Formula Database

Size24 KB
OwnerEdgar Malinovsky
Last Modified:18 Jul 2017

Brahmabrot {

// This is different from standart Buddhabrot in that
// colours are calculated from progressive curves
// using Wave Trichrome method, who are inspired by RGB Buddhabrots but needs fewer iterations.
// As it don't tests for insdes or outsides of fractal, but mixes buddhabrot and antibuddhabrot.
// Alsou it used both mandelbrot and newton bailout.
// source code for this mostly is taken from Susan D. Chambless buddhabrot.
// and one more loop.
// Some formulas like Swirl transform, Royal, SummonerEye, Gavarun are by Kram1032.
// Buddhabrot technique is by Melinda Green.

//By Edgar Malinovsky 02.12.2012.

// 08.12.2012
// Added newton bailout revealing more features.
// Tweeking of parameters, so that there are less dots.
// Changed some formulas for another.

// 21.12.2012 + QuasiJulia set (mix of mandelbrot and julia sets)
// + faster bailout using modulus without sqrt.
// You may redistribute this algorithm, modify, derivate or use comercialy as you wish as long as you give proper credits.

// 21.01.2013 + Sigmoid transfer function.

// 21.05.2013
// + equalisation for large sample size.
// + few formula changes.

//15.08.2013. + triangle transfer function and more control over equalisation.
//03.09.2013. + two formulas and one code simplification.
//01.10.2013. + more equaly distributed float sequences (halton+RND)/2.
//26.10.2013. + swirlbox formula. Would require zoom out and 8;8 pixel source.
//30.10.2014. + fractalus tehna formula.

#define DIRECT
float increaser, maxcolour, antilightr, antilightg, antilightb;
parameter float lightr, lightg, lightb;
int seed,pwid,phgt,irandx1,irandy1,superloop,slcounter;
parameter int seedinput;
float datar,datag,datab;
float pixr[trunc(width),trunc(height)];  // offscreen image
float pixg[trunc(width),trunc(height)];  // offscreen image
float pixb[trunc(width),trunc(height)];  // offscreen image
parameter int Parm_maxiter;
complex locations[Parm_maxiter];  // collect locations
float colourcnt;
int Var_x,Var_y, iter, locindex,cnt,xcrd,ycrd;
float xc,yc,bscale,dx,dy, srcminx, srcminy,nsamples,srcx1,srcy1;
parameter float srcwidth, srcheight;
complex Var_z, c, zold;
parameter int sampledensity, starpower, formula;
parameter float power, talisadd, unitvector,quadfactor,frequency,spin, stargeom, scalarr,scalarg,scalarb, ambient, sigmoidlight;
float resultr,resultg,resultb, resultalpha,sumr,sumg,sumb;
parameter int postfn,switchrgb,palette, settype;
color gradcolor;
parameter complex julia, centralorbit;
parameter bool equalisation, addhalton;
float haltonx,haltony, form;
int cycle;

	void init_once(void)
		seed= seedinput;

		pwid= trunc(width);
		phgt= trunc(height);

		//3 arrays for RGB
		//calculate buddha loop many times

		colourcnt= 0;  //colourcounter
		Var_x= 0;		Var_y= 0;  // Loop counters & integer coords
		xc=  real(center);  // Scaling constants
		yc= -imag(center);

		srcminx= - (srcwidth* 0.5);
		srcminy= - (srcheight* 0.5);
		bscale= (height* magn) / 3;

		// Initialize arrays of RGB pixels with neutral colour.
		while  (Var_x< width)
			Var_y= 0;
			while  (Var_y< height)
				pixr[Var_x, Var_y] = ambient;
				pixg[Var_x, Var_y] = ambient;
				pixb[Var_x, Var_y] = ambient;
				Var_y= Var_y+ 1;
			Var_x= Var_x+ 1;

		// Main buddha iteration loop
		nsamples= round(width* height* magn);
		cnt= 0;// Loop counter

		//if sample number is too large, divide single
		//loop in many small. 12 divides better than 10, so multiples of 12 is used.
		if  (sampledensity> 497664)
			nsamples= trunc(nsamples/3456);
		else if  (sampledensity> 41472)
			nsamples= trunc(nsamples/288);
		else if  (sampledensity> 3456)
			nsamples= trunc(nsamples/24);
			nsamples= trunc(nsamples/4);

		nsamples=  nsamples* sampledensity;

		while  (slcounter< superloop)  // superloop
			while  (cnt< nsamples)  //main buddha loop
				// generate random integers (-#randomrange to #randomrange)
				irandx1= seed= random(seed);
				irandy1= seed= random(seed);

				if  (addhalton==true)
					haltonx= 0;
					form= 0.5;
					cycle= cnt+34;
					while  (cycle> 0)
						haltonx= haltonx+ form* (cycle% 2);
						cycle= floor(cycle*0.5);
						form= form*0.5;

					haltony= 0;
					form= 0.2;
					cycle= cnt+34;
					while  (cycle> 0)
						haltony= haltony+ form* (cycle% 5);
						cycle= floor(cycle*0.2);
						form= form*0.2;

					// mean of random float and halton numbers
					srcx1= (abs(irandx1) / randomrange+haltonx)*0.5*srcwidth+ srcminx;
					srcy1= (abs(irandy1) / randomrange+haltony)*0.5*srcheight+ srcminy;

					//convert to random floats.
					srcx1= (abs(irandx1) / randomrange)*srcwidth+ srcminx;
					srcy1= (abs(irandy1) / randomrange)*srcheight+ srcminy;

if  (settype=="Mset")
				// Mset with random c value
				Var_z= 0;
				c= complex( srcx1, srcy1);
else if  (settype=="QuasiJulia")
				//like julia set with random start z and c = julia + pixel
				Var_z= complex( srcx1, srcy1);
				c= Var_z+julia;
				// iteration count and modulus, this don't need large bailout
				iter= 0;
				while  ( (|Var_z| < 16) && (|zold-Var_z| >0.000001 ) && (iter< Parm_maxiter) )  //fractal formula loop
					if  (formula==0)
						Var_z= sqr(Var_z)+c;
					else if  (formula==1)
						Var_z= Var_z^power/(Var_z^(power-1) + talisadd) +c;
					else if  (formula==2)
						Var_z= Var_z*0.5 - Var_z*Var_z*Var_z+ c;
					else if  (formula==3)
						Var_z= conj(sqr(Var_z))+c;
					else if  (formula==4)
					else if  (formula==5)
						//8th modulus Mbrot
					else if  (formula==6)
						//Unit Vector - Mbrot
						Var_z= Var_z/cabs(Var_z)*unitvector+Var_z;
					else if  (formula==7)
						//Quadratic General
						Var_z=complex( sqr(real(Var_z)) + sqr(imag(Var_z)), real(Var_z)*imag(Var_z)*2) + c;
					else if  (formula==8)
						//Celtic Mandelbrot
						Var_z= Var_z^power;
						Var_z= Var_z- real(Var_z) + abs(real(Var_z)) - c;
					else if  (formula==9)
						//Rotated Mandelbrot
					else if  (formula==10)
						Var_z= (sqr(Var_z)*(35 * sqr(Var_z) - 30) + 3) / 8 + c;
					else if  (formula==11)
						Var_z=Var_z^power*iter*0.05 +c;
					else if  (formula==12)
					else if  (formula==13)
						Var_z= conj(Var_z^power*iter*0.05)+c;
					else if  (formula==14)
						Var_z= abs(Var_z^power*iter*0.05)+c;
					else if  (formula==15)
						Var_z= complex( sqr(real(Var_z)) + sqr(imag(Var_z)), real(Var_z)*imag(Var_z)*quadfactor )*iter*0.05 + c;
					else if  (formula==16)
						Var_z= sqr(Var_z) + zold + c;
					else if  (formula==17)
						//Multipowerbrot Odd
						Var_z= ((((Var_z^3*c+1i)^3)+1i)^3)+1i;
					else if  (formula==18)
					else if  (formula==19)
						Var_z= c*(sqr(Var_z)*(sqr(Var_z)*8+8)+1);
					else if  (formula==20)
						Var_z=complex( sqr(real(Var_z)) - sqr(imag(Var_z)), -2*imag(Var_z)*abs(real(Var_z))  ) + c;
					else if  (formula==21)
						//Royal Imagination
						Var_z=complex( sqr(real(Var_z))- sqr(sqr(imag(Var_z))) ,  2*real(Var_z)*imag(Var_z)  ) +c;
					else if  (formula==22)
						//Swirl Mbrot
						Var_z=(exp(complex(0, atan2(Var_z)*spin + frequency*cabs(Var_z)  ) )*Var_z )^power+c;
					else if  (formula==23)
						Var_z=(Var_z+ c) / ( conj(Var_z)- c+ talisadd);
					else if  (formula==24)
						Var_z=(complex( cabs(Var_z), 0 )^complex(talisadd, atan2(Var_z)  )) +c;
					else if  (formula==25)
						Var_z=sinh(Var_z)*Var_z - sqr(c);
					else if  (formula==26)
						//Multipowerbrot Even
						Var_z= sqr( ( sqr( Var_z*Var_z*c +1 )) -1 ) -1;
					else if  (formula==27)
						Var_z= sqr(flip ( Var_z^power /( talisadd+1e-15 + Var_z^(power-1) )+c) );
					else if  (formula==28)
								if  (cabs(Var_z)< cabs(c))
								Var_z= sqr(Var_z) + c;
								else if  (cabs(Var_z)== cabs(c))
								Var_z= sqr(Var_z);
								Var_z= sqr(Var_z)- c;
					else if   (formula==29)

					else if   (formula==30)
						Var_z=(Var_z+c)*(Var_z-c) *c+ Var_z*centralorbit;
					else if   (formula==31)
						Var_z=Var_z+ abs(real(Var_z)-1) - abs(real(Var_z)+1) + flip(  abs(imag(Var_z)-1) - abs(imag(Var_z)+1) );
						Var_z=exp(flip( frequency*cabs(Var_z)+ spin*atan2(Var_z)) ) *Var_z+c;
					else if   (formula==32)
						//Fractalus Techna
						Var_z=Var_z-Var_z/(ceil(Var_z) +1.0e-20)+c;

					locations[iter] = Var_z;
					iter= iter+ 1;

				}   //end fractal formula loop
				locindex= 1;  //for background contrast starts with 1.
				while ( locindex< iter)  //colour loop
					cnt= cnt+1;

					dx=  real( locations[locindex] ) - xc;
					dy=  imag( locations[locindex] ) - yc;

					// Scale to image
					Var_x= round(dx*bscale+ pwid*0.5);
					Var_y= round(dy*bscale+ phgt*0.5);

					// Plot the point only if inside image
					if  (Var_x>= 0 && Var_x< pwid&& Var_y>= 0 && Var_y< phgt)

						//colours calculated as RGB curves
						datar=  (datar+ increaser)/( scalarr+ abs(pixr[Var_x, Var_y])*antilightr);
						datag=  (datag+ increaser)/( scalarg+ abs(pixg[Var_x, Var_y])*antilightg);
						datab=  (datab+ increaser)/( scalarb+ abs(pixb[Var_x, Var_y])*antilightb);

						pixr[Var_x, Var_y] = pixr[Var_x, Var_y] + datar;
						pixg[Var_x, Var_y] = pixg[Var_x, Var_y] + datag;
						pixb[Var_x, Var_y] = pixb[Var_x, Var_y] + datab;

					locindex= locindex+ 1;

				}   //end colour loop
			}    //end main buddha loop
			//increase superloop counter,
			//set main loop to 0 and go throught next cycle.
			slcounter= slcounter+1;
		}   //end superloop

//for Equalisation only.
//loop calculates brightest pixel colour.
		if  (equalisation==true)
			while  (Var_x< width)
				Var_y= 0;
				while  (Var_y< height)
					pixr[Var_x, Var_y]=abs(pixr[Var_x, Var_y]);
					pixg[Var_x, Var_y]=abs(pixg[Var_x, Var_y]);
					pixb[Var_x, Var_y]=abs(pixb[Var_x, Var_y]);

					if  ( pixr[Var_x, Var_y] > maxcolour)
					{maxcolour=pixr[Var_x, Var_y];}
					if ( pixg[Var_x, Var_y] > maxcolour)
					{maxcolour=pixg[Var_x, Var_y];}
					if ( pixb[Var_x, Var_y] > maxcolour)
					{maxcolour=pixb[Var_x, Var_y];}

					Var_y= Var_y+ 1;
				Var_x= Var_x+ 1;
		} //end equalisation loop.		
//now formula will go throught pixels by fractal generator.
	void init(void)
		xcrd= 0;
		ycrd= 0;
		resultr= 0;
		resultg= 0;
		resultb= 0;
	void final(void)
		xcrd= x;
		ycrd= y;
		resultr= abs(pixr[xcrd, ycrd]);
		resultg= abs(pixg[xcrd, ycrd]);
		resultb= abs(pixb[xcrd, ycrd]);

//for equalisation. Uses sigmoid function.
if  (equalisation==true)
resultr=(sigmoidlight+1)*(resultr)/(sigmoidlight+ maxcolour);
resultg=(sigmoidlight+1)*(resultg)/(sigmoidlight+ maxcolour);
resultb=(sigmoidlight+1)*(resultb)/(sigmoidlight+ maxcolour);

		if  (postfn==0)
		else if  (postfn==1)

		else if  (postfn==2)
			resultr=1- resultr;
			resultg=1- resultg;
			resultb=1- resultb;

		else if  (postfn==3)

		else if  (postfn==4)

		else if  (postfn==5)
			sumr= resultr;
			sumg= resultg;
			sumb= resultb;
		else if  (postfn==6)
			resultr= abs( resultr-round(resultr) );
			resultg= abs( resultg-round(resultg) );
			resultb= abs( resultb-round(resultb) );

		else if  (postfn==7)

		else if  (postfn==8)
			resultr=sin((resultr) )*cos((resultg));
			resultg=sin((resultg) )*cos((resultr));
			resultb=sin((resultb) )*cos((resultr));
		else if  (postfn==9)
		else if  (postfn==10)
		else if  (postfn==11)
		// switching colour channels.
		if  (switchrgb==0)
		else if  (switchrgb==1)
		else if  (switchrgb==2)
		else if  (switchrgb==3)

		//colour mode: direct, using palette, or mixed.
		if  (palette==0)

			pixelcolor= rgb(resultr, resultg, resultb);

		else if  (palette==1)
			pixelcolor= gradient(resultg);

		else if  (palette==2)
			//gradient is by arithmetic mean of RGB
			gradcolor=gradient( (resultr+resultg+resultb)*0.333333333333333 );
			//harmonic of gradient and RGB
			resultr=2/(  recip (red(gradcolor))+ recip(resultr) );
			resultg=2/(  recip (green(gradcolor))+ recip(resultg) );
			resultb=2/(  recip (blue(gradcolor))+ recip(resultb) );
			pixelcolor= rgba(resultr, resultg, resultb,resultalpha);

		else if  (palette==3)
			// colour mode like of Fractal Explorer.
			// uses pallete, but each chanell is calculated seperately.
			resultalpha=alpha(gradient( resultg));

			pixelcolor= rgba(resultr, resultg, resultb, resultalpha);

		else if  (palette==4)
			//all waves included.
			pixelcolor=gradient(3/(recip(resultr) + recip(resultg) + recip(resultb) ) );
	void description(void)
		this.title = "Brahmabrot";
		separator.label2.caption  = "Use with NOP Formula aka Pixel.";

		separator.label3.caption  = "Buddha Block";
		sampledensity.caption = "Sample density/incrse";
		sampledensity.default =  250;
		sampledensity.hint="Main variable. The larger value, the more points hits image, the more detailed will be image. Put relatively small value for fast first calculation, then increase for smooth result. Larger image requires larger value, but then its slower.";
		Parm_maxiter.caption = "Max Iterations";
		Parm_maxiter.default =  250;
		Parm_maxiter.hint = "Maxiter for fractal. Long orbits will stay in certain alredy dense region, but small maxiter will make this too blury.";
		seedinput.caption = "Lucky Number";
		seedinput.default =  -8;
		seedinput.hint="Random seed used to calculate random numbers, who actualy are determined random like sequences. Different seeds marks different first(?) orbits.";

		addhalton.caption ="add Halton LDS";
		addhalton.default =  true;
		addhalton.hint="For better image quality. Adds Halton Sequences to Random float numbers and calculates arithmetic mean so that it have better distrubution and randomness.";

		separator.label4.caption  = "Formula Block";
		formula.caption="Fractal Formula";
		formula.default= 0;
		formula.enum= "Mandelbrot\nTalis\nStarbrot\nTricorn\nBurningSihp\n8th modulus Mbrot\nUnit Vector - Mbrot\nQuadratic General\nCeltic Mandelbrot\nRotated Mandelbrot\nChebyshevAxolotl\nMbrot*iters\nTalis+iters\nTricorn*iters\nBurningShip*iters\nQuadGen*iters\nManowar\nMultipowerbrot Odd\nMagnetII\nChebyshevT4\nPerpendicularMbrot\nRoyal Mbrot\nSwirl Mbrot\nSummonerEye\nGavarun\nMalinovskyDeco\nMultipowerbrot Even\nBumblebrot\nLogicTurtle\nTangent*Z\nCentral\nSwirlbox\nFractalus Techna";
		formula.hint= "Fractal formula used for calculation. Mbrot here stands fro Mandelbrot.";
		power.default= 2;
		power.visible =  (formula== 0||formula== 1||formula== 3||formula== 4||formula== 6||formula== 8||formula== 9||formula== 11||formula== 12||formula== 13||formula== 14||formula== 22||formula== 25||formula==27||formula==28||formula== 32);
		power.hint="Degree of formula.";
		starpower.caption="Star Power";
		starpower.default= 7;
		starpower.hint="Star sides = power-1";
		starpower.visible =  (formula== 2);
stargeom.caption="Star Geometry";
stargeom.default= 0.5;
stargeom.visible =  (formula== 2);
		unitvector.caption="Unit vector amount";
		unitvector.default= -0.5;
		unitvector.hint="Coefficient N for z=z+N*z/|z|";
		unitvector.visible =  (formula== 6);
		talisadd.caption="Talis addition";
		talisadd.default= 1;
		talisadd.hint="In Talis adds value to z z=z^2/(z+add). In another fomulas adds value in respective places. In Gavarun it is real part of complex power.";
		talisadd.visible =  (formula== 1||formula==23||formula==24||formula==27);
		quadfactor.caption="Factor of x*y";
		quadfactor.default= 2;
		quadfactor.visible =  (formula== 7||formula==15);

		frequency.default= 1;
		frequency.visible =  (formula==22||formula==31);
		frequency.hint="How strongly swirls.";
		spin.caption="Spin Number";
		spin.default= 1;
		spin.visible =  (formula==22||formula==31);
		spin.hint="Each 0.5 of spin gives additional simmetry axis.";

		centralorbit.default= (0.5,0);
		centralorbit.visible =  (formula==30||formula==31);
		centralorbit.hint="Changes center oriented shapes. Imaginary value rotates, real value changes shape. For Swirlbox works like scale for mandelbox.";

		settype.caption="Set type";
		settype.default= 0;
		settype.hint="Normal mandelbrot set or Quasi julia set initialised with z=randompixel and c=julia seed + randompixel. Good with some formulas. Coz normal julia sets don't works with as buddhabrots.";

		julia.caption="Julia Seed";
		julia.default= (-0.4, 0.25);
		julia.visible = (settype=="QuasiJulia");

		separator.label5.caption  = "Pixel input Block";
		srcwidth.caption = "Pixel source Width";
		srcwidth.default =  5.0;
		srcwidth.hint="Input pixel area depends on width and height. Too much is waste of PC resources, not enough will mean that some fractal parts will dissapear. ";
		srcheight.caption = "Pixel source Height";
		srcheight.default =  4.0;

		separator.label6.caption  = "Colour Block";
		switchrgb.caption = "Switch Colours";
		switchrgb.enum ="None\nSwitch Red and Green\nSwitch Red and Blue\nSwitch Green and Blue";
		switchrgb.default= 0;
		switchrgb.hint= "Switch colour channels to change image tones in direct mode, so that don't need to change unscrutinable light and scalar of RGB.";
		ambient.caption = "Ambient Light";
		ambient.default =  0.13;
		ambient.hint="Greyscale colour value of uniterated pixel. Result then is added / substracted from this.";
		postfn.caption = "Transfer Function";
		postfn.enum = "0- None\n1- Sin (periodic)\n2- Inverted\n3- Square Power (sharper)\n4- SinInverted (periodic)\n5- Accentuate RGB\n6- Solarisation (periodic)\n7- Hyperbolic Tangent\n8- SineCosineMix (periodic)\n9- Haversine (periodic)\n10- Sigmoid\n11- Triangle (periodic)";
		postfn.default =   0;
		postfn.hint="The same as UF, but applied before colour mode, and works with direct colour. Periodic will allways turn white regions into colour.";

		palette.caption = "Colour Mode";
		palette.enum= "Direct Colouring\nGradient Based\nMixed Harmonic\nFractal Explorer like\nGradient by Harmonic";
		palette.default= 0;
		palette.hint= "Gradient Based is gradient calculated from green channel, gradient harmonic is gradient calc from mean of all channels. Mixed is harmonic mean between gradient colour (by mean of RGB) and RGB channels. Fractal Explorer like is RGB values calculated seperately from gradient. All exept direct colouring uses gradient and alpha channel.";
		equalisation.caption ="Sigma Equalisation";
		equalisation.default =  false;
		equalisation.hint="Darkens all the pixels so that only brightest have max colour. For sample density when large areas are white. Large sample density + equalisation allows smooth pictures but then result depends on image size.";
		sigmoidlight.caption = "sigmoid Light";
		sigmoidlight.default =  10;
		sigmoidlight.visible =  (equalisation);
		sigmoidlight.hint="The larger value the less effect thus lighter image.";

//Simplified and expanded (non)Buddhabrot. Use with PIXEL aka no formula and wait. 
//To increase quality increase sample density. 
//Difference from Buddhabrot is that it don't test for escaping or non escaping orbits, 
//uses dual divergent (mandelbrot) and convergent (newton) bailout conditions 
//and RGB colours are by Wave Trichrome method. It's faster than Buddhabrot. 
//It is s suposed to work with direct colouring but 'll work with gradients 
//especialy with smoothing like Sigma Equalisation or Accentuate RGB. 
//With large density try periodic transfer funtions and -1< ambient light <1.
// On resize it changes hits per pixel, so sample density should be increased 
//(1280x960 = 1 228 800 pixels / 480x360 = 172 800 pixels is 1 228 800/172 800 = 7 
//thus density must be increased 7 times. But it 'll take 7x7 times longer to render). 
//With extreme density and resolution it could exceeded integer numbers limits. 

		separator.label7.caption  = "RGB block";
		lightr.caption = "Red light";
		lightr.default =  0.38;
		scalarr.caption = "Red scalar";
		scalarr.default =  0.7;
		lightg.caption = "Green light";
		lightg.default =  0.98;
		scalarg.caption = "Green scalar";
		scalarg.default =  1.6;
		lightb.caption = "Blue light";
		lightb.default =  0.14;
		scalarb.caption = "Blue scalar";
		scalarb.default =  0.3;
separator.label8.caption  = "http://edo555.deviantart.com/";