glDrawArrays不工作。在GTK3中使用GtkGLArea

时间:2015-05-19 23:29:13

标签: c opengl gtk3

我正在尝试使用GtkGLArea小部件。类似问题的答案似乎都与这种情况无关。

glClear()可以很好地设置背景颜色,但实际绘制的三角形数组不是。

根据this教程,下面的代码应该有效。

编辑 2015年5月21日:添加着色器,仍然获得相同的结果。

下面的新代码

这里是main.cSConstruct所以你可以用scons构建:

已解决:标题 SOLUTION:main.c 下的工作代码可以使用相同的SConstruct文件构建示例

的main.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <glib.h>

#include <gdk/gdkx.h>
#include <epoxy/glx.h>
#include <epoxy/gl.h>
#include <gtk/gtk.h>
#include <gtk/gtkglarea.h>

#define IGNORE_VAR(type, identifier) \
{ \
  type IGNORED_VARIABLE_abcd = identifier; \
  identifier = IGNORED_VARIABLE_abcd; \
}

const GLchar *vert_src ="\n" \
"#version 330                                  \n" \
"                                              \n" \
"layout(location = 0) in vec2 in_position;     \n" \
"                                              \n" \
"void main()                                   \n" \
"{                                             \n" \
"      gl_Position = in_position;              \n" \
"}                                             \n";

const GLchar *frag_src ="\n" \
"void main (void)                              \n" \
"{                                             \n" \
"     gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); \n" \
"}                                             \n";

GLuint gl_buffer, gl_program;

static gboolean realise(GtkGLArea *area, GdkGLContext *context)
{
  IGNORE_VAR(GdkGLContext*, context);

  gtk_gl_area_make_current(GTK_GL_AREA(area));
  if (gtk_gl_area_get_error (GTK_GL_AREA(area)) != NULL)
  {
    printf("Failed to initialiize buffers\n");
    return FALSE;
  }

  GLfloat verts[] = 
  {
    +0.0f, +1.0f,
    -1.0f, -1.0f,
    +1.0f, -1.0f,
  };

  GLuint frag_shader, vert_shader;
  frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
  vert_shader = glCreateShader(GL_VERTEX_SHADER);

  glShaderSource(frag_shader, 1, &frag_src, NULL);
  glShaderSource(vert_shader, 1, &vert_src, NULL);

  glCompileShader(frag_shader);
  glCompileShader(vert_shader);

  gl_program = glCreateProgram();
  glAttachShader(gl_program, frag_shader);
  glAttachShader(gl_program, vert_shader);
  glLinkProgram(gl_program);

  glGenBuffers(1, &gl_buffer);
  glBindBuffer(GL_ARRAY_BUFFER, gl_buffer);
  glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);


  return TRUE;
}

static gboolean render(GtkGLArea *area, GdkGLContext *context)
{
  IGNORE_VAR(GdkGLContext*, context);
  IGNORE_VAR(GtkGLArea*, area);

  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glBindBuffer(GL_ARRAY_BUFFER, gl_buffer);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
  //glUseProgram(gl_program);
  glDrawArrays(GL_TRIANGLES, 0, 3);
  glDisableVertexAttribArray(0);

  return TRUE;
}

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

  GtkWidget *window  = gtk_window_new(GTK_WINDOW_TOPLEVEL),
            *gl_area = gtk_gl_area_new();

  g_signal_connect(window,  "delete-event", G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(gl_area, "realize",      G_CALLBACK(realise),       NULL);
  g_signal_connect(gl_area, "render",       G_CALLBACK(render),        NULL);

  gtk_container_add(GTK_CONTAINER(window), gl_area);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

Sconstruct

import os

env = Environment(CC='gcc', CCFLAGS='--std=c11', ENV={'PATH':os.environ['PATH']})

env.Append(LIBS = ['GL', 'epoxy'])
env.ParseConfig('pkg-config --cflags --libs gtk+-3.0')
#env.ParseConfig('pkg-config --cflags  gdkglext-1.0')

env.Program(target='gl', source=['main.c'])

# vim: set filetype=python:

解决方案:main.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <glib.h>

#include <gdk/gdkx.h>
#include <epoxy/glx.h>
#include <epoxy/gl.h>
#include <gtk/gtk.h>

#define IGNORE_VAR(type, identifier) \
{ \
  type IGNORED_VARIABLE_abcd = identifier; \
  identifier = IGNORED_VARIABLE_abcd; \
}

const GLchar *vert_src ="\n" \
"#version 330                                  \n" \
"#extension GL_ARB_explicit_attrib_location: enable  \n" \
"                                              \n" \
"layout(location = 0) in vec2 in_position;     \n" \
"                                              \n" \
"void main()                                   \n" \
"{                                             \n" \
"  gl_Position = vec4(in_position, 0.0, 1.0);  \n" \
"}                                             \n";

const GLchar *frag_src ="\n" \
"void main (void)                              \n" \
"{                                             \n" \
"  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);    \n" \
"}                                             \n";

GLuint gl_vao, gl_buffer, gl_program;

static gboolean realise(GtkGLArea *area, GdkGLContext *context)
{
  IGNORE_VAR(GdkGLContext*, context);

  gtk_gl_area_make_current(GTK_GL_AREA(area));
  if (gtk_gl_area_get_error (GTK_GL_AREA(area)) != NULL)
  {
    printf("Failed to initialiize buffers\n");
    return FALSE;
  }

  GLfloat verts[] = 
  {
    +0.0f, +1.0f,
    -1.0f, -1.0f,
    +1.0f, -1.0f,
  };

  GLuint frag_shader, vert_shader;
  frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
  vert_shader = glCreateShader(GL_VERTEX_SHADER);

  glShaderSource(frag_shader, 1, &frag_src, NULL);
  glShaderSource(vert_shader, 1, &vert_src, NULL);

  glCompileShader(frag_shader);
  glCompileShader(vert_shader);

  gl_program = glCreateProgram();
  glAttachShader(gl_program, frag_shader);
  glAttachShader(gl_program, vert_shader);
  glLinkProgram(gl_program);

  glGenVertexArrays(1, &gl_vao);
  glBindVertexArray(gl_vao);

  glGenBuffers(1, &gl_buffer);
  glBindBuffer(GL_ARRAY_BUFFER, gl_buffer);
  glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
  glBindVertexArray(0);

  glDeleteBuffers(1, &gl_buffer);

  return TRUE;
}

static gboolean render(GtkGLArea *area, GdkGLContext *context)
{
  IGNORE_VAR(GdkGLContext*, context);
  IGNORE_VAR(GtkGLArea*, area);

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glClearColor(0.0, 0.0, 0.0, 1.0);

  glUseProgram(gl_program);
  glBindVertexArray(gl_vao);
  glDrawArrays(GL_TRIANGLES, 0, 3);

  glBindVertexArray (0);
  glUseProgram (0);

  glFlush();

  return TRUE;
}

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

  GtkWidget *window  = gtk_window_new(GTK_WINDOW_TOPLEVEL),
            *gl_area = gtk_gl_area_new();

  g_signal_connect(window,  "delete-event", G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(gl_area, "realize",      G_CALLBACK(realise),       NULL);
  g_signal_connect(gl_area, "render",       G_CALLBACK(render),        NULL);

  gtk_container_add(GTK_CONTAINER(window), gl_area);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

3 个答案:

答案 0 :(得分:2)

您似乎没有任何着色器。您需要fragmentvertex着色器。

以下是有关如何编写和使用它们的教程:https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/loading.php

答案 1 :(得分:0)

您正在使用通用顶点属性。因此你应该使用着色器。如果您在兼容性配置文件中,则使用顶点属性0可能会被解释为内置属性“顶点位置”,但这不是给定的。因此,如果您想“按书”操作,则必须提供着色器(或坚持使用已弃用的内置属性)。

旁注:不建议启用顶点属性数组并在初始化代码中设置指针。这两者之间的OpenGL上下文可能会发生任何事情,包括绑定其他顶点数组,禁用/启用(其他)顶点属性数组,设置不同的缓冲区指针等。

根据经验,任何与绘图状态直接相关的内容(即不构成一次数据初始化/加载)都属于绘图代码的相应位置。在你的情况下

static gboolean render(GtkGLArea *area, GdkGLContext *context)
{
  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  //glFrontFace(GL_CW);

  /* added these ---> */
  glBindBuffer(GL_ARRAY_BUFFER, gl_buffer);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
  /* <--- */

  glDrawArrays(GL_TRIANGLES, 0, 3);

  //gtk_widget_get_realized(area);

  return TRUE;
}

不这样做会导致从长远来看混淆你。

答案 2 :(得分:0)

您错过了VAO的创建; GTK +将创建GL核心配置文件上下文,这意味着您需要自己创建和选择VAO,否则将不使用顶点缓冲区对象。

初始化GL状态时,请添加:

.list {
    display: inline-block;
    font-size: 0;
    height: 100%;
    min-width: 100%;
    overflow: hidden;
    position: relative;
    right: 0;
    white-space: nowrap;
}

在创建VBO之前。

您应该查看my blog post about using OpenGL with GTK+及其相关的example code