2016-07-25 109 views
1

我在OpenGL方面很新穎,所以我從頭開始。我做的第一件事就是用舊的方式(用glBegin()和glEnd())顯示一個基本的2D紋理,它工作。然後,我試圖改進我的代碼,以便將來能夠使用VBO和VAO,所以我不得不使用Shaders。我設法使用了着色器,但是我遇到了紋理問題。Qt/OpenGL試圖顯示2D紋理

這裏是我的代碼:

glwidget.h

#ifndef GLWIDGET_H 
#define GLWIDGET_H 

#include <QOpenGLWidget> 
#include <QOpenGLFunctions> 
#include <QOpenGLBuffer> 
#include <QDebug> 
#include <QOpenGLTexture> 
#include <GL/gl.h> 
#include <QGLFunctions> 
#include <QOpenGLShader> 
#include <QOpenGLShaderProgram> 



class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions 
{ 
    Q_OBJECT 
public: 
    explicit GLWidget(QWidget *parent = 0); 

    void initializeGL(); 
    void paintGL(); 
    void resizeGL(int w, int h); 
    void LoadGLTextures(); 

private : 

    QOpenGLShaderProgram *program; 
    GLuint tex; 


public slots: 



private slots: 



}; 

#endif // GLWIDGET_H 

glwidget.cpp

#include "glwidget.h" 


GLWidget::GLWidget(QWidget *parent) : 
     QOpenGLWidget(parent) 
{ 

} 

void GLWidget::LoadGLTextures(){ 

    QImage img; 

    if(!img.load("C:\\Users\\Adrien\\Desktop\\open3.bmp")){ 

     qDebug()<<"Image loading failed"; 
    } 

    QImage t = (img.convertToFormat(QImage::Format_RGBA8888)).mirrored(); 

    glGenTextures(1, &tex); 

    glBindTexture(GL_TEXTURE_2D, tex); 

     glTexImage2D(GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits()); 

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    glBindTexture(GL_TEXTURE_2D, 0); 



} 

void GLWidget::initializeGL(){ 

    initializeOpenGLFunctions(); 

    glClear(GL_COLOR_BUFFER_BIT); 

    glEnable(GL_TEXTURE_2D); 
    LoadGLTextures(); 

    QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); 
    const char *vsrc = 
     "#version 150 core\n" 
     "in vec2 in_Vertex;\n" 
     "in vec2 vertTexCoord;\n" 
     "out vec2 fragTexCoord;\n" 
     "void main(void)\n" 
     "{\n" 
     " gl_Position = vec4(in_Vertex, 0.0, 1.0);\n" 
     " fragTexCoord = vertTexCoord;\n" 
     "}\n"; 
    vshader->compileSourceCode(vsrc); 

    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); 
    const char *fsrc = 
      "#version 150 core\n" 
      "uniform sampler2D tex;\n" 
      "in vec2 fragTexCoord;\n" 
      "void main(void)\n" 
      "{\n" 
      " gl_FragColor = texture2D(tex,fragTexCoord);\n" 
      "}\n"; 
    fshader->compileSourceCode(fsrc); 

    program = new QOpenGLShaderProgram; 
    program->addShader(vshader); 
    program->addShader(fshader); 

    program->link(); 
    program->bind(); 
    program->setUniformValue("tex", tex); 

} 

void GLWidget::paintGL(){ 

    glClear(GL_COLOR_BUFFER_BIT); 

    program->bind(); 
    { 
     float vertices[] = {-1.0,-1.0, 1.0,-1.0, 1.0,1.0, -1.0,1.0}; 

     float coordTexture[] = {0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0}; 

     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
     glEnableVertexAttribArray(0); 

     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, coordTexture); 
     glEnableVertexAttribArray(2); 

     glBindTexture(GL_TEXTURE_2D, tex); 

     glDrawArrays(GL_QUADS, 0, 4); 

     glBindTexture(GL_TEXTURE_2D, 0); 

     glDisableVertexAttribArray(2); 
     glDisableVertexAttribArray(0); 


    } 
    program->release(); 

} 

void GLWidget::resizeGL(int w, int h){ 

    glViewport(0, 0, (GLint)w, (GLint)h); 

} 

我只有一個黑色的屏幕。一切都在2D(我不需要爲我的項目3D),我暫時不使用VBO和VAO,我試圖讓它首先工作。 LoadGLTexture()似乎工作,因爲我以前已經使用它。頂點和片段着色器被使用並且在片段着色器中用顏色工作。

感謝

+1

每次gl調用後調用glGetError。記錄是否發生錯誤。同時檢查着色器編譯錯誤,記錄着色器編譯器的輸出。發佈日誌。 – Dutow

回答

1

其中的答案和註釋中規定的其他問題,你的位置和屬性texcoord位置是錯誤的:

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, coordTexture); 

第一個參數是位置。它由司機分配,你只是假設這些位置是有效的。爲了解決這個問題,從查詢着色器中的位置:

GLint vertexLocation = glGetAttribLocation(shaderProgram, "in_Vertex"); 
GLint texcoordLocation = glGetAttribLocation(shaderProgram, "vertTexCoord"); 

然後給這些值來glVertexAttribPointer的第一個參數和glEnableVertexAttribArray

+0

啊,好的電話。對於OP來說,使用版本3.1並僅使用顯式佈局來表示屬性是明智的。 – rwols

+0

非常感謝,下面rwols給出的修正工作。我現在更瞭解它。 – Megatron300

1
program->setUniformValue("tex", tex); 

tex變量是手柄到紋理,而你需要設置紋理單元。它變成

glActiveTexture(GL_TEXTURE0); 
program->setUniformValue("tex", 0);