- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我希望有人能帮助我在我在 OpenGL ES 2.0 和 iPhone 4 上做的一些纹理基准测试中取得一些进展。
我有一个包含 Sprite 对象的数组。渲染循环循环遍历每个纹理的所有 Sprite ,并检索它们的所有纹理坐标和顶点坐标。它使用退化的顶点和索引将它们添加到一个巨大的交错数组中,并将它们发送到 GPU(我嵌入的代码在底部)。这一切都是按纹理完成的,所以我绑定(bind)一次纹理,然后创建我的交错数组,然后绘制它。一切都很好,屏幕上的结果也正是它们应有的样子。
所以我的基准测试是通过在不同的不透明度下每次触摸添加 25 个新 Sprite 并在更新时更改它们的顶点,以便它们在旋转时在屏幕上弹跳并在应用程序上运行 OpenGL ES Analyzer。
在这里我希望得到一些帮助......我可以得到大约 275 个 32x32 的 Sprite ,它们具有不同的不透明度,以 60 fps 的速度在屏幕上弹跳。到 400 帧时,我的帧率下降到 40 fps。当我运行 OpenGL ES Performance Detective 时,它告诉我...
The app rendering is limited by triangle rasterization - the process of converting triangles into pixels. The total area in pixels of all of the triangles you are rendering is too large. To draw at a faster frame rate, simplify your scene by reducing either the number of triangles, their size, or both.
事情是我刚刚在 cocos2D 中使用 CCSpriteBatchNode 使用相同的纹理进行了测试,并创建了 800 个透明 Sprite ,帧速率很容易达到 60fps。
下面是一些可能相关的代码...
Shader.vsh(一开始就设置一次矩阵)
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * position;
texCoordOut = texCoordIn;
colorOut = colorIn;
}
Shader.fsh(colorOut用于计算不透明度)
void main()
{
lowp vec4 fColor = texture2D(texture, texCoordOut);
gl_FragColor = vec4(fColor.xyz, fColor.w * colorOut.a);
}
VBO 设置
glGenBuffers(1, &_vertexBuf);
glGenBuffers(1, &_indiciesBuf);
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(TDSEVertex)*12000, &vertices[0].x, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(8));
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(16));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indiciesBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*12000, indicies, GL_STATIC_DRAW);
glBindVertexArrayOES(0);
更新代码
/*
Here it cycles through all the sprites, gets their vert info (includes coords, texture coords, and color) and adds them to this giant array
The array is of...
typedef struct{
float x, y;
float tx, ty;
float r, g, b, a;
}TDSEVertex;
*/
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuf);
//glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices[0])*(start), sizeof(TDSEVertex)*(indicesCount), &vertices[start]);
glBufferData(GL_ARRAY_BUFFER, sizeof(TDSEVertex)*indicesCount, &vertices[start].x, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
渲染代码
GLKTextureInfo* textureInfo = [[TDSETextureManager sharedTextureManager].textures objectForKey:textureName];
glBindTexture(GL_TEXTURE_2D, textureInfo.name);
glBindVertexArrayOES(_vertexArray);
glDrawElements(GL_TRIANGLE_STRIP, indicesCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(start));
glBindVertexArrayOES(0);
这是 400 个 Sprite (800 个三角形 + 800 个退化三角形)的屏幕截图,可以了解纹理移动时的不透明度分层......我应该再次注意到,正在为每个纹理创建和发送一个 VBO,因此我绑定(bind)然后每帧只绘制两次(因为只有两个纹理)。
抱歉,如果这是压倒性的,但这是我在这里发表的第一篇文章,希望内容详尽。任何帮助将不胜感激。
PS,我知道我可以只使用 Cocos2D 而不是从头开始编写所有内容,但是其中的乐趣(和学习)在哪里?!
更新#1当我将片段着色器切换为仅是
gl_FragColor = texture2D(texture, texCoordOut);
它以 50fps 的速度达到 802 个 Sprite (4804 个三角形,包括退化三角形),尽管设置 Sprite 不透明度丢失了。关于我如何在不以 1/4 速度运行的情况下仍然处理我的着色器中的不透明度有什么建议吗?
更新#2所以我放弃了 GLKit 的 View 和 View Controller ,并编写了一个从 AppDelegate 加载的自定义 View 。 902 个 Sprite ,不透明度和透明度为 60fps。
最佳答案
主要是杂念……
如果您的三角形有限,请尝试从 GL_TRIANGLE_STRIP
切换到 GL_TRIANGLES
。您仍然需要指定完全相同数量的索引——每个四边形六个——但 GPU 永远不必发现四边形之间的连接三角形退化(即,它永远不必将它们转换为零像素)。您需要进行概要分析,看看您最终是否会因为不再隐式共享边而付出代价。
您还应该缩小顶点的足迹。我敢想象您可以将 x、y、tx 和 ty 指定为 16 位整数,并将您的颜色指定为 8 位整数,而不会在渲染中产生任何明显的变化。这会将每个顶点的占用空间从 32 字节(八个组件,每个组件的大小为四个字节)减少到 12 字节(四个两字节值加上四个一字节值,不需要填充,因为所有内容都已经对齐)——削减几乎63% 的内存带宽成本都在那里。
由于您实际上似乎受到填充率的限制,因此您也应该考虑您的源纹理。您可以采取任何措施来减少其字节大小,这将直接有助于提取纹素,从而提高填充率。
看起来您正在使用有意识地关注像素的艺术,因此切换到 PVR 可能不是一种选择。也就是说,人们有时没有意识到 PVR 纹理的全部好处;例如,如果你切换到每像素 4 位模式,那么你可以将图像放大两倍宽和两倍高,以减少压缩伪影,并且仍然只在每个源像素上支付 16 位,但可能会得到比 16 bpp RGB 纹理更好的亮度范围。
假设您当前正在使用 32 bpp 纹理,您至少应该看看普通的 16 bpp RGB 纹理是否足以使用任何提供的硬件模式(尤其是如果 1 位 alpha 加上每个颜色 channel 5 位是适合您的艺术作品,因为与原始作品相比,它仅损失了 9 位颜色信息,同时将带宽成本降低了 50%)。
看起来您也在每一帧上传索引。仅当您将额外的对象添加到场景或上次上传的缓冲区比需要的大得多时才上传。您可以只限制传递给 glDrawElements
的计数以减少对象而无需重新上传。您还应该通过将顶点上传到 VBO 来检查您是否真的获得了任何东西,然后如果它们只是改变每一帧则重新使用它们。直接从客户端内存中提供它们可能会更快。
关于ios - 优化 openGL ES 2.0 2D 纹理输出和帧率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9780579/
我使用 QBFC v13 和 Delphi XE6。 目标是从我的应用程序创建 Estimate 并将其参数设置到 QuickBooks 中。 我从 QBFC13 导入类型库并将其添加到我的项目中。
我有一个数据库,其中有很多格式不正确的地址。在这个地址中,我只有一个街道地址或带有城市名称的街道。在我的应用程序中,用户选择一些类别,然后我想在 map 上显示例如 50,100,300 等地址。(不
在大多数软件项目中,缺陷源自需求、设计、编码和缺陷更正。根据我的经验,大多数缺陷都源于编码阶段。 我有兴趣了解软件开发人员使用哪些实用方法来降低缺陷注入(inject)率。 我已经看到以下方法的使用取
我正在使用实时 API 中的标签订阅构建一个应用程序,并且有一个与容量规划相关的问题。我们可能有大量用户同时发布到订阅的主题标签,因此问题是 API 实际发布到我们的订阅处理端点的频率是多少?例如,如
尝试使用 NULLIF 或 IFNULL 函数,但仍收到被零除的消息。 SELECT client_id ,COUNT(distinct CASE WHEN status = 'failed' THE
我目前正在开发一个使用 Django-rest-framework 制作的 API。我必须根据每个用户组设置限制率。 我们目前使用默认配置的 memcached 作为缓存后端,即按站点缓存。 在使用
我认为有时在神经网络(特别是一般对抗网络)训练期间改变丢失率可能是一个好主意,从高丢失率开始,然后线性地将丢失率降低到零。您认为这有意义吗?如果是的话,是否有可能在 tensorflow 中实现这一点
我有一个 Windows Server 2008,Plesk 运行着两个网站。有时服务器运行缓慢,并且有一个 named.exe 进程使 CPU 峰值达到 100%。它持续很短的时间,过一会儿它又来了
我正在使用 scikit-learn 随机森林分类器,我想通过将成功投票所需的树数量从大于 50% 增加到 75% 来降低 FP 率,在阅读文档后我不这样做确定如何做到这一点。有没有人有什么建议。 (
当我连续按下按键事件(字母 k)时,为什么以下按键事件不会减慢 3000 密耳?如果我按住手指,计数会迅速增加,因为 mcount 上没有 setTimeout。这是为什么?每次计数之间应该有延迟,但
我是一名优秀的程序员,十分优秀!