[SOLVED] QOpenGLShaderProgram segfault
-
I wanna write some app that use QOpenGLWidget and QOpenGLFunctions. And I have problem when I try to use any of functions from QOpenGLShaderProgram in other function that initializeGL or paintGL. Exactly when I even try to use program->log() i have segmentation fault. In that function I have makeCurrent(). When I create new QOpenGLShaderProgram in that function there's no problem, but when not (and I'm sure that object of QOpenGLShaderProgram exists at the time) i have segfault. Have you had problem like this?
-
Hi and welcome
I haveclass GLRender : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT QOpenGLShaderProgram* m_program; ..
and tried from
void mousePressEvent(QMouseEvent *) { qDebug () << m_program->log(); emit RenderSelected(this); }
And no crashes.
-
Hi and welcome
I haveclass GLRender : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT QOpenGLShaderProgram* m_program; ..
and tried from
void mousePressEvent(QMouseEvent *) { qDebug () << m_program->log(); emit RenderSelected(this); }
And no crashes.
Hey, thanks for your answers. It looks exactly like this:
#include "openglcontroller.h" #include "global.h" #include <cmath> #include <QWidget> #include <QMouseEvent> #include <QWheelEvent> #include <QOpenGLShaderProgram> #include <QDebug> OpenGLController::OpenGLController(QWidget * parent) : QOpenGLWidget(parent), m_parent(parent), m_f(nullptr), m_wheelMesh(parent), m_camAngleX(0.0f), m_camAngleY(0.0f), m_camFar(3.0f), m_camYPos(0.5f) { m_objectMesh = nullptr; } OpenGLController::~OpenGLController() { clean(); } void OpenGLController::initializeGL() { bool ok = true; makeCurrent(); m_f = QOpenGLContext::currentContext()->functions(); initializeOpenGLFunctions(); connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLController::clean); glClearColor(g_bgColor.x(), g_bgColor.y(), g_bgColor.z(), g_bgColor.w()); m_colorShader = new QOpenGLShaderProgram/*(QOpenGLContext::currentContext())*/; ok &= m_colorShader->addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/colorS.vs"); ok &= m_colorShader->addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/colorS.fs"); if(ok) { m_colorShader->bindAttributeLocation("vVertex",0); m_colorShader->link(); m_colorShader->bind(); m_projMatInfo.id = m_colorShader->uniformLocation(m_projMatInfo.name = "Mproj"); m_moveMatInfo.id = m_colorShader->uniformLocation(m_moveMatInfo.name = "Mmove"); m_colorInfo.id = m_colorShader->uniformLocation(m_colorInfo.name = "materialColor"); setWheelGrid(); m_colorShader->release(); } else { emit sendLog(Log(log_critical,tr("Nie znaleziono zawartości w katalogu shaders lub nie udało się uruchomić programów cieniujących"), -1,"OpenGLController","initializeGL")); } doneCurrent(); } void OpenGLController::resizeGL(int w, int h) { m_projMat.setToIdentity(); m_projMat.perspective(80.0f,(float)(w)/(float)h,0.1f,20.0f); } void OpenGLController::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); m_moveMat.setToIdentity(); m_moveMat.translate(0.0f, 0.0f, -m_camFar); m_moveMat.rotate(m_camAngleX,1.0f,0.0f,0.0f); m_moveMat.rotate(m_camAngleY,0.0f,1.0f,0.0f); m_moveMat.translate(0.0f, -m_camYPos, 0.0f); m_colorShader->bind(); m_colorShader->setUniformValue(m_projMatInfo.id, m_projMat); m_colorShader->setUniformValue(m_moveMatInfo.id, m_moveMat); m_colorShader->setUniformValue(m_colorInfo.id, m_wheelColor); m_wheelMesh.vao.bind(); m_f->glEnable(GL_LINE_SMOOTH); m_f->glLineWidth(g_gridBold); m_f->glDrawArrays(GL_LINES, 0, m_wheelMesh.vCount); m_f->glDisable(GL_LINE_SMOOTH); if(m_objectMesh != nullptr) { m_objectMesh->vao.bind(); m_colorShader->bind(); m_colorShader->setUniformValue(m_projMatInfo.id, m_projMat); m_colorShader->setUniformValue(m_moveMatInfo.id, m_moveMat); m_colorShader->setUniformValue(m_colorInfo.id, m_wheelColor); m_f->glDrawArrays(GL_POINTS, 0, m_objectMesh->vCount); } m_colorShader->release(); } // Funkcję można poprawić poprzez uwzględnienie rozmiaru renderowanego obszaru void OpenGLController::mouseMoveEvent(QMouseEvent * event) { // ... here is some code } void OpenGLController::wheelEvent(QWheelEvent * event) { //.... Here is some code } void OpenGLController::createObjectsMesh(unsigned horizontalPts, unsigned verticalPts) { delete m_objectMesh; m_objectMesh = new OGLCMesh(m_parent); m_objectMesh->vao.create(); m_objectMesh->vao.bind(); m_objectMesh->vbo.create(); m_objectMesh->vbo.bind(); m_objectMesh->vbo.allocate(horizontalPts * verticalPts * 4 * sizeof(GLfloat)); //m_colorShader->log(); HERE IS SEGFAULT } void OpenGLController::addObjectsSubMesh(unsigned vertsCount, double * vertices) { makeCurrent(); GLfloat * vConverted = new GLfloat[vertsCount * 4]; for(unsigned i=0; i < vertsCount * 4; i++) vConverted[i] = vertices[i]; m_objectMesh->vbo.write(m_objectMesh->vCount * 4, vConverted, vertsCount * 4); m_objectMesh->vCount += vertsCount; delete [] vConverted; update(); doneCurrent(); } void OpenGLController::setWheelGrid(float radius, unsigned rings, unsigned diameters) { float angleStep = 360.0f / diameters; float radStep = radius / rings; unsigned edgesCount = (rings + 1) * diameters; unsigned vertsCount = edgesCount * 2; if(m_wheelMesh.vTab != nullptr) { delete [] m_wheelMesh.vTab; m_wheelMesh.vTab = nullptr; } m_wheelMesh.vCount = vertsCount; m_wheelMesh.vTab = new GLfloat[vertsCount * 4]; unsigned index = 0; //Najpierw promienie for(unsigned i = 0; i < diameters; i++) { double currentAngle = (double)angleStep * i * g_pi / 180.0; double nextAngle = (double)angleStep * (i+1) * g_pi / 180.0; m_wheelMesh.vTab[index++] = 0.0f; m_wheelMesh.vTab[index++] = 0.0f; m_wheelMesh.vTab[index++] = 0.0f; m_wheelMesh.vTab[index++] = 1.0f; //Współrzędne środka m_wheelMesh.vTab[index++] = radius * cos(currentAngle); m_wheelMesh.vTab[index++] = 0.0f; m_wheelMesh.vTab[index++] = radius * sin(currentAngle); m_wheelMesh.vTab[index++] = 1.0f; //Następnie kolejne okręgi for(unsigned j = 0; j < rings; j++) { m_wheelMesh.vTab[index++] = radStep * (j+1) * cos(currentAngle); m_wheelMesh.vTab[index++] = 0.0f; m_wheelMesh.vTab[index++] = radStep * (j+1) * sin(currentAngle); m_wheelMesh.vTab[index++] = 1.0f; m_wheelMesh.vTab[index++] = radStep * (j+1) * cos(nextAngle); m_wheelMesh.vTab[index++] = 0.0f; m_wheelMesh.vTab[index++] = radStep * (j+1) * sin(nextAngle); m_wheelMesh.vTab[index++] = 1.0f; } } if(!m_wheelMesh.vao.isCreated()) m_wheelMesh.vao.create(); m_wheelMesh.vao.bind(); if(!m_wheelMesh.vbo.isCreated()) m_wheelMesh.vbo.create(); m_wheelMesh.vbo.setUsagePattern(QOpenGLBuffer::StaticDraw); m_wheelMesh.vbo.bind(); m_wheelMesh.vbo.allocate(m_wheelMesh.vTab, m_wheelMesh.vCount*4*sizeof(GLfloat)); m_colorShader->enableAttributeArray(0); m_colorShader->setAttributeArray(0,GL_FLOAT,0,4); } void OpenGLController::clean() { makeCurrent(); m_wheelMesh.vao.destroy(); m_wheelMesh.vbo.destroy(); if(m_objectMesh != nullptr) { m_objectMesh->vao.destroy(); m_objectMesh->vbo.destroy(); } delete m_colorShader; m_colorShader = 0; // delete m_f; doneCurrent(); }
And the problem is in function createObjectsMesh. When I will create QOpenGLShaderProgram again in this function there will be no problem, but if I do like this I have segmentation fault.
m_colorShader is QOpenGLShaderProgram with which i have problem.
-
I wanna write some app that use QOpenGLWidget and QOpenGLFunctions. And I have problem when I try to use any of functions from QOpenGLShaderProgram in other function that initializeGL or paintGL. Exactly when I even try to use program->log() i have segmentation fault. In that function I have makeCurrent(). When I create new QOpenGLShaderProgram in that function there's no problem, but when not (and I'm sure that object of QOpenGLShaderProgram exists at the time) i have segfault. Have you had problem like this?
Ok, I found solution. Well, i have made mistake in class MainWindow.
Now this is part from MainWindow:namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; OpenGLController * m_glController; // Here I had: OpenGLController m_glController };
And in MainWindow.cpp constructor:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_glController = ui->openGLWidget; // I did not wrote this line earlier }
And how I execute function createObjectsMesh(...) :
m_glController->createObjectsMesh(ui->sb_pointsHorizontal->value(), 480); // Earlier it was just object, not pointer - like this: // m_glController.createObjectsMesh(ui->sb_pointsHorizontal->value(), 480);
So in my app I had 2 objects of QOpenGLWidget - one that is made in GUI (Qt Form) and one which I had in my MainWindow class. And when I executed function createObjectsMesh(...) I did it for second of them, not first which were actually drawn in GUI.
I should just not to create another QOpenGLWidget in MainWindow class, but only get pointer to this one from GUI, like this:m_glController = ui->openGLWidget;
So now I have only one QOpenGLWidget - this one that is drawn in GUI.
Anyway - thanks for your help :D
-
ahh, tricky one :)