Reputation: 19
So I'm trying to implement an editor for my game using Qt, and I can't seem to decipher how the QOpenGLWidget works. Right now, I just want to get a simple triangle to render, then I can worry about moving in all the rest of my stuff.
Right now, it will open the window, and, in the QOpenGLWidget, will clear to the custom color I set in the subclass (so I did promote it), but it won't draw the triangle described in the class below. I've tried following the Qt OpenGLWindow example as well as the examples in QOpenGLWidget and QOpenGLShaderProgram, I also checked every function that returns a bool to make sure they were all being executed properly, and they are, but still no triangle.
Did I miss a vital function call? Am I doing things in the absolute wrong way? Or is it something super subtle and strange with Qt?
Here's the header:
#include<qopenglwidget.h>
#include<QtGui/qopenglfunctions.h>
class EditorViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
EditorViewWidget(QWidget *parent);
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
QOpenGLShaderProgram* shaderProgram;
QOpenGLVertexArrayObject vao;
QOpenGLBuffer VBO;
int position_attribute;
int color_uniform;
float Vertices[9];
const char* vert="#version 150 \n"
" \n"
" in vec3 position; \n"
" \n"
" void main() \n"
" { \n"
" gl_Position = vec4(position, 1.0); \n"
" }";
const char* frag="#version 150 \n"
" \n"
" uniform vec3 Color; \n"
" out vec4 outColor; \n"
" \n"
" void main() \n"
" { \n"
" outColor = vec4(Color, 1.0); \n"
" }";
};
and the source:
EditorViewWidget::EditorViewWidget(QWidget* parent)
:QOpenGLWidget(parent)
{
float v[] = {
0.0, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0
};
for (int i = 0; i < 9; i++)
Vertices[i] = v[i];
}
void EditorViewWidget::initializeGL()
{
initializeOpenGLFunctions();
vao.create();
vao.bind();
//glGenBuffers(1, &VBO);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
shaderProgram = new QOpenGLShaderProgram(this);
shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vert);
shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, frag);
shaderProgram->link();
shaderProgram->bind();
position_attribute = shaderProgram->attributeLocation("position");
color_uniform = shaderProgram->uniformLocation("Color");
VBO.create();
VBO.bind();
VBO.allocate(&Vertices, 9*sizeof(float));
shaderProgram->enableAttributeArray(position_attribute);
shaderProgram->setAttributeArray(position_attribute, Vertices, 3);
shaderProgram->setUniformValue(color_uniform, 1.0f, 1.0f, 1.0f);
//glVertexAttribPointer(position_attribute, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
}
void EditorViewWidget::resizeGL(int w, int h)
{
}
void EditorViewWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
VBO.bind();
VBO.allocate(&Vertices, 9 * sizeof(float));
shaderProgram->enableAttributeArray(position_attribute);
shaderProgram->setAttributeArray(position_attribute, Vertices, 3, 0);
shaderProgram->setUniformValue(color_uniform, 1.0f, 1.0f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, 3);
shaderProgram->disableAttributeArray(position_attribute);
}
Upvotes: 1
Views: 953
Reputation: 1152
I have ported the example to Qt6:
QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
to the main()
. At least on my laptop the program doesn't work without this line of code. This error message will be printed to the Qt debug console: GLSL 1.50 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, and 3.00 ES
setAttributeBuffer
instead of setAttributeArray
VBO.bind()
inside of paintGL
. You should call VAO.bind()
onlysetAttributeBuffer/enableAttributeArray
inside of paintGL
because you have made it inside of initializeGL
VBO.release();
and VAO.release();
inside of initializeGL
VAO.release();
after glDrawArrays(GL_TRIANGLES, 0, 3);
VBO.allocate
inside of paintGL
because you have made it inside of initializeGL
shaderProgram->setUniformValue(uColorLocation, 1.0f, 1.0f, 1.0f);
inside of paintGL
because you have made it inside of initializeGL
float v[] = {
0.f, 0.5f, 0.f,
-0.5f, -0.5f, 0.f,
0.5f, -0.5f, 0.f
};
But this one doesn't:
float v[] = {
0.f, 0.5f, 0.f,
0.5f, -0.5f, 0.f,
-0.5f, -0.5f, 0.f
};
pro
QT += core gui openglwidgets
win32: LIBS += -lopengl32
CONFIG += c++17
SOURCES += \
main.cpp \
editor_view_widget.cpp
HEADERS += \
editor_view_widget.h
main.cpp
#include "editor_view_widget.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
QApplication app(argc, argv);
EditorViewWidget w;
w.show();
return app.exec();
}
editor_view_widget.h
#ifndef EDITOR_VIEW_WIDGET_H
#define EDITOR_VIEW_WIDGET_H
#include <QtGui/QOpenGLFunctions>
#include <QtOpenGL/QOpenGLBuffer>
#include <QtOpenGL/QOpenGLShaderProgram>
#include <QtOpenGL/QOpenGLVertexArrayObject>
#include <QtOpenGLWidgets/QOpenGLWidget>
class EditorViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
EditorViewWidget(QWidget *parent = nullptr);
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
private:
QOpenGLShaderProgram *shaderProgram;
QOpenGLVertexArrayObject VAO;
QOpenGLBuffer VBO;
int aPositionLocation;
int uColorLocation;
float vertices[9];
const char* vert="#version 150 \n"
" \n"
" in vec3 aPosition; \n"
" \n"
" void main() \n"
" { \n"
" gl_Position = vec4(aPosition, 1.0); \n"
" }";
const char* frag="#version 150 \n"
" \n"
" uniform vec3 uColor; \n"
" out vec4 outColor; \n"
" \n"
" void main() \n"
" { \n"
" outColor = vec4(uColor, 1.0); \n"
" }";
};
#endif // EDITOR_VIEW_WIDGET_H
editor_view_widget.cpp
#include "editor_view_widget.h"
EditorViewWidget::EditorViewWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
setWindowTitle("Example");
resize(350, 350);
// float v[] = {
// 0.f, 0.5f, 0.f,
// 0.5f, -0.5f, 0.f,
// -0.5f, -0.5f, 0.f
// };
float v[] = {
0.f, 0.5f, 0.f,
-0.5f, -0.5f, 0.f,
0.5f, -0.5f, 0.f
};
for (int i = 0; i < 9; i++)
{
vertices[i] = v[i];
}
}
void EditorViewWidget::initializeGL()
{
initializeOpenGLFunctions();
VAO.create();
VAO.bind();
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
shaderProgram = new QOpenGLShaderProgram(this);
shaderProgram->addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vert);
shaderProgram->addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, frag);
shaderProgram->link();
shaderProgram->bind();
aPositionLocation = shaderProgram->attributeLocation("aPosition");
uColorLocation = shaderProgram->uniformLocation("uColor");
shaderProgram->setUniformValue(uColorLocation, 1.0f, 1.0f, 1.0f);
VBO.create();
VBO.bind();
VBO.allocate(vertices, sizeof(vertices));
shaderProgram->setAttributeBuffer(aPositionLocation, GL_FLOAT, 0, 2);
shaderProgram->enableAttributeArray(aPositionLocation);
VBO.release();
VAO.release();
}
void EditorViewWidget::resizeGL(int w, int h)
{
Q_UNUSED(w);
Q_UNUSED(h);
}
void EditorViewWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
VAO.bind();
shaderProgram->bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
VAO.release();
}
Upvotes: 0
Reputation: 402
You are allocating and setting the attributes of your VBO everytime you call paintGL. VBOs are so that you can just initialize them once and then use them many times. Then you can just bind your VAO in your paintGL, call glDrawArrays and then unbind your VAO. Also, unbinding/releasing your VBO and VAO should be done after the glDrawArrays and after you first set the attribute data. You don't need a VAO if you are only using one VBO. VAOs only purpose is to hold multiple VBOs.
You are calling enableAttributeArray instead of setAttributeBuffer.
I am not sure which of the above caused your triangle not to draw properly but I am almost certain it was one of them :).
Upvotes: 1
Reputation: 36
You specified the vertices of your triangle in clockwise order. OpenGL expects them in counterclockwise order by default. Switch the 2nd and 3rd vertex and you should see your triangle
Upvotes: 2