Mandelbrot Set未显示

时间:2017-05-25 18:27:41

标签: c opengl mandelbrot

I am trying to display使用C编程和OpenGL设置Mandelbrot分形。这是我的代码。它现在只在中心显示一个点。我无法弄清楚我哪里出错了。我很确定我的数学是正确的。也许我有错误的循环?

This picture is what Im trying to get

到目前为止,这是我的代码:

#include <GLUT/glut.h>
#include <math.h>

void init(void);
void display(void);

const int screenWidth = 640;
const int screenHeight = 480;

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(screenWidth, screenHeight);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("Mandelbrot");

    // glViewport(-320, -320, 320, 320);
    init();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

void init(void) {
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(-500.0, screenWidth, -500.0, screenHeight);
    // A = screenWidth / 4.0;
    // B = 0.0;
    // C = D = screenHeight / 2.0;
}

void display(void) {
    GLdouble x, f, y, xtemp, y0, x0, iteration, maxInteration;
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glPointSize(1);
    glColor3f(0.0, 0.0, 0.0);

    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    for (y0 = - 1; y0 < 1.1; y0 = y0 + 0.0025) {
        for (x0 = -2.5; x0 < 1.1; x0 = x0 + 0.0025) {
            x = 0;
            y = 0;
            iteration = 0;
            maxInteration = 1000;

            while (((x * x) + (y * y) < (2 * 2)) && iteration < maxInteration) {
                xtemp = (x * x) - (y * y) + x0;
                y = (2 * x * y) + y0;
                x = xtemp;
                iteration = iteration + 1;

                if (y <= 2) {
                    glBegin(GL_POINTS);

                    glVertex2d(x / 750, y / 750);
                    glEnd();
                }
            }
        }
    }    
    glFlush();
}

这是我在评论中修复建议后更新的代码..它导致上面的图像..但是,现在我试图创建对象周围的灰色圆圈???我试图通过最后的其他方式做到这一点......任何想法?

#include <GLUT/glut.h>
#include <math.h>

void init(void);
void display(void);


const int screenWidth = 640;
const int screenHeight = 640;
GLdouble A, B, C, D;

int main(int argc, char** argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  glutInitWindowSize(screenWidth, screenHeight);
  glutInitWindowPosition(0, 0);
  glutCreateWindow("Mandelbrot");
glViewport(-1, 1, -1, 1);
  init();
  glutDisplayFunc(display);
  glutMainLoop();
  return 0;
}

  void init(void) {
  //glMatrixMode(GL_PROJECTION);
   gluOrtho2D(-3.0, 3.0, -3.0, 3.0);
  A = screenWidth / 4.0;
  B = 0.0;
  C = D = screenHeight / 2.0;
}

void display(void)
{
GLdouble x, f, y, xtemp, y0, x0, iteration, maxInteration;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);


glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);



for(y0 = -1; y0< 1.1; y0 = y0 + 0.0025){

for (x0 = -2.5; x0 < 1.1; x0 = x0 + 0.0025) {
    x = 0;
    y = 0;
    iteration = 0;
    maxInteration = 200;

    while(((x*x) + (y*y) <(2*2)) && iteration <maxInteration){
        xtemp = (x*x) - (y*y) + x0;
        y = (2*x*y) +y0;
        x = xtemp;
        iteration = iteration + 1;


        }
    if(iteration >= maxInteration){
        glBegin(GL_POINTS);

        glVertex2d(x0 , y0);
         glColor3f(0.0, 0.0, 0.0);
        glEnd();
    }
    else{
        ????

    }



}
}



glFlush();
  }

2 个答案:

答案 0 :(得分:1)

首先,这里有关于您的代码的一些建议:

  • 使用复数或向量时我建议你使用一个合适的快速数学库,这样你可以避免使用单个组件,有非常快的cpu数学库,可以使用SIMD指令和你的代码将变得更具可读性
  • 你绘制mandelbrot的方式确实是一个坏主意。我的意思是,是的,如果你只想转储简单的图像并学习基础知识,那就好了。不要使用GL_POINTS并尝试直接渲染/更新纹理,甚至更好,使用片段着色器+ glsl(推荐方式),这样即使您使用非优化数学,您的mandelbrot也会非常快速地渲染。
  • 协调系统,如果你仍然坚持按照你正在做的方式使用GL_POINTS,我只是直接使用窗口坐标并从那个空间到mandelbrot数学域,即:[0,0, W,H] LT; - &GT; [ - 1,-1,1,1]

这是我的意思的一个小例子:

#include <GL/glut.h>
#include <math.h>
#include <stdio.h>

const int screen_width = 640;
const int screen_height = 480;
float c[4];
float z[4];

float clamp(float x, float vmin, float vmax) {
    if (x < vmin) {
        return vmin;
    } else if (x > vmax) {
        return vmax;
    }

    return x;
}

void dc_add(float *a, float *b, float *res) {
    res[0] = a[0] + b[0];
    res[1] = a[1] + b[1];
    res[2] = a[2] + b[2];
    res[3] = a[3] + b[3];
}

void dc_mul(float *a, float *b, float *res) {
    res[0] = a[0] * b[0] - a[1] * b[1];
    res[1] = a[0] * b[1] + a[1] * b[0];
    res[2] = a[0] * b[2] + a[2] * b[0] - a[1] * b[3] - a[3] * b[1];
    res[3] = a[0] * b[3] + a[3] * b[0] + a[2] * b[1] + a[1] * b[2];
}

void dc_sqr(float *a, float *res) {
    res[0] = a[0] * a[0] - a[1] * a[1];
    res[1] = 2.0f * a[0] * a[1];
    res[2] = 2.0f * (a[0] * a[2] - a[1] * a[3]);
    res[3] = 2.0f * (a[0] * a[3] + a[1] * a[2]);
}

float dot(float x, float y) { return x * x + y * y; }

void init(void) {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, screen_width, 0, screen_height);
}

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glPointSize(1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    for (int y = 0; y < screen_height; y++) {
        for (int x = 0; x < screen_width; x++) {
            float px = -1.0f + 2.0f * (float)x / (float)screen_width;
            float py = -1.0f + 2.0f * (float)y / (float)screen_height;
            px *= (float)screen_width / (float)screen_height;

            float tz = 0.5f;
            float zo = powf(1.2f, 1.2f);

            float m2 = 0.0f;
            float co = 0.0f;
            float temp[4];
            c[0] = px * zo; c[1] = py * zo; c[2] = 1.0; c[3] = 0.0;
            z[0] = 0.0f; z[1] = 0.0f; z[2] = 0.0f; z[3] = 0.0f;

            for (int i = 0; i < 256; i++) {
                if (m2 > 1024.0f) continue;

                dc_sqr(z, temp);
                dc_add(temp, c, z);
                m2 = dot(z[0], z[1]);
                co += 1.0f;
            }

            float d = 0.0f;
            if (co < 256.0f) {
                d = sqrtf((dot(z[0], z[1]) / dot(z[2], z[3]))) *
                    logf(dot(z[0], z[1]));
            }

            d = clamp(4.0f * d / zo, 0.0f, 1.0f);
            d = powf(d, 0.25f);
            glColor3f(d, d, d);
            glBegin(GL_POINTS);
            glVertex2d(x, y);
            glEnd();
        }
    }

    glFlush();
    glutSwapBuffers();
}

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(screen_width, screen_height);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("Mandelbrot");
    init();
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();

    return 0;
}

这是输出:

enter image description here

以上示例的数学基于this shadertoy。

上面的代码是非常低效和缓慢的,但它的主要目的是证明你你不应该编码一个合适的mandelbrot。

快乐的编码。

答案 1 :(得分:0)

代码中存在一个简单的问题:使用除法而不是乘法来计算像素坐标:将glVertex2d(x / 750, y / 750);更改为

glVertex2d(x * 750, y * 750);

但是,这不是计算Mandelbrot集的正确方法。您应该计算平方模块的迭代次数,使其超过4.0,然后将(x0 * 300,y0 * 300)处的像素颜色设置为该数字作为调色板条目或灰度级。