Mandelbrot shader

Andreas999

Newcomer
Hi,
I wrote a mandelbrot and julia program which you can find here: http://www.lichtundliebe.info/projects/2DFractal/2DFractal.jnlp. Here is the code: http://www.lichtundliebe.info/projects/2DFractal.zip
If you have no deep zoom, the program works at all shader model 3.0 cards. If you have deeper zoom (5-6x click at the fractal), it uses a fixed point arithmetic for higher precision:
Code:
varying vec2 position;
//uniform sampler2D myColorTable;

uniform float maxIter;
uniform vec4 deltaVectorX1;
uniform vec4 deltaVectorX2;
uniform vec4 deltaVectorY1;
uniform vec4 deltaVectorY2;
uniform vec4 lowerLeftCornerX1;
uniform vec4 lowerLeftCornerX2;
uniform vec4 lowerLeftCornerY1;
uniform vec4 lowerLeftCornerY2;

//1/1024.0=0.0009765625
// the float mantissa has only 23 bits => number->number1 should be enough
void convertToBigSize(in float number,out vec4 number1, out vec4 number2){
	number1=vec4(0.0);
	number2=vec4(0.0);
	float signum=sign(number);
	number=abs(number);
	float temp=floor(number);
	number1.r=temp;
	number-=temp;
	number*=1024.0;
	temp=floor(number);
	number1.g=temp;
	number-=temp;
	number*=1024.0;
	temp=floor(number);
	number1.b=temp;
	number-=temp;
	number*=1024.0;
	temp=floor(number);
	number1.a=temp;
	number1*=signum;
}

//41 Ops
void add(inout vec4 a1, inout vec4 a2, in vec4 b1, in vec4 b2){
	a1+=b1;
	a2+=b2;
	//the values after the point have to be greater than 0.0
	a1.r-=2.0;//-2
	a2.a+=2048.0;
	a1.gba+=2046.0;
	a2.rgb+=2046.0;
		
	float temp=floor(a2.a*0.0009765625);
	a2.b+=temp;
	a2.a-=temp*1024.0;
		
	temp=floor(a2.b*0.0009765625);
	a2.g+=temp;
	a2.b-=temp*1024.0;
	
	temp=floor(a2.g*0.0009765625);
	a2.r+=temp;
	a2.g-=temp*1024.0;
	
	temp=floor(a2.r*0.0009765625);
	a1.a+=temp;
	a2.r-=temp*1024.0;
	
	temp=floor(a1.a*0.0009765625);
	a1.b+=temp;
	a1.a-=temp*1024.0;
	
	temp=floor(a1.b*0.0009765625);
	a1.g+=temp;
	a1.b-=temp*1024.0;
	
	temp=floor(a1.g*0.0009765625);
	a1.r+=temp;
	a1.g-=temp*1024.0;
	
}
//44+30+63=137ops
void mult(inout vec4 a1, inout vec4 a2, in vec4 b1, in vec4 b2){
	vec4 z11=a1*b1.r;
	vec4 z12=a2*b1.r;
	vec4 z21=a1*b1.g;
	vec4 z22=a2*b1.g;
	vec4 z31=a1*b1.b;
	vec4 z32=a2*b1.b;
	vec4 z41=a1*b1.a;
	vec4 z42=a2*b1.a;
	vec4 z51=a1*b2.r;
	vec4 z52=a2*b2.r;
	vec4 z61=a1*b2.g;
	vec4 z62=a2*b2.g;
	vec4 z71=a1*b2.b;
	vec4 z72=a2*b2.b;
	vec4 z81=a1*b2.a;
	vec4 z82=a2*b2.a;
	vec3 tempM2=z82.gba;
	tempM2.rg+=z72.ba;
	tempM2.r+=z62.a;
	vec4 tempM1=z52;
	tempM1.a+=z82.r;
	tempM1.rgb+=z81.gba;
	tempM1.ba+=z72.rg;
	tempM1.rg+=z71.ba;
	tempM1.gba+=z62.rgb;
	tempM1.r+=z61.a;
	tempM1.rgb+=z42.gba;
	tempM1.rg+=z32.ba;
	tempM1.r+=z22.a;
	a2=z51;
	a2.a+=z81.r;
	a2.ba+=z71.rg;
	a2.gba+=z61.rgb;
	a2.a+=z42.r;
	a2.rgb+=z41.gba;
	a2.ba+=z32.rg;
	a2.rg+=z31.ba;
	a2.gba+=z22.rgb;
	a2.r+=z21.a;
	a2+=z12;
	a1=z11;
	a1.gba+=z21.rgb;
	a1.ba+=z31.rg;
	a1.a+=z41.r;
	
	float tempSign=sign(tempM2.g);	
	float temp=floor(abs(tempM2.g)*0.0009765625);
	tempM2.r+=temp*tempSign;
	tempSign=sign(tempM2.r);
	temp=floor(abs(tempM2.r)*0.0009765625);
	tempM1.a+=temp*tempSign;
	tempSign=sign(tempM1.a);
	temp=floor(abs(tempM1.a)*0.0009765625);
	tempM1.b+=temp*tempSign;
	tempSign=sign(tempM1.b);
	temp=floor(abs(tempM1.b)*0.0009765625);
	tempM1.g+=temp*tempSign;
	tempSign=sign(tempM1.g);
	temp=floor(abs(tempM1.g)*0.0009765625);
	tempM1.r+=temp*tempSign;
	tempSign=sign(tempM1.r);
	temp=floor(abs(tempM1.r)*0.0009765625);
	a2.a+=temp*tempSign;
	
	tempSign=sign(a2.a);
	temp=floor(abs(a2.a)*0.0009765625);
	a2.b+=temp*tempSign;
	a2.a-=temp*1024.0*tempSign;
		
	tempSign=sign(a2.b);	
	temp=floor(abs(a2.b)*0.0009765625);
	a2.g+=temp*tempSign;
	a2.b-=temp*1024.0*tempSign;
	
	tempSign=sign(a2.g);	
	temp=floor(abs(a2.g)*0.0009765625);
	a2.r+=temp*tempSign;
	a2.g-=temp*1024.0*tempSign;
	
	tempSign=sign(a2.r);	
	temp=floor(abs(a2.r)*0.0009765625);
	a1.a+=temp*tempSign;
	a2.r-=temp*1024.0*tempSign;
	
	tempSign=sign(a1.a);	
	temp=floor(abs(a1.a)*0.0009765625);
	a1.b+=temp*tempSign;
	a1.a-=temp*1024.0*tempSign;
	
	tempSign=sign(a1.b);	
	temp=floor(abs(a1.b)*0.0009765625);
	a1.g+=temp*tempSign;
	a1.b-=temp*1024.0*tempSign;
	
	tempSign=sign(a1.g);	
	temp=floor(abs(a1.g)*0.0009765625);
	a1.r+=temp*tempSign;
	a1.g-=temp*1024.0*tempSign;
		
}

/*//only for test purposes
float convertToFloat(in vec4 X1, in vec4 X2){
	float number=X1.r;
	float divi=1024.0;
	number+=X1.g/divi;
	divi*=1024.0;
	number+=X1.b/divi;
	divi*=1024.0;
	number+=X1.a/divi;
	divi*=1024.0;
	number+=X2.r/divi;
	divi*=1024.0;
	number+=X2.g/divi;
	divi*=1024.0;
	number+=X2.b/divi;
	divi*=1024.0;
	number+=X2.a/divi;
	return number;
}*/

//a=a+b-4, 41 Ops
void add2(inout vec4 a1, inout vec4 a2, in vec4 b1, in vec4 b2){
	a1+=b1;
	a2+=b2;
	//the values after the point have to be smaller than 0.0
	a1.r-=2.0;//-4+2
	a2.a-=2048.0;
	a1.gba-=2046.0;
	a2.rgb-=2046.0;
	
	float temp=ceil(a2.a*0.0009765625);
	a2.b+=temp;
	a2.a-=temp*1024.0;
		
	temp=ceil(a2.b*0.0009765625);
	a2.g+=temp;
	a2.b-=temp*1024.0;
	
	temp=ceil(a2.g*0.0009765625);
	a2.r+=temp;
	a2.g-=temp*1024.0;
	
	temp=ceil(a2.r*0.0009765625);
	a1.a+=temp;
	a2.r-=temp*1024.0;
	
	temp=ceil(a1.a*0.0009765625);
	a1.b+=temp;
	a1.a-=temp*1024.0;
	
	temp=ceil(a1.b*0.0009765625);
	a1.g+=temp;
	a1.b-=temp*1024.0;
	
	temp=ceil(a1.g*0.0009765625);
	a1.r+=temp;
	a1.g-=temp*1024.0;
	
	//a1.r=floor(a1.r);
	//a1.g=floor(a1.g);
}





void main ()
{
	//position=lowerLeftCorner+(gl_Position.xy+vec2(1.0,1.0))*deltaVector;
	vec4 tempPositionX1=vec4(0.0);
	vec4 tempPositionX2=vec4(0.0);
	vec4 tempPositionY1=vec4(0.0);
	vec4 tempPositionY2=vec4(0.0);
	
	vec2 tmpPosition=position+1.0;
	convertToBigSize(tmpPosition.r,tempPositionX1, tempPositionX2);
	convertToBigSize(tmpPosition.g,tempPositionY1, tempPositionY2);
	
	mult(tempPositionX1,tempPositionX2, deltaVectorX1, deltaVectorX2);
	mult(tempPositionY1,tempPositionY2, deltaVectorY1, deltaVectorY2); 
	vec4 positionX1=lowerLeftCornerX1;
	vec4 positionX2=lowerLeftCornerX2;
	vec4 positionY1=lowerLeftCornerY1;
	vec4 positionY2=lowerLeftCornerY2;
	add(positionX1, positionX2, tempPositionX1, tempPositionX2);
	add(positionY1, positionY2, tempPositionY1, tempPositionY2);
	//z=position
	vec4 zX1=positionX1;
	vec4 zX2=positionX2;
	vec4 zY1=positionY1;
	vec4 zY2=positionY2;
	gl_FragColor = vec4(1.0,1.0,1.0,1.0);
	
	
	//vec2 tempZ=z*z;
	
	vec4 tempZX1=zX1;
	vec4 tempZX2=zX2;
	vec4 tempZY1=zY1;
	vec4 tempZY2=zY2;
	mult(tempZX1, tempZX2, zX1, zX2);
	mult(tempZY1, tempZY2, zY1, zY2);
	vec4 temp1=tempZX1;
	vec4 temp2=tempZX2;
	
	//tempZ.x+tempZ.y
	add2(temp1,temp2,tempZY1, tempZY2);
	
	float i=float(0.0);
	float temp=0.0;
	float tempSign=0.0;
	vec3 tempM2=vec3(0.0);
	vec4 tempM1=vec4(0.0);
	vec4 z11=vec4(0.0);
	vec4 z12=vec4(0.0);
	vec4 z21=vec4(0.0);
	vec4 z22=vec4(0.0);
	vec4 z31=vec4(0.0);
	vec4 z32=vec4(0.0);
	vec4 z41=vec4(0.0);
	vec4 z42=vec4(0.0);
	vec4 z51=vec4(0.0);
	vec4 z52=vec4(0.0);
	vec4 z61=vec4(0.0);
	vec4 z62=vec4(0.0);
	vec4 z71=vec4(0.0);
	vec4 z72=vec4(0.0);
	vec4 z81=vec4(0.0);
	vec4 z82=vec4(0.0);
	
	//(tempZ.x+tempZ.y)<=4 equivalent to tempZ.x+tempZ.y-4<=0.0
	while (i<=maxIter && all(lessThanEqual(temp1,vec4(0.0))) && all(lessThanEqual(temp2,vec4(0.0))))
	{
		//z = vec2(tempZ.x - tempZ.y, 2.0*z.x*z.y) + position;
		
		//add(tempZX1, tempZX2, -tempZY1, -tempZY2);
		tempZX1-=tempZY1;
		tempZX2-=tempZY2;
		//the values after the point have to be greater than 0.0
		tempZX1.r-=2.0;//-2
		tempZX2.a+=2048.0;
		tempZX1.gba+=2046.0;
		tempZX2.rgb+=2046.0;
		
		temp=floor(tempZX2.a*0.0009765625);
		tempZX2.b+=temp;
		tempZX2.a-=temp*1024.0;
		
		temp=floor(tempZX2.b*0.0009765625);
		tempZX2.g+=temp;
		tempZX2.b-=temp*1024.0;
		
		temp=floor(tempZX2.g*0.0009765625);
		tempZX2.r+=temp;
		tempZX2.g-=temp*1024.0;
	
		temp=floor(tempZX2.r*0.0009765625);
		tempZX1.a+=temp;
		tempZX2.r-=temp*1024.0;
	
		temp=floor(tempZX1.a*0.0009765625);
		tempZX1.b+=temp;
		tempZX1.a-=temp*1024.0;
	
		temp=floor(tempZX1.b*0.0009765625);
		tempZX1.g+=temp;
		tempZX1.b-=temp*1024.0;
	
		temp=floor(tempZX1.g*0.0009765625);
		tempZX1.r+=temp;
		tempZX1.g-=temp*1024.0;
				
		//mult(zY1, zY2, zX1, zX2);
		z11=zY1*zX1.r;
		z12=zY2*zX1.r;
		z21=zY1*zX1.g;
		z22=zY2*zX1.g;
		z31=zY1*zX1.b;
		z32=zY2*zX1.b;
		z41=zY1*zX1.a;
		z42=zY2*zX1.a;
		z51=zY1*zX2.r;
		z52=zY2*zX2.r;
		z61=zY1*zX2.g;
		z62=zY2*zX2.g;
		z71=zY1*zX2.b;
		z72=zY2*zX2.b;
		z81=zY1*zX2.a;
		z82=zY2*zX2.a;
		tempM2=z82.gba;
		tempM2.rg+=z72.ba;
		tempM2.r+=z62.a;
		tempM1=z52;
		tempM1.a+=z82.r;
		tempM1.rgb+=z81.gba;
		tempM1.ba+=z72.rg;
		tempM1.rg+=z71.ba;
		tempM1.gba+=z62.rgb;
		tempM1.r+=z61.a;
		tempM1.rgb+=z42.gba;
		tempM1.rg+=z32.ba;
		tempM1.r+=z22.a;
		zY2=z51;
		zY2.a+=z81.r;
		zY2.ba+=z71.rg;
		zY2.gba+=z61.rgb;
		zY2.a+=z42.r;
		zY2.rgb+=z41.gba;
		zY2.ba+=z32.rg;
		zY2.rg+=z31.ba;
		zY2.gba+=z22.rgb;
		zY2.r+=z21.a;
		zY2+=z12;
		zY1=z11;
		zY1.gba+=z21.rgb;
		zY1.ba+=z31.rg;
		zY1.a+=z41.r;
	
		tempSign=sign(tempM2.g);	
		temp=floor(abs(tempM2.g)*0.0009765625);
		tempM2.r+=temp*tempSign;
		tempSign=sign(tempM2.r);
		temp=floor(abs(tempM2.r)*0.0009765625);
		tempM1.a+=temp*tempSign;
		tempSign=sign(tempM1.a);
		temp=floor(abs(tempM1.a)*0.0009765625);
		tempM1.b+=temp*tempSign;
		tempSign=sign(tempM1.b);
		temp=floor(abs(tempM1.b)*0.0009765625);
		tempM1.g+=temp*tempSign;
		tempSign=sign(tempM1.g);
		temp=floor(abs(tempM1.g)*0.0009765625);
		tempM1.r+=temp*tempSign;
		tempSign=sign(tempM1.r);
		temp=floor(abs(tempM1.r)*0.0009765625);
		zY2.a+=temp*tempSign;
	
		tempSign=sign(zY2.a);
		temp=floor(abs(zY2.a)*0.0009765625);
		zY2.b+=temp*tempSign;
		zY2.a-=temp*1024.0*tempSign;
		
		tempSign=sign(zY2.b);	
		temp=floor(abs(zY2.b)*0.0009765625);
		zY2.g+=temp*tempSign;
		zY2.b-=temp*1024.0*tempSign;
	
		tempSign=sign(zY2.g);	
		temp=floor(abs(zY2.g)*0.0009765625);
		zY2.r+=temp*tempSign;
		zY2.g-=temp*1024.0*tempSign;
	
		tempSign=sign(zY2.r);	
		temp=floor(abs(zY2.r)*0.0009765625);
		zY1.a+=temp*tempSign;
		zY2.r-=temp*1024.0*tempSign;
	
		tempSign=sign(zY1.a);	
		temp=floor(abs(zY1.a)*0.0009765625);
		zY1.b+=temp*tempSign;
		zY1.a-=temp*1024.0*tempSign;
	
		tempSign=sign(zY1.b);	
		temp=floor(abs(zY1.b)*0.0009765625);
		zY1.g+=temp*tempSign;
		zY1.b-=temp*1024.0*tempSign;
	
		tempSign=sign(zY1.g);	
		temp=floor(abs(zY1.g)*0.0009765625);
		zY1.r+=temp*tempSign;
		zY1.g-=temp*1024.0*tempSign;
		
		//add(zY1, zY2, zY1, zY2);
		zY1+=zY1;
		zY2+=zY2;
		//the values after the point have to be greater than 0.0
		zY1.r-=2.0;//-2
		zY2.a+=2048.0;
		zY1.gba+=2046.0;
		zY2.rgb+=2046.0;
		
		temp=floor(zY2.a*0.0009765625);
		zY2.b+=temp;
		zY2.a-=temp*1024.0;
		
		temp=floor(zY2.b*0.0009765625);
		zY2.g+=temp;
		zY2.b-=temp*1024.0;
	
		temp=floor(zY2.g*0.0009765625);
		zY2.r+=temp;
		zY2.g-=temp*1024.0;
	
		temp=floor(zY2.r*0.0009765625);
		zY1.a+=temp;
		zY2.r-=temp*1024.0;
	
		temp=floor(zY1.a*0.0009765625);
		zY1.b+=temp;
		zY1.a-=temp*1024.0;
	
		temp=floor(zY1.b*0.0009765625);
		zY1.g+=temp;
		zY1.b-=temp*1024.0;
	
		temp=floor(zY1.g*0.0009765625);
		zY1.r+=temp;
		zY1.g-=temp*1024.0;
		
		zX1=tempZX1;
		zX2=tempZX2;
		//add(zX1, zX2, positionX1, positionX2);
		zX1+=positionX1;
		zX2+=positionX2;
		//the values after the point have to be greater than 0.0
		zX1.r-=2.0;//-2
		zX2.a+=2048.0;
		zX1.gba+=2046.0;
		zX2.rgb+=2046.0;
		
		temp=floor(zX2.a*0.0009765625);
		zX2.b+=temp;
		zX2.a-=temp*1024.0;
		
		temp=floor(zX2.b*0.0009765625);
		zX2.g+=temp;
		zX2.b-=temp*1024.0;
	
		temp=floor(zX2.g*0.0009765625);
		zX2.r+=temp;
		zX2.g-=temp*1024.0;
	
		temp=floor(zX2.r*0.0009765625);
		zX1.a+=temp;
		zX2.r-=temp*1024.0;
	
		temp=floor(zX1.a*0.0009765625);
		zX1.b+=temp;
		zX1.a-=temp*1024.0;
	
		temp=floor(zX1.b*0.0009765625);
		zX1.g+=temp;
		zX1.b-=temp*1024.0;
	
		temp=floor(zX1.g*0.0009765625);
		zX1.r+=temp;
		zX1.g-=temp*1024.0;
		
		//add(zY1, zY2, positionY1, positionY2);
		zY1+=positionY1;
		zY2+=positionY2;
		//the values after the point have to be greater than 0.0
		zY1.r-=2.0;//-2
		zY2.a+=2048.0;
		zY1.gba+=2046.0;
		zY2.rgb+=2046.0;
		
		temp=floor(zY2.a*0.0009765625);
		zY2.b+=temp;
		zY2.a-=temp*1024.0;
		
		temp=floor(zY2.b*0.0009765625);
		zY2.g+=temp;
		zY2.b-=temp*1024.0;
	
		temp=floor(zY2.g*0.0009765625);
		zY2.r+=temp;
		zY2.g-=temp*1024.0;
	
		temp=floor(zY2.r*0.0009765625);
		zY1.a+=temp;
		zY2.r-=temp*1024.0;
	
		temp=floor(zY1.a*0.0009765625);
		zY1.b+=temp;
		zY1.a-=temp*1024.0;
	
		temp=floor(zY1.b*0.0009765625);
		zY1.g+=temp;
		zY1.b-=temp*1024.0;
	
		temp=floor(zY1.g*0.0009765625);
		zY1.r+=temp;
		zY1.g-=temp*1024.0;
		
		//tempZ=z*z;
		
		tempZX1=zX1;
	    tempZX2=zX2;
	    tempZY1=zY1;
	    tempZY2=zY2;
	   // mult(tempZX1, tempZX2, zX1, zX2);
		//mult(tempZY1, tempZY2, zY1, zY2);
		
		//tempZ.x+tempZ.y
		
		temp1=tempZX1;
		temp2=tempZX2;
		//add2(temp1,temp2, tempZY1, tempZY2);
		temp1+=tempZY1;
		temp2+=tempZY2;
		//the values after the point have to be smaller than 0.0
		temp1.r-=2.0;//-4+2
		temp2.a-=2048.0;
		temp1.gba-=2046.0;
		temp2.rgb-=2046.0;
	
		temp=ceil(temp2.a*0.0009765625);
		temp2.b+=temp;
		temp2.a-=temp*1024.0;
		
		temp=ceil(temp2.b*0.0009765625);
		temp2.g+=temp;
		temp2.b-=temp*1024.0;
	
		temp=ceil(temp2.g*0.0009765625);
		temp2.r+=temp;
		temp2.g-=temp*1024.0;
	
		temp=ceil(temp2.r*0.0009765625);
		temp1.a+=temp;
		temp2.r-=temp*1024.0;
	
		temp=ceil(temp1.a*0.0009765625);
		temp1.b+=temp;
		temp1.a-=temp*1024.0;
	
		temp=ceil(temp1.b*0.0009765625);
		temp1.g+=temp;
		temp1.b-=temp*1024.0;
	
		temp=ceil(temp1.g*0.0009765625);
		temp1.r+=temp;
		temp1.g-=temp*1024.0;
		
		i+=1.0;	
		
	}
	if (i <= maxIter)
		{
			float color=i/maxIter;
			gl_FragColor=vec4(color,color,1.0,1.0);	
				
		}
		
}

At an ATI x1600 card, this glsl fragment shader causes crashing. Using the gpu shaderanalyzer, I read, this shader is not supported by HW for x1x00 cards.
But at my hd2600xt card, the precision shaders are working. I don't understand why. But, I found out, it's something with the main loop. Do you know, how to fix this code?

Best,
Andreas
 
Back
Top