首页 文章

Qt5 OpenGL纹理采样

提问于
浏览
0

我正在尝试使用Qt5和着色器程序的OpenGL包装类来渲染 QImage . 我有以下着色器和3.3核心上下文 . 我'm also using a VAO for the attributes. However, I keep getting a blank red frame (red is the background clear color that I set). I'我不确定它是否是MVP矩阵或其他问题 . 使用片段着色器将输出颜色设置为某种固定颜色(黑色)仍然会产生红色框 . 我完全迷失在这里 .

EDIT-1: 我也注意到试图从 QOpenGLShaderProgram 获得 texRGB 均匀的位置导致-1 . 但我有'm not sure if that has anything to do with the problem I' . 在顶点着色器中为MVP矩阵定义的制服具有位置0和1 .

Vertex Shader

#version 330

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec2 inTexCoord;

out vec2 vTexCoord;

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;


void main(void)
{
    gl_Position = projectionMatrix * modelViewMatrix * vec4(inPosition, 1.0);

    // pass the input texture coordinates to fragment shader
    vTexCoord = inTexCoord;    
}

Fragment Shader

#version 330

uniform sampler2DRect texRGB;

in vec2 vTexCoord;

out vec4 fColor;

void main(void)
{
    vec3 rgb = texture2DRect(texRGB, vTexCoord.st).rgb;
    fColor = vec4(rgb, 0.0);
}

OGLWindow.h

#include <QOpenGLWindow>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>

#include <QDebug>
#include <QString>

class OGLWindow : public QOpenGLWindow, protected QOpenGLFunctions
{
public:
    OGLWindow();
    ~OGLWindow();

    // OpenGL Events
    void initializeGL();
    void resizeGL(int width, int height);
    void paintGL();

    // a method for cleanup
    void teardownGL();

private:
    bool isInitialized;

    // OpenGL state information
    QOpenGLBuffer               m_vbo_position;
    QOpenGLBuffer               m_vbo_index;
    QOpenGLBuffer               m_vbo_tex_coord;
    QOpenGLVertexArrayObject    m_object;
    QOpenGLShaderProgram*       m_program;

    QImage                      m_image;
    QOpenGLTexture*             m_texture;

    QMatrix4x4                  m_projection_matrix;
    QMatrix4x4                  m_model_view_matrix;

};

OGLWindow.cpp

#include "OGLWindow.h"

// vertex data
static const QVector3D vertextData[] = {
                           QVector3D(-1.0f, -1.0f,  0.0f),
                           QVector3D( 1.0f, -1.0f,  0.0f),
                           QVector3D( 1.0f,  1.0f,  0.0f),
                           QVector3D(-1.0f,  1.0f,  0.0f)
};

// indices
static const GLushort indices[] = {
                           0,  1,  2,
                           0,  2,  3
};

OGLWindow::OGLWindow() :
    m_vbo_position      (QOpenGLBuffer::VertexBuffer),
    m_vbo_tex_coord     (QOpenGLBuffer::VertexBuffer),
    m_vbo_index         (QOpenGLBuffer::IndexBuffer),
    m_program           (nullptr),
    m_texture           (nullptr),
    isInitialized       (false)
{
}

OGLWindow::~OGLWindow()
{
    makeCurrent();
    teardownGL();
}

void OGLWindow::initializeGL()
{
    qDebug() << "initializeGL()";

    initializeOpenGLFunctions();
    isInitialized = true;

    QColor backgroundColor(Qt::red);
    glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), 1.0f);

    // load texture image
    m_image = QImage(":/images/cube.png");

    m_texture = new QOpenGLTexture(QOpenGLTexture::TargetRectangle);

    // set bilinear filtering mode for texture magnification and minification
    m_texture->setMinificationFilter(QOpenGLTexture::Nearest);
    m_texture->setMagnificationFilter(QOpenGLTexture::Nearest);

    // set the wrap mode
    m_texture->setWrapMode(QOpenGLTexture::ClampToEdge);

    m_texture->setData(m_image.mirrored(), QOpenGLTexture::MipMapGeneration::DontGenerateMipMaps);

    int imgWidth = m_image.width();
    int imgHeight = m_image.height();

    m_projection_matrix.setToIdentity();
    m_projection_matrix.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
//    m_projection_matrix.ortho(0.0, (float) width(), (float) height(), 0.0f, -1.0f, 1.0f);

    m_model_view_matrix.setToIdentity();

    glViewport(0, 0, width(), height());

    m_program = new QOpenGLShaderProgram();
    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl");
    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl");
    m_program->link();
    m_program->bind();

    // texture coordinates
    static const QVector2D textureData[] = {
                               QVector2D(0.0f,              0.0f),
                               QVector2D((float) imgWidth,  0.0f),
                               QVector2D((float) imgWidth,  (float) imgHeight),
                               QVector2D(0.0f,              (float) imgHeight)
    };

    // create Vertex Array Object (VAO)
    m_object.create();
    m_object.bind();

    // create position VBO
    m_vbo_position.create();
    m_vbo_position.bind();
    m_vbo_position.setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_vbo_position.allocate(vertextData, 4 * sizeof(QVector3D));

    // create texture coordinates VBO
    m_vbo_tex_coord.create();
    m_vbo_tex_coord.bind();
    m_vbo_tex_coord.setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_vbo_tex_coord.allocate(textureData, 4 * sizeof(QVector2D));

    // create the index buffer
    m_vbo_index.create();
    m_vbo_index.bind();
    m_vbo_index.setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_vbo_index.allocate(indices, 6 * sizeof(GLushort));

    // enable the two attributes that we have and set their buffers
    m_program->enableAttributeArray(0);
    m_program->enableAttributeArray(1);

    m_program->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(QVector3D));
    m_program->setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));

    // Set modelview-projection matrix
    m_program->setUniformValue("projectionMatrix", m_projection_matrix);
    m_program->setUniformValue("modelViewMatrix", m_model_view_matrix);

    // use texture unit 0 which contains our frame
    m_program->setUniformValue("texRGB", 0);

    // release (unbind) all
    m_object.release();
    m_vbo_position.release();
    m_vbo_tex_coord.release();
    m_vbo_index.release();
    m_program->release();    
}

void OGLWindow::resizeGL(int width, int height)
{
    qDebug() << "resizeGL(): width =" << width << ", height=" << height;
    if (isInitialized) {

        // avoid division by zero
        if (height == 0) {
            height = 1;
        }

        m_projection_matrix.setToIdentity();
        m_projection_matrix.perspective(60.0, (float) width / (float) height, -1, 1);

        glViewport(0, 0, width, height);
    }

}

void OGLWindow::paintGL()
{
    // clear
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // render using our shader
    m_program->bind();
    {
        m_texture->bind();

        m_object.bind();
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0) );
        m_object.release();
    }
    m_program->release();
}

void OGLWindow::teardownGL()
{
    // actually destroy our OpenGL information
    m_object.destroy();
    m_vbo_position.destroy();
    m_vbo_color.destroy();
    delete m_program;    
}

EDIT-2: 我正在创建上下文,如下所示:

QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3,3);

1 回答

  • 0

    片段着色器代码中的这一行无效:

    vec3 rgb = texture2DRect(texRGB, vTexCoord.st).rgb;
    

    texture2DRect() 不是内置函数 .

    由于您使用的是GLSL 3.30核心配置文件(除非指定 compatibility ,否则 core 是版本的默认配置文件),您应该使用重载的 texture() 函数,该函数将替换核心配置文件中的旧类型特定函数,如 texture2D() .

    除非使用前向兼容的核心配置文件上下文,否则GLSL 3.30核心仍支持 texture2D() 等功能 . 因此,根据上下文的创建方式,您仍然可以使用这些函数 .

    但是, sampler2DRect 仅作为GLSL 1.40中的采样器类型添加,作为在OpenGL 3.1中向标准添加矩形纹理的一部分 . 当时,旧的采样函数已被标记为已弃用,并且仅为矩形纹理定义了新的 texture() 函数 . 这意味着 any GLSL版本中不存在 texture2DRect() .

    正确的电话是:

    vec3 rgb = texture(texRGB, vTexCoord.st).rgb;
    

    您的代码的另一部分可以阻止它呈现任何内容是这个投影矩阵:

    m_projection_matrix.perspective(60.0, (float) width / (float) height, -1, 1);
    

    标准投影矩阵的近和远平面都需要是正的 . 此调用将在原点上设置一个"camera"的投影变换,向下看负z轴 . 近和远值是距离原点的距离 . 有效的通话可能如下所示:

    m_projection_matrix.perspective(60.0, (float) width / (float) height, 1.0f, 10.0f);
    

    然后,您还需要设置模型矩阵,以将对象的坐标转换为负z轴上的此范围 . 例如,您可以通过 (0.0f, 0.0f, -5.0f) 应用翻译 .

    或者,如果您只想查看某些内容,如果您只是使用单位矩阵进行投影,那么四边形也应该变得可见 .

相关问题