Мандельброт установлен в OpenGL - C - PullRequest
0 голосов
/ 26 июня 2019

Я новичок в OpenGL и пытаюсь получить набор Мандельброта, вычисленный с помощью OpenGL и GLFW.

Я нашел код здесь , но freeglut не работает в моей системе и по какой-то причине жалуется на то, что обратный вызов не установлен, хотя он явно установлен. Тем не менее, он мигает один кадр, а затем падает, в этом кадре я вижу набор mandelbrot, поэтому я знаю, что математика верна.

Я подумал, что это будет хорошей возможностью узнать больше об OpenGL и GLFW, поэтому я начал работать над тем, чтобы это произошло.

После двойной проверки всего я вижу, что он определенно вычисляет значения, а затем правильно переключает буферы.

Однако я думаю, что мне не хватает двух вещей:

  1. Вершина, к которой фактически может быть применена текстура

РЕДАКТИРОВАТЬ: (из learnopengl.com ) "После вызова glTexImage2D объект привязанной в данный момент текстуры теперь имеет прикрепленное к нему изображение текстуры.", Поэтому он не может быть # 2

  1. не уверен, что происходит с вычислением, но похоже, что оно связывает текстуру с именем 'texture', но затем вычисляет значения в массиве struct, который, похоже, никак не связан. Я связываю текстуру с tex (текстурой) и затем отправляю массив struct в glTexImage2D

Если бы кто-то мог просто указать мне правильное направление или подтвердить мои подозрения, это было бы здорово.

Мой код здесь:

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>

    #define  GLEW_STATIC
    #include <GL/glew.h>
    #include <pthread.h>

    #include <GLFW/glfw3.h>

    #include <GL/gl.h>

    #define VAL 255

    typedef struct {
      uint8_t r; 
      uint8_t g;
      uint8_t b;
    }rgb_t;

    rgb_t **tex_array = 0;
    rgb_t *image;
    int gwin;
    int width = 640;
    int height = 480;
    int tex_w, tex_h;
    double scale = 1./256;
    double cx = -.6, cy = 0;
    int color_rotate = 0;
    int saturation = 1;
    int invert = 0;
    int max_iter = 256;
    int dump = 1;
    GLFWwindow* window;
    int global_iterator = 0;
    int conversion_iterator_x = 0;
    int conversion_iterator_y = 0;

    GLFWwindow* init_glfw();
    void set_texture(GLuint tex); 
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    void render(GLuint tex);
    void screen_dump();
    void keypress(unsigned char key, int x, int y);
    void hsv_to_rgb(int hue, int min, int max, rgb_t *p);
    void calc_mandel(rgb_t* px);
    void alloc_texture();
    void set_texture();
    void mouseclick(int button, int state, int x, int y);
    void resize(int w, int h);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);


    int main(int c, char **v)
    {

      GLFWwindow* win = init_glfw();
      glfwSetWindowPos(win, 1000, 500);

      GLuint texture;
      glGenTextures(1, &texture);
      set_texture(texture);

      /* Loop until the user closes the window */
           while (!glfwWindowShouldClose(win))
        {

            render(texture);  

            /* Swap front and back buffers */
            glfwSwapBuffers(win);

            /* Poll for and process events */
            glfwPollEvents();

            if(glfwGetKey(win, GLFW_KEY_ESCAPE) == GLFW_PRESS){
               glfwSetWindowShouldClose(win, GL_TRUE);
            }
        }

        return 0;
    }


    void set_texture(GLuint tex)
    {
      printf("Allocating space\n");
        alloc_texture();
      printf("Calculating mandel... %d\n", global_iterator);
      ++global_iterator;
        calc_mandel(image);
      printf("mandel calculation complete\n");

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, tex);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h,
            0, GL_RGB, GL_UNSIGNED_BYTE, tex_array[0]);

      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

      printf("Rendering to screen...\n");
        render(tex);
    }

    void alloc_texture()
    {
        int i;
      int ow = tex_w;
      int oh = tex_h;

        for (tex_w = 1; tex_w < width;  tex_w <<= 1);
        for (tex_h = 1; tex_h < height; tex_h <<= 1);

        if (tex_h != oh || tex_w != ow){
            tex_array = realloc(tex_array, tex_h * tex_w * 3 + tex_h * sizeof(rgb_t*));
      }

        for (tex_array[0] = (rgb_t *)(tex_array + tex_h), i = 1; i < tex_h; i++){
            tex_array[i] = tex_array[i - 1] + tex_w;
      }
    }


    void render(GLuint tex)
    {
        double  x = (double)width /tex_w,
            y = (double)height/tex_h;

        glClear(GL_COLOR_BUFFER_BIT);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

        glBindTexture(GL_TEXTURE_2D, tex);

        glBegin(GL_QUADS);

        glTexCoord2f(0, 0); glVertex2i(0, 0);
        glTexCoord2f(x, 0); glVertex2i(width, 0);
        glTexCoord2f(x, y); glVertex2i(width, height);
        glTexCoord2f(0, y); glVertex2i(0, height);

        glEnd();

        glFlush();
        glFinish();
    }

    GLFWwindow* init_glfw()
    {

        /* Initialize the library */
        if (!glfwInit()){
            return NULL;
        }

        /*
         * Configure window options here if you so desire
         *
         * i.e.
         */
         glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
         glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
         glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
         //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

         //glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);


        //the fourth parameter of glfwCreateWindow should be NULL for windowed mode and 
        //glfGetPrimaryMonitor() for full screen mode
        /* Create a windowed mode window and its OpenGL context */
        window = glfwCreateWindow(width, height, "Mandelbrot", NULL, NULL);
        if (!window)
        {
            glfwTerminate();
            return NULL;
        }

        /* Make the window's context current */
        glfwMakeContextCurrent(window);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

        /*
         * Initialize glew here
         */

        glewExperimental = GL_TRUE;
        glewInit();


      return window;

    }


    void calc_mandel(rgb_t* px)
    {
        int i, j, iter, min, max;
        double x, y, zx, zy, zx2, zy2;

      min = max_iter; 
      max = 0;

      for (i = 0; i < height; i++) {
            px = tex_array[i];
            y = (i - height/2) * scale + cy;
            for (j = 0; j  < width; j++, px++) {
                x = (j - width/2) * scale + cx;
                iter = 0;
                zx = hypot(x - .25, y);

                if (x < zx - 2 * zx * zx + .25){
            iter = max_iter;
          }
                if ((x + 1)*(x + 1) + y * y < 1/16){
            iter = max_iter;
          }

                zx = zy = zx2 = zy2 = 0;
                for (; iter < max_iter && zx2 + zy2 < 4; iter++) {
                    zy = 2 * zx * zy + y;
                    zx = zx2 - zy2 + x;
                    zx2 = zx * zx;
                    zy2 = zy * zy;
                }

                if (iter < min){
            min = iter;
          }
                if (iter > max){ 
            max = iter;
          }
                *(unsigned short *)px = iter;
            }
        }

        for (i = 0; i < height; i++){
            for (j = 0, px = tex_array[i]; j  < width; j++, px++){
                hsv_to_rgb(*(unsigned short*)px, min, max, px);
        }
      }

    }

    void hsv_to_rgb(int hue, int min, int max, rgb_t *p)
    {

      printf("Converting hsv to rbg... \n");
        if (min == max){
        max = min + 1;
      }
        if (invert){
        hue = max - (hue - min);
      }
        if (!saturation) {
            p->r = p->g = p->b = 255 * (max - hue) / (max - min);
            printf("done! (!saturation)\n");
        return;
        }
        double h = fmod(color_rotate + 1e-4 + 4.0 * (hue - min) / (max - min), 6);
        double c = VAL * saturation;
        double X = c * (1 - fabs(fmod(h, 2) - 1));

        p->r = p->g = p->b = 0;

        switch((int)h) {
        case 0: p->r = c; p->g = X; break;
        case 1: p->r = X; p->g = c; break;
        case 2: p->g = c; p->b = X; break;
        case 3: p->g = X; p->b = c; break;
        case 4: p->r = X; p->b = c; break;
        default:p->r = c; p->b = X; break;
        }
        printf("done! (sauration)\n");
    }

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
    glOrtho(0, width, 0, height, -1, 1);
    //set_texture();
}




  [1]: https://rosettacode.org/wiki/Mandelbrot_set#PPM_non_interactive
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...