2015-06-23 55 views
8

工作,我把glViewport在QOpenGLWidget :: resizeGL overwritted虛函數,它沒有被調用,並設置視口僅使用的小工具空間的一部分。但它沒有任何效果,內容仍然繪製到全尺寸的小部件。我錯過了什麼嗎?glViewport沒有對Qt5.4 QOpenGLWidget :: resizeGL

這裏是我的代碼,

mywidget.h:

class MyWidget : public QOpenGLWidget, protected QOpenGLFunctions 
{ 
    Q_OBJECT 

public: 
    explicit MyWidget(QWidget* parent = NULL); 

protected: 
    virtual void initializeGL(); 
    virtual void paintGL(); 
    virtual void resizeGL(int w, int h); 

private: 
    QOpenGLShaderProgram program; 
}; 

和mywidget.cpp:

MyWidget::MyWidget(QWidget* parent) : QOpenGLWidget(parent) 
{ 
} 

static const GLfloat squareVertices[] = { 
    -1.0f, -1.0f, 
    1.0f, -1.0f, 
    -1.0f, 1.0f 
}; 

void MyWidget::initializeGL() 
{ 
    initializeOpenGLFunctions(); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

    program.addShaderFromSourceCode(QOpenGLShader::Vertex, 
     "attribute highp vec4 vec;\n" 
     "void main(void)\n" 
     "{\n" 
     " gl_Position = vec;\n" 
     "}"); 
    program.addShaderFromSourceCode(QOpenGLShader::Fragment, 
     "void main(void)\n" 
     "{\n" 
     " gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);\n" 
     "}"); 
    program.link(); 
    program.bind(); 

    program.enableAttributeArray(0); 
    program.setAttributeArray(0, squareVertices, 2); 
} 

void MyWidget::paintGL() 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 

    //glViewport(0, 0, width()/2, height()/2); 
    // if I put glViewport here, everything work as intended, 
    // but we shouldn't need to set viewport everytime render a frame 

    program.bind(); 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); 
} 

void MyWidget::resizeGL(int w, int h) 
{ 
    glViewport(0, 0, w/2, h/2); 
    // this line didn't have any effect, opengl still draw using full widget space 
} 
+0

我不認爲你可以做到這一點的方式。 glViewport僅處理從規範化設備空間到屏幕空間的仿射變換。如果只想渲染GL窗口的一部分,則必須繪製具有實際渲染紋理的四邊形。這將會非常複雜並且效率不高,所以如果你只是解釋了爲什麼你只想渲染到窗口的一部分,這將會有所幫助。也許有一個更好的解決方案,你想要做什麼!另請參閱https://www.khronos.org/opengles/sdk/docs/man/xhtml/glViewport.xml以瞭解glViewport的具體功能。 –

回答

0

glViewport應該是卡萊d在繪圖代碼中,即paintGL處理程序,而不是其他地方。在窗口重塑處理程序中調用glViewport是一種很糟糕的反模式,這在OpenGL教程中太過分散了;它不屬於那裏。

+0

計算和復位glViewport在paintGL處理每一幀似乎是一個很大的浪費給我,因爲glViewport只改變時,窗口大小調整(resizeGL處理) – user3724853

+0

@ user3724853:在許多節目在渲染單個幀期間視口會多次更改。例如每時的圖像渲染到紋理,或視圖被分割在多個窗格等。設置視口實際上是非常便宜的是,在其它圖形API,如福爾康,設置視口被認爲是不可或缺的一部分渲染一個框架。調用glViewport ss既不浪費也不低效,實際上這是唯一可行的方法。設置投影矩陣BTW也是一樣。 *和我說說:* *「我會在每幀開始時調用glViewport。」* – datenwolf

0

嘗試以下,

void MyWidget::resizeGL(int w, int h) 
{ 
    glViewport(0, 0, w, h); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    GLdouble dWt; 
    GLdouble dHt; 

    if(w > h) { 
     dHt = 1; 
     dWt = ((double)w)/h; 
    } else { 
     dHt = ((double)h)/w; 
     dWt = 1; 
    } 

    if(bPerspective) { 
     glFrustum(-dWt, dWt, -dHt, dHt, 5, 100); 
    } else { 
     glOrtho(-dWt, dWt, -dHt, dHt, 5.0, 100.0); 
    } 

    gluLookAt(5.0, 2.0, -10.0, 
       0.0, 0.0, 0.0, 
       0.0, 1.0, 0.0); 

    glMatrixMode(GL_MODELVIEW); 
} 
+0

我使用着色器,所以MatrixModes在這裏沒有意義(我沒有使用它)。就我所知,glViewport設置在着色器之外,但似乎Qt的實現在resizeGL事件期間沒有采用它? – user3724853

+0

當我推出我自己的2D OpenGL框架時,我在onPaint之前強制執行了glViewPort,因此如果您有源代碼,請查看onPaint之前會發生的情況。無論如何glViewPort只是一個方便的方法來影響內部的變換矩陣。所以有一些優點可以嘗試以上方法,特別是在glViewport之前使用glMatrixMode。最後,如果你正在寫你的着色器,也許你有把這些矩陣轉換成consieration –