我试图学习LWJGL(OpenGL),我不得不说我很难过。
我试图在窗口上绘制一个三角形和一个四边形,我终于设法做到了。
但我还有一个问题 提前抱歉,如果这个问题听起来很愚蠢,但我还没能在网上找到非常详细的教程,所以很难理解,因为这是我第一次使用OpenGL。
话虽如此,这是代码的相关部分:
public void init() {
vertexCount = indices.length;
vaoId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoId);
vboId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, coords, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
idxVboId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, idxVboId);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
GL30.glBindVertexArray(0);
}
public void render() {
GL30.glBindVertexArray(vaoId);
GL20.glEnableVertexAttribArray(0);
GL11.glDrawElements(GL11.GL_TRIANGLES, vertexCount, GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
让我们说程序以60 fps运行。
这意味着渲染方法每秒被游戏循环调用60次。
渲染方法步骤为:
glBindVertexArray(vaoId)
glEnableVertexAttribArray(0)
glDisableVertexAttribArray(0)
glBindVertexArray(0)
我的问题是:是否每次都需要拨打步骤1,2,4和5?如果是,为什么?
同样的问题适用于init()
方法的最后一行(glBindVertexArray(0)
)。
对不起我的英语,这不是我的母语 提前谢谢。
答案 0 :(得分:1)
我的问题是:是否有必要每次都拨打第1,2,4和5步?如果是,为什么?
不,不是。 OpenGL被设计为状态机。您有一个GL上下文,其中包含全局状态和您创建的对象(如VAO,VBO)。对象本身可以包含数据和每对象状态。重要的是在某个特定GL函数调用时设置的状态,它以某种方式依赖于某些状态值。
在glDrawElements()
的情况下,顶点数组指针和启用位以及GL_ELEMENT_ARRAY_BUFFER
绑定与为绘制调用提供输入数据相关。 (影响绘图的所有其他状态,如纹理绑定,着色器程序,深度测试设置,......也是相关的,但不要在这里关注这些。)。所有该状态实际上都封装在顶点数组对象(VAO)中。
使用OpenGL的状态机设计,状态保持不变,除非明确更改。由于您似乎只绘制了一个对象并且从不需要不同的attrib指针或元素数组,因此您只需将它们设置一次并将render()
方法简化为glDrawElements()
调用即可。这当然假设渲染循环中没有其他代码可以影响状态变化。
值得注意的一点是:VAO确实存储了每个属性数组的启用,因此您的第2步属于VAO初始化,而第4步在此方案中完全没用。
这也意味着当你想管理不同的对象时,你可以为每个对象创建一个VAO,VBO和EBO,你的渲染方法只是遍历对象,设置适当的VAO,并发出绘制调用: / p>
for every object obj
glBindVertexArray(obj.vao);
glDrawElements(...values depending on obj...);
绑定VAO 0在现代OpenGL中实际上从未严格要求。在绘制调用时,您将始终必须绑定一些VAO,因此您最终必须再次绑定非0 VAO。 unbinding 提供的唯一值是它可以防止对某些对象的意外更改。由于传统的OpenGL API总是使用 biding targets 的间接来修改对象,因此可以创建绑定对象的情况,这些对象当时不应被绑定,导致难以调试之间的错误行为。显然不相关的代码部分。