qt - 如何使用 Qt 在 OpenGL 中使用顶点缓冲区对象绘制矩形?

标签 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;
 }

最佳答案

我猜你在这里失去了 3 个:

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

->

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

I think all the VBO part does is to copy vertices to GPU? (Why so many lines?)

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

What are the two first lines doing? Maybe telling the shader that there is a vertex buffer named "vertex" of type GL_FLOAT? However I did not specify any name when creating the VBO!? How do OpenGL know that this is "vertex"?

第一行:

QGLShaderProgram::setAttributeBuffer() “在此着色器程序中名为 name 的属性上设置顶点值数组,从当前绑定(bind)的顶点缓冲区中的特定偏移量开始。” - 来自手册。再说一次,这就是 OpenGL 的工作原理。这是一个状态机。您将特定的缓冲区绑定(bind)到 GL_ARRAY_BUFFER 绑定(bind)点,接下来告诉 OpenGL 这是存储“顶点”属性数据的缓冲区。 “vertex”是着色器程序中的属性名称。 (也许您应该将其更改为“gl_Vertex”)猜猜,Qt 调用 glVertexAttribLocation() 来查找属性的位置,然后调用 glVertexAttribPointer()

第二行:

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

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

添加:

glDrawElements(GL_TRIANGLES, numTriangles, GL_UNSIGNED_INT, indices);

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

关于qt - 如何使用 Qt 在 OpenGL 中使用顶点缓冲区对象绘制矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13893202/

相关文章:

c++ - 更改 Qt 应用程序的当前路径

qt - QML 焦点如何传播?

opengl - View 矩阵应该按什么顺序计算?

c++ - 使用模板管理 glUniform 函数

OpenGL将光线距离与深度缓冲区进行比较

opengl - 如何将有关 GPU(OpenGL、OpenCL、mesa 等版本)的数据/信息从主机传递到 dockerimagr?

c++ - QMultihash 的持久化

windows - 如何将 OpenSSL 与基于 Qt WebKit 的应用程序一起分发到 Windows?

c++ - 在 QString 中推送 QChar

linux - Linux 上的 gDebugger libGL 错误