3

我正在尝试为我正在编写的 Java2D 等距游戏编写一些照明代码 - 我找到了一些我想尝试实现的算法 - 我在这里找到了其中一个:

这里

问题是这种算法需要一些最佳的像素着色效果,而我还没有找到通过 Java2D 实现的方法。最好是通过图形硬件的某种方法,但如果那是不可能的 - 至少是一种在软件中快速实现相同效果的方法。

如果那不可能,有人可以指导我使用 Java2D 的更优化算法吗?我已经考虑过按瓷砖照明 - 但是我发现 drawPolygon 方法不是硬件加速的,因此执行速度非常慢。

我想尝试避免本机依赖项或小程序中提升权限的要求。

谢谢

4

1 回答 1

2

自从我发布这个问题以来,我做了很多研究——有很多替代品,JavaFX 确实打算(在以后的版本中)为感兴趣的人包含自己的着色器语言。当然还有一个 LWJGL 允许您将自己的着色器加载到 GPU 上。

但是,如果您被困在 Java2D 中(就像我一样),仍然可以在等距游戏中实现光照,这只是“尴尬”,因为您无法在每个像素级别上执行光照着色。

它的外观:

我已经实现了(高度未抛光 - 经过一些抛光后,我可以向您保证它看起来很棒)效果,用于投射阴影、对光照贴图进行深度排序,以及在不降低帧速率的情况下应用光照。这是它的外观:

投射阴影和深度对光照贴图进行排序

你会在这个屏幕截图中看到一个漫射光(没有阴影,但我说的那个步骤与到达那里的步骤相比相对容易)投射阴影 - 实体后面的区域阻碍了光的通过,也在灯光的最大衰减范围内作为环境照明被着色,但实际上这个区域被传递给灯光渲染例程以考虑已经发生的障碍物的数量,以便灯光可以应用更漂亮的渐变(或某种褪色效果。)

漫射照明的当前实现只是简单地将受阻区域渲染为环境颜色,并将非受阻区域渲染为光的颜色 - 显然,尽管当您远离光时您会应用褪色效果(实现的那部分我还没有完成 - 但正如我所说,这相对容易。)

我是怎么做到的: 我不保证这是最理想的方法,但对于那些感兴趣的人来说:

本质上,这种效果是通过使用大量 Java 形状操作来实现的——光照贴图的渲染通过使用 VolatileImage 来加速。

生成光照贴图时,渲染例程执行以下操作:

  1. 创建一个包含覆盖整个屏幕的 Rectangle 的 Area 对象。该区域将包含您的环境照明。

  2. 然后它会遍历灯光,询问他们如果路上没有障碍物,他们的投光区域会是什么。

  3. 它获取该区域对象并在世界中搜索包含在该区域内的 Actors\Tiles,该区域将投射光。

  4. 对于它发现的阻碍光源投射区域视野的每个图块,它将计算光源位置和障碍物位置的差异(本质上是创建一个矢量,从光源指向障碍物 - 这是你想要的方向投射你的影子)这个指向向量(在世界空间中)需要被转换到屏幕空间。

  5. 完成此操作后,将采用垂直于该向量的垂直线并对其进行归一化。这实际上为您提供了一条可以向上或向下移动的线,方法是将其乘以任何给定的长度以沿给定的方向行进。该向量垂直于您要投射阴影的方向。

  6. 几乎完成了,您构造了一个由四个点组成的多边形。前两个点位于障碍物中心点的屏幕坐标的底部。要获得第一点,您需要沿垂直矢量(以 5 计算)向上移动瓷砖高度的一半 [这是一个相对准确的近似值,尽管我认为算法的这一部分有点不正确 - 但它没有明显的视觉效果衰减] - 然后当然添加障碍物的起源。为了获得第二个,你做同样的事情,但要往下走。

  7. 两个点的其余部分的计算方式完全相同 - 只有这些点需要按照在 4 中计算的阴影投影矢量的方向向外投影。 - 您可以选择任意大的量将其向外投影 - 只要它至少到达你光的投射区域之外(所以如果你只是想愚蠢地将你的阴影投影矢量乘以 10 倍,你应该是安全的)

  8. 从您刚刚构建的这个多边形中,构建一个区域,然后使用您的灯光区域作为第一个参数调用“相交”方法 - 这将确保您的阴影区域不会超出您的灯光投射区域的边界超过。

  9. 从您的灯光投射中减去您在上面构建的阴影区域。此时,您现在有两个区域 - 光投射不受阻碍的区域,以及光投射到受阻的区域 - 如果您的 Actors 具有用于确定特定 Actor 阻碍视野的可见性阻碍因子 – 您也有它阻挡视图的等级,您可以稍后在绘制灯光效果时应用(这将允许您在更暗\更亮的阴影之间进行选择,具体取决于被阻挡的光量

  10. 从您在 (1) 中构建的光照区域和受阻光照区域中减去环境光区域,这样您就不会将环境光应用到光照效果将接管并渲染到的区域

现在您需要将光照贴图与深度缓冲世界的渲染例程合并

现在您已经渲染了光照贴图,并且它包含在可变图像中,您需要将其放入世界的渲染例程和深度排序算法中。由于后台缓冲区和光照贴图都是易失性图像,因此在世界范围内渲染光照贴图是相对最优的。

您需要构建一个多边形,该多边形本质上是一个带,其中包含您的世界图块的垂直条将被渲染成的内容(看看我的屏幕截图,您会看到一组细对角线分隔这些条。这些条是什么我指的是)。您可以逐条渲染此光照贴图条的部分(在您渲染该条中的最后一个图块后将其渲染到条带上,因为 - 显然 - 必须将光照贴图应用地图上)。您可以使用相同的图像映射,只需将该条用作图形的剪辑 - 您需要在每次渲染条时将该条多边形向下平移。

无论如何,就像我说的那样,我不保证这是最理想的方式 - 但到目前为止它对我来说效果很好。光照贴图应用 p

于 2013-08-08T22:17:31.690 回答