PDA

View Full Version : [SOLVED] Drawing a triangle using PyQt5 and OpenGL (rewriting the Qt C++ example)



8Observer8
19th November 2020, 16:58
My current PyQt5 example does not show a window and does not give me any error messages.

This is Qt C++ example that works very good. I want to use QOpenGLBuffer in my PyQt5 code.

main.cpp


#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>

class Widget : public QOpenGLWidget {
Q_OBJECT
public:
Widget(QWidget *parent = nullptr) : QOpenGLWidget(parent) { }
private:
QOpenGLShaderProgram m_program;
QOpenGLBuffer m_vertPosBuffer;

void initializeGL() override {
glClearColor(0.5f, 0.8f, 0.7f, 1.f);
resize(400, 500);
const char *vertShaderSrc =
"attribute vec3 aPosition;"
"void main()"
"{"
" gl_Position = vec4(aPosition, 1.0);"
"}";
const char *fragShaderSrc =
"void main()"
"{"
" gl_FragColor = vec4(0.5, 0.2, 0.9, 1.0);"
"}";
m_program.addShaderFromSourceCode(QOpenGLShader::V ertex, vertShaderSrc);
m_program.addShaderFromSourceCode(QOpenGLShader::F ragment, fragShaderSrc);
m_program.link();
m_program.bind();
float vertPositions[] = {
-0.5f, -0.5f, 0.f,
0.5f, -0.5f, 0.f,
0.f, 0.5f, 0.f
};
m_vertPosBuffer.create();
m_vertPosBuffer.bind();
m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
m_program.bindAttributeLocation("aPosition", 0);
m_program.setAttributeBuffer(0, GL_FLOAT, 0, 3);
m_program.enableAttributeArray(0);
}
void paintGL() override {
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void resizeGL(int w, int h) override {
glViewport(0, 0, w, h);
}
};

#include "main.moc"

int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}

This is my trying to rewrite the code above to PyQt5. As you can see I want to rewrite it very close to Qt C++. I want to have two very similar example. But this code does not show a windows and does not show any error messages.

main.py


import sys
import numpy as np
from OpenGL import GL as gl
from PyQt5.QtWidgets import QOpenGLWidget, QApplication
from PyQt5.QtGui import (QOpenGLBuffer, QOpenGLShaderProgram,
QOpenGLShader)
from PyQt5.QtCore import Qt

class OpenGLWidget(QOpenGLWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Triangle, PyQt5, OpenGL ES 2.0")
self.resize(300, 300)
def initializeGL(self):
gl.glClearColor(0.5, 0.8, 0.7, 1.0)
vertShaderSrc = """
attribute vec3 aPosition;
void main()
{
gl_Position = vec4(aPosition, 1.0);
}
"""
fragShaderSrc = """
void main()
{
gl_FragColor = vec4(0.5, 0.2, 0.9, 1.0);
}
"""
program = QOpenGLShaderProgram()
program.addShaderFromSourceCode(QOpenGLShader.Vert ex, vertShaderSrc)
program.addShaderFromSourceCode(QOpenGLShader.Frag ment, fragShaderSrc)
program.link()
program.bind()
vertPositions = np.array([
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0], dtype=np.float32)
vertPosBuffer = QOpenGLBuffer()
vertPosBuffer.create()
vertPosBuffer.bind()
vertPosBuffer.allocate(vertPositions, len(vertPositions) * 4)
program.bindAttributeLocation("aPosition", 0)
program.setAttributeBuffer(0, gl.GL_FLOAT, 0, 3)
program.enableAttributeArray(0)

def paintGL(self):
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)

def main():
QApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
a = QApplication(sys.argv)
w = OpenGLWidget()
w.show()
sys.exit(a.exec_())

if __name__ == "__main__":
main()


Added after 1 14 minutes:

eyllanesc solved my problem here: https://stackoverflow.com/questions/64914388/drawing-a-triangle-using-pyqt5-and-opengl-rewriting-the-qt-c-example/64915511#64915511


The problem is that the QOpenGLBuffer is a local variable that is destroyed instantly, whereas in C++ QOpenGLBuffer is an attribute of the class. The solution is to change vertPosBuffer to self.vertPosBuffer