#include #include struct _OpenGlPreviewGui { GObject super; GtkWindow *main_window; GtkGLArea *gl_area; unsigned int polygon_shader_prog; unsigned int vao; unsigned int vbo; float color[4]; }; G_DEFINE_TYPE(OpenGlPreviewGui, opengl_preview_gui, G_TYPE_OBJECT) static void opengl_preview_gui_dispose(GObject *gobj) { OpenGlPreviewGui *self; self = GDS_RENDER_OPENGL_PREVIEW_GUI(gobj); g_clear_object(&self->gl_area); if (self->main_window) { gtk_widget_destroy(GTK_WIDGET(self->main_window)); self->main_window = NULL; } G_OBJECT_CLASS(opengl_preview_gui_parent_class)->dispose(gobj); } static void opengl_preview_gui_class_init(OpenGlPreviewGuiClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS(klass); oclass->dispose = opengl_preview_gui_dispose; } static gboolean gl_area_render(GtkGLArea *area, GdkGLContext *context, gpointer user) { OpenGlPreviewGui *gui; int loc; gui = GDS_RENDER_OPENGL_PREVIEW_GUI(user); gtk_gl_area_make_current(area); glClearColor (0, 0, 0, 1.0); glClear (GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glUseProgram(gui->polygon_shader_prog); glBindVertexArray(gui->vao); loc = glGetUniformLocation(gui->polygon_shader_prog, "const_color"); glUniform4fv(loc, 1, gui->color); glDrawArrays(GL_TRIANGLES, 0, 3); glFlush(); return TRUE; } static int compile_shader_from_resource(GLenum shader_type, const char *res_name, unsigned int *shader) { int success; GBytes *res_bytes; const char *data; gsize size; int size_int; int sh; res_bytes = g_resources_lookup_data(res_name, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); data = g_bytes_get_data(res_bytes, &size); sh = glCreateShader(shader_type); size_int = (int)size; glShaderSource(sh, 1, &data, &size_int); glCompileShader(sh); glGetShaderiv(sh, GL_COMPILE_STATUS, &success); g_bytes_unref(res_bytes); if (shader) *shader = sh; return success; } static gboolean gl_area_realize(GtkGLArea *area, gpointer user) { unsigned int vbo; unsigned int vs; unsigned int fs; unsigned int prog; unsigned int vao; OpenGlPreviewGui *gui; int success; gui = GDS_RENDER_OPENGL_PREVIEW_GUI(user); gui->color[0] = 0.6f; gui->color[1] = 0.5f; gui->color[2] = 0.12f; gui->color[3] = 1.0f; gtk_gl_area_make_current(area); if (!compile_shader_from_resource(GL_VERTEX_SHADER, "/shaders/polygon.vs", &vs)) { g_warning("Error compiling vertex shader"); } if (!compile_shader_from_resource(GL_FRAGMENT_SHADER, "/shaders/polygon.fs", &fs)) { g_warning("Error compiling fragment shader"); } prog = glCreateProgram(); glAttachShader(prog, vs); glAttachShader(prog, fs); glLinkProgram(prog); glGetProgramiv(prog, GL_LINK_STATUS, &success); if (!success) { g_warning("Error linking shader"); } glUseProgram(prog); glDeleteShader(vs); glDeleteShader(fs); float vertices[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.5f, }; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void *)0); glEnableVertexAttribArray(0); gui->polygon_shader_prog = prog; gui->vao = vao; gui->vbo = vbo; return TRUE; } static void opengl_preview_gui_init(OpenGlPreviewGui *self) { GtkBuilder *builder; builder = gtk_builder_new_from_resource("/gui/preview-window.glade"); self->main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window")); self->gl_area = GTK_GL_AREA(gtk_builder_get_object(builder, "gl-area")); g_signal_connect(self->gl_area, "render", G_CALLBACK(gl_area_render), self); g_signal_connect(self->gl_area, "realize", G_CALLBACK(gl_area_realize), self); g_object_ref(self->gl_area); } OpenGlPreviewGui *opengl_preview_gui_new(void) { return GDS_RENDER_OPENGL_PREVIEW_GUI(g_object_new(TYPE_GDS_RENDER_OPENGL_PREVIEW_GUI, NULL)); } void opengl_preview_gui_show(OpenGlPreviewGui *self) { gtk_widget_show(GTK_WIDGET(self->main_window)); }