14

我已经使用 lwjgl (opengl) 成功实现了一个简单的二维游戏,其中对象随着远离玩家而逐渐消失。这种淡化最初是通过计算从玩家到每个对象的原点的距离并使用它来缩放对象的 alpha/opacity 来实现的。

然而,当使用较大的对象时,这种方法显得有点过于粗糙。我的解决方案是为对象中的每个像素实现 alpha/opacity 缩放。这不仅看起来更好,而且还将计算时间从 CPU 转移到 GPU。

我想我可以使用 FBO 和临时纹理来实现它。
通过绘制到 FBO 并使用特殊的混合模式使用预先计算的距离图(纹理)对其进行遮罩,我打算实现这种效果。算法是这样的:

0) 初始化 opengl 并设置 FBO
1) 将背景渲染到标准缓冲区
2) 切换到自定义 FBO 并清除它
3) 渲染对象(到 FBO)
4) 使用距离纹理遮罩 FBO
5) 切换到标准缓冲区
6) 临时渲染 FBO纹理(到标准缓冲区)
7)渲染 hud 元素

一些额外的信息:

  • 临时纹理具有与窗口相同的大小(因此是标准缓冲区)
  • 第4步使用特殊的混合模式来达到想要的效果:
    GL11.glBlendFunc(GL11.GL_ZERO, GL11.GL_SRC_ALPHA);
  • 我的临时纹理是使用 min/mag 过滤器创建的:GL11.GL_NEAREST
  • 数据分配使用: org.lwjgl.BufferUtils.createByteBuffer(4 * width * height);
  • 纹理初始化使用: GL11.glTexImage2D( GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, dataBuffer);
  • 我的代码中没有 GL 错误。

这确实达到了预期的结果。然而,当我进行一些性能测试时,我发现我的 FBO 方法会削弱性能。我通过请求 1000 次连续渲染并测量时间来进行测试。结果如下:

在 512x512 分辨率下:

  • 正常:~1.7s
  • FBO:~2.5s
  • (FBO - 第 6 步:~1.7 秒)
  • (FBO - 第 4 步:~1.7 秒)

在 1680x1050 分辨率下:

  • 正常:~1.7s
  • FBO:~7s
  • (FBO - 第 6 步:~3.5 秒)
  • (FBO - 第 4 步:~6.0s)

正如你所看到的,这真的很糟糕。更糟糕的是,我打算做第二次这种类型的传球。就我的目标受众而言,我测试的机器应该是高端的,所以我可以预期人们使用这种方法的帧率远低于 60 fps,这对于这么简单的游戏来说是难以接受的。

我能做些什么来挽救我的表现?

4

1 回答 1

5

正如 Damon 和 sidewinderguy 所建议的,我使用片段着色器(和顶点着色器)成功地实现了类似的解决方案。我的性能比我最初的基于 cpu 运行的基于对象的计算要好一点,这比我的 FBO 方法快得多。同时,它提供了更接近 FBO 方法的视觉结果(重叠对象的行为有点不同)。

对于任何感兴趣的人,片段着色器基本上都会转换 gl_FragCoord.xy 并进行纹理查找。我不确定这是否提供了最佳性能,但仅激活了 1 个其他纹理,我不希望通过省略查找和直接计算纹理值来提高性能。此外,我现在不再有性能瓶颈,因此应该等到发现需要进一步优化。

此外,我非常感谢我收到的所有帮助、建议和意见 :-)

于 2011-05-10T07:55:45.660 回答