一些术语有些偏离:
- A
Vertex Array
只是一个float[]
包含顶点数据的数组(通常为)。它不需要绑定任何东西。不要与a Vertex Array Object
或VAO 混淆,我将在稍后进行介绍
- 当您存储顶点时
Buffer Object
,通常称为A ,简称Vertex Buffer Object
VBO Buffer
。
- 什么都不会保存回顶点数组,其
glVertexAttribPointer
工作原理完全相同glVertexPointer
或glTexCoordPointer
起作用,只是提供一个数字来指定您自己的属性,而不仅仅是命名属性。您将此值传递为index
。您的所有glVertexAttribPointer
通话都会在您下次通话glDrawArrays
或时排队glDrawElements
。如果您绑定了VAO,则VAO将存储所有属性的设置。
这里的主要问题是您将顶点属性与VAO混淆了。顶点属性只是为绘制定义顶点,texcoords,法线等的新方法。VAO存储状态。我首先要说明绘图如何与顶点属性一起使用,然后说明如何减少VAO的方法调用次数:
- 必须先启用属性,然后才能在着色器中使用它。例如,如果要将顶点发送到着色器,则很有可能将其作为第一个属性0发送。因此,在渲染之前,需要使用启用它
glEnableVertexAttribArray(0);
。
- 现在启用了属性,您需要定义将要使用的数据。为此,您需要绑定VBO-
glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
。
- 现在我们可以定义属性-
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
。按参数顺序排列:0是要定义的属性,3是每个顶点的大小,GL_FLOAT
是类型,GL_FALSE
表示不对每个顶点进行规范化,后两个零表示顶点上没有步幅或偏移。
- 用它画东西-
glDrawArrays(GL_TRIANGLES, 0, 6);
- 接下来绘制的内容可能不会使用属性0(实际上会使用属性0,但这只是一个示例),因此我们可以将其禁用-
glDisableVertexAttribArray(0);
将其包装在glUseProgram()
调用中,您将拥有一个与着色器正确配合的渲染系统。但是,假设您有5种不同的属性,即顶点,texcoords,法线,颜色和光照贴图坐标。首先,您将对glVertexAttribPointer
这些属性中的每一个进行一次调用,并且必须事先启用所有属性。假设您将属性0-4定义为列出的属性。您可以像这样启用所有功能:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
然后,您将不得不为每个属性绑定不同的VBO(除非将它们全部存储在一个VBO中并使用offsets / stride),然后需要进行5个不同的glVertexAttribPointer
调用,分别是从glVertexAttribPointer(0,...);
到glVertexAttribPointer(4,...);
顶点到光照贴图坐标。
希望该系统本身有意义。现在,我将继续介绍VAO,以解释在进行这种类型的渲染时如何使用它们来减少方法调用的次数。请注意,没有必要使用VAO。
A Vertex Array Object
或VAO用于存储所有glVertexAttribPointer
呼叫的状态以及进行每个glVertexAttribPointer
呼叫时所针对的VBO 。
您通过调用生成一个glGenVertexArrays
。要将所需的一切存储在VAO中,请与之绑定glBindVertexArray
,然后进行完整的绘图调用。所有的抽签绑定调用都会被VAO拦截并存储。您可以将VAO与glBindVertexArray(0);
现在,当你想拉拢的对象,你并不需要全部重新调用VBO结合或glVertexAttribPointer
电话,你只需要到VAO绑定glBindVertexArray
然后打电话glDrawArrays
或者glDrawElements
,你会被绘制同样的事情,就像你正在进行所有这些方法调用。您可能以后也想取消绑定VAO。
解除绑定VAO后,所有状态将恢复为绑定VAO之前的状态。我不确定在绑定VAO时是否保留您所做的任何更改,但是可以通过测试程序轻松找出。我想您可以将glBindVertexArray(0);
其绑定为“默认” VAO ...
更新:有人提醒我需要进行实际抽奖。事实证明,设置VAO时实际上不需要进行FULL绘制调用,只需绑定所有东西即可。不知道为什么我以前认为有必要,但现在已解决。