繁体   English   中英

Qt 5.5 with QOpenGLWidget,核心配置文件中的不可见三角形

[英]Qt 5.5 with QOpenGLWidget, invisible triangle in core profile

我无法将用Glew和GLFW在Qt之外进行的hello三角形移植到Qt 5.5和QOpenGlWidget中,使用“新”方式处理诸如QSurfaceFormat,QOpenGLfunctions,带有核心配置文件和opengl> =的QOpenGLShaderProgram 3.3。

这是我的QOpenGLWidget子类“ OGLWidget”,我从本文改编了子类 这个Qt教程

#include "oglwidget.h"

#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>

OGLWidget::OGLWidget(QWidget *parent)
    :QOpenGLWidget(parent)
    , m_program(0)
{

}


OGLWidget::~OGLWidget()
{

}

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "}\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   gl_FragColor = col;\n"
    "}\n";

void OGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();
    m_posAttr = m_program->attributeLocation("posAttr");
    m_colAttr = m_program->attributeLocation("colAttr");
    m_matrixUniform = m_program->uniformLocation("matrix");
}

void OGLWidget::paintGL()
{

    const qreal retinaScale = devicePixelRatio();
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);
    glClear(GL_COLOR_BUFFER_BIT);
    m_program->bind();
    m_program->setUniformValue(m_matrixUniform, matrix);

    GLfloat vertices[] = {
        0.0f, 0.707f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    };

    GLfloat colors[] = {
        1.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 1.0f
    };

    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_TRIANGLES, 0 , 3);

    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

}

void OGLWidget::resizeGL(int w, int h)
{
    matrix.setToIdentity();
    matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
    matrix.translate(0, 0, -2);
}

与此main.cpp一起正常工作:

#include <QApplication>
#include <QSurfaceFormat>

#include "oglwidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(3, 3);

    QSurfaceFormat::setDefaultFormat(format);

    OGLWidget myGLWidget;
    myGLWidget.resize(640, 480);
    myGLWidget.show();

    return a.exec();
}

但是,当我添加时: format.setProfile(QSurfaceFormat::CoreProfile); 到上面的块,然后将着色器更改为我最近在使用Core概要文件和GLSL 3.3的openGL教程中学到的知识:

static const char *vertexShaderSource =
"#version 330 core;\n"
"layout (location = 0) in vec3 posAttr;\n"
"layout (location = 1) in vec3 colAttr;\n"
"out vec3 fragColor;\n"
"void main(){\n"
"    gl_Position = matrix * vec4(posAttr, 1.0f);\n"
"    fragColor = colAttr;\n"
"}\n";

static const char *fragmentShaderSource =
"#version 330 core;\n"
"in vec3 fragColor;\n"
"out vec4 color;\n"
"void main(){\n"
"    color = vec4(fragColor, 1.0f);"
"}\n";

我的代码可以编译,但是黑屏。 没有三角形了。

我在Macbook Pro视网膜上使用Qt 5.5,优胜美地10.10.5。 GPU Intel Iris。

知道我要在那里修改以再次向我的彩色三角形问好吗?

谢谢

编辑

这是解释注释的代码的新版本,建议添加VAO。 我以为需要VBO,但是我暂时没有使用这些最近的Qt类的工作示例。 但是,我的三角形仍然没有显示。 我在这里进行了简化,因为我使用了直接在着色器中编码的单色。

OGLWidget::OGLWidget(QWidget *parent)
    :QOpenGLWidget(parent)
    , m_program(0)
{

}


OGLWidget::~OGLWidget()
{

}


static const char *vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 posAttr;\n"
"uniform mat4 matrix;\n"
"void main(){\n"
"    gl_Position = matrix * vec4(posAttr, 1.0f);\n"
"}\n";

static const char *fragmentShaderSource =
"#version 330 core\n"
"out vec4 color;\n"
"void main(){\n"
"    color = vec4(0.5f, 0.0f, 0.0f, 1.0f);\n"
"}\n";


void OGLWidget::initializeGL()
{

    initializeOpenGLFunctions();

    GLfloat vertices[] = {
        0.0f, 0.707f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    };

    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();
    m_posAttr = m_program->attributeLocation("posAttr");
    m_matrixUniform = m_program->uniformLocation("matrix");

    const qreal retinaScale = devicePixelRatio();
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);



    // Create Vertex Array Object
    m_vao.create();
    m_vao.bind();

    // Create Vertex Buffer (Do not release until VAO is created)
    m_vertexBuffer = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_vertexBuffer.create();
    m_vertexBuffer.bind();
    m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_vertexBuffer.allocate(sizeof(vertices));

    m_program->bind();

    m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3*sizeof(GLfloat));
    m_program->enableAttributeArray(m_posAttr);
    m_program->setAttributeArray(m_posAttr, vertices, 3);

    m_vao.release();
    m_vertexBuffer.release();
    m_program->release();

}

void OGLWidget::paintGL()
{

    glClear(GL_COLOR_BUFFER_BIT);

    m_program->bind();
    m_program->setUniformValue(m_matrixUniform, matrix);

    m_vao.bind();
    glDrawArrays(GL_TRIANGLES, 0 , 3);
    m_vao.release();

    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

    m_program->release();

}

void OGLWidget::resizeGL(int w, int h)
{
    matrix.setToIdentity();
    matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
    matrix.translate(0, 0, -2);
}

阅读并测试了部分代码后,我在这里提交了一些可行的方法。 如果您认为有一种甚至更好的方式(相对于Qt或openGL推荐的方式更好),请务必纠正我。

(main.cpp不变)

oglwidget.h

#include <QWidget>
#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>

class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;

class OGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
    OGLWidget(QWidget *parent = 0);
    ~OGLWidget();

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

private:
    bool prepareShaderProgram( const QString& vertexShaderPath,
                               const QString& fragmentShaderPath );

    QOpenGLVertexArrayObject m_vao;
    QOpenGLBuffer m_vertexBuffer;
    QOpenGLShaderProgram m_shader;
};

我没有将以上内容放在我的原始帖子中。 因此,这将使事情变得更清楚。 下面是更正后的oglwidget.cpp,用于显示红色三角形。

oglwidget.cpp

OGLWidget::OGLWidget(QWidget *parent)
    :QOpenGLWidget(parent)
    , m_shader(0)
    , m_vertexBuffer(QOpenGLBuffer::VertexBuffer)
{

}


OGLWidget::~OGLWidget()
{

}


void OGLWidget::initializeGL()
{

    initializeOpenGLFunctions();


    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    if ( !prepareShaderProgram( "/file Path To vertex shader source file", "/file Path To fragment shader source file" ) )
     return;

    GLfloat vertices[] = {
        0.0f, 0.707f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    };
    // Setup Vertex Buffer
    m_vertexBuffer.create();
    m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
    // Bind Vertex Buffer + check
    if ( !m_vertexBuffer.bind() )
     {
     qWarning() << "Could not bind vertex buffer to the context";
     return;
     }
    m_vertexBuffer.allocate(vertices, sizeof(vertices));

    // Bind the shader program so that we can associate variables from
    // our application to the shaders
    if ( !m_shader.bind() )
     {
     qWarning() << "Could not bind shader program to context";
     return;
     }

    // Create Vertex Array Object
    m_vao.create();
    m_vao.bind();

    m_shader.setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
    m_shader.enableAttributeArray("vertex");

    m_vao.release();
    m_vertexBuffer.release();
    m_shader.release();

}

void OGLWidget::paintGL()
{


    glClear(GL_COLOR_BUFFER_BIT);

    m_shader.bind();

    m_vao.bind();
    glDrawArrays(GL_TRIANGLES, 0 , 3);
    m_vao.release();

    m_shader.release();

}

void OGLWidget::resizeGL(int w, int h)
{
//    const qreal retinaScale = devicePixelRatio();
//    glViewport(0, 0, width() * retinaScale, height() * retinaScale);
      glViewport( 0, 0, w, qMax( h, 1 ) );
}

bool OGLWidget::prepareShaderProgram(const QString &vertexShaderPath, const QString &fragmentShaderPath)
{
    // First we load and compile the vertex shader…
     bool result = m_shader.addShaderFromSourceFile( QOpenGLShader::Vertex, vertexShaderPath );
     if ( !result )
     qWarning() << m_shader.log();

    // fragment shader
     result = m_shader.addShaderFromSourceFile( QOpenGLShader::Fragment, fragmentShaderPath );
     if ( !result )
     qWarning() << m_shader.log();

    // link the shaders
     result = m_shader.link();
     if ( !result )
     qWarning() << "Could not link shader program:" << m_shader.log();

    return result;
}

我不清楚是否需要使用:我在非Qt代码中一直使用的glDisableVertexAttribArray 在这里我没有,但是如果必须的话,什么时候应该使用它? 无论如何,都会显示三角形。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM