creator and c++ qt opengl ubuntu qglwidget

c++ - and - ¿Por qué QGLWidget solo muestra una pantalla en blanco?



qt creator and opengl (2)

He usado OpenGL en SDL antes, pero recién comencé a aprender QT. En QT, usar OpenGL está demostrando ser un poco doloroso. Tengo los siguientes dos archivos:

main.cpp

#include <stdio.h> #include <QApplication> #include "glwidget.hpp" #include <QGLFormat> int main(int args, char *argv[]) { QApplication app(args, argv); GLWidget openGLWidget; openGLWidget.show(); return app.exec(); }

glwidget.hpp

#include <GL/glew.h> #include <QGLWidget> class GLWidget : public QGLWidget { protected: void initializeGL(); void paintGL(); }; void GLWidget::initializeGL() { if(glewInit() != GLEW_OK) { fprintf(stderr, "GLEW failed to initialize."); } } void GLWidget::paintGL() { glClearColor(1, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); QGLWidget::swapBuffers(); }

helloworld.pro

TEMPLATE = app INCLUDEPATH += . LIBS += -lGL -lGLEW # Input SOURCES += main.cpp HEADERS += glwidget.hpp QT += widgets opengl

Cuando compilo y ejecuto esto, obtengo una ventana que tiene todo lo que estaba detrás de ella en el momento de la creación impresa en él. Lo que estoy esperando es una pantalla roja. ¿Qué me estoy perdiendo?

ACTUALIZAR

He editado mi implementación de GLWidget, y lo hice funcionar. Sin embargo, solo funciona cuando llamo a glDrawArrays (vea la función paintGL a continuación). En SDL, glDrawArrays no fue necesario para ver una pantalla en blanco. Sin glDrawArrays, qt parece ignorar glClear () por alguna razón. ¿Alguien sabe por qué?

GLWidget::GLWidget(QGLWidget* parent) : QGLWidget(QGLFormat(), parent) { } void GLWidget::initializeGL() { if(glewInit() != GLEW_OK) { fprintf(stderr, "GLEW failed to initialize."); } glClearColor(1, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, "vertexShader.vert"); shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, "fragmentShader.frag"); shaderProgram.link(); GLuint vertexBuffer; glGenBuffers(1, &vertexBuffer); } void GLWidget::paintGL() { shaderProgram.bind(); glClearColor(1, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); setAutoBufferSwap(false); //glDrawArrays(GL_TRIANGLES, 0, 1); swapBuffers(); shaderProgram.release(); } void GLWidget::resizeGL(int width, int height) { if(height == 0) { height = 1; } if(width == 0) { width = 1; } glViewport(0, 0, width, height); }

ACTUALIZACIÓN 2

Pensé que tal vez Qt estaba haciendo algo furtivo, y que si lo hacía todo de forma manual, me desharía del problema. Pero todavía sé de alguna manera si estoy usando un programa o no, y si estoy usando glDrawArrays o no. En el siguiente código, sacar glDrawArrays o glUseProgram hace que el código no funcione. Debe tener algo que ver con lo que sucede dentro de QGLContext.

#include <stdio.h> #include <fstream> #include <string> #include "glwidget.hpp" GLWidget::GLWidget(QWidget* parent) : QGLWidget(QGLFormat(), parent) { } void GLWidget::initializeGL() { if(glewInit() != GLEW_OK) { fprintf(stderr, "GLEW failed to initialize."); } glContext = this->context(); if(!glContext->create()) { fprintf(stderr, "Failed to create context./n"); } glContext->makeCurrent(); program = glCreateProgram(); addShader(program, GL_VERTEX_SHADER, "vertexShader.vert"); addShader(program, GL_FRAGMENT_SHADER, "fragmentShader.frag"); linkProgram(program); setAutoBufferSwap(false); } void GLWidget::paintGL() { glUseProgram(program); glClearColor(1, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 1); glContext->swapBuffers(); glUseProgram(0); } void GLWidget::resizeGL(int width, int height) { if(height == 0) { height = 1; } if(width == 0) { width = 1; } glViewport(0, 0, width, height); } GLuint GLWidget::addShader(GLuint programID, GLuint shaderType, std::string fileName) { GLuint shader = glCreateShader(shaderType); std::ifstream file(fileName.c_str()); std::string source = ""; if(file.is_open()) { std::string line; while(getline(file, line)) { source += line + "/n"; } } else { fprintf(stderr, "File %s failed to open./n", fileName.c_str()); } const char* sourceC = source.c_str(); glShaderSource(shader, 1, &sourceC, NULL); glCompileShader(shader); GLint compileStatus; glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); if(compileStatus == GL_FALSE) { fprintf(stderr, "Shader %s failed to compile./n", fileName.c_str()); return 0; } glAttachShader(programID, shader); return shader; } void GLWidget::linkProgram(GLuint programID) { glLinkProgram(programID); GLint linkStatus; glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus); if(linkStatus == GL_FALSE) { fprintf(stderr,"Failed to link program./n"); } }


Es posible que tenga un problema de configuración en su PC.

Este es el ejemplo que uso en debian amd64 / stable con Qt4.8.

encabezamiento

#ifndef GLWIDGET_HPP #define GLWIDGET_HPP #include <QGLWidget> class GlWidget: public QGLWidget { public: GlWidget(QWidget *parent=0); ~GlWidget(); protected: void initializeGL(); void paintGL(); }; #endif // GLWIDGET_HPP

implementación

#include "glwidget.hpp" GlWidget::GlWidget(QWidget* parent) : QGLWidget(QGLFormat(), parent) { } GlWidget::~GlWidget() { } void GlWidget::initializeGL() { } void GlWidget::paintGL() { glClearColor(1.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); }

El único problema que veo es la creación de otra ventana propiedad de GLEW. Pero puedes cerrarlo. La instancia de QGLWidget se promociona en la parte inferior derecha.


Encontré la solución a mi problema. QGLWidget está en desuso. Cualquiera que vea esta pregunta en el futuro debería usar QOpenGLWidget en su lugar.

#include "GLShaderWidget.hpp" GLShaderWidget::GLShaderWidget(QWidget* parent) : QOpenGLWidget(parent) { } GLShaderWidget::~GLShaderWidget() { } void GLShaderWidget::initializeGL() { glClearColor(1, 0, 0, 1); } void GLShaderWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT); }

Este código funciona bien. La única diferencia es que estoy usando QOpenGLWidget en lugar de QGLWidget. Es mucho mejor que QGLWidget de todos modos, ya que automáticamente reajusta el tamaño del puerto de visualización, y realmente utiliza dos frame-buffers internamente (aparentemente QGLWidget solo pretendía usar dos búferes).