gpt4 book ai didi

iphone - 如何在 iOS 上的 OpenGL ES 1.0 中使用顶点缓冲对象 (VBO) 而不是调用 glDrawArrays 数千次?

转载 作者:行者123 更新时间:2023-11-28 19:21:49 26 4
gpt4 key购买 nike

为了进行模拟,我们创建了一个带有 32 x 48 矩形网格的 OpenGL1.1 View 。

每次 CADisplayLink 调用我们的绘制函数时,我们都会绘制此网格,并且顶点位置永远不会改变。帧与帧之间唯一变化的是顶点的颜色。

这是我们如何做的一个简化示例:

- (void)drawFrame {
// draw grid
for (int i = 0; i < numRectangles; i++) {
// ... calculate CGPoint values for vertices ...

GLshort vertices[ ] = {
bottomLeft.x, bottomLeft.y,
bottomRight.x, bottomRight.y,
topLeft.x, topLeft.y,
topRight.x, topRight.y
};

glVertexPointer(2, GL_SHORT, 0, vertices);
glColor4f(r, g, b, 1);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}

OpenGL 仪器推荐使用顶点缓冲对象 (VBO) 以获得更好的性能。

是否有示例说明在顶点不随帧变化的情况下如何设置顶点缓冲区对象的非常基本、简单的用法?

Apple 正在提供示例 over here, under the section Use Vertex Buffer Objects to Manage Copying Vertex Data , 但它是不完整的。

GLuint    vertexBuffer;
GLuint indexBuffer;

void CreateVertexBuffers()
{

glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

}

它没有显示如何真正创建数据。前面的 list (应该是一个“坏例子”)包含这两行:

const vertexStruct vertices[] = {...};
const GLubyte indices[] = {...};

因此必须将这两个数组或结构传递到:

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

?

根据 Apple 在 Use Interleaved Vertex Data 下的说法,这是 iOS 首选的“交错(结构数组)”格式吗? 部分?

最佳答案

您不应该使用 glDrawArrays 绘制单个基元,而是大批量绘制。到目前为止,您只使用了常规顶点数组,而不是顶点缓冲区对象。

想法是,将所有矩形的几何体放入一个 VBO(VBO 本质上是一个存储在“OpenGL”中的顶点数组,而不是您的进程)。使用 glBufferSubData 可以更改单个顶点。

顶点颜色可以放入顶点数组,因此也可以放入 VBO。

更新

假设你有一些六边形:

GLfloat vertices[2][] = {
{0, 0}, // 0
{1, 0}, // 1
{0.5, 0.866}, // 2
{-0.5, 0.866}, // 3
{-1, 0}, // 4
{0.5, -0.866}, // 5
{-0.5, -0.866}, // 6
};

并且您只想绘制三角形的一部分,比如由顶点 [0,1,2]、[0,3,4] 和 [0,5,6] 组成的三角形,那么您将创建以下索引数组

GLushort indices[] = {
0, 1, 2,
0, 3, 4,
0, 5, 6
};

并将其用作 glDrawElements 的索引。

更新2

许多计算机图形学和 OpenGL 新手都会犯的一个错误是,顶点不仅仅是一个位置,而且是顶点属性的组合。哪些属性构成顶点是程序员做出的设计选择。但是常用的顶点属性是

  • 职位
  • 正常
  • 纹理坐标
  • 顶点颜色

在 OpenGL-3 核心之前,position 属性是强制性的。由于 OpenGL-3 内核强制着色器,顶点属性只是着色器的任意输入数据,只要顶点着色器设法提供 *gl_Position* 输出,OpenGL 就会很高兴。

重要的是,只有在所有属性都相同的情况下,两个顶点才相同。如果它们仅在一个属性上不同,那么它们就不是同一个顶点。现在让我们以我们之前的六边形为例。我们现在正在制作红色、绿色和蓝色的三角形并且将添加两个三角形,将红色和绿色的三角形扩展成类似菱形的形状:

// x, y, red, green, blue
GLfloat vertices[5][] = {
// red
{0, 0, 1, 0, 0}, // 0
{1, 0, 1, 0, 0}, // 1
{0.5, 0.866, 1, 0, 0}, // 2
{1, 1, 1, 0, 0}, // 3

// green
{0, 0, 0, 1, 0}, // 4
{-0.5, 0.866, 0, 1, 0}, // 5
{-1, 0, 0, 1, 0}, // 6
{-1, 1, 0, 1, 0}, // 7

// blue
{0, 0, 0, 0, 1}, // 8
{0.5, -0.866, 0, 0, 1}, // 9
{-0.5, -0.866, 0, 0, 1}, // 10
};

我们现在要画的三角形是

GLushort indices[] = {
// the two red triangles
0, 1, 2,
3, 2, 1,

// the two green triangles
4, 5, 6,
5, 7, 6,

// the blue triangle
8, 9, 10
};

现在我们需要将顶点数组的结构告诉 OpenGL。这就是 gl…Pointer 函数的 stride 参数发挥作用的地方。如果非零,则步幅告诉 OpenGL 数组中每个顶点开始之间的距离(以字节为单位)。通过传递具有正确偏移量的 data 指针,这使得 OpenGL 可以访问正确的内容。在我们的例子中,一个顶点由

  • 2 个偏移量为 0 的 GLfloat 位置元素
  • GLfloat 的 3 个颜色元素,偏移量为 2*sizeof(GLfloat)

并且每个顶点相隔 sizeof(GLfloat)*5 字节。

我们将让 C 编译器为我们计算偏移量,方法是简单地取消引用正确的数组元素并获取它的地址:

glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*5, &vertices[0][0]);
glColorPointer(3, GL_FLOAT, sizeof(GLfloat)*5, &vertices[0][2]);

剩下的只是 glDrawElements(GL_TRIANGLES, 5, GL_UNSIGNED_SHORT, indices)

请注意,此时我们不使用 VBO,而仅使用客户端顶点数组。 VBO 建立在顶点数组之上。因此,我强烈建议您在处理 VBO 之前先牢牢掌握顶点数组。它们实际上很容易使用,但是有一些概念上的缺陷,比如欺骗编译器为指针参数传递一个数字。

关于iphone - 如何在 iOS 上的 OpenGL ES 1.0 中使用顶点缓冲对象 (VBO) 而不是调用 glDrawArrays 数千次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8329546/

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