diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d31c40..b67f8d4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,7 @@ add_compile_options(-Wall)
add_executable(${PROJECT_NAME} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
add_dependencies(${PROJECT_NAME} glib-resources)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
-target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m pthread ${OPENCL_LIBRARIES} ${GLUT_LIBRARIES} ${OPENGL_gl_LIBRARIES} ${GLUT_LIBRARIES} epoxy)
+target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m pthread ${OPENCL_LIBRARIES} epoxy)
install (TARGETS ${PROJECT_NAME} DESTINATION bin)
message(STATUS "OpenCL found: ${OPENCL_FOUND}")
diff --git a/glade/main.glade b/glade/main.glade
index 909da17..6b42667 100644
--- a/glade/main.glade
+++ b/glade/main.glade
@@ -11,11 +11,7 @@
-
+
diff --git a/mandelbrot.cl b/mandelbrot.cl
index b7fd9c5..d33b52e 100644
--- a/mandelbrot.cl
+++ b/mandelbrot.cl
@@ -1,4 +1,4 @@
-__kernel void mandelbrot(__global unsigned int *out_buff, unsigned int iter, double cx, double cy, double xs, double ys, unsigned int width, unsigned int height)
+__kernel void mandelbrot(__global unsigned char *out_buff, unsigned int iter, double cx, double cy, double xs, double ys, unsigned int width, unsigned int height)
{
const int idx = get_global_id(0);
@@ -6,6 +6,8 @@ __kernel void mandelbrot(__global unsigned int *out_buff, unsigned int iter, dou
double z_real, z_imag;
double z2_real, z2_imag;
double pt_real, pt_imag;
+ double color_scale;
+ unsigned int r, g, b;
const unsigned int pix_x = idx % width;
const unsigned int pix_y = (unsigned int)idx / width;
@@ -30,5 +32,15 @@ __kernel void mandelbrot(__global unsigned int *out_buff, unsigned int iter, dou
break;
}
- out_buff[idx] = i;
+ color_scale = (double)(i) / (double)iter;
+ if (i != iter) {
+ r = (unsigned char)(255.0 * sqrt((1-color_scale)));
+ g = (unsigned char)(255.0 * color_scale*color_scale);
+ b = (unsigned char)(255.0 * color_scale);
+ } else {
+ r = g = b = 0;
+ }
+ out_buff[idx*3] = r;
+ out_buff[idx*3+1] = g;
+ out_buff[idx*3+2] = b;
}
diff --git a/src/main.c b/src/main.c
index db15eaf..dabb0a2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,9 +5,34 @@
#include
#include
#include
+#include
+
+
+static const char * const vertex_shader = "#version 330 core\n \
+ layout (location = 0) in vec3 aPos;\n \
+ layout (location = 1) in vec2 aTexCoord;\n\
+ out vec2 texCoord;\n \
+ void main()\n \
+ {\n \
+ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n \
+ texCoord = aTexCoord;\n\
+ }\n";
+
+static const char * const orange_framgment_shader = " \
+ #version 330 core\n \
+ out vec4 FragColor;\n \
+ in vec4 vertexColor;\n \
+ in vec2 texCoord;\n \
+ uniform sampler2D ourTexture;\n \
+ \n \
+ void main()\n \
+ {\n \
+ FragColor = texture(ourTexture, texCoord);\n \
+ }";
+
struct canvas_buffer {
- unsigned int *mandelbrot_buffer;
+ unsigned char *mandelbrot_buffer;
unsigned int iterations;
unsigned int height;
unsigned int width;
@@ -78,16 +103,15 @@ static int calculate_mandelbrot(struct canvas_buffer *buff)
char *source_code = NULL;
char temp_buff[100];
size_t data_size;
- size_t work_size = 64;
- unsigned int *data_array;
+ size_t work_size = 10;
+
data_size = buff->width*buff->height;
if (!buff->mandelbrot_buffer)
- buff->mandelbrot_buffer = (unsigned int *)calloc(data_size, sizeof(buff->mandelbrot_buffer[0]));
+ buff->mandelbrot_buffer = (unsigned char *)malloc(data_size*3);
- data_array = buff->mandelbrot_buffer;
- if (!data_array)
+ if (!buff->mandelbrot_buffer)
return -ENOMEM;
@@ -138,7 +162,7 @@ static int calculate_mandelbrot(struct canvas_buffer *buff)
dat_buff = clCreateBuffer(context, CL_MEM_WRITE_ONLY |
CL_MEM_COPY_HOST_PTR,
- sizeof(data_array[0])*data_size, data_array, &error);
+ 3*data_size, buff->mandelbrot_buffer, &error);
check_error(error);
load_kernel_from_file("cl_kernels/mandelbrot.cl", &source_code);
@@ -161,9 +185,9 @@ static int calculate_mandelbrot(struct canvas_buffer *buff)
clSetKernelArg(kernel, 7, sizeof(unsigned int), (void *)&buff->height);
ret = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &data_size, &work_size, 0, NULL, NULL);
- check_error(ret);
+ check_error(ret);
- clEnqueueReadBuffer(queue, dat_buff, CL_TRUE, 0, data_size*sizeof(data_array[0]), data_array, 0, NULL, NULL);
+ clEnqueueReadBuffer(queue, dat_buff, CL_TRUE, 0, data_size*3, buff->mandelbrot_buffer, 0, NULL, NULL);
printf("Calculation finished!\n");
@@ -181,74 +205,155 @@ static int calculate_mandelbrot(struct canvas_buffer *buff)
}
-// This will identify our vertex buffer
-GLuint vertexbuffer;
-
-// An array of 3 vectors which represents 3 vertices
-static const GLfloat g_vertex_buffer_data[] = {
- -10.0f, -10.0f, 0.0f,
- 10.0f, -10.0f, 0.0f,
- 0.0f, 10.0f, 0.0f,
+float vertices[] = {
+ // Vertex Texture
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left
+ -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left
+ 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right
};
+unsigned int indices[] = {
+ 0, 1, 2,
+ 2, 1, 3
+};
-static gboolean render(GtkGLArea *area, GdkGLContext *context)
+static unsigned int vertex_buffer_object;
+static unsigned int element_buffer_object;
+static unsigned int vertex_array_object;
+static unsigned int shader_program_id;
+static unsigned int texture_id;
+
+gboolean render(GtkGLArea *gl_area, GdkGLContext *context, gpointer user_data)
{
- gtk_gl_area_make_current(area);
- glClearColor (1, 0, 1, 0.5);
- //glClear (GL_COLOR_BUFFER_BIT);
+ gtk_gl_area_make_current(gl_area);
- // Generate 1 buffer, put the resulting identifier in vertexbuffer
- glGenBuffers(1, &vertexbuffer);
- // The following commands will talk about our 'vertexbuffer' buffer
- glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
- // Give our vertices to OpenGL.
- glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(shader_program_id);
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ glBindVertexArray(vertex_array_object);
+ //glDrawArrays(GL_TRIANGLES, 0, 3);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
- glVertexAttribPointer(
- 0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
- 3, // size
- GL_FLOAT, // type
- GL_FALSE, // normalized?
- 0, // stride
- (void*)0 // array buffer offset
- );
- // Draw the triangle !
- glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
- glDisableVertexAttribArray(0);
+ glFlush();
-
- return TRUE;
+ return TRUE;
}
+void realize(GtkGLArea *gl_area, gpointer user_data)
+{
+ unsigned int vertex_shader_id;
+ unsigned int fragment_shader_id;
+ struct canvas_buffer *mandelbrot_buff = (struct canvas_buffer *)user_data;
+
+ int success;
+ char info_log[512];
+
+ gtk_gl_area_make_current(gl_area);
+ glClearColor(0, 0, 0, 1);
+
+ glGenVertexArrays(1, &vertex_array_object);
+ glBindVertexArray(vertex_array_object);
+
+ glGenBuffers(1, &vertex_buffer_object);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ glGenBuffers(1, &element_buffer_object);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+ vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex_shader_id, 1, &vertex_shader, NULL);
+ glCompileShader(vertex_shader_id);
+ glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &success);
+
+ if (!success) {
+ glGetShaderInfoLog(vertex_shader_id, 512, NULL, info_log);
+ printf("%s\n", info_log);
+ } else {
+ printf("Vertex shader compilation successful\n");
+ }
+
+ fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment_shader_id, 1, &orange_framgment_shader, NULL);
+ glCompileShader(fragment_shader_id);
+ glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &success);
+
+ if (!success) {
+ glGetShaderInfoLog(fragment_shader_id, 512, NULL, info_log);
+ printf("%s\n", info_log);
+ } else {
+ printf("Fragment shader compilation successful\n");
+ }
+
+ shader_program_id = glCreateProgram();
+ glAttachShader(shader_program_id, vertex_shader_id);
+ glAttachShader(shader_program_id, fragment_shader_id);
+ glLinkProgram(shader_program_id);
+
+ glGetShaderiv(shader_program_id, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(shader_program_id, 512, NULL, info_log);
+ printf("%s\n", info_log);
+ } else {
+ printf("Shader Core linked successfully\n");
+ }
+
+ glUseProgram(shader_program_id);
+ glDeleteShader(vertex_shader_id);
+ glDeleteShader(fragment_shader_id);
+
+
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
+ glEnableVertexAttribArray(0);
+
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
+ glEnableVertexAttribArray(1);
+
+ glGenTextures(1, &texture_id);
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mandelbrot_buff->width, mandelbrot_buff->height,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, mandelbrot_buff->mandelbrot_buffer);
+ glGenerateMipmap(GL_TEXTURE_2D);
+
+
+
+ //glClear(GL_COLOR_BUFFER_BIT);
+}
int main(int argc, char **argv)
{
+ GtkGLArea *gl_area;
GtkWindow *window;
GtkBuilder *builder;
- GtkGLArea *glarea;
+ GtkWidget *temp;
static struct canvas_buffer mandelbrot_buff;
gtk_init(&argc, &argv);
builder = gtk_builder_new_from_resource("/main.glade");
- glarea = GTK_GL_AREA(gtk_builder_get_object(builder, "glarea"));
- g_object_unref(builder);
+ window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window"));
+ g_signal_connect(window, "delete-event", G_CALLBACK(on_main_window_close), NULL);
- mandelbrot_buff.x_span = 1;//2.8;
- mandelbrot_buff.y_span = 0.5;//2.25;
+
+
+ mandelbrot_buff.x_span = 0.075;//2.8;
+ mandelbrot_buff.y_span = 0.075;//2.25;
mandelbrot_buff.center_x = -0.6;
- mandelbrot_buff.center_y = 0.6;
- mandelbrot_buff.width = 1920*3;
- mandelbrot_buff.height = 1080*3;
- mandelbrot_buff.iterations = 70;
+ mandelbrot_buff.center_y = 0.45;
+ mandelbrot_buff.width = 3000;
+ mandelbrot_buff.height = 3000;
+ mandelbrot_buff.iterations = 200;
mandelbrot_buff.mandelbrot_buffer = NULL;
//calculate_mandelbrot(&mandelbrot_buff);
@@ -260,6 +365,22 @@ int main(int argc, char **argv)
g_signal_connect(glarea, "render", G_CALLBACK(render), NULL);
+
+ gl_area = GTK_GL_AREA(gtk_gl_area_new());
+ gtk_gl_area_set_auto_render(gl_area, TRUE);
+ gtk_widget_set_vexpand(GTK_WIDGET(gl_area), TRUE);
+ gtk_widget_set_hexpand(GTK_WIDGET(gl_area), TRUE);
+ g_signal_connect(gl_area, "realize", G_CALLBACK(realize), &mandelbrot_buff);
+ g_signal_connect(gl_area, "render", G_CALLBACK(render), NULL);
+
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(gl_area));
+ gtk_widget_show(GTK_WIDGET(gl_area));
+
+ g_object_unref(builder);
+
+ gtk_gl_area_make_current(gl_area);
+
+
gtk_main();
return 0;