具有一般指数的 OpenGL ES GLSL Mandelbrot

Posted

技术标签:

【中文标题】具有一般指数的 OpenGL ES GLSL Mandelbrot【英文标题】:OpenGL ES GLSL Mandelbrot with general exponent 【发布时间】:2019-03-19 05:47:42 【问题描述】:

我已经成功地在 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 生成的图像看起来像

虽然它应该看起来像

我很茫然。这可能是一件微不足道的事情。如有任何建议,我将不胜感激。

【问题讨论】:

【参考方案1】:

我不确定是否将极坐标计算用于如此简单的交互计算,这对我来说似乎有点矫枉过正。这是一个使用来自我的 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(用于直接 GPU 计算),polar 背后的想法是模糊地记住复杂指数最好使用极坐标中的 de Moivre 公式。这实际上也在这里使用,但更简单,并且不执行极坐标中的其他计算。

以上是关于具有一般指数的 OpenGL ES GLSL Mandelbrot的主要内容,如果未能解决你的问题,请参考以下文章