我正在尝试使用Qt SDK编写一个现代的OpenGL(可编程管道)程序.Qt OpenGL示例仅显示固定的管道实现。关于如何初始化着色器程序的文档非常差。这是关于如何进行的最佳示例设置着色器程序并加载它们具有的着色器:http://doc.trolltech.com/4.6/qglshaderprogram.html#details 人们可以看到,这不是很具描述性。 我试图遵循这个文档,不能让Shader程序工作。当程序试图将属性分配给着色器时获取分段错误。我认为问题是我以错误的方式访问上下文。但我不能找到有关如何设置或检索渲染上下文的任何参考。我的代码如下:
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");
}
这是渲染循环:
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);
}
有人可以帮忙进行此设置吗?非常感谢。
答案 0 :(得分:2)
您创建了一个本地program
变量,并让您的pprogram
指针指向其地址。但是当initShaderProgram
返回时,本地program
的生命周期结束,并且您将程序指向垃圾,因此当您尝试使用它时会出现段错误。您应该动态创建程序并让Qt处理内存管理:
pprogram = new QGLShaderProgram(context.currentContext(), this);
这假定OpenGLWrapper
从QObject
派生出一些内容,如果没有,那么你需要手动删除其析构函数中的程序(或使用一些智能指针,或其他)。
否则你的初始化代码看起来很合理。你的矩阵变量应该是一个统一的而不是一个属性,但我愿意将其归类为拼写错误。您也不应该在整个生命周期内bind
,因为这相当于对glUseProgram
的调用。您应该在渲染例程中使用bind
(和release
,glUseProgram(0)
)。
答案 1 :(得分:1)
根据我的经验,OpenGL对象的Qt包装器相当差且有限,我只是为直接的OpenGL对象做了一个瘦包装器(通过GLEW实现了跨平台和简单),并在QGLWidget中进行了常规的OpenGL调用。在与Qt的等价物挣扎了一段时间后,它没有问题。