GtkGLArea清除背景但不绘制

时间:2017-01-16 00:50:11

标签: c++ c opengl gtk gtk3

我一直在编写一个简单的GTK +应用程序,我刚开始使用图形开发。我知道这可能不是一个好的开始,直接进入3D渲染的地方,但我之前已经完成了少量的使用Glade和阅读大量文档取得了巨大的成功,我认为它不会难以整合两者 - 我想错了。手头的问题是glDrawArrays似乎不起作用。我看了this question,不幸的是,它没有帮助我。我跟着this tutorial on OpenGLthis tutorial on GtkGLArea中的一些再次无效。

有人能指出我在这个方向上正确的方向吗?我不确定从哪里开始。

相关代码如下:

#include "RenderingManager.hpp"

RenderingManager::RenderingManager()  {
  ///GTK+ Setup///
  std::cout << "starting render constructor" << std::endl;
  glArea = GTK_GL_AREA(gtk_gl_area_new());
  std::cout << "got new glarea" << std::endl;
  g_signal_connect(GTK_WIDGET(glArea), "render", G_CALLBACK(signal_render), this);
  g_signal_connect(GTK_WIDGET(glArea), "realize", G_CALLBACK(signal_realize), this);
  g_signal_connect(GTK_WIDGET(glArea), "unrealize", G_CALLBACK(signal_unrealize), this);
  gtk_widget_show(GTK_WIDGET(glArea));
  ///Get Shaders///
  // vshader.open("vertex.shader");
  // fshader.open("fragment.shader");

  std::cout << "finished render constructor" << std::endl;
}

void RenderingManager::onRender() {
    // Dark blue background
    glClearColor(0.1f, 0.0f, 0.1f, 0.0f);
    draw_triangle();
    glFlush();
}
void RenderingManager::initBuffers () {
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

  glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

}

void RenderingManager::loadShaders()  {
  // Read the Vertex Shader code from the file
    std::ifstream VertexShaderStream("vertex.shader", std::ios::in);
    if(VertexShaderStream.is_open()){
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            vshader += "\n" + Line;
        VertexShaderStream.close();
    }

    // Read the Fragment Shader code from the file
    std::ifstream FragmentShaderStream("fragment.shader", std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            fshader += "\n" + Line;
        FragmentShaderStream.close();
    }

  GLuint vsh, fsh;
  vsh = glCreateShader(GL_VERTEX_SHADER);
  fsh = glCreateShader(GL_FRAGMENT_SHADER);
  vshp = vshader.data();
  fshp = fshader.data();
  // vshp = vshader.get().c_str();
  // fshp = fshader.get().c_str();
  // vshader.get(vshp);
  // fshader.get(fshp);
  printf("%s\n%s\n", vshp, fshp);
  glShaderSource(vsh, 1, &vshp, NULL);
  glShaderSource(fsh, 1, &fshp, NULL);

  glCompileShader(vsh);
  glCompileShader(fsh);

  shaderProgramID = glCreateProgram();
  glAttachShader(shaderProgramID, vsh);
  glAttachShader(shaderProgramID, fsh);
  glLinkProgram(shaderProgramID);

  GLint Result = GL_FALSE;
  int InfoLogLength;
  // Check Vertex Shader
    glGetShaderiv(vsh, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(vsh, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        char* VertexShaderErrorMessage = new char[InfoLogLength+1];
        glGetShaderInfoLog(vsh, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        printf("%s\n", &VertexShaderErrorMessage[0]);
    }
  // Check Fragment Shader
    glGetShaderiv(fsh, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(fsh, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        char* FragmentShaderErrorMessage = new char[InfoLogLength+1];
        glGetShaderInfoLog(fsh, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        printf("%s\n", &FragmentShaderErrorMessage[0]);
    }
}
void RenderingManager::onActivate() {

  // We need to make the context current if we want to
  // call GL API
  gtk_gl_area_make_current (glArea);

  glewExperimental = GL_TRUE;
  glewInit();

  loadShaders();
  initBuffers();

}
void RenderingManager::signal_render(GtkGLArea *a, gpointer *user_data) {
  reinterpret_cast<RenderingManager*>(user_data)->onRender();

}
void RenderingManager::signal_realize(GtkGLArea *a, gpointer *user_data)  {
  reinterpret_cast<RenderingManager*>(user_data)->onActivate();

}
void RenderingManager::signal_unrealize(GtkGLArea *a, gpointer *user_data)  {
    //Don't do this
    //reinterpret_cast<RenderingManager*>(user_data)->~RenderingManager();
}
void RenderingManager::draw_triangle()  {
  // Clear the screen
        glClear( GL_COLOR_BUFFER_BIT );

        // Use our shader
        glUseProgram(shaderProgramID);

        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        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); // 3 indices starting at 0 -> 1 triangle

        glDisableVertexAttribArray(0);

}
GtkGLArea *RenderingManager::expose()  {
  //yikes
  return glArea;
}

RenderingManager::~RenderingManager() {
  glDeleteBuffers(1, &vbo);
    glDeleteVertexArrays(1, &vao);
    glDeleteProgram(shaderProgramID);
  std::cout << "GL Resources deleted." << std::endl;
}

1 个答案:

答案 0 :(得分:1)

由于X11的异步特性(Gtk +使用它),gl-context不能在窗口实现之前创建(与X11建立连接)。

在signal_realize()中创建gl-context并在绘制之前使其成为当前的,应该处理信号expose_event(gtk + 2)或draw(gtk + 3)< / p>

相关问题