当前位置: 首页 > 知识库问答 >
问题:

打开GL 顶点数组缓冲区

太叔何平
2023-03-14

我正在努力学习LWJGL (OpenGL)不得不说我很艰难。

我试着在窗户上画一个三角形和一个四边形,最后我设法做到了。

但我还有一个问题
如果您觉得这个问题很愚蠢,请提前表示歉意,但我在网上找不到非常详细的html" target="_blank">教程,所以很难理解,因为这是我第一次使用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的速度运行。< br >这意味着渲染方法每秒钟被游戏循环调用60次。

该渲染方法的步骤是:

    < Li > < code > glBindVertexArray(vaoId) < Li > < code > glEnableVertexAttribArray(0) < li >绘制四边形 < Li > < code > glDisableVertexAttribArray(0) < Li > < code > glBindVertexArray(0)

我的问题是:是否每次都需要调用步骤1、2、4和5?如果是,为什么?

同样的问题也适用于< code>init()方法的最后一行(< code > glBindVertexArray(0))。


对不起,我的英语不是我的母语。

共有1个答案

管翼
2023-03-14

我的问题是:是否每次都需要调用步骤1、2、4和5?如果是,为什么?

不,不是。OpenGL被设计为状态机。您有一个包含全局状态和您创建的对象(如VAO、VBO)的GL上下文。对象本身可以包含数据和每个对象的状态。重要的是在某些特定GL函数调用时设置的状态,该状态在某种程度上取决于其中一些状态值。

在<code>glDrawElements()绑定与为绘制调用提供输入数据相关。(影响绘图的所有其他状态,如纹理绑定、着色器程序、深度测试设置等,也都是相关的,但此处不重点讨论这些。)。所有这些状态实际上都封装在顶点阵列对象(VAO)中。

使用OpenGL的状态机设计,状态保持不变,除非它被明确更改。由于您似乎只绘制一个对象并且永远不需要不同的attrib指针或元素数组,因此您只需设置一次并将您的渲染()方法简化为glDrawElements()调用。这当然假设渲染循环中没有其他代码会影响状态更改。

值得注意的一点是:VAO确实存储每个属性的启用数组,因此步骤2属于VAO初始化,而步骤4在此方案中完全无用。

这也意味着,当您想要管理不同的对象时,可以为每个对象创建VAO、VBO和EBO,而渲染方法只需在对象上循环,设置适当的VAO,并发出绘制调用:

for every object obj
    glBindVertexArray(obj.vao);
    glDrawElements(...values depending on obj...);

绑定VAO 0实际上在现代OpenGL中从未严格要求过。在调用绘制时,您始终必须绑定一些 VAO,因此您最终必须在以后再次绑定非 0 VAO。这种解除绑定提供的唯一价值是它可以防止对某些对象进行意外更改。由于传统的OpenGL API总是使用竞价目标的间接性来修改对象,因此可以创建当时不应绑定的对象的情况,从而导致难以调试明显不相关的代码部件之间的不当行为。

 类似资料:
  • 下面的lwjgl3代码设置缓冲区等,用于呈现三角形。我能看到三角形。现在我正努力弄明白到底是怎么回事。 下面是我对代码的理解。我们首先创建一个顶点缓冲区对象,它只是一个数组的容器。glBindBuffer()和glBufferData()使用顶点数组填充顶点缓冲区对象。我们再次对第二个顶点数组执行此操作。然后我们编译顶点和片段着色器,并将它们添加到着色器程序中。不知怎么的,这个程序访问第二个顶点缓

  • 我正在努力理解这两个,如何使用它们,以及它们是如何联系的。假设我想创建一个简单的地形和一个有纹理的立方体。对于这两个对象,我有三角形、顶点的数组,对于立方体,我有一个包含纹理数据的数组。我的问题是:我如何使用VAOs和VBOs来创建和呈现这两个? null

  • 我目前正在使用LWJGL / OpenGL创建一个2D,自上而下的游戏,但是在绘制实体之后,在使用顶点缓冲区对象渲染实体后,在让它们四处移动的过程中,我遇到了一些问题。这是渲染线程的 run() 方法,以及设置方法: 实体从抽象超类继承这些方法来设置 VBO 并绘制实体(呈现线程中的 drawEntities 方法仅调用该方法,实体更新方法(见下文),而 setUpEntities 调用 setU

  • 我正在尝试从ArrayList读取并创建VBO,然后对其进行渲染。问题是我只是渲染了一个空白屏幕。当我立即渲染时,一切都很好;只有现在VBO的才不起作用。 游戏循环如下所示,相机调用glTranslate和glRotate函数。 渲染方法: 阵列列表具有顶点和链接的颜色。每个体素将其顶点添加到ArrayList(而不是立即渲染)。

  • 我想做一个OpenGL游戏,但现在意识到我在学校学到的- 1)我应该使用OpenGL的glDrawArray还是glDrawElements? 2) 对于具有多个实体/场地/对象的游戏,渲染函数必须是多个glDrawArrays(): 或者只有一个glDrawArrays()封装每个实体: 3)每个图形层(如DirectX)现在都标准化顶点缓冲区对象吗?

  • null null null 在原始OpenGL中这样做虽然简单,但如果为单个缓冲区设置了许多属性,就会失去控制。我想我可以简化调用属性函数的过程,使用具有如下API的可变模板: 然而,这是不可行的,因为模板参数(AFAIK)实际上不是可变的,而是只能使参数可变。我不想使用函数参数的原因是,我希望能够输入C++关键字和,它们不能用作参数。我目前的解决方案是将参数与重复基本类型的枚举一起使用,例如和