Używam OpenGL w SDL, ale dopiero zacząłem uczyć się QT. W QT korzystanie z OpenGL okazuje się nieco uciążliwe. Mam następujące dwa pliki:Dlaczego QGLWidget renderuje tylko pusty ekran?
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
Kiedy skompilować i uruchomić ten, mam okno, które ma wszystko, co było za nim w momencie nadrukowania na nim. Oczekuję tylko czerwonego ekranu. czego mi brakuje?
UPDATE
Mam edytowany moje wykonanie GLWidget, i mam go do pracy. Działa to jednak tylko wtedy, gdy wywołuję glDrawArrays (zobacz poniżej funkcję paintGL). W SDL glDrawArrays nie był konieczny, aby zobaczyć pusty kolorowy ekran. Bez glDrawArrays qt wydaje się ignorować glClear() z jakiegoś powodu. Czy ktoś wie, dlaczego?
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);
}
UPDATE 2
Myślałem, że może Qt robił coś ukrytych pod maską, i że jeśli zrobiłem wszystko ręcznie, chciałbym pozbyć się tego problemu. Ale qt nadal jakoś wie, czy używam programu, czy nie, i czy używam glDrawArrays, czy nie. W poniższym kodzie wyjęcie programu glDrawArrays lub glUseProgram powoduje, że kod nie działa. Musi mieć coś wspólnego z tym, co dzieje się wewnątrz 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");
}
}
Przyczyna może być następująca: Dokumentacja QT dla pustej QGLWidget :: swapBuffers(): > Zamienia zawartość ekranu za pomocą bufora poza ekranem. Działa to tylko wtedy, gdy format widżetu określa tryb podwójnego bufora. > Zazwyczaj nie ma potrzeby jawnego wywoływania tej funkcji, ponieważ jest ona wykonywana automatycznie po odświeżeniu widżetu, tj. Za każdym razem po wykonaniu malowania GL(). – rpress
@rpress Grałem z tym pomysłem trochę, ale nie sądzę, że to jest problem. Zobacz aktualizację, aby uzyskać więcej szczegółów. –
@WilliamOliver był pierwotnym problemem - przynajmniej mogę odtworzyć "pusty ekran" w twoim oryginalnym kodzie, i ustawić żądany czerwony ekran * albo * usuwając wywołanie 'swapBuffers' lub dodając wywołanie' setAutoBufferSwap (false) '. Czy to nie zadziałało? – Lack