Qt/OpenGL 试图显示 2D 纹理

Posted

技术标签:

【中文标题】Qt/OpenGL 试图显示 2D 纹理【英文标题】:Qt/OpenGL Trying to display a 2D texture 【发布时间】:2016-07-25 11:37:04 【问题描述】:

我是 OpenGL 的新手,所以我从头开始。我做的第一件事是使用旧方法(使用 glBegin() 和 glEnd())显示基本的 2D 纹理,它工作。然后我尝试改进我的代码以便将来能够使用 VBO 和 VAO,所以我不得不使用 Shaders。我设法将着色器与颜色一起使用,但我遇到了纹理问题。

这是我的代码:

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() 似乎可以工作,因为我之前已经使用过它。顶点和片段着色器被使用并与片段着色器中的颜色一起工作。

谢谢

【问题讨论】:

每次 gl 调用后调用 glGetError。如果发生错误,请记录。还要检查着色器编译错误,记录着色器编译器的输出。发布日志。 【参考方案1】:

在答案和 cmets 中陈述的其他问题中,您的 position 和 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

【讨论】:

啊是的好电话。 OP 使用 3.1 版本可能是明智的,并且只对属性使用显式布局。 非常感谢,对下面 rwols 给出的修正进行了修正。我现在更明白了。【参考方案2】:
program->setUniformValue("tex", tex);

tex 变量是纹理的句柄,而您需要设置纹理单元。改成

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

【讨论】:

以上是关于Qt/OpenGL 试图显示 2D 纹理的主要内容,如果未能解决你的问题,请参考以下文章

将纹理添加到 QT OpenGL 场景图

Qt OpenGL 纹理透明度问题

Qt OpenGL纹理是黑色的

不断更新OpenGL窗口

QVectors2D 的 QT OpenGL QList 未正确绘制

分离线程中的 Qt4/Opengl bindTexture