簡體   English   中英

Qt5 OpenGL紋理采樣

[英]Qt5 OpenGL Texture Sampling

我正在嘗試使用Qt5和着色器程序的OpenGL包裝器類渲染QImage 我有以下着色器和3.3核心上下文。 我還在屬性中使用VAO。 但是,我一直得到一個空白的紅色框(紅色是我設置的背景透明色)。 我不確定MVP矩陣或其他問題。 使用片段着色器將輸出顏色設置為某個固定顏色(黑色)仍會導致紅框。 我在這里完全迷路了。

EDIT-1:我還注意到,嘗試從QOpenGLShaderProgram獲取texRGB統一的位置QOpenGLShaderProgram導致-1。 但是我不確定這是否與我遇到的問題有關。 在頂點着色器中為MVP矩陣定義的均勻位置為0和1。

頂點着色器

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

片段着色器

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

您的片段着色器代碼中的這一行無效:

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()函數。 這意味着texture2DRect()任何 GLSL版本中都不存在。

正確的呼叫是:

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

您的代碼的另一部分可以防止其呈現任何內容,是此投影矩陣:

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

標准投影矩陣的近平面和遠平面都必須為正。 此調用將建立投影變換,其原點帶有“相機”,並沿負z軸向下看。 接近值和遠端值是距原點的距離。 有效的呼叫可能如下所示:

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

然后,您還需要設置模型矩陣,以將對象的坐標轉換為負z軸上的該范圍。 例如,您可以應用(0.0f, 0.0f, -5.0f)

或者,如果您只想看一些東西 ,則只需將恆等矩陣用於投影,四邊形也應可見。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM