OpenGL ES - 如何使用/不同的 Alpha、旋转和比例批量渲染 500 多个粒子?

2023-12-20

我正在开发一款 iOS 游戏,需要一次渲染 500-800 个粒子。我了解到,在 OpenGL ES 中批量渲染许多精灵而不是调用是一个好主意glDrawArrays(..)在游戏中的每个精灵上,以便能够渲染更多精灵而不大幅降低帧速率。

我的问题是: 我如何batch渲染 500 多个粒子,它们都具有不同的 Alpha、旋转和比例,但共享相同的纹理图集?这个问题的重点在于不同的 alphas, 旋转, and scales对于每个粒子。

我意识到这个问题非常类似于如何在 iPhone OpenGL ES 粒子系统中绘制 1000 多个粒子(具有独特的旋转、缩放和 Alpha)而不减慢游戏速度? https://stackoverflow.com/questions/7435123/how-do-i-draw-1000-particles-w-unique-rotation-scale-and-alpha-in-iphone-o然而,这个问题并没有解决批量渲染的问题。在利用顶点缓冲区对象之前,我想了解 OpenGL ES 中的批量渲染,以及独特的 alpha、旋转和缩放(但具有相同的纹理)。因此,虽然我计划最终使用 VBO,但我想首先采用这种方法。

代码示例将不胜感激,如果您像某些示例一样使用索引数组,请解释索引数组的结构和用途。

EDIT我正在使用 OpenGL ES 1.1。

EDIT下面是我如何渲染场景中每个粒子的代码示例。假设它们共享相同的纹理,并且在执行此代码之前该纹理已绑定在 OpenGL ES 1.1 中。

- (void) render {

    glPushMatrix();

    glTranslatef(translation.x, translation.y, translation.z);

    glRotatef(rotation.x, 1, 0, 0);
    glRotatef(rotation.y, 0, 1, 0);
    glRotatef(rotation.z, 0, 0, 1);

    glScalef(scale.x, scale.y, scale.z);

    // change alpha
    glColor4f(1.0, 1.0, 1.0, alpha);

    // glBindTexture(GL_TEXTURE_2D, texture[0]);

    glVertexPointer(2, GL_FLOAT, 0, texturedQuad.vertices);
    glEnableClientState(GL_VERTEX_ARRAY);


    glTexCoordPointer(2, GL_FLOAT, 0, texturedQuad.textureCoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glPopMatrix();
}

此方法的替代代码将不胜感激!


一种可能性是将这些值包含在顶点属性数组中 - 我认为这是最好的选择。如果您使用的是 OpenGL ES 1.1 而不是 2.0,那么您就无法使用此方法。顶点 attrib 数组允许您在每个顶点存储值,在这种情况下,您可以将 alpha 和旋转分别存储在它们自己的 attrib 数组中,并将它们传递给着色器glVertexAttribArray。然后着色器将使用 Alpha 进行旋转变换和颜色处理。

另一种选择是在 CPU 上进行旋转变换,然后将具有相似 alpha 值的粒子批处理到多个绘制调用中。此版本需要更多的工作,并且不会是单个绘制调用,但如果着色器不是一个选项,它仍然有助于优化。

注意:您链接到的问题还推荐了数组解决方案

EDIT:鉴于您的代码是 OpenGL ES 1.0,这里有一个使用的解决方案glColorPointer:

// allocate buffers to store an array of all particle data
verticesBuffer = ... 
texCoordBuffer = ...
colorBuffer = ...

for (particle in allParticles)
{
  // Create matrix from rotation
  rotMatrix = matrix(particle.rotation.x, particle.rotation.y, particle.rotation.z)
  // Transform particle by matrix
  verticesBuffer[i] = particle.vertices * rotMatrix

  // copy other data
  texCoordBuffer[i] = particle.texCoords;
  colorBuffer[i] = color(1.0, 1.0, 1.0, particle.alpha);
}

glVertexPointer(verticesBuffer, ...)
glTexCoordPointer(texCoodBuffer, ...)
glColorPointer(colorBuffer, ...)

glDrawArrays(particleCount * 4, ...);

此解决方案的一个很好的优化是共享每个渲染的缓冲区,这样您就不必在每一帧都重新分配它们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL ES - 如何使用/不同的 Alpha、旋转和比例批量渲染 500 多个粒子? 的相关文章

随机推荐

  • 如何使用 dplyr 将多列转变为新的多列

    我正在尝试将 3 列更改为更大表 包含更多列 中的 3 个新列 其中 3 个新列依赖于前 3 个现有列 第四个新列仅依赖于第四个现有列 基本上 我想在 3D 空间中旋转点的坐标 在 x y z 列中 并存储在新列 x rot y rot z
  • 安装 Python3 的 PySide

    当我尝试为 Python 3 6 安装 PySide 时 它 说它只兼容 Python 3 4 是否有任何解决方法可以为 Python 3 6 安装它 似乎仅支持以下 Python 版本 2 6 2 7 3 2 3 3 3 4 要获取最新的
  • HBase - java 中的 java.lang.NoClassDefFoundError

    我只是想使用 Java 与 Hbase 交互 import org apache hadoop conf Configuration import org apache hadoop hbase import org apache hado
  • 动态添加到 Highcharts

    我有一个 json 对象 我正在尝试将其添加到我的 highcharts 选项中 我可以通过 API 接收该对象 并将其传递给我的 highcharts 函数 但我无法将我的数据添加到它周围的静态数据中 var datas datas ge
  • 使用声明性数据绑定 ASP.NET 进行评估

    我一直在尝试使用声明性数据绑定 ASP NET 并与幕后发生的 魔法 作斗争 我如何让它在 ASP Net 2 0 中工作 这是在数据范围内FormView控制
  • 从提交历史记录中获取 GitHub 用户名

    我将一个存储库克隆到我的机器上 然后做了 git log 但在日志中 它显示了该人的全名和电子邮件 而不是他们的 github 用户名 有没有一种方法可以在不依赖 GitHub 网站的情况下将提交与用户关联 如果你想使用 git log 似
  • Google Sheets 功能可对行进行分组和连接

    样本表 https docs google com spreadsheets d 1AeP0sxDi0 3aaesUdCNTKfricIimjTMFaKO FX9 g50 edit usp sharing https docs google
  • 如何使用 htaccess 从 url 中删除 GET 参数?

    我的网站除了一页之外不使用任何 GET 参数 尽管如此 我可以看到 Google 成功地使用 GET 参数索引了我的一堆页面 这对于 SEO 重复内容 来说不太好 因此 我尝试编辑 htaccess 以在所有带 GET 参数的 url 到不
  • 订阅我自己的 C# 事件会造成内存泄漏吗?

    如果基类发布 C 事件并且派生类订阅该事件 即订阅其自身 事件订阅会阻止对象被垃圾收集吗 或者垃圾收集器是否足够聪明来检测这种循环引用情况 乍一看 似乎应该如此 但我很确定我已经看到了执行此操作的控制代码 这是一个如此基本的问题 我不敢相信
  • 在 jquery 中获取数据绑定值

    我正在使用 knockout js 设置跨度值 HTML 代码 span span 这工作正常并在用户界面上显示用户名 我正在尝试从 js 文件中获取该值 使用下面的代码 alert this attr data bind 这是这样的服务结
  • 调整 UITextField 或 UITextView 出现键盘时的界面

    我有一个表格 每个单元格都包含一个标签和一个文本字段 问题是 当我去编辑最后一行时 键盘隐藏了表格的下部 我看不到正在输入的内容 如何将界面移动到键盘上方以便看到正在输入的内容 谢谢 穆斯塔法 你需要注册你的 viewControllerU
  • Android + 致命异常:Timer-0(使用计时器删除 ImageView)

    在我的 Android 应用程序中 我使用计时器来使用 TIMER 显示相应的 ImageView 我收到一个错误 02 27 06 39 33 999 E AndroidRuntime 1325 FATAL EXCEPTION Timer
  • UISegmentedControl 选择的索引始终为 0?

    我有一个 UISegmentedControl 它有 6 个段 是我在 Interface Builder 中创建的 我在值更改时调用以下方法 IBAction segmentedChartButtonChanged id sender s
  • appView.addJavascriptInterface() 不适用于 API 17

    我可以使用我的phonegap java脚本函数和android 2 2中的java函数 但相同的代码不在 API 17 上运行 我应该做什么才能从 API 17 中的 java 脚本调用本机 java 代码 我在我的java文件中使用这个
  • JAXB 解组中 XML 中的命名空间存在问题

    我有一个 XML 需要使用 JAXB 进行解组 如果我从元素中删除所有命名空间属性 则代码可以正常工作 但如果保留命名空间属性 则在解组后会得到一个空对象 XML 是这样的
  • 不允许使用 POST 动词

    有点基本 但我尝试了一些方法来解决以下错误 但无法得到正确的解决方案
  • 如何在 javascript 中使用 clojurescript 的复杂返回对象

    我想编写一个 clojurescript 函数 它返回一个复杂的项目 例如 foo bar 或 list foo bar 并且我希望能够从 javascript 调用此函数并获取返回值 如何做呢 就我而言 我要返回的向量 列表 集合中的项目
  • 将字符串/字符转换为C++中的类成员/方法

    有没有办法将字符串或字符转换为类成员 成员函数以动态访问它们 对于前 这个特定的代码 include
  • Adb 安装失败:INSTALL_CANCELED_BY_USER

    我尝试通过 adb 安装应用程序并收到错误 adb d install Users dimon Projects one place myprogram platforms android build outputs apk android
  • OpenGL ES - 如何使用/不同的 Alpha、旋转和比例批量渲染 500 多个粒子?

    我正在开发一款 iOS 游戏 需要一次渲染 500 800 个粒子 我了解到 在 OpenGL ES 中批量渲染许多精灵而不是调用是一个好主意glDrawArrays 在游戏中的每个精灵上 以便能够渲染更多精灵而不大幅降低帧速率 我的问题是