在Mandelbrot set
WebGl
代OpenGl
代播放时,我不可避免地偶然发现float
的32位double
的精确度很低。然而,当我找到this great article时,新的希望就诞生了
小心翼翼地,我从上述来源中获取了函数,并在JS方面添加了doubles
解构。
据我所知,JS对于浮点数有64位function doubleToFloat(d) {
return new Float32Array([d])[0];
};
function splitDouble(dbl) { //splits JS number to array of 2 32bit floats
var arr = [];
arr[0] = doubleToFloat(dbl);
arr[1] = doubleToFloat(dbl - arr[0]);
//console.log(dbl, arr);
arr = new Float32Array(arr);
dlog(dbl,arr);
return arr;
};
///Somewhere inside rendering function - binding data to webGl
var planeH = 4/settings.magnification;
var planeMult = planeH/canvasH; //screen to complex plane dimensions multiplier
var planeW = canvasW*planeMult;
var planeWOffset = planeW/2; //offset to align plane's 0:0 at screen's center
var planeHOffset = planeH/2;
bindUniforms(program, {
WIDTH: canvasW,
HEIGHT: canvasH,
CENTER_X: {value:splitDouble(settings.centerX),type:"2fv"},
CENTER_Y: {value:splitDouble(settings.centerY),type:"2fv"},
MAGNIFICATION: settings.magnification,
PLANE_W_OFFSET: {value:splitDouble(planeWOffset),type:"2fv"},
PLANE_H_OFFSET: {value:splitDouble(planeHOffset),type:"2fv"},
PLANE_MULT: {value:splitDouble(planeMult),type:"2fv"},
uSampler: {value:texIndex,type:"1i"}
});
--> sent to webGL
,所以我的想法是计算JS方面的一些准备数据,将它作为浮动对发送到GPU并继续进行mandelbrot循环。
可悲的是,最后我看到结果图像的差异几乎没有,我真的不知道我的失败点在哪里。
JS:
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
precision mediump int;
const int ITER_LIMIT = <%=iterLimit%>;
uniform float MAGNIFICATION;
uniform vec2 CENTER_X;
uniform vec2 CENTER_Y;
uniform float WIDTH;
uniform float HEIGHT;
uniform vec2 PLANE_W_OFFSET;
uniform vec2 PLANE_H_OFFSET;
uniform vec2 PLANE_MULT;
uniform sampler2D uSampler;
const float threshold = 10.0;
///Double emulation functions///////////////
vec2 ds(float a) {
vec2 z;
z.x = a;
z.y = 0.0;
return z;
}
vec2 ds_add(vec2 dsa, vec2 dsb) {
vec2 dsc;
float t1, t2, e;
t1 = dsa.x + dsb.x;
e = t1 - dsa.x;
t2 = ((dsb.x - e) + (dsa.x - (t1 - e))) + dsa.y + dsb.y;
dsc.x = t1 + t2;
dsc.y = t2 - (dsc.x - t1);
return dsc;
}
vec2 ds_mult(vec2 dsa, vec2 dsb) {
vec2 dsc;
float c11, c21, c2, e, t1, t2;
float a1, a2, b1, b2, cona, conb, split = 8193.;
cona = dsa.x * split;
conb = dsb.x * split;
a1 = cona - (cona - dsa.x);
b1 = conb - (conb - dsb.x);
a2 = dsa.x - a1;
b2 = dsb.x - b1;
c11 = dsa.x * dsb.x;
c21 = a2 * b2 + (a2 * b1 + (a1 * b2 + (a1 * b1 - c11)));
c2 = dsa.x * dsb.y + dsa.y * dsb.x;
t1 = c11 + c2;
e = t1 - c11;
t2 = dsa.y * dsb.y + ((c2 - e) + (c11 - (t1 - e))) + c21;
dsc.x = t1 + t2;
dsc.y = t2 - (dsc.x - t1);
return dsc;
}
vec2 ds_sub(vec2 dsa, vec2 dsb) {
return ds_add(dsa, ds_mult(ds(-1.0),dsb));
}
///End of Double emulation functions/////////
///Inside main()////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
float sqThreshold = threshold*threshold;
vec2 X = ds_mult(ds(gl_FragCoord.x),PLANE_MULT);
vec2 Y = ds_mult(ds(gl_FragCoord.y),PLANE_MULT);
vec2 planeX = ds_add(ds_sub(X,PLANE_W_OFFSET),CENTER_X);
vec2 planeY = ds_sub(ds_sub(Y,PLANE_H_OFFSET),CENTER_Y);
vec4 outcome = vec4(ds(0.0),ds(0.0));
vec4 C = vec4(planeX,planeY);
int iters = 0;
for (int i = 0; i < ITER_LIMIT; i++) {
iters = i;
vec2 sqRe = ds_mult(outcome.xy,outcome.xy);
vec2 sqIm = ds_mult(outcome.zw,outcome.zw);
vec4 Zsq = vec4(
ds_sub(sqRe,sqIm),
ds_mult(ds(2.0),ds_mult(outcome.xy,outcome.zw))
);
outcome.xy = ds_add(Zsq.xy,C.xy);
outcome.zw = ds_add(Zsq.zw,C.zw);
vec2 sqSumm = ds_add(ds_mult(outcome.xy,outcome.xy),ds_mult(outcome.zw,outcome.zw));
if (sqSumm.x > sqThreshold) break;
};
--> Proceed to coloring
WebGL(片段着色器):
DateDif( interval, date1, date2, [firstdayofweek], [firstweekofyear] )
borrowed from https://www.techonthenet.com/excel/formulas/datediff.php
结果(右侧的位置/ maginfication数据): 没有双重仿真的相同图像的零差异。
感谢您阅读此文本和代码,任何提示和/或想法?