java - 尝试使用Java2D在平铺的2D等距环境中实现动态照明

标签 java game-engine java-2d lighting isometric

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

here

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

如果这不可能,那么有人可以在考虑Java2D的情况下指导我使用更优化的算法吗?我已经考虑了平铺照明-但是我发现drawPolygon方法不是硬件加速的,因此执行起来非常慢。

我想尝试避免本机依赖性或在applet中对提升权限的需求。

谢谢

最佳答案

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

但是,如果您陷入了Java2D的困境(就我而言),仍然有可能在等距游戏中实现照明,这只是“尴尬”,因为您无法在每个像素级别执行光照着色。

外观:

我实现了(高度抛光-经过一定的抛光后,我可以保证它会看起来很不错)的效果,用于投射阴影,对光照贴图进行深度排序以及在不降低帧频的情况下应用照明。外观如下:

您将在此屏幕快照中看到一个漫射光(没有阴影,但是我要说的是,与到达那里的步骤相比,此步骤相对容易)投射阴影-实体后面阻碍光通过的区域,但是在最大照明范围内,将阴影作为环境照明进行遮蔽,但实际上,该区域将传递到灯光渲染例程,以考虑已发生的障碍物的数量,以便灯光可以应用更漂亮的渐变(或某种衰落效果。)

漫射照明的当前实现是仅将障碍区域渲染为环境颜色,而将非障碍区域渲染为光源的颜色-显然,随着距离光源的距离越来越远,您将应用淡入淡出效果(实现的那一部分尚未完成-但正如我所说的,这相对容易。)

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

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

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

  • 创建一个Area对象,该对象包含一个矩形,该矩形覆盖了
    整个屏幕。该区域将包含您的环境
    灯光。
  • 然后在灯光下迭代,询问他们
    如果路途中没有障碍物,那将是一个光铸区。
  • 接收该区域对象并在世界中搜索Actors \ Tiles
    包含在将要投射光的区域中。
  • 对于在光源投射区域中发现的所有遮挡视线的图块,它将计算光源位置和遮挡物的位置之差
    位置(基本上是创建指向AT的向量
    光源的阻碍-这是您要投射阴影的方向)此指向向量(在世界上
    空间)需要转换为屏幕空间。
  • 完成此操作后,将获取与该矢量垂直的线,
    标准化。从本质上讲,这为您提供了一条可以上行或
    通过将其乘以任何给定长度来向下传播,以向给定方向行进。
    垂直于您要投射阴影的方向。
  • 差不多完成了,您要构造一个包含四个点的多边形。
    前两个点位于屏幕坐标的底部
    您的障碍物的中心点。要获得第一点,您想
    沿垂直向量(以5计算)向上移动
    瓷砖高度的一半[这是相对准确的
    虽然我认为算法的这一部分略有近似
    错误-但视觉效果没有明显的下降]-
    那么当然会增加障碍物的起源。为了得到
    其次,您执行相同的操作,但要向下走。
  • 两点的其余部分的计算方法完全相同-
    仅这些点需要朝着的方向向外投射
    您的阴影的投影矢量的计算方法为4。-您可以选择任意大的量将其向外投影-只要它至少到达光源的投射区域之外即可(因此,如果您只想这样做,则请愚蠢地将阴影投影矢量相乘)乘以10的倍数,您就应该安全了)
  • 您刚刚从这个多边形中构建了一个区域,然后
    以灯光区域为第一个调用“相交”方法
    论点-这将确保您的阴影区域不会到达
    在您的光线投射到的区域之外。
  • 减去灯光投射的阴影区域
    以上。此时,您现在有两个区域-
    光线不受阻碍,并且光线投射的区域
    受阻-如果您的演员有可见度受阻因素
    您曾经用来确定某个特定演员正在阻碍
    视图-您还拥有阻止视图的等级
    您可以稍后在绘制灯光效果时应用(这将使您可以根据受阻的光线数量在较暗\较亮的阴影之间进行选择
  • 减去您在(1)中构造的环境光区域
    灯光区域和受阻的灯光区域,因此您无需申请
    环境光到照明效果将取代的区域
    并渲染成

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

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

    您需要构造一个多边形,该多边形本质上是一个 strip ,其中包含要渲染的世界瓷砖的垂直 strip (看一下我的屏幕截图,您会看到将这些 strip 分开的细对角线阵列。这些 strip 就是我指的是)。然后,您可以逐条地渲染此光照贴图的各个部分(渲染了该光照贴图中的最后一个图块之后,将其渲染到该光照贴上,因为-显然,必须将光照贴图应用于该贴图)。您可以使用相同的图像贴图,只需将该 strip 用作图形的剪辑-您将需要根据 strip 的每个渲染向下转换该 strip 多边形。

    无论如何,就像我说的那样,我不保证这是最理想的方法-但到目前为止,它对我来说还不错。
    光照贴图p

    关于java - 尝试使用Java2D在平铺的2D等距环境中实现动态照明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18118319/

    相关文章:

    Java:在运行时将类作为参数传递

    用于创建图像的 Scala 库

    javascript - 如何在javascript中画一条线?什么是 Swing/Awt?我需要下载它们吗?

    java - 有没有办法将实时数据发送到JBOSS

    java - 迭代元素时获取文档标签名称

    java - map函数的方法引用,key为String类型时编译报错

    c - 在C中,变量不保留我分配给它的值并返回到0

    C++控制台游戏输入&&刷新函数

    java - 形状旋转问题 - Java2d

    java - Android 拍照并保存到变量