如何使用带有Qt的OpenGL中的顶点缓冲区对象绘制矩形?

时间:2012-12-15 14:49:14

标签: qt opengl

我正在尝试使用带有Qt的OpenGL中的顶点缓冲区对象绘制一个样方。 这是我的几何:

numVertices = 4;
vertices = new float[3*numVertices];
int i = 0;
vertices[i++] = 0.0f; vertices[i++] = 0.0f; vertices[i++] = 0.0f; // (0,0,0)
vertices[i++] = 1.0f; vertices[i++] = 0.0f; vertices[i++] = 0.0f; // (1,0,0)
vertices[i++] = 1.0f; vertices[i++] = 1.0f; vertices[i++] = 0.0f; // (1,1,0)
vertices[i++] = 0.0f; vertices[i++] = 1.0f; vertices[i++] = 0.0f; // (0,1,0)
i = 0;
// spilt quad into two triangles:
numTriangles = 2;
indices = new unsigned int[numTriangles*3];
indices[i++] = 0; indices[i++] = 1; indices[i++] = 2; 
indices[i++] = 0; indices[i++] = 2; indices[i++] = 3;

接下来是initializeGL方法:

QGLBuffer vertexBuffer;
vertexBuffer.create();
vertexBuffer.bind();
vertexBuffer.allocate(vertices, numVertices*sizeof(float));

QGLShaderProgram* shaderProgram_ = new QGLShaderProgram;
shaderProgram_->addShaderFromSourceFile(QGLShader::Vertex,"C:/src/light.vert.glsl") ) {
shaderProgram_->addShaderFromSourceFile(QGLShader::Fragment, "C:/src/light.frag.glsl");
bool ok = shaderProgram_->link();
ok = shaderProgram_->bind();

我认为所有VBO部分都是将顶点复制到GPU? (为什么这么多行?)

着色器部分与旧式glBegin(GL_QUADS)完美配合;

接下来是我的paintGL方法:

shaderProgram_->setAttributeBuffer("vertex", GL_FLOAT, 0, 3, 0);
shaderProgram_->enableAttributeArray("vertex");
glDrawElements(GL_TRIANGLES, numTriangles, GL_UNSIGNED_INT, indices);

两条第一线做什么?也许告诉着色器有一个名为“vertex”的GL_FLOAT类型的顶点缓冲区? 但是在创建VBO时我没有指定任何名称!? OpenGL如何知道这是“顶点”?

无论如何我不是在做什么!? 我有什么步骤吗? 我的着色器是简单的通过槽:

# version 120  
varying vec4 color;
void main() {
    vec4 vertex = gl_Vertex;
    // pass trough:
    gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vertex; 
    color = gl_Color; 
}

# version 120 
varying vec4 color;
void main (void) 
{   
    // pass-trough:    
 gl_FragColor = color;
 }

1 个答案:

答案 0 :(得分:2)

我猜你在这里失去了3:

vertexBuffer.allocate(vertices, numVertices*sizeof(float));

- >

vertexBuffer.allocate(vertices, numVertices*sizeof(float)*3);
  

我认为所有VBO部分都是将顶点复制到GPU? (为什么这么多   行?)

是。这就是OpenGL的工作原理。要在VBO中存储内容,您必须创建它,绑定它并复制数据。

  

两条第一线做什么?也许告诉着色器   有一个名为“vertex”的GL_FLOAT类型的顶点缓冲区?但是,我   在创建VBO时没有指定任何名称!? OpenGL如何知道   这是“顶点”吗?

第一行:

QGLShaderProgram::setAttributeBuffer()“在此着色器程序中设置名为name的属性的顶点值数组,从当前绑定的顶点缓冲区中的特定偏移量开始。” - 来自手册。再一次,这就是OpenGL的工作原理。这是一台状态机。将特定缓冲区绑定到GL_ARRAY_BUFFER绑定点,然后告诉OpenGL这是存储“顶点”属性数据的缓冲区。 “vertex”是着色器程序中的属性名称。 (可能你应该把它改成“gl_Vertex”)猜猜,Qt打电话给glVertexAttribLocation()找到属性的位置,然后调用glVertexAttribPointer()

第二行:

OpenGL必须知道它应该将数据从某个缓冲区复制到着色器程序可以找到的特殊位置。这是通过为特定位置启用属性数组来完成的。猜猜,Qt在这里拨打glVertexAttribLocation()glEnableAttribArray()

顺便说一句: 您是否在代码中指定了任何模型视图和投影矩阵?我不确定它们是否默认设置。尝试从着色器中删除这些值以进行测试。

添加了:

glDrawElements(GL_TRIANGLES, numTriangles, GL_UNSIGNED_INT, indices);

第二个参数不是三角形数,而是索引数,它将从索引数组中读取。这应该是numTriangles*3