Mandelbrot Example Program

This is a complete program that calculates a Mandelbrot fractal, and displays it via OpenGL.
You find more example programs in the GOOPAX package.

mandelbrot
    














#include <goopax_gl.h>        GOOPAX is included as a library. All parsing is done by a standard C++ compiler.
#include <glfw3.h>
#include <complex>
using namespace goopax;
using namespace std;

static struct mandelbrot :                   GPU kernels are perfectly embedded into the host code.
  kernel<mandelbrot>
{
  void program(image_resource<2, array<uint8_t, 4>, true>& image,  
    const complex<gpu_float> center,
    const gpu_float scale)
  {
    gpu_for(gpu_uint y=group_id(), image.height(), num_groups())
      gpu_for(gpu_uint x=local_id(), image.width(), local_size())
        {
          auto c = center + scale * complex<gpu_float>(x - image.width() * 0.5f,
                                        y - image.height() * 0.5f);
          complex<gpu_float> z = {0,0};           Using std::complex and std::array from the STL library.

          gpu_uint iter=0;
          gpu_while((iter < 256) && (norm(z) < 4))
          {
            z = z*z + c;
            ++iter;
          }

          array<gpu_float, 4> color = {pow(sinpi(iter/16.f + 11.0/15), 4),
                                       pow(sinpi(iter/16.f + 1.0/15), 4),
                                       pow(sinpi(iter/16.f + 6.0/15), 4), 1};
          image.write({x,y}, cond(iter==256, {0,0,0,1}, color));
        }
  }
} Mandelbrot;


int main()
{
  // Setting up OpenGL
  glfwInit();
  GLFWwindow* window = glfwCreateWindow(1024, 768, "Mandelbrot", nullptr, nullptr);
  glfwMakeContextCurrent(window);
  int width, height;
  glfwGetFramebufferSize(window, &width, &height);

  GLuint texture_id;
  glGenTextures(1, &texture_id);
  glBindTexture(GL_TEXTURE_2D, texture_id);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

  // Getting device for OpenGL interoperability
  goopax_device device = get_device_from_gl();
  
  // Sharing OpenGL texture with GOOPAX
  auto image = image_buffer<2, array<uint8_t, 4>, true>::create_from_gl(device, texture_id);

  for (int i=0; !glfwWindowShouldClose(window); ++i)
    {
      complex<float> center = {-0.7965709041,-0.1836522060};
      float scale = exp(cos(i/200.0)*6-6)*5E-3;

      // Call the kernel
      Mandelbrot(image, center, scale);     Easy programming. No complicated system calls.

      // Display using OpenGL
      glEnable(GL_TEXTURE_2D);
      glPushMatrix();
      glOrtho(-1.0, 1.0, 1.0, -1.0, -1.0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glViewport(0, 0, width, height);

      glBegin(GL_QUADS);
      glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
      glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
      glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
      glTexCoord2f(0.0, 1.0);  glVertex2f(-1.0, 1.0);
      glEnd();
    
      glMatrixMode(GL_PROJECTION);
      glPopMatrix();
      glDisable(GL_TEXTURE_2D);

      glfwSwapBuffers(window);
      glfwPollEvents();
    }
  glfwTerminate();
}