简体   繁体   中英

Qt OpengGL Shader Program fails

I am trying to write a modern OpenGL (programmable pipeline) program using Qt SDK .Qt OpenGL examples show only the fixed pipeline implementation.The documentation on how to initialize Shader Program is very poor.This is the best example on how to setup a shader program and load shaders they have:http://doc.trolltech.com/4.6/qglshaderprogram.html#details This is not very descriptive as one can see. I tried to follow this doc and cann't get the Shader program working .Getting segmentation error when the program tries to assign attributes to the shaders.I think the problem is that I access the context in the wrong way.But I can't find any reference on how to setup or retrieve the rendering context.My code goes like this:

static GLfloat const triangleVertices[] = {
    60.0f,  10.0f,  0.0f,
    110.0f, 110.0f, 0.0f,
    10.0f,  110.0f, 0.0f
};

QColor color(0, 255, 0, 255);
int vertexLocation =0;
int matrixLocation =0;
int colorLocation =0;
QGLShaderProgram *pprogram=0;
void OpenGLWrapper::initShaderProgram(){
    QGLContext context(QGLFormat::defaultFormat());

    QGLShaderProgram program(context.currentContext());
    pprogram=&program;
    program.addShaderFromSourceCode(QGLShader::Vertex,
     "attribute highp vec4 vertex;\n"
     "attribute mediump mat4 matrix;\n"
     "void main(void)\n"
     "{\n"
     "   gl_Position = matrix * vertex;\n"
     "}");
     program.addShaderFromSourceCode(QGLShader::Fragment,
     "uniform mediump vec4 color;\n"
     "void main(void)\n"
     "{\n"
     "   gl_FragColor = color;\n"
     "}");
     program.link();
     program.bind();

vertexLocation= pprogram->attributeLocation("vertex");
matrixLocation= pprogram->attributeLocation("matrix");
colorLocation=  pprogram->uniformLocation("color");
}

And here is the rendering loop:

void OpenGLWrapper::paintGL()
{
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


     QMatrix4x4 pmvMatrix;
     pmvMatrix.ortho(rect());

    pprogram->enableAttributeArray(vertexLocation);
    pprogram->setAttributeArray(vertexLocation, triangleVertices, 3);
    pprogram->setUniformValue(matrixLocation, pmvMatrix);
    pprogram->setUniformValue(colorLocation, color);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    pprogram->disableAttributeArray(vertexLocation);
}

Anybody has can help with this setup? Thanks a lot .

You create a local program variable and let your pprogram pointer point to its address. But when initShaderProgram returns, the local program 's lifetime ends and you pprogram points to garbage, therefore the segfault when you try to use it. You should rather create the program dynamically and let Qt handle the memory management:

pprogram = new QGLShaderProgram(context.currentContext(), this);

This assumes OpenGLWrapper derives somewhoe from QObject , if not, then you need to delete the program in its destructor manually (or use some smart pointer, or whatever).

Otherwise your initialization code looks quite reasonable. Your matrix variable should be a uniform and not an attribute, but I'm willing to classfiy this as a typo. You should also not bind the program for the whole lifetime, as this is equivalent to a call to glUseProgram . You should rather use bind (and release , which does glUseProgram(0) ) in your render routine.

In my experience the Qt wrappers for OpenGL objects are rather poor and limited, I just made a thin-wrapper for straight OpenGL objects (made cross-platform and easy via GLEW), and made the usual OpenGL calls in QGLWidget. It worked no problem, after struggling for awhile with Qt's equivalents.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM