gpt4 book ai didi

opengl - glVertexAttribPointer 和 glEnableVertexAttribArray 的作用域是什么?

转载 作者:行者123 更新时间:2023-12-04 18:43:50 25 4
gpt4 key购买 nike

我在 Android 上使用 OpenGL ES 2.0,但我认为这个问题是一个通用的 OpenGL 问题。

我正在学习 OpenGL,并试图准确了解每一帧必须调用哪些 API,而不是只调用一次。我最初调用 glVertexAttribPointerglEnableVertexAttribArray每一帧,但是当我将测试程序更改为每个着色器程序只调用一次时,我得到的行为不是我所期望的。

好像是 glVertexAttribPointerglEnableVertexAttribArray应该只需要调用一次,而不是每一帧,因为它们只在特定着色器程序的上下文中才有意义。我这么说是因为glVertexAttribPointer将其作为第一个参数 GLuint indexglGetAttribLocation 返回它指定与着色器程序中的变量名称对应的字符串。因此,数据似乎与特定着色器程序中的特定“属性”变量相关联。

我的测试程序使用两个完全不同的程序渲染两个不相交的形状(三角形) - 不同的片段着色器源,不同的顶点着色器源,对 glLinkProgram 的单独调用等等。我最初为每一帧运行了以下代码,一切都按预期工作——我看到两个形状都正确渲染了。

m_glhook.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

// Shape/Program 1
m_glhook.glUseProgram(m_iGlProgramId);
int iPositionLocation = m_glhook.glGetAttribLocation(m_iGlProgramId, "a_Position");
m_bfVertices.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices);
m_glhook.glEnableVertexAttribArray(iPositionLocation);
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

// Shape/Program 2
m_glhook.glUseProgram(m_iGlProgramId2);
int iPositionLocation2 = m_glhook.glGetAttribLocation(m_iGlProgramId2, "a_Position");
m_bfVertices2.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation2, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices2);
m_glhook.glEnableVertexAttribArray(iPositionLocation2);
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

然后我修改了对每一帧的调用,如下所示。 m_bFirstDraw第一帧为真,后续帧为假。
m_glhook.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

// Shape/Program 1
m_glhook.glUseProgram(m_iGlProgramId);
if (m_bFirstDraw)
{
int iPositionLocation = m_glhook.glGetAttribLocation(m_iGlProgramId, "a_Position");
m_bfVertices.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices);
m_glhook.glEnableVertexAttribArray(iPositionLocation);
}
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

// Shape/Program 2
m_glhook.glUseProgram(m_iGlProgramId2);
if (m_bFirstDraw)
{
int iPositionLocation2 = m_glhook.glGetAttribLocation(m_iGlProgramId2, "a_Position");
m_bfVertices2.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation2, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices2);
m_glhook.glEnableVertexAttribArray(iPositionLocation2);
}
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
m_bFirstDraw = false;

我在上面的代码中看到的行为是,对于第一帧,一切都很好(这是有道理的,因为对于第一帧,调用序列完全相同)。但是对于连续的帧,Shape1 是用 Shape2 的顶点绘制的。所以我只看到 Shape2,因为它完全绘制在 Shape1 之上。

请帮助我理解这一点......为什么为一个程序设置数据(形状顶点)会影响另一个程序在连续帧中使用的数据?我错过了一些东西...

最佳答案

尽管 GLSL 程序(尤其是顶点着色器)使用基于通用槽号的顶点属性,但您实际上并没有为 GLSL 程序提供顶点指针。

这些指针是顶点数组状态的一部分,在较新版本的 OpenGL 中完全由 Vertex Array Objects 处理。 .如果您希望每个程序都有自己的一组指针,我建议您创建一个 VAO 来存储状态并在绑定(bind)程序时绑定(bind) VAO。

如果 VAO 不可用,则每次切换 GLSL 程序时都必须手动设置指针。请注意,在这种情况下,有一个全局上下文,其中存储了顶点数组指针、绑定(bind)的顶点缓冲区、启用/禁用的数组等。所以你必须小心禁用你不使用的顶点属性数组,否则你可能会导致 GL 从无效内存中读取。

VAO 是一个更优雅的解决方案,只要它们可用,您就应该喜欢它们。

关于opengl - glVertexAttribPointer 和 glEnableVertexAttribArray 的作用域是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18645148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com