Qt 5.5 с QOpenGLWidget, невидимым треугольником в профиле ядра

У меня проблемы с переносом треугольника приветствия, из которого я привык делать вне Qt с Glew и GLFW, в Qt 5.5 и QOpenGlWidget с «новым» способом с такими вещами, как QSurfaceFormat, QOpenGLfunctions, QOpenGLShaderProgram с профилем Core и opengl> = 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);
в приведенный выше блок, и меняю мои шейдеры на те, которые я недавно изучал с помощью учебных пособий 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.

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

Спасибо

РЕДАКТИРОВАТЬ

Вот новая версия кода, которая учитывает комментарии, предлагая добавить 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);
}

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

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

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]