如何在 OpenGL 3.2+ 中渲染多个形状和对象?
Posted
技术标签:
【中文标题】如何在 OpenGL 3.2+ 中渲染多个形状和对象?【英文标题】:How to render multiple shapes and objects in OpenGL3.2+? 【发布时间】:2014-03-31 06:47:49 【问题描述】:我正在按照本指南http://open.gl/ 学习如何使用现代 opengl 进行编程。我被困在一件事上。早期使用较旧的 opengl Api,我曾经创建不同的函数来绘制不同类型的形状。像drawRect()、drawCircle()等。我需要做的就是在glBegin()和glEnd()中以不同的组合使用glVertex3f()。
但是在OpenGl3.2+中,即使是画一个矩形,我们也得写很多代码。我知道它可以让您更好地控制渲染,但是当您同时渲染多个东西(例如绘制矩形、圆形等)时,我对该怎么做感到困惑。我是否需要多次编写所有代码,包括着色器,或者我可以重复使用这些代码。
我已经实现了这段代码http://open.gl/content/code/c2_triangle_elements.txt 这个例子画了一个矩形,但是如果我想在这个矩形上画一个三角形,那我该怎么做呢。
【问题讨论】:
我认为您需要充分了解着色器和缓冲区如何以更深入的方式工作。使用顶点缓冲区绑定,您可以映射顶点并像那样更改它们,或者使用模型矩阵和着色器中的制服来移动形状并使用不同的模型矩阵绘制两次。 【参考方案1】:您可以重复使用大部分代码。所有着色器都可以通过调用glUseProgram
加载一次并重复使用。至于所有缓冲区,您可以创建它们一次,然后根据需要多次重复使用它们。
您可能想要创建一些类,例如 ShaderClass
和 ShapeClass
。
基本着色器类通常有 2 或 3 个参数,例如 program
、vertexShader
和 fragmentShader
(都是一些 ID)。当您扩展它们时,还添加来自着色器的所有制服和属性,以便您以后可以使用它们来修改您的绘图(例如更改颜色)。
ShapeClass
通常包含顶点缓冲区 ID(和可选的索引缓冲区 ID)和要绘制的顶点数。
所以最后,当你想要绘制一些形状时,你只需要使用你已经创建和编译的着色器,绑定并设置你的形状缓冲区中的顶点数据并调用绘图。
【讨论】:
hmm...我明白了...谢谢 :) 我对顶点数组对象有点困惑。我是在开始时创建一次还是为每个 ShaderClass 创建一次。我也必须每次在链接和使用程序后调用 glVertexAttribPointer() 还是只调用一次。 VAO 与着色器完全无关。您可以将同一个 VAO 与多个着色器一起使用。您确实需要在调用 glUseProgram 之后(并且仅在之后)设置着色器所需的所有数据,包括顶点指针。除非您将顶点着色器和片段着色器组合在一起(您可能只有 1 个顶点着色器和 2 个片段着色器然后共享它们),否则您不会将着色器链接两次,但这与 VAO 无关,因为在您重新链接着色器后,您将需要调用 glUseProgram 然后重新绑定属性和制服数据。 另外请注意,如果您绘制不同的形状,在使用该程序后您可能会调用多个 glVertexAttribPointer。每次您想要绘制不同的形状(三角形、正方形)时,您可以使用不同的 VAO,在这种情况下,您可以绑定不同的指针但也绑定不同的缓冲区。 我尝试在一个类中实现所有这些。但它不起作用。这是代码pastebin.com/2fEMgae6 我不知道您为什么将 VAO 打包到同一个班级,但没关系。首先,您需要在调用 Attribute() 之前调用 Use()。其次,我不太确定您的着色器会以这种方式编译。在 glShaderSource 中尝试删除对字符串指针的引用(删除 &),或者将您的 Init 定义为 Init(const GLchar **vertShaderSource... 顺便说一句,除了“它不工作”之外,您还有关于这个问题的更多信息吗?以上是关于如何在 OpenGL 3.2+ 中渲染多个形状和对象?的主要内容,如果未能解决你的问题,请参考以下文章
为在 OpenGL 中使用基本物理和渲染寻找一个好的形状类设计
如何通过实例渲染将每个实例数据(例如定位)传递给 OpenGL 3.2 中的着色器?