- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在阅读Beginning Android Games (马里奥·泽克纳)目前。
在阅读有关使用 OpenGL ES 1.0 的 2D 游戏时,作者介绍了 SpriteBatcher 的概念,它为每个 Sprite 渲染坐标和角度。然后 SpriteBatcher 计算 Sprite 矩形的最终坐标并将其放入一个大缓冲区中。
在渲染方法中,SpriteBatcher一次为所有 Sprite 设置状态(纹理、混合、顶点缓冲区、纹理坐标缓冲区)。所有 Sprite 都使用相同的纹理,但纹理坐标不同。
这种行为的优点是:
但我看到了一个主要缺点:
但是 SpriteBatcher 方法比使用大量 glRotate/glTranslate 逐一渲染 Sprite 要快得多。
最后我的问题:
最佳答案
But I see a major disadvantage:
- For rotation the CPU has to calculate the sine and cosine and perform 16 multiplication for each sprite. As far as I know calculating sine and cosine is very expensive and slow.
实际上,sin 和 cos 非常快,在现代架构上,如果管道之前没有停止过,它们需要 1 个时钟周期来执行。然而,如果每个 Sprite 单独旋转并使用普通的平截头体透视投影,则此代码的作者不知道他的线性代数。
如果有人记得模型 View 矩阵将线性局部/世界坐标图映射到眼睛空间,则整个任务可以简化很多。旋转位于左上方的 3×3 子矩阵中,该列形成局部基向量。通过取该子矩阵的倒数,您将获得所需的向量作为 Sprite 基础,以将平面映射到眼睛空间。如果仅应用旋转(可能还有缩放),则左上角 3×3 的逆是转置;因此,通过使用左上角的 3×3 行作为 Sprite 基础,您无需执行任何三角函数即可获得该效果:
/* 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);
}
如果着色器可用,则可以使用几何着色器或顶点着色器,而不是在每帧的 CPU 上重建 Sprite 数据。几何着色器将采用位置、比例、纹理等向量并发出四边形。使用顶点着色器,您将发送大量 [-1,1] 四边形,其中每个顶点将携带其所属 Sprite 的中心位置作为附加 vec3 属性。
Finally my questions:
- Why is it faster? Are OpenGL state changes really that expensive?
某些状态更改的成本极其高昂,您将尽可能避免这些情况。切换纹理非常昂贵,切换着色器则稍微昂贵。
- The GPU is optimized for vector multiplications and rotations, while the CPU is not. Why doesn't that matter?
这不是GPU和CPU之间的区别。 GPU 与 CPU 的不同之处在于,它并行地对大量记录(渲染到的帧缓冲区的每个像素)执行相同的操作序列。另一方面,CPU 一次运行一条记录。
但是 CPU 执行矢量运算的能力同样好,甚至比 GPU 还要好。特别是在精度很重要的情况下,CPU 仍然优于 GPU。 MMX、SSE 和 3DNow!是矢量数学指令集。
- Would one use a SpriteBatcher on a desktop with a dedicated GFX-card?
可能不是这种形式,因为现在可以使用几何和顶点着色器,从而解放 CPU 来处理其他事情。但更重要的是,这节省了 CPU 和 GPU 之间的带宽。带宽是更严格的瓶颈,处理能力并不是当今的第一个问题(当然处理能力永远不会足够)。
- Is there a point where the SpriteBatcher becomes inefficient?
是的,即CPU→GPU传输瓶颈。如今,人们使用几何着色器和实例来完成这种事情,速度非常快。
关于opengl-es - 为什么 Sprite Batcher 更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6677344/
您好,我有一个关于 Batcher 的奇偶合并排序的问题。我有以下代码: public class Batcher { public static void batchsort(int a[],
有没有人对 Batcher 的合并交换排序有很好的指导/解释? 这与 Batcher 的双调排序或 Batcher 的奇偶归并排序不是同一种算法,尽管许多文章假装它是同一种算法。 最佳答案 Donal
我试图掌握 Batcher Sort 的概念.但是,我在网上找到的大多数资源都完全侧重于证明或低级伪代码。在查看证明之前,我想了解 Batcher Sort 的工作原理。有人可以在没有过于冗长的伪代码
带有 MySQL 方言的 NHibernate 不支持开箱即用的批处理。我在 nuget 上找到了适用于 NHibernate 的自定义 MySQL Batcher。此外,以下是 github 链接:
我正在阅读Beginning Android Games (马里奥·泽克纳)目前。 在阅读有关使用 OpenGL ES 1.0 的 2D 游戏时,作者介绍了 SpriteBatcher 的概念,它为每
目前我了解到 batcher.draw 可以在屏幕上绘制 Assets 。它可用于在屏幕外绘制移动 Assets 。 我在想,如果 Assets 超过某个 x 值,是否无论如何都会让绘制的 Asset
这些天,我一直在尝试使用最少数量的比较交换单元实现大小为 32 的排序网络(在大小方面是最优的,而不是在深度方面) .截至目前,我已经能够使用以下资源来生成我的网络: 排序网络 0 到 16:Perl
我是一名优秀的程序员,十分优秀!