Discussion created by Andreas999 on Oct 2, 2008
Latest reply on Dec 3, 2008 by bpurnomo

Hi,

I wrote a Mandelbrot shader with a fixed point arithmetic for a higher precision. Here is my 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 temp2=z82.gba;
temp2.rg+=z72.ba;
temp2.r+=z62.a;
vec4 temp1=z52;
temp1.a+=z82.r;
temp1.rgb+=z81.gba;
temp1.ba+=z72.rg;
temp1.rg+=z71.ba;
temp1.gba+=z62.rgb;
temp1.r+=z61.a;
temp1.rgb+=z42.gba;
temp1.rg+=z32.ba;
temp1.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(temp2.g);
float temp=floor(abs(temp2.g)*0.0009765625);
temp2.r+=temp*tempSign;
tempSign=sign(temp2.r);
temp=floor(abs(temp2.r)*0.0009765625);
temp1.a+=temp*tempSign;
tempSign=sign(temp1.a);
temp=floor(abs(temp1.a)*0.0009765625);
temp1.b+=temp*tempSign;
tempSign=sign(temp1.b);
temp=floor(abs(temp1.b)*0.0009765625);
temp1.g+=temp*tempSign;
tempSign=sign(temp1.g);
temp=floor(abs(temp1.g)*0.0009765625);
temp1.r+=temp*tempSign;
tempSign=sign(temp1.r);
temp=floor(abs(temp1.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;
//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

float i=float(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;

mult(zY1, zY2, zX1, zX2);
zX1=tempZX1;
zX2=tempZX2;

//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;

i+=1.0;

}
if (i <= maxIter)
{
float color=i/maxIter;
gl_FragColor=vec4(color,color,1.0,1.0);

}

}

At my HD 2600, it's working fine. But, looking at the gpu shaderanalyzer this program is not compiled for x1x00 cards. They support the shader model 3.0 and I don't understand, why this is not working.

Would be nice, if you could help.

Best,
Andreas