SalmaYasser

Untitled

Feb 26th, 2020
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.14 KB | None | 0 0
  1. #include <glad/glad.h>
  2. #include <glfw3.h>
  3. #include <math.h>
  4. #include <vector>
  5. #include <stack>
  6. #include <iostream>
  7. #include <fstream>
  8. #include <chrono>
  9. #include <random>
  10. #include <sstream>
  11. typedef float HeatmapType;
  12. using namespace std;
  13.  
  14. vector<float> vertices;
  15. // settings
  16. const int IMAGE_HEIGHT = 200;
  17. const int IMAGE_WIDTH = 200;
  18. const int RED_ITERS = 200;
  19. const int BLUE_ITERS = 800;
  20. const int GREEN_ITERS = 200;
  21. const long long int SAMPLE_COUNT = IMAGE_WIDTH * IMAGE_HEIGHT * 100;
  22.  
  23. class Complex
  24. {
  25.   public:
  26.     Complex(double r = 0.0, double i = 0.0)
  27.         : _r(r), _i(i)
  28.     {
  29.     }
  30.  
  31.     Complex(const Complex &) = default;
  32.  
  33.     double r() const { return _r; }
  34.     double i() const { return _i; }
  35.  
  36.     Complex operator*(const Complex &other)
  37.     {
  38.         // (a + bi) (c + di)
  39.         return Complex(_r * other._r - _i * other._i, _r * other._i + _i * other._r);
  40.     }
  41.  
  42.     Complex operator+(const Complex &other)
  43.     {
  44.         return Complex(_r + other._r, _i + other._i);
  45.     }
  46.  
  47.     double sqmagnitude() const
  48.     {
  49.         return _r * _r + _i * _i;
  50.     }
  51.  
  52.   private:
  53.     double _r, _i;
  54. };
  55.  
  56. //
  57. // Utility
  58. //
  59. void AllocHeatmap(HeatmapType **&o_heatmap, int width, int height)
  60. {
  61.     o_heatmap = new HeatmapType *[height];
  62.     for (int i = 0; i < height; ++i)
  63.     {
  64.         o_heatmap[i] = new HeatmapType[width];
  65.         for (int j = 0; j < width; ++j)
  66.         {
  67.             o_heatmap[i][j] = 0;
  68.         }
  69.     }
  70. }
  71.  
  72. void FreeHeatmap(HeatmapType **&o_heatmap, int height)
  73. {
  74.     for (int i = 0; i < height; ++i)
  75.     {
  76.         delete[] o_heatmap[i];
  77.         o_heatmap[i] = nullptr;
  78.     }
  79.     delete o_heatmap;
  80.     o_heatmap = nullptr;
  81. }
  82.  
  83. vector<Complex> buddhabrotPoints(const Complex &c, int nIterations)
  84. {
  85.     int n = 0;
  86.     Complex z;
  87.  
  88.     vector<Complex> toReturn;
  89.     toReturn.reserve(nIterations);
  90.  
  91.     while (n < nIterations && z.sqmagnitude() <= 2.0)
  92.     {
  93.         z = z * z + c;
  94.         ++n;
  95.  
  96.         toReturn.push_back(z);
  97.     }
  98.  
  99.     // If point remains bounded through nIterations iterations, the point
  100.     //  is bounded, therefore in the Mandelbrot set, therefore of no interest to us
  101.     if (n == nIterations)
  102.     {
  103.         return vector<Complex>();
  104.     }
  105.     else
  106.     {
  107.         return toReturn;
  108.     }
  109. }
  110.  
  111. int rowFromReal(double real, double minR, double maxR, int imageHeight)
  112. {
  113.     // [minR, maxR]
  114.     // [0, maxR - minR] // subtract minR from n
  115.     // [0, imageHeight] // multiply by (imageHeight / (maxR - minR))
  116.     return (int)((real - minR) * (imageHeight / (maxR - minR)));
  117. }
  118.  
  119. int colFromImaginary(double imag, double minI, double maxI, int imageWidth)
  120. {
  121.     return (int)((imag - minI) * (imageWidth / (maxI - minI)));
  122. }
  123.  
  124. void GenerateHeatmap(HeatmapType **o_heatmap, int imageWidth, int imageHeight,
  125.                      const Complex &minimum, const Complex &maximum, int nIterations, long long nSamples,
  126.                      HeatmapType &o_maxHeatmapValue, string consoleMessagePrefix)
  127. {
  128.     mt19937 rng;
  129.     uniform_real_distribution<double> realDistribution(minimum.r(), maximum.r());
  130.     uniform_real_distribution<double> imagDistribution(minimum.i(), maximum.i());
  131.  
  132.     rng.seed(chrono::high_resolution_clock::now().time_since_epoch().count());
  133.     // Collect nSamples samples... (sample is just a random number c)
  134.     for (long long sampleIdx = 0; sampleIdx < nSamples; ++sampleIdx)
  135.     {
  136.         //  Each sample, get the list of points as the function
  137.         //    escapes to infinity (if it does at all)
  138.  
  139.         Complex sample(realDistribution(rng), imagDistribution(rng));
  140.         vector<Complex> pointsList = buddhabrotPoints(sample, nIterations);
  141.  
  142.         for (Complex &point : pointsList)
  143.         {
  144.             if (point.r() <= maximum.r() && point.r() >= minimum.r() && point.i() <= maximum.i() && point.i() >= minimum.i())
  145.             {
  146.                 int row = rowFromReal(point.r(), minimum.r(), maximum.r(), imageHeight);
  147.                 int col = colFromImaginary(point.i(), minimum.i(), maximum.i(), imageWidth);
  148.                 ++o_heatmap[row][col];
  149.  
  150.                 if (o_heatmap[row][col] > o_maxHeatmapValue)
  151.                 {
  152.                     o_maxHeatmapValue = o_heatmap[row][col];
  153.                 }
  154.             }
  155.         }
  156.     }
  157. }
  158.  
  159. float colorFromHeatmap(HeatmapType inputValue, HeatmapType maxHeatmapValue, float maxColor)
  160. {
  161.     double scale = (1.0f * (maxColor)) / (1.0f * maxHeatmapValue);
  162.     return inputValue * scale;
  163. }
  164.  
  165. void framebuffer_size_callback(GLFWwindow *window, int width, int height);
  166. void mouse_button_callback(GLFWwindow *window, int button, int action, int mods);
  167. void processInput(GLFWwindow *window);
  168.  
  169. const char *vertexShaderSource = "#version 330 core\n"
  170.                                  "layout (location = 0) in vec3 aPos;\n"
  171.                                  "layout (location = 1) in vec3 aColor;\n"
  172.                                  "out vec3 vertexColor;\n"
  173.                                  "void main()\n"
  174.                                  "{\n"
  175.                                  "   gl_Position = vec4(aPos,1.0);\n"
  176.                                  "vertexColor = aColor;\n"
  177.                                  "}\0";
  178. const char *fragmentShaderSource = "#version 330 core\n"
  179.                                    "out vec4 FragColor;\n"
  180.                                    "in vec3 vertexColor;\n"
  181.                                    "void main()\n"
  182.                                    "{\n"
  183.                                    "   FragColor =  vec4(vertexColor, 1.0);\n"
  184.                                    "}\n\0";
  185.  
  186. int points;
  187.  
  188. float mapX(float x)
  189. {
  190.     return x * 2.0 / IMAGE_WIDTH - 1.0;
  191. }
  192.  
  193. float mapY(float y)
  194. {
  195.     return y * 2.0 / IMAGE_HEIGHT - 1.0;
  196. }
  197.  
  198. int main()
  199. {
  200.     const Complex MINIMUM(-2.0, -2.0);
  201.     const Complex MAXIMUM(2.0, 2.0);
  202.     vector<float> vertices;
  203.     vertices.reserve(IMAGE_HEIGHT * IMAGE_WIDTH);
  204.  
  205.     // Allocate a heatmap of the size of our image
  206.     HeatmapType maxHeatmapValue = 0;
  207.     HeatmapType **red;
  208.     HeatmapType **green;
  209.     HeatmapType **blue;
  210.     AllocHeatmap(red, IMAGE_WIDTH, IMAGE_HEIGHT);
  211.     AllocHeatmap(green, IMAGE_WIDTH, IMAGE_HEIGHT);
  212.     AllocHeatmap(blue, IMAGE_WIDTH, IMAGE_HEIGHT);
  213.  
  214.     GenerateHeatmap(red, IMAGE_WIDTH, IMAGE_HEIGHT, MINIMUM, MAXIMUM, RED_ITERS,
  215.                     SAMPLE_COUNT, maxHeatmapValue, "Red Channel: ");
  216.     GenerateHeatmap(blue, IMAGE_WIDTH, IMAGE_HEIGHT, MINIMUM, MAXIMUM, BLUE_ITERS,
  217.                     SAMPLE_COUNT, maxHeatmapValue, "Blue Channel: ");
  218.  
  219.     GenerateHeatmap(green, IMAGE_WIDTH, IMAGE_HEIGHT, MINIMUM, MAXIMUM, GREEN_ITERS,
  220.                     SAMPLE_COUNT, maxHeatmapValue, "green Channel: ");
  221.  
  222.     // Scale the heatmap down
  223.     for (int row = 0; row < IMAGE_HEIGHT; ++row)
  224.     {
  225.         for (int col = 0; col < IMAGE_WIDTH; ++col)
  226.         {
  227.  
  228.             red[row][col] = colorFromHeatmap(red[row][col], maxHeatmapValue, 1);
  229.             blue[row][col] = colorFromHeatmap(blue[row][col], maxHeatmapValue, 1);
  230.             green[row][col] = colorFromHeatmap(green[row][col], maxHeatmapValue, 1);
  231.  
  232.             //cout<<red[row][col]<<endl;
  233.             vertices.push_back(-mapX(col));
  234.             vertices.push_back(-mapY(row));
  235.             vertices.push_back(0.0f);
  236.             vertices.push_back(red[row][col]);
  237.             vertices.push_back(green[row][col]);
  238.             vertices.push_back(blue[row][col]);
  239.  
  240.             //  cout<<red[row][col]<<endl;
  241.             //vertices.push_back(0.0f);
  242.             //vertices.push_back(0.0f);
  243.         }
  244.     }
  245.  
  246.     // glfw: initialize and configure
  247.     // ------------------------------
  248.     glfwInit();
  249.     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  250.     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  251.     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  252.  
  253. #ifdef __APPLE__
  254.     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
  255. #endif
  256.  
  257.     // glfw window creation
  258.     // --------------------
  259.     GLFWwindow *window = glfwCreateWindow(IMAGE_WIDTH, IMAGE_HEIGHT, "Algorithmic Modeling Fractal Buddhabrot Set", NULL, NULL);
  260.     if (window == NULL)
  261.     {
  262.         std::cout << "Failed to create GLFW window" << std::endl;
  263.         glfwTerminate();
  264.         return -1;
  265.     }
  266.     glfwMakeContextCurrent(window);
  267.     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
  268.     //    glfwSetMouseButtonCallback(window, mouse_button_callback);
  269.  
  270.     // glad: load all OpenGL function pointers
  271.     // ---------------------------------------
  272.     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
  273.     {
  274.         std::cout << "Failed to initialize GLAD" << std::endl;
  275.         return -1;
  276.     }
  277.  
  278.     // build and compile our shader program
  279.     // ------------------------------------
  280.     // vertex shader
  281.     int vertexShader = glCreateShader(GL_VERTEX_SHADER);
  282.     glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
  283.     glCompileShader(vertexShader);
  284.     // check for shader compile errors
  285.     int success;
  286.     char infoLog[512];
  287.     glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
  288.     if (!success)
  289.     {
  290.         glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
  291.         std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"
  292.                   << infoLog << std::endl;
  293.     }
  294.     // fragment shader
  295.     int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  296.     glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
  297.     glCompileShader(fragmentShader);
  298.     // check for shader compile errors
  299.     glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
  300.     if (!success)
  301.     {
  302.         glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
  303.         std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"
  304.                   << infoLog << std::endl;
  305.     }
  306.     // link shaders
  307.     int shaderProgram = glCreateProgram();
  308.     glAttachShader(shaderProgram, vertexShader);
  309.     glAttachShader(shaderProgram, fragmentShader);
  310.     glLinkProgram(shaderProgram);
  311.     // check for linking errors
  312.     glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
  313.     if (!success)
  314.     {
  315.         glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
  316.         std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"
  317.                   << infoLog << std::endl;
  318.     }
  319.     glDeleteShader(vertexShader);
  320.     glDeleteShader(fragmentShader);
  321.  
  322.     // set up vertex data (and buffer(s)) and configure vertex attributes
  323.     // ------------------------------------------------------------------
  324.  
  325.     points = vertices.size();
  326.  
  327.     // uncomment this call to draw in wireframe polygons.
  328.     //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  329.  
  330.     // render loop
  331.     cout << "done" << endl;
  332.     unsigned int VBO, VAO;
  333.  
  334.     glGenVertexArrays(1, &VAO);
  335.     glGenBuffers(1, &VBO);
  336.     // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
  337.     glBindVertexArray(VAO);
  338.  
  339.     glBindBuffer(GL_ARRAY_BUFFER, VBO);
  340.     glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
  341.  
  342.     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)0);
  343.     glEnableVertexAttribArray(0);
  344.     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)(3 * sizeof(float)));
  345.     glEnableVertexAttribArray(1);
  346.     // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
  347.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  348.  
  349.     // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
  350.     // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
  351.     glBindVertexArray(0);
  352.     // -----------
  353.     while (!glfwWindowShouldClose(window))
  354.     {
  355.  
  356.         processInput(window);
  357.  
  358.         //glClearColor(1,1, 1, 1.0f);
  359.         //glClear(GL_COLOR_BUFFER_BIT);
  360.  
  361.         // draw our first triangle
  362.         glUseProgram(shaderProgram);
  363.         glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
  364.         glDrawArrays(GL_POINTS, 0, points);
  365.         glfwSwapBuffers(window);
  366.         glfwPollEvents();
  367.         // ------------------------------------------------------------------
  368.     }
  369.  
  370.     //glDeleteVertexArrays(1, &VAO);
  371.     //glDeleteBuffers(1, &VBO);
  372.     // optional: de-allocate all resources once they've outlived their purpose:
  373.     // ------------------------------------------------------------------------
  374.  
  375.     // glfw: terminate, clearing all previously allocated GLFW resources.
  376.  
  377.     glfwTerminate();
  378.     return 0;
  379. }
  380.  
  381. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
  382. // ---------------------------------------------------------------------------------------------------------
  383. void processInput(GLFWwindow *window)
  384. {
  385.     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
  386.         glfwSetWindowShouldClose(window, true);
  387. }
  388.  
  389. // glfw: whenever the window size changed (by OS or user resize) this callback function executes
  390. // ---------------------------------------------------------------------------------------------
  391.  
  392. void framebuffer_size_callback(GLFWwindow *window, int width, int height)
  393. {
  394.     // make sure the viewport matches the new window dimensions; note that width and
  395.     // height will be significantly larger than specified on retina displays.
  396.     glViewport(0, 0, width, height);
  397. }
Add Comment
Please, Sign In to add comment