我已经使用 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,这对于这么简单的游戏来说是难以接受的。
我能做些什么来挽救我的表现?