具有一般指数的 OpenGL ES GLSL Mandelbrot
OpenGL ES GLSL Mandelbrot with general exponent
我已经在 GLSL(OpenGL ES) 上成功地实现了几个分形,但是我似乎对 Mandelbrot 集的变化毫无进展,其中指数是任意正数。
我正在复数极坐标中求幂,但是算法某处有误,至于 exponent = 2 出现了不同于经典 Mandelbrot 集的其他东西。
当前代码如下:
precision mediump float;
uniform sampler2D palette;
uniform float centerX;
uniform float centerY;
uniform float scale;
uniform float iterations;
uniform vec2 resolution;
uniform float exponent;
#define maxiter 65535
vec2 cplx_polar(vec2 z) {
return vec2(length(z), atan(z.y,z.x));
}
vec2 cplx_polar_add(vec2 z1, vec2 z2) {
//https://math.stackexchange.com/a/1365938
return vec2(sqrt(z1.x*z1.x + z2.x*z2.x + 2.*z1.x*z2.x*cos(z2.y-z1.y)),
z1.y+atan(z2.x*sin(z2.y-z1.y),(z1.x+z2.x*cos(z2.y-z1.y))));
}
vec2 exponentiate(vec2 z) {
return pow(z.x, exponent)* vec2(cos(z.y), sin(z.y));
}
void main() {
vec2 center = vec2(centerX, centerY);
vec2 coord = vec2(gl_FragCoord.x, gl_FragCoord.y) / resolution;
vec2 c = cplx_polar((coord - center) / scale);
int j = 0;
vec2 z = c;
for(int i = 0; i<maxiter; i++) {
if (float(i) >= iterations) break;
j++;
vec2 znew = cplx_polar_add(exponentiate(z), c);
if(znew.x > 2.0) break;
z = znew;
}
gl_FragColor = texture2D(palette, vec2((j == int(iterations) ? 0.0 : float(j)) / iterations, 0.5));
}
main 函数中一定有错误,因为对于没有极坐标的简单 z = z ^ 2 + c 基本相同。指数 = 2 的生成图像看起来像
虽然它应该看起来像
我很茫然。这可能是微不足道的事情。如果有任何建议,我将不胜感激。
我不确定将极坐标计算用于如此简单的交互计算,这对我来说似乎有点过分了。这是一个使用源自我的 FractalCanvas 应用程序的笛卡尔数学的解决方案。
Java中的简单表达式是 pow(double f) { return log().times(f).exp(); }.
我不认识你使用的语言,但这可以提供一些想法。
public vec2 pow(vec2 z, double f) {
// log()
double d = Math.log(Math.sqrt(z.x * z.x + z.y * z.y));
z.x = Math.atan2(z.y, z.x);
z.y = d;
// times(f)
z.x *= f;
z.y *= f;
// exp()
double exp = Math.exp(z.x);
z.x = Math.cos(z.y) * exp;
z.y = Math.sin(z.y) * exp;
return z;
}
顺便说一句,我严重建议您不要在迭代循环的中间创建对象。创建和销毁它们需要有限的时间,并且循环可能 运行 数十亿次来计算图像。当我从我的应用程序中删除此类创作时,我注意到速度有了显着提高。
我已经在 GLSL(OpenGL ES) 上成功地实现了几个分形,但是我似乎对 Mandelbrot 集的变化毫无进展,其中指数是任意正数。
我正在复数极坐标中求幂,但是算法某处有误,至于 exponent = 2 出现了不同于经典 Mandelbrot 集的其他东西。
当前代码如下:
precision mediump float;
uniform sampler2D palette;
uniform float centerX;
uniform float centerY;
uniform float scale;
uniform float iterations;
uniform vec2 resolution;
uniform float exponent;
#define maxiter 65535
vec2 cplx_polar(vec2 z) {
return vec2(length(z), atan(z.y,z.x));
}
vec2 cplx_polar_add(vec2 z1, vec2 z2) {
//https://math.stackexchange.com/a/1365938
return vec2(sqrt(z1.x*z1.x + z2.x*z2.x + 2.*z1.x*z2.x*cos(z2.y-z1.y)),
z1.y+atan(z2.x*sin(z2.y-z1.y),(z1.x+z2.x*cos(z2.y-z1.y))));
}
vec2 exponentiate(vec2 z) {
return pow(z.x, exponent)* vec2(cos(z.y), sin(z.y));
}
void main() {
vec2 center = vec2(centerX, centerY);
vec2 coord = vec2(gl_FragCoord.x, gl_FragCoord.y) / resolution;
vec2 c = cplx_polar((coord - center) / scale);
int j = 0;
vec2 z = c;
for(int i = 0; i<maxiter; i++) {
if (float(i) >= iterations) break;
j++;
vec2 znew = cplx_polar_add(exponentiate(z), c);
if(znew.x > 2.0) break;
z = znew;
}
gl_FragColor = texture2D(palette, vec2((j == int(iterations) ? 0.0 : float(j)) / iterations, 0.5));
}
main 函数中一定有错误,因为对于没有极坐标的简单 z = z ^ 2 + c 基本相同。指数 = 2 的生成图像看起来像
我不确定将极坐标计算用于如此简单的交互计算,这对我来说似乎有点过分了。这是一个使用源自我的 FractalCanvas 应用程序的笛卡尔数学的解决方案。
Java中的简单表达式是 pow(double f) { return log().times(f).exp(); }.
我不认识你使用的语言,但这可以提供一些想法。
public vec2 pow(vec2 z, double f) {
// log()
double d = Math.log(Math.sqrt(z.x * z.x + z.y * z.y));
z.x = Math.atan2(z.y, z.x);
z.y = d;
// times(f)
z.x *= f;
z.y *= f;
// exp()
double exp = Math.exp(z.x);
z.x = Math.cos(z.y) * exp;
z.y = Math.sin(z.y) * exp;
return z;
}
顺便说一句,我严重建议您不要在迭代循环的中间创建对象。创建和销毁它们需要有限的时间,并且循环可能 运行 数十亿次来计算图像。当我从我的应用程序中删除此类创作时,我注意到速度有了显着提高。