2015-11-10 3 views
2

У меня проблемы с переносом треугольника привет из я привык делать вне Qt с Glew и GLFW, в Qt 5.5 и QOpenGlWidget, с «новым» способом с вещами как QSurfaceFormat, QOpenGLfunctions, QOpenGLShaderProgram с профилем Core и opengl> = 3.3.Qt 5.5 с QOpenGLWidget, невидимый треугольник в основном профиле

Вот мой QOpenGLWidget подкласс "OGLWidget", который я приспособил от this post. и это Qt tutorial

#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); к вышеперечисленному блоку и изменение моих шейдеров до того, что я недавно изучал с помощью обучающих программ openGL, которые используют профиль Core и GLSL 3.3:

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"; 

Мой код компилируется, но у меня есть черный экран. Больше нет треугольника.

Я использую Qt 5.5, на macbook pro retina, yosemite 10.10.5. Графический процессор Intel Iris.

Любая идея, что я изменю там, чтобы снова поздороваться с моим красочным треугольником?

Благодаря

EDIT

Вот новая версия кода, который приходится комментариев, предложив добавить ВАО. Я предположил, что 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); 
} 
+0

Основной профиль capital-R Требуется создать и привязать VAO до того, как вы установите атрибут enable/pointer & render. – genpfault

+0

Как связывает VAO отличную от всех функций привязки класса QOpenGLShaderProgram, который я уже использую? Не могу ли я использовать метод этого класса для этого? –

+0

Я вижу, что Qt 5 имеет [обертку] (http://doc.qt.io/qt-5/qopenglvertexarrayobject.html) для VAO, но неясно, должно ли это взаимодействовать с классом QOpenGLShaderProgram. Я не могу найти рабочий пример. –

ответ

0

После прочтения и тестирования фрагментов кодов я представляю здесь что-то, что работает. Если вы считаете, что существует даже «лучший» способ (лучше в отношении рекомендуемых способов 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; 
} 

Неясно мне, если мне нужно использовать: glDisableVertexAttribArray, которые я использую в не-Qt кодов. Здесь я этого не делаю, но если мне нужно, когда я буду использовать его? Во всяком случае, отображается треугольник.

Смежные вопросы