GtkGLArea 清除背景但不绘制
Posted
技术标签:
【中文标题】GtkGLArea 清除背景但不绘制【英文标题】:GtkGLArea clears background but does not draw 【发布时间】:2017-01-16 00:50:11 【问题描述】:我一直在编写一个简单的 GTK+ 应用程序,并且刚刚开始进行图形开发。我知道这可能不是一个好的开始,直接跳入 3D 渲染,但我之前已经完成了少量工作,并且使用 Glade 并阅读了大量文档并取得了巨大成功,我认为这并不难整合两者 - 我想错了。手头的问题是glDrawArrays
似乎不起作用。我看了this question,不幸的是,它对我没有帮助。我再次关注了一些this tutorial on OpenGL 和this 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;
【问题讨论】:
对于唯一的reinterpret_cast
"haxx" 来说,有一个你没有标记为 "haxx" 的值——直接调用你自己的析构函数。我很惊讶这在 C++ 中甚至是合法的。无论如何,即使你让它更理智(delete reinterpret_cast<...>(...)
),这确实意味着一旦你没有意识到,你将永远不会再次被安全地意识到。考虑重组这些处理程序...
@andlabs 可以,我不知道。
【参考方案1】:
由于 X11 的异步特性(Gtk+ 使用它),在窗口实现之前无法创建 gl-context(与 X11 建立连接)。
在你的 signal_realize() 中创建 gl-context 并在绘制之前使其成为当前状态,这应该在处理信号 expose_event
(gtk+ 2) 或 draw
(gtk+ 3) 时完成
【讨论】:
我不确定你的意思是什么——我认为这已经发生了。onActivate
处理realize
信号,onRender
处理render
信号。如何创建 GL 上下文?如果我正确阅读了文档,我认为 GtkGLArea 会为我做到这一点......
看这里的实现示例:developer.gnome.org/gtk3/unstable/…
@TingPing 当我开始的时候我遵循了那个。我的代码包括所有这些元素,并且我已经填写了加载着色器和缓冲区等。不幸的是,我仍然卡住了。以上是关于GtkGLArea 清除背景但不绘制的主要内容,如果未能解决你的问题,请参考以下文章
room-views-用窗口颜色清除背景(Clear Background with Window Colour)选项