Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 绘制多个移动对象_Iphone_Ios_Opengl Es - Fatal编程技术网

Iphone 绘制多个移动对象

Iphone 绘制多个移动对象,iphone,ios,opengl-es,Iphone,Ios,Opengl Es,我目前正在做一个iOS游戏,长话短说,我需要画很多移动的立方体——每帧大约最多200个。重点放在移动上,因为是的,我确实已经在谷歌上搜索了好几个小时这个主题,还没有找到一个合适的解决方案来快速、高效地绘制多个对象,它们的位置每一帧都会更新 通过我对这一主题的无休止的研究,大多数人似乎都提到了VBOs,但我不确定这是否适合我的情况,即每一个对象的位置每一帧都会发生变化 目前我正在使用OpenGL 1-我有工作代码,在第3/4代+设备(支持OpenGL 2的设备,ha)上以合理的帧率运行-但是在我的

我目前正在做一个iOS游戏,长话短说,我需要画很多移动的立方体——每帧大约最多200个。重点放在移动上,因为是的,我确实已经在谷歌上搜索了好几个小时这个主题,还没有找到一个合适的解决方案来快速、高效地绘制多个对象,它们的位置每一帧都会更新

通过我对这一主题的无休止的研究,大多数人似乎都提到了VBOs,但我不确定这是否适合我的情况,即每一个对象的位置每一帧都会发生变化

目前我正在使用OpenGL 1-我有工作代码,在第3/4代+设备(支持OpenGL 2的设备,ha)上以合理的帧率运行-但是在我的(旧的,是的)第二代iPod touch上测试时,它非常缓慢,基本上无法播放

我的代码由一个“立方体”的静态顶点数组和一个包含每个立方体的位置和颜色的数组组成。我的游戏逻辑循环更新数组中每个立方体的位置。目前,我正在遍历多维数据集数组,为每个多维数据集调用glTranslatef和gldrawArray。从我所读到的来看,这是非常低效的,但是我完全不知道如何优化它。有什么想法吗


(也许我不应该把目标放在陈旧的、已经停产的iOS设备上,但鉴于我认为我的代码效率极低,我想不管我是否能找到解决这个问题的方法,这都会有助于我今后的工作)

你可以通过将所有多维数据集的坐标都放在一个数组中来进行优化,并通过一个glDrawArrays调用来绘制它

我不确定您为什么要将多维数据集拆分为单独的数组,可能是因为它使您的数据结构更加优雅/面向对象,但这是我首先考虑改进的地方


将多维数据集坐标转储到一个大数组中,并将每个多维数据集对象的索引放入该数组中,这样您仍然可以保持更新逻辑的划分(如中所示,多维数据集n拥有x到y范围内的坐标,并负责更新它们,但当您实际绘制坐标时,您可以直接在集中式坐标系数组上运行glDrawArrays,而不是在多维数据集对象中循环并单独渲染它们).

对于这样简单的对象,我会制作一个大型VBO,比如200个对象*nVerticeSPerCube,将所有数据交错放置在顶点、法线、UV、顶点、法线、UV等

在我的游戏中,我在海狸的关键帧动画中做了类似的事情,我从以下内容开始:

glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:@"beaver01" ofType:@"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
    memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat));        // 0
    vbo_buffer += 8*sizeof(GLfloat);
    counter++;
}
glUnmapBufferOES(GL_ARRAY_BUFFER); 
glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
    GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
这将创建具有正确大小的VBO缓冲区(在本例中为8*sizeof(GLfloat),即3个顶点、3个法线和2个UV),并将第一个关键帧复制到缓冲区,您可以对初始对象位置执行相同的操作,或者只需保留该操作并计算后一个

然后在每一帧中,我为我的海狸的每个顶点在两个关键帧之间进行插值,只需进行一次绘图调用,这对于我的海狸拥有的4029个顶点来说非常快,在我的iPhone 3G上以60FPS的速度工作

如果只做gltranslates,则更简单,只需将x、y、z的值添加到每个立方体的每个顶点

您将按如下方式更新它:

glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:@"beaver01" ofType:@"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
    memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat));        // 0
    vbo_buffer += 8*sizeof(GLfloat);
    counter++;
}
glUnmapBufferOES(GL_ARRAY_BUFFER); 
glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
    GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
将vbo缓冲区和mapit绑定到缓冲区变量。 在一个临时变量上计算你想要的东西

            memcpy(vbo_buffer, currentVert, 6*sizeof(GLfloat));        // 0
            vbo_buffer += 8*sizeof(GLfloat);
复制它并将缓冲区更新到下一个对象,重复,直到所有对象更新。。。 您也可以在一个单独的数组中执行所有更新并复制整个数组,但这样您将复制通常不会更改的额外信息(法线和UV)。或者您无法使用交错数据并复制该数据

        glUnmapBufferOES(GL_ARRAY_BUFFER);
取消映射VBO缓冲区

    glVertexPointer(3, GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL));
    glNormalPointer(GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
    glTexCoordPointer(2, GL_FLOAT,8*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat))); 
    glDrawArrays(GL_TRIANGLES, 0, beaverVerts);
设置你的绘图调用,然后全部绘图

如果您需要旋转对象,而不仅仅是平移对象,则需要在此过程中添加一些矩阵乘法

编辑**

好的,用手做一个gltranste其实很容易(旋转等有点棘手)

我使用的是一个交错的平面,用三角形而不是三角形绘制,但原理是一样的

  float beltInter[] = {
0.0, 0.0, 0.0,             // vertices[0]
0.0, 0.0, 1.0,             // Normals [0]
6.0, 1.0,                  // UV [0]
0.0, 480, 0.0,             // vertices[1]
0.0, 0.0, 1.0,             // Normals [1]
0.0, 1.0,                  // UV      [1]
320.0, 0.0, 0.0,           // vertices[2]
0.0, 0.0, 1.0,             // Normals [2]
6.0, 0.0,                  // UV      [2]
320.0, 480, 0.0,       // vertices[3]
0.0, 0.0, 1.0,             // Normals [3]
0.0, 0.0                   // UV      [3]
  };
这是交错的顶点,你们得到了顶点,然后是法线,然后是UV,若你们并没有用纹理代替UV的颜色

最简单的方法是有一个数组,里面有所有的对象(如果所有的对象都是一样大小的话就容易做),并且在绘制之后更新位置(而不是在OpenGL框架的中间),最好还是做一个分离的线程,创建2个VBOS,同时从另一个中提取其中一个,这样的东西:

glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:@"beaver01" ofType:@"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
    memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat));        // 0
    vbo_buffer += 8*sizeof(GLfloat);
    counter++;
}
glUnmapBufferOES(GL_ARRAY_BUFFER); 
glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
    GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
  • 线程1 OpenGL DrawFrom VBO0
  • 线程2游戏更新,更新内部数组上的位置并复制到VBO1,将变量设置为VBO1 yes ready(因此线程1仅在所有更新完成后从绘图更改为VBO1)
  • VBO1中的线程1 OpenGL绘图
  • 线程2游戏更新,同样的事情,但更新VBO0
  • 继续用同样的逻辑
这称为双缓冲,您可以使用它来提高稳定性,如果没有它,有时您的游戏逻辑将更新VBO,而图形卡需要它,图形卡将不得不等待,从而降低FPS

无论如何,回到话题上来

要使等效于gltranslatef(10,20,30),只需执行以下操作:

int最大顶点=4;
浮点数x=10;
浮动y=20;
浮点数z=30;
int计数器=0;
int stride=8;//步长为8=3 x垂直+3 x正常+2 x UV根据需要更改为3 x颜色或4 x颜色
glBindBuffer(GL_数组_BUFFER,vboObjects[myObjects]);
GLvoid*vbo_buffer=glMapBufferOES(GL_数组_buffer,GL_只写_-OES);
而(计数器<(最大顶点*8)){
beltInter[counter]+=x;//只需将每个计数器对应的值求和即可
beltInter[计数器+1]+=y;
beltInter[计数器+2]+=z;
memcpy(vbo_buffer,currentVert,3*sizeof(GLfloat));//再次只复制您需要的,在本例中只复制顶点,如果您正在更新所有数据,您只需执行以下操作