Opengl es 为什么雪碧配料器更快?
我现在正在读(马里奥·泽克纳) 在阅读OpenGL ES 1.0的2D游戏时,作者介绍了SpriteBatcher的概念,它为每个精灵提供坐标和角度。SpriteBatcher然后计算sprite矩形的最终坐标,并将其放入单个大缓冲区 在渲染方法中,SpriteBatcher为所有精灵设置一次状态(纹理、混合、顶点缓冲区、纹理坐标缓冲区)。所有精灵使用相同的纹理,但不使用相同的纹理坐标 这种行为的优点是:Opengl es 为什么雪碧配料器更快?,opengl-es,Opengl Es,我现在正在读(马里奥·泽克纳) 在阅读OpenGL ES 1.0的2D游戏时,作者介绍了SpriteBatcher的概念,它为每个精灵提供坐标和角度。SpriteBatcher然后计算sprite矩形的最终坐标,并将其放入单个大缓冲区 在渲染方法中,SpriteBatcher为所有精灵设置一次状态(纹理、混合、顶点缓冲区、纹理坐标缓冲区)。所有精灵使用相同的纹理,但不使用相同的纹理坐标 这种行为的优点是: 渲染管道不会暂停,因为渲染所有精灵时没有状态更改 OpenGL调用更少。(=更少的JNI
- 渲染管道不会暂停,因为渲染所有精灵时没有状态更改
- OpenGL调用更少。(=更少的JNI开销)
- 对于旋转,CPU必须计算正弦和余弦,并对每个精灵执行16次乘法。据我所知,计算正弦和余弦是非常昂贵和缓慢的
- 为什么速度更快?OpenGL状态更改真的那么昂贵吗
- GPU针对矢量乘法和旋转进行了优化,而CPU则没有。为什么这不重要
- 有人会在带有专用GFX卡的桌面上使用SpriteBatcher吗
- SpriteBatcher是否存在效率低下的问题
- 它更快,因为它使用更少的状态更改,更重要的是,使用更少的draw调用。移动平台对每帧的抽奖呼叫数有特别严格的限制
- 这并不重要,因为他们可能正在使用CPU进行旋转。一、 就个人而言,没有理由不使用GPU,这将大大加快速度并消除带宽负载
- 考虑到第1点,我想这仍然是一个很好的优化
- 我可以想到两种极端情况:精灵太少,或者合成纹理(包含所有旋转的精灵)变得太大(移动设备的大小限制较低)
- 对于旋转,CPU必须计算正弦和余弦,并对每个精灵执行16次乘法。据我所知,计算正弦和余弦是非常昂贵和缓慢的
/* populates the currently bound VBO with sprite geometry */
void populate_sprites_VBO(std::vector<vec3> sprite_positions)
{
GLfloat mv[16];
GLfloat sprite_left[3];
GLfloat sprite_up[3];
glGetMatrixf(GL_MODELVIEW_MATRIX, mv);
for(int i=0; i<3; i++) {
sprite_left[i] = mv[i*4];
sprite_up[i] = mv[i*4 + 4];
}
std::vector<GLfloat> sprite_geom;
for(std::vector<vec3>::iterator sprite=sprite_positions.begin(), end=sprite_positions.end();
sprite != end;
sprite++ ){
sprite_geom.append(sprite->x + (-sprite_left[0] - sprite_up[0])*sprite->scale);
sprite_geom.append(sprite->y + (-sprite_left[1] - sprite_up[1])*sprite->scale);
sprite_geom.append(sprite->z + (-sprite_left[2] - sprite_up[2])*sprite->scale);
sprite_geom.append(sprite->x + ( sprite_left[0] - sprite_up[0])*sprite->scale);
sprite_geom.append(sprite->y + ( sprite_left[1] - sprite_up[1])*sprite->scale);
sprite_geom.append(sprite->z + ( sprite_left[2] - sprite_up[2])*sprite->scale);
sprite_geom.append(sprite->x + ( sprite_left[0] + sprite_up[0])*sprite->scale);
sprite_geom.append(sprite->y + ( sprite_left[1] + sprite_up[1])*sprite->scale);
sprite_geom.append(sprite->z + ( sprite_left[2] + sprite_up[2])*sprite->scale);
sprite_geom.append(sprite->x + (-sprite_left[0] + sprite_up[0])*sprite->scale);
sprite_geom.append(sprite->y + (-sprite_left[1] + sprite_up[1])*sprite->scale);
sprite_geom.append(sprite->z + (-sprite_left[2] + sprite_up[2])*sprite->scale);
}
glBufferData(GL_ARRAY_BUFFER,
sprite_positions.size() * sizeof(sprite_positions[0]), &sprite_positions[0],
GL_DRAW_STREAM);
}
/*使用精灵几何体填充当前绑定的VBO*/
void填充精灵VBO(标准::矢量精灵位置)
{
glmv[16];
GLfloat sprite_左[3];
GLfloat sprite_up[3];
GLGETMARIxF(GLU模型视图矩阵,mv);
对于(int i=0;ix+(-sprite_left[0]-sprite_up[0])*sprite->scale);
精灵几何附加(精灵->y+(-sprite\u left[1]-sprite\u up[1])*精灵->缩放);
精灵几何附加(精灵->z+(-sprite\u left[2]-sprite\u up[2])*精灵->缩放);
精灵几何附加(精灵->x+(精灵左[0]-精灵向上[0])*精灵->缩放);
精灵几何附加(精灵->y+(精灵左[1]-精灵向上[1])*精灵->缩放);
精灵几何附加(精灵->z+(精灵左[2]-精灵向上[2])*精灵->缩放);
精灵几何附加(精灵->x+(精灵左[0]+精灵上[0])*精灵->比例);
精灵几何附加(精灵->y+(精灵左[1]+精灵向上[1])*精灵->缩放);
精灵几何附加(精灵->z+(精灵左[2]+精灵向上[2])*精灵->缩放);
精灵几何附加(精灵->x+(-sprite\u left[0]+sprite\u up[0])*精灵->缩放);
精灵几何附加(精灵->y+(-sprite\u left[1]+sprite\u up[1])*精灵->缩放);
精灵几何附加(精灵->z+(-sprite\u left[2]+sprite\u up[2])*精灵->缩放);
}
glBufferData(GL_数组_缓冲区,
sprite_positions.size()*sizeof(sprite_positions[0]),&sprite_positions[0],
GL(绘制流);
}
如果着色器可用,则可以使用几何体着色器或顶点着色器,而不是在每个帧上重建精灵数据。几何体着色器将采用位置、比例、纹理等向量并发射四边形。使用顶点着色器可以发送大量[-1,1]四边形,其中每个顶点都会携带它所属精灵的中心位置作为附加的vec3属性
最后,我的问题是:
- 为什么速度更快?OpenGL状态更改真的那么昂贵吗
- GPU针对矢量乘法和旋转进行了优化,而CPU则没有。为什么这不重要