2015-01-17 3 views
13

मैंने पहले एसडीएल में ओपनजीएल का उपयोग किया है, लेकिन मैंने अभी क्यूटी सीखना शुरू कर दिया है। क्यूटी में, ओपनजीएल का उपयोग करना दर्द का कुछ हद तक साबित हो रहा है।QGLWidget केवल खाली स्क्रीन क्यों प्रस्तुत करता है?

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 

जब मैं संकलन और इस चलाने के लिए, मैं: मैं निम्न दो फ़ाइलें है एक खिड़की जिस पर सृजन के समय उसके पीछे जो कुछ भी था, उस पर छापे हुए थे। मैं जो उम्मीद कर रहा हूं वह एक लाल स्क्रीन है। मैं क्या खो रहा हूँ?

अद्यतन

मैं अपने GLWidget कार्यान्वयन संपादित किया है, और मैं इसे काम करने के लिए मिला है। हालांकि, यह केवल तब काम करता है जब मैं glDrawArrays को कॉल करता हूं (नीचे पेंटजीएल फ़ंक्शन देखें)। एसडीएल में, एक खाली रंगीन स्क्रीन देखने के लिए glDrawArrays आवश्यक नहीं था। GlDrawArrays के बिना, qt कुछ कारणों से glClear() को अनदेखा करता है। क्या किसी को पता है क्यों?

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); 
} 

अद्यतन 2

मैंने सोचा कि शायद क्यूटी हुड के नीचे कुछ डरपोक कर रहा था, और है कि अगर मैं सब कुछ मैन्युअल रूप से किया था, मैं इस समस्या से छुटकारा मिलेगा। लेकिन क्यूटी अभी भी किसी भी तरह से जानता है कि मैं प्रोग्राम का उपयोग कर रहा हूं या नहीं, और क्या मैं glDrawArrays का उपयोग कर रहा हूं या नहीं। नीचे दिए गए कोड में, या तो glDrawArrays या glUseProgram लेना कोड को काम नहीं करता है। 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"); 
    } 
} 
+0

कारण यह हो सकता है। यह केवल तभी काम करता है जब विजेट का प्रारूप डबल बफर मोड निर्दिष्ट करता है। > आम तौर पर, इस फ़ंक्शन को स्पष्ट रूप से कॉल करने की कोई आवश्यकता नहीं है क्योंकि यह प्रत्येक विजेट रीपेंट के बाद स्वचालित रूप से किया जाता है, यानी पेंटजीएल() को निष्पादित करने के बाद प्रत्येक बार। – rpress

+0

@rpress मैंने उस विचार के साथ थोड़ा सा खेला, लेकिन मुझे नहीं लगता कि यह समस्या है। अधिक जानकारी के लिए अद्यतन देखें। –

+0

@WilliamOliver जो मूल समस्या थी - कम से कम, मैं आपके मूल कोड में "रिक्त स्क्रीन" को पुन: उत्पन्न कर सकता हूं, और वांछित लाल स्क्रीन * या तो * को 'स्वैपबफर' पर कॉल हटाकर या 'setAutoBufferSwap' पर कॉल जोड़कर (गलत) '। क्या यह काम नहीं करता? – Lack

उत्तर

5

मैं मेरी समस्या का हल मिल गया। QGLWidget बहिष्कृत है। भविष्य में इस प्रश्न को देखने वाले किसी भी व्यक्ति को इसके बजाय QOpenGLWidget का उपयोग करना चाहिए।

#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); 
} 

यह कोड ठीक काम करता है। केवल अंतर यह है कि मैं QGLWidget के बजाय QOpenGLWidget का उपयोग कर रहा हूं। यह QGLWidget से कहीं भी बेहतर है, क्योंकि यह स्वचालित रूप से दृश्य पोर्ट को फिर से आकार देता है, और वास्तव में आंतरिक रूप से दो फ्रेम-बफर का उपयोग करता है (स्पष्ट रूप से QGLWidget दो बफर का उपयोग करने का नाटक कर रहा था)।शून्य QGLWidget :: swapBuffers() के लिए क्यूटी डॉक्स: > एक ऑफ स्क्रीन बफर के साथ स्क्रीन सामग्री स्वैप

+1

आपने उल्लेख नहीं किया कि आप Qt5 का उपयोग कर रहे थे। –

+0

@ फ़ैबियनआर मैं नहीं था, लेकिन प्रलेखन 4.8 –

+1

का उपयोग करने से बचने के लिए कहता है, मैं कहूंगा कि [QOpenGLWidget] (http://doc.qt.io/qt-5/qopenglwidget.html) Qt5.4 में दिखाई दिया था। –

0

आपके पीसी पर कॉन्फ़िगरेशन समस्या हो सकती है।

उदाहरण है कि मैं डेबियन amd64/स्थिर पर Qt4.8 के साथ उपयोग करता हूं।

हैडर

#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 

कार्यान्वयन

#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); 

    } 

समस्या सिर्फ मैं देख रहा हूँ Glew के स्वामित्व में एक और खिड़की के निर्माण है। लेकिन आप इसे बंद कर सकते हैं। QGLWidget उदाहरण नीचे दाईं ओर प्रचारित किया जाता है।

QGLWidget

संबंधित मुद्दे