Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <strings.h>
- #include <stdlib.h>
- #include <gtk/gtk.h>
- #include <gtk/gtkgl.h>
- #include <GL/gl.h>
- const GLfloat rect[] = {-0.5f, 0.5f,
- 0.5f, 0.5f,
- 0.5f, -0.5f,
- -0.5f, -0.5f};
- const GLfloat tri[] = { 0.0f, 1.0f,
- 0.5f, 0.5f,
- -0.5f, 0.5f};
- const GLchar *v_src = "#version 440\n"
- "in vec2 pos;"
- "void main() {"
- " gl_Position = vec4(pos, 0.0, 1.0);"
- "}";
- const GLchar *f_src = "#version 440\n"
- "out vec4 col;"
- "void main() {"
- " col = vec4(0.5, 0.3, 0.0, 1.0);"
- "}";
- void print_gl_err(const char *operation) {
- GLenum err = glGetError();
- if(err != GL_NO_ERROR) {
- fprintf(stderr, "%s: ", operation);
- fprintf(stderr, err == GL_INVALID_ENUM ? "invalid enumeration\n" :
- err == GL_INVALID_VALUE ? "invalid value\n" :
- err == GL_INVALID_OPERATION ? "invalid operation\n" :
- err == GL_INVALID_FRAMEBUFFER_OPERATION ? "invalid framebuffer operation\n" :
- err == GL_OUT_OF_MEMORY ? "out of memory\n" :
- err == GL_STACK_UNDERFLOW ? "stack underflow\n" :
- err == GL_STACK_OVERFLOW ? "stack overflow\n" : "unknown error\n");
- }
- }
- gboolean on_destroy(GtkWidget *main_window, gpointer data) {
- gtk_main_quit();
- return TRUE;
- }
- gboolean on_expose(GtkWidget *main_window, GdkEventExpose *event, gpointer data) {
- GdkGLDrawable *gl_window = gtk_widget_get_gl_drawable(main_window);
- GdkGLContext *context = gtk_widget_get_gl_context(main_window);
- gdk_gl_drawable_gl_begin(gl_window, context);
- // gl commands for drawing
- glClearColor(0.2, 0.1, 0.1, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
- GLuint vbo[2];
- glGenBuffers(2, vbo);
- print_gl_err("buffer allocation");
- GLuint vshader, fshader, prog;
- vshader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vshader, 1, &v_src, NULL);
- glCompileShader(vshader);
- GLint compile_status;
- char compile_log[512];
- glGetShaderiv(vshader, GL_COMPILE_STATUS, &compile_status);
- if(compile_status != GL_TRUE) {
- bzero(compile_log, sizeof(compile_log));
- glGetShaderInfoLog(vshader, 512, NULL, compile_log);
- fprintf(stderr, "%-512s\n", compile_log);
- }
- fshader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fshader, 1, &f_src, NULL);
- glCompileShader(fshader);
- glGetShaderiv(fshader, GL_COMPILE_STATUS, &compile_status);
- if(compile_status != GL_TRUE) {
- bzero(compile_log, sizeof(compile_log));
- glGetShaderInfoLog(vshader, 512, NULL, compile_log);
- fprintf(stderr, "%-512s\n", compile_log);
- }
- print_gl_err("shader compilation");
- prog = glCreateProgram();
- glAttachShader(prog, vshader);
- glAttachShader(prog, fshader);
- glLinkProgram(prog);
- print_gl_err("program linking");
- glUseProgram(prog);
- print_gl_err("program usage");
- GLuint varr;
- glGenVertexArrays(1, &varr);
- glBindVertexArray(varr);
- // draw triangle
- glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
- glBufferStorage(GL_ARRAY_BUFFER, sizeof(tri), tri, 0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
- // alternative way to map attributes with binding points
- /*glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0);
- glVertexAttribBinding(0, 0);
- glBindVertexBuffer(0, vbo[0], 0, 2 * sizeof(GLfloat));*/
- glEnableVertexAttribArray(0);
- // draw rectangle
- glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
- glBufferStorage(GL_ARRAY_BUFFER, sizeof(rect), rect, 0);
- glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
- // alternative way to map attributes with binding points
- /*glVertexAttribFormat(3, 2, GL_FLOAT, GL_FALSE, 0);
- glVertexAttribBinding(3, 3);
- glBindVertexBuffer(3, vbo[1], 2 * sizeof(GLfloat), 2 * sizeof(GLfloat));*/
- glEnableVertexAttribArray(3);
- print_gl_err("vertex array binding");
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
- print_gl_err("drawing");
- glDeleteProgram(prog);
- glDeleteShader(vshader);
- glDeleteShader(fshader);
- glDeleteVertexArrays(1, &varr);
- glDeleteBuffers(2, vbo);
- print_gl_err("deletion");
- if(gdk_gl_drawable_is_double_buffered(gl_window))
- gdk_gl_drawable_swap_buffers(gl_window);
- else
- glFlush();
- gdk_gl_drawable_gl_end(gl_window);
- return TRUE;
- }
- int main(int argc, char *argv[]) {
- const gchar *name = "OpenGL test";
- const gint w = 800, h = 600;
- gtk_init(&argc, &argv);
- if(!gtk_gl_init_check(&argc, &argv)) {
- fprintf(stderr, "Unable to initialize OpenGL system\n");
- return EXIT_FAILURE;
- }
- GtkWidget *main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_size_request(main_window, w, h);
- gtk_window_set_title(GTK_WINDOW(main_window), name);
- g_signal_connect(main_window, "destroy", G_CALLBACK(on_destroy), NULL);
- GtkWidget *drawing_area = gtk_drawing_area_new();
- gtk_widget_set_size_request(drawing_area, w, h);
- gtk_widget_set_events(drawing_area, GDK_EXPOSURE_MASK);
- gtk_container_add(GTK_CONTAINER(main_window), drawing_area);
- // make drawing area drawable by realizing(making it visible) the attached window
- // don't attach the draw event handlers yet
- gtk_widget_show(main_window);
- // RGBA colour mode and double buffered window
- GdkGLConfig *gl_conf = gdk_gl_config_new_by_mode(
- GDK_GL_MODE_RGBA
- |GDK_GL_MODE_DOUBLE
- );
- if(!gl_conf || !gtk_widget_set_gl_capability(drawing_area, gl_conf, NULL, TRUE, GDK_GL_RGBA_TYPE)) {
- fprintf(stderr, "Unable to configure OpenGL system\n");
- return EXIT_FAILURE;
- }
- // GTK2 version of draw event
- g_signal_connect(drawing_area, "expose-event", G_CALLBACK(on_expose), NULL);
- gtk_widget_show_all(main_window);
- gtk_main();
- return EXIT_SUCCESS;
- }
Add Comment
Please, Sign In to add comment