2017-12-11 22 views
-1

이전에 PyGObject에서 GLArea 위젯을 사용하는 것에 대해 질문했습니다 (Use of the Gtk.GLArea in Pygobject GTK3). 나는 그것을 이해하기 위해 C 버전을 제공 할 것이라고 생각 했으므로 명령을 그리기 위해 파이썬 버전을 얻지 못했습니다. Gtk3이 모두 포함되어 있기 때문에 우분투 16을 사용하여, 나는 그것을 쐈다. 다음 코드는 오류나 경고없이 컴파일되고 실행되지만 포함 된 GL_LINES 명령어는 그리지 않습니다. 정말 이상한 것은 glClearColor가 배경을 변경하고 GL_LINES가 같은 기능을 변경하는 것입니다. 당신이 볼 수 있듯이 우분투에 포함 된 에폭시/글루 라이브러리를 사용하고 있는데, GL/gl과 동등하다고 생각합니다. 어떤 아이디어?C에서 Gtk GLArea 위젯에 gl 명령이 표시되지 않습니다.

/*to compile -> 
gcc `pkg-config --cflags gtk+-3.0` -o gl_area gl_area.c `pkg-config --libs gtk+-3.0 epoxy`*/ 
#include <math.h> 
#include <gtk/gtk.h> 
#include <epoxy/gl.h> 
#include <stdio.h> 


gint init(GtkWidget *widget) 
{ 
    /* Setup the viewport*/ 
     glViewport(0, 0, gtk_widget_get_allocated_width (widget), 
         gtk_widget_get_allocated_height(widget)); 
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     glOrtho(0,100, 100,0, -1,1); 
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 

     printf("ran init method\n"); 
     return TRUE; 
} 



/* When widget is exposed it's contents are redrawn. */ 
static gboolean 
render (GtkGLArea *area, GdkGLContext *context) 
{ 
    /* OpenGL functions can be called only if make_current returns true */ 

     /* Draw simple triangle */ 
     glClearColor(.3,.3,.3,1); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glColor4f(1,1,1,1); 
     glBegin(GL_LINES); 
{ 
     glVertex2f(0,0); 
     glVertex2f(10000,10000); 
     glVertex2f(0,0); 
     glVertex2f(-10000,-10000); 
     glVertex2f(0,0); 
     glVertex2f(10000,-10000); 
     glVertex2f(0,0); 
     glVertex2f(-10000,10000); 
} 
     glEnd(); 
     printf("ran render method\n"); 
    return TRUE; 
} 

/* When glarea widget size changes, viewport size is set to match the new size */ 
gint reshape(GtkWidget *widget, GdkEventConfigure *event) 
{ 
    /* OpenGL functions can be called if context is current */ 
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     printf("ran rehsape method\n"); 
    glViewport(0, 0, gtk_widget_get_allocated_width (widget), 
         gtk_widget_get_allocated_height(widget)); 
    return TRUE; 
} 


int main(int argc, char **argv) 
{ 
/* initialize gtk */ 
gtk_init(&argc, &argv); 

/* Create new top level window. */ 
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
gtk_window_set_title(GTK_WINDOW(window), "GL Area Test"); 
gtk_window_set_default_size (GTK_WINDOW(window), 
          640, 
          480); 
    gtk_container_set_border_width(GTK_CONTAINER(window), 10); 

    /* Quit main if got delete event */ 
    g_signal_connect(G_OBJECT(window), 
        "delete-event", 
        G_CALLBACK(gtk_main_quit), 
        NULL); 

    /* Create new OpenGL widget. */ 
GtkWidget *glarea = gtk_gl_area_new(); 

    /* Do initialization when widget has been realized. */ 
g_signal_connect(glarea, "realize", G_CALLBACK(init), NULL); 
    /* When window is resized viewport needs to be resized also. */ 
g_signal_connect(glarea, "configure-event", G_CALLBACK(reshape), NULL); 

    /* Render signal should be sent once the context is set to current. */ 
g_signal_connect (glarea, "render", G_CALLBACK (render), NULL); 


    /* set minimum size */ 
gtk_widget_set_size_request(glarea, 100,100); 

    /* put glarea into window and show it all */ 
gtk_container_add(GTK_CONTAINER(window), glarea); 
gtk_widget_show_all (window); 
gtk_main(); 
return 0; 
} 
+1

IMHO, :;'당신'glMatrixMode (GL_PROJECTION)를 호출, 다시''glLoadIdentity 함수(); 'glOrtho (0100, 100,0, -1,1)이 후'. 이것은'glOrtho()'의 이전 호출을 덮어 쓴다. (만약 내가 기억한다면'glOrtho (-1, 1, -1, -1, -1, 1);'). 그러나'glMatrixMode (GL_MODELVIEW);' 대신'glMatrixMode()')를 사용하십시오. – Scheff

+0

Completeley는 관련이 없지만'delete-event'가 아닌'destroy'에 연결하면'gtk_main_quit'가 호출됩니다. – liberforce

+0

'gtk-demo'를 실행하십시오. gl 예제를 보시면 어떨까요? 그 예도 여기에 있습니다 : https://git.gnome.org/browse/gtk+/tree/demos/gtk-demo/glarea.c – liberforce

답변

0

enter image description here 좋아, 내가 OpenGL을 쉐이더의 사용에 대한 더 많은 이해합니다. 기본적으로, GLArea가 가진 문제는 명령이 현재 컨텍스트의 활성 버퍼에 "바인딩 된"배열에 있지 않다는 것입니다. 이 혀는 많은 도움이되었습니다. https://www.youtube.com/watch?v=Q_kFcRlLTk0 간단한 데모 코드를 해킹하고 셰이더 소스 코드를 C 코드에 문자열로 가져 왔습니다. 그랬더니 데모 앱에서 열리 며 슬라이더로 삼각형을 행렬로 회전 시켰습니다. 나는 그것을 가장 기본적인 창으로 내려 내려고 노력했다. 이것은 컴파일 및 오류없이 실행됩니다. 이제 PyGObject에서 시도해 보겠습니다. 아마 오류하지만

/* OpenGL Area 
* 
* GtkGLArea is a widget that allows custom drawing using OpenGL calls. 
*/ 
#include <string.h> 
#include <stdio.h> 
#include <math.h> 
#include <gtk/gtk.h> 
#include <epoxy/gl.h> 

const GLchar *FRAGMENT_SOURCE = 
"#version 330\n" 
"in vec4 inputColor;\n" 
"out vec4 outputColor;\n" 
"void main() {\n" 
"outputColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);\n" //constant red. I know it's a poor shader 
"}"; 
const GLchar *VERTEX_SOURCE = 
"#version 330\n" 
"in vec4 position;\n" 
"void main()\n{gl_Position = position;\n" 
"}"; 


/* the GtkGLArea widget */ 
static GtkWidget *gl_area = NULL; 

/* The object we are drawing */ 
static const GLfloat vertex_data[] = { 
    0.f, 0.5f, 0.f, 1.f, 
    0.5f, -0.366f, 0.f, 1.f, 
-0.5f, -0.366f, 0.f, 1.f, 
}; 

/* Initialize the GL buffers */ 
static void 
init_buffers (GLuint *vao_out, 
       GLuint *buffer_out) 
{ 
    GLuint vao, buffer; 

    /* We only use one VAO, so we always keep it bound */ 
    glGenVertexArrays (1, &vao); 
    glBindVertexArray (vao); 

    /* This is the buffer that holds the vertices */ 
    glGenBuffers (1, &buffer); 
    glBindBuffer (GL_ARRAY_BUFFER, buffer); 
    glBufferData (GL_ARRAY_BUFFER, sizeof (vertex_data), vertex_data, GL_STATIC_DRAW); 
    glBindBuffer (GL_ARRAY_BUFFER, 0); 

    if (vao_out != NULL) 
    *vao_out = vao; 

    if (buffer_out != NULL) 
    *buffer_out = buffer; 
} 

/* Create and compile a shader */ 
static GLuint 
create_shader (int type) 
{ 
    GLuint shader; 
    int status; 
    shader = glCreateShader (type); 
if (type== GL_FRAGMENT_SHADER){ 
    glShaderSource (shader, 1, &FRAGMENT_SOURCE, NULL);} 
if (type== GL_VERTEX_SHADER){ 
    glShaderSource (shader, 1, &VERTEX_SOURCE, NULL);} 
    glCompileShader (shader); 

    glGetShaderiv (shader, GL_COMPILE_STATUS, &status); 
    if (status == GL_FALSE) 
    { 
     int log_len; 
     char *buffer; 
     glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &log_len); 
     buffer = g_malloc (log_len + 1); 
     glGetShaderInfoLog (shader, log_len, NULL, buffer); 
     g_warning ("Compile failure in %s shader:\n%s", 
       type == GL_VERTEX_SHADER ? "vertex" : "fragment", 
       buffer); 
     g_free (buffer); 
     glDeleteShader (shader); 
     return 0; 
    } 

    return shader; 
} 

/* Initialize the shaders and link them into a program */ 
static void 
init_shaders (GLuint *program_out) 
{ 
    GLuint vertex, fragment; 
    GLuint program = 0; 
    int status; 
    vertex = create_shader (GL_VERTEX_SHADER); 

    if (vertex == 0) 
    { 
     *program_out = 0; 
     return; 
    } 

    fragment = create_shader (GL_FRAGMENT_SHADER); 

    if (fragment == 0) 
    { 
     glDeleteShader (vertex); 
     *program_out = 0; 
     return; 
    } 

    program = glCreateProgram(); 
    glAttachShader (program, vertex); 
    glAttachShader (program, fragment); 

    glLinkProgram (program); 

    glGetProgramiv (program, GL_LINK_STATUS, &status); 
    if (status == GL_FALSE) 
    { 
     int log_len; 
     char *buffer; 

     glGetProgramiv (program, GL_INFO_LOG_LENGTH, &log_len); 

     buffer = g_malloc (log_len + 1); 
     glGetProgramInfoLog (program, log_len, NULL, buffer); 

     g_warning ("Linking failure:\n%s", buffer); 

     g_free (buffer); 

     glDeleteProgram (program); 
     program = 0; 

     goto out; 
    } 


    glDetachShader (program, vertex); 
    glDetachShader (program, fragment); 

out: 
    glDeleteShader (vertex); 
    glDeleteShader (fragment); 

    if (program_out != NULL) 
    *program_out = program; 

} 


static GLuint position_buffer; 
static GLuint program; 

/* We need to set up our state when we realize the GtkGLArea widget */ 
static void 
realize (GtkWidget *widget) 
{ 
    GdkGLContext *context; 
    gtk_gl_area_make_current (GTK_GL_AREA (widget)); 
    if (gtk_gl_area_get_error (GTK_GL_AREA (widget)) != NULL) 
    return; 
    context = gtk_gl_area_get_context (GTK_GL_AREA (widget)); 
    init_buffers (&position_buffer, NULL); 
    init_shaders (&program); 
} 

/* We should tear down the state when unrealizing */ 
static void 
unrealize (GtkWidget *widget) 
{ 
    gtk_gl_area_make_current (GTK_GL_AREA (widget)); 

    if (gtk_gl_area_get_error (GTK_GL_AREA (widget)) != NULL) 
    return; 

    glDeleteBuffers (1, &position_buffer); 
    glDeleteProgram (program); 
} 

static void 
draw_triangle (void) 
{ 

    /* Use our shaders */ 
    glUseProgram (program); 


    /* Use the vertices in our buffer */ 
    glBindBuffer (GL_ARRAY_BUFFER, position_buffer); 
    glEnableVertexAttribArray (0); 
    glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, 0); 
    /* Draw the three vertices as a triangle */ 
    glDrawArrays (GL_TRIANGLES, 0, 3); 

    /* We finished using the buffers and program */ 
    glDisableVertexAttribArray (0); 
    glBindBuffer (GL_ARRAY_BUFFER, 0); 
    glUseProgram (0); 
} 

static gboolean 
render (GtkGLArea *area, 
     GdkGLContext *context) 
{ 
    if (gtk_gl_area_get_error (area) != NULL) 
    return FALSE; 

    /* Clear the viewport */ 
    glClearColor (0.0, 0.0, 0.0, 1.0); 
    glClear (GL_COLOR_BUFFER_BIT); 

    /* Draw our object */ 
    draw_triangle(); 

    /* Flush the contents of the pipeline */ 
    glFlush(); 

    return TRUE; 
} 

static void 
on_axis_value_change (void) 
{ 
    gtk_widget_queue_draw (gl_area); 
} 



int main(int argc, char **argv) 
{ 
GtkWidget *window, *box; 
/* initialize gtk */ 
gtk_init(&argc, &argv); 
/* Create new top level window. */ 
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_default_size (GTK_WINDOW(window),1000,1000); 
    gtk_window_set_title(GTK_WINDOW(window), "GL Area"); 
    gtk_container_set_border_width(GTK_CONTAINER(window), 10); 
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE); 
    g_object_set (box, "margin", 12, NULL); 
    gtk_box_set_spacing (GTK_BOX (box), 6); 
    gtk_container_add (GTK_CONTAINER (window), box); 
gl_area = gtk_gl_area_new(); 
    gtk_box_pack_start (GTK_BOX(box), gl_area,1,1, 0); 
    /* We need to initialize and free GL resources, so we use 
    * the realize and unrealize signals on the widget 
    */ 
    g_signal_connect (gl_area, "realize", G_CALLBACK (realize), NULL); 
    g_signal_connect (gl_area, "unrealize", G_CALLBACK (unrealize), NULL); 

    /* The main "draw" call for GtkGLArea */ 
    g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL); 
    /* Quit form main if got delete event */ 
    g_signal_connect(G_OBJECT(window), "delete-event", 
        G_CALLBACK(gtk_main_quit), NULL); 
gtk_widget_show_all(GTK_WIDGET(window)); 
gtk_main(); 

    return 0; 
}