patterncppMinor
Mandelbrot Fractal Drawer in C++
Viewed 0 times
fractaldrawermandelbrot
Problem
As an exercise to learn how OpenGL and image creation worked, as well as to satisfy a curiosity I've developed for Chaos Theory, I decided to create a mandelbrot fractal drawer in C++, which can either draw to an OpenGL context or to a PNG image. I am a beginner at C++, and would much appreciate any constructive feedback. Also, please ridicule me on how I create my images, and how I can make them look better as well.
main.cpp
```
#include
#include
#include
#include "Window.h"
#include "Draw_Buffer.h"
#include "Image_Buffer.h"
#include "Buffer_Base.h"
static constexpr float COMPLEX_INCREMENT = 0.005f;
template
int iterations_till_escape(const std::complex &c, int max_iterations) {
std::complex z(0, 0);
for (int iter = 0; iter 2) {
return iter;
}
}
return -1;
}
template
RGB calculate_pixel(const std::complex &c) {
int iterations = iterations_till_escape(c, 255);
if (iterations == -1) {
return RGB{0, 0, 0};
}
else {
GLubyte blue = iterations * 5;
return RGB{0, 0, blue};
}
}
int main() {
// Declare window object to represent the complex plane
Window complex_plane(-2.2, 1.2, -1.7, 1.7);
// Declare window object to represent the OpenGL window
Window window(0, ((std::abs(complex_plane.get_x_min()) + complex_plane.get_x_max()) / COMPLEX_INCREMENT),
0, ((std::abs(complex_plane.get_y_min()) + complex_plane.get_y_max()) / COMPLEX_INCREMENT));
std::unique_ptr> pixel_buffer;
std::cout > response))
;
if (response == 'W' || response == 'w') {
// Initialise pointer to a draw buffer
pixel_buffer.reset(new Draw_Buffer(&window, "vertex_shader.glsl", "fragment_shader.glsl"));
}
else if (response == 'I' || response == 'i') {
std::cout > src))
;
// Initialise pointer to an image buffer
pixel_buffer.reset(new Image_Buffer(&window, src));
}
std::complex pixel_iterato
main.cpp
```
#include
#include
#include
#include "Window.h"
#include "Draw_Buffer.h"
#include "Image_Buffer.h"
#include "Buffer_Base.h"
static constexpr float COMPLEX_INCREMENT = 0.005f;
template
int iterations_till_escape(const std::complex &c, int max_iterations) {
std::complex z(0, 0);
for (int iter = 0; iter 2) {
return iter;
}
}
return -1;
}
template
RGB calculate_pixel(const std::complex &c) {
int iterations = iterations_till_escape(c, 255);
if (iterations == -1) {
return RGB{0, 0, 0};
}
else {
GLubyte blue = iterations * 5;
return RGB{0, 0, blue};
}
}
int main() {
// Declare window object to represent the complex plane
Window complex_plane(-2.2, 1.2, -1.7, 1.7);
// Declare window object to represent the OpenGL window
Window window(0, ((std::abs(complex_plane.get_x_min()) + complex_plane.get_x_max()) / COMPLEX_INCREMENT),
0, ((std::abs(complex_plane.get_y_min()) + complex_plane.get_y_max()) / COMPLEX_INCREMENT));
std::unique_ptr> pixel_buffer;
std::cout > response))
;
if (response == 'W' || response == 'w') {
// Initialise pointer to a draw buffer
pixel_buffer.reset(new Draw_Buffer(&window, "vertex_shader.glsl", "fragment_shader.glsl"));
}
else if (response == 'I' || response == 'i') {
std::cout > src))
;
// Initialise pointer to an image buffer
pixel_buffer.reset(new Image_Buffer(&window, src));
}
std::complex pixel_iterato
Solution
I see a number of things that may help you improve your code.
Fix the bugs
There are a couple of bugs in this program that should be fixed. First, the include guard in
Check for errors sooner
With some versions of GLEW and GL, even a successful call to
This is a call in the
However, the argument is a
Fix the bugs
There are a couple of bugs in this program that should be fixed. First, the include guard in
Window.h is missing an #endif, but that's an easy fix. Second, there is an object ownership problem that's a little more subtle. Within main, the window object is created as a regular variable which means that the destructor will be called when it goes out of scope at the end of main. However, the Buffer_Base class gets a std::unique_ptr to the same object, resulting, eventually, in a double delete. Either use a plain pointer within the Buffer_Base class or, better, use std::make_unique within main when constructing the window.Check for errors sooner
With some versions of GLEW and GL, even a successful call to
glewInit() can cause a GL_INVALID_ENUM error. My machine happens to have one of the combinations that causes this. Unfortunately, the only place in the current code that calls glGetError() is in Draw_Buffer::flush(), by which time the actual cause of the error is ancient history. It took some time for me to trace this error back to its source, but if each operation (or group of related operations) had been followed by a call to glGetError(), this would have been much easier to find.NULL is not 0This is a call in the
Draw_Buffer destructors:glBindVertexArray(NULL);However, the argument is a
GLuint and not a pointer, so 0 should be used and not NULL.Code Snippets
glBindVertexArray(NULL);Context
StackExchange Code Review Q#160287, answer score: 6
Revisions (0)
No revisions yet.