1

我尝试以现代管道实现的方式在 OS X 10.9 上使用 Qt (v5.1.1) 编写 OpenGL 项目。该程序应该是一个基于多智能体的系统或粒子系统。但是我缺乏理解如何从另一个类中提取一些东西。

在 cinder 中,您可以调用一些简单的 drawThisAndThat() 命令。我阅读了第 6 版的“OpenGL Superbible”。从这个和几个教程中,所有示例似乎都只涵盖了所有修改都来自初始化 OpenGL 的类的程序。

我想实例化一些在网格上移动的对象并绘制像素以显示它们的位置。我知道我必须打电话void glVertexAttrib4fv(GLuint index, const GLfloat * vi);,但这还不够。

  • 我还需要打电话吗?glEnableVertexAttribArray(1);还有glDrawArrays(GL_POINTS, 0, 3);什么?
  • 我是对的,在实例化 OpenGL 并在主循环之后实例化控制粒子的类吗?
  • 我如何管理粒子在擦除他被绘制的位置时绘制自己?

该程序基于此代码

4

1 回答 1

1

为了完全回答你的问题,我必须写一堵文字墙,我会尽量只指出最重要的方面。我希望这将帮助您充分利用您的知识并可能进一步阅读以使其发挥作用。

所有修改都是由初始化 OpenGL 的类进行的

您可以封装对象的方法update(time)draw()方法,然后在主循环中调用它们。

我还需要打电话吗?glEnableVertexAttribArray(1);还有glDrawArrays(GL_POINTS, 0, 3);什么?

我会将所有粒子放入一个顶点数组中,以避免在每个粒子之后重新绑定不同的顶点数组。然后你必须在你的 draw() 调用中使用glBindVertexArray(vaid);and 。glDrawArrays(GL_POINTS, 0, vertexCount);小心vertexCount,它不是浮点数(正如您的问题所暗示的那样),而是顶点数,在您的示例中应该是 1 或者在我建议的方法中应该是粒子数(如果我正确假设3代表“我的顶点的 x、y 和 z”)。

而且由于您只有粒子glDrawElements(...);,因此可能已经满足您的需求。

我是对的,在实例化 OpenGL 并在主循环之后实例化控制粒子的类吗?

可能你的实例化顺序是正确的。在您的案例中,您绝对应该在调用主循环之前进行所有实例化。

我如何管理粒子在擦除他被绘制的位置时绘制自己?

如果正确理解您的最后一个问题:只需更改缓冲区对象 ( glBufferData(...);) 中的元素。由于您将在每次循环后清除屏幕并交换缓冲区,这将使它们移动。只需通过update(time)调用更新它们的位置,例如pos = pos + dir * time;,将新位置放入缓冲区并将该缓冲区推glBufferData(...)送到顶点数组。请记住在推送缓冲区之前绑定顶点数组。


我想指出一些额外的事情。

glEnableVertexAttribArray(1);是使着色器程序中的顶点属性能够将数据传递给该属性。您应该创建一个着色器程序

  id = glCreateProgram()
  // ... create and attach shaders here
  // then bind attribute locations, e.g. positionMC
  glBindAttribLocation(id, 0, "positionMC"); 
  glLinkProgram(id);

在初始化顶点数组后,glGenVertexArrays();您应该在着色器程序中启用顶点数组所需的所有属性。在此示例positionMC中将位于位置 0,因此您可以调用类似

  glUseProgram(pid);
  glBindVertexArray(vaid);
  glEnableVertexAttribArray(1);
  glVertexAttribPointer(...);

这只需要做一次,因为 OpenGL 存储每个特定顶点数组的状态。通过重新绑定顶点数组,您将恢复该状态。

在主循环中,您现在要做的就是调用更新和绘制方法,例如:

  handleInputs();
  update(deltaTime);
  glClear(...);
  draw();
  swapBuffers();
于 2013-11-18T10:04:15.700 回答