【问题标题】:2D Software Lighting Issues in JavaJava 中的 2D 软件照明问题
【发布时间】:2013-03-19 18:45:02
【问题描述】:

我正在用纯 Java 创建一个 2D 自上而下的平铺游戏,现在我正在尝试实现一种照明方式。

首先,关于我如何渲染的一些细节:有一个处理所有渲染的屏幕类。像素被放入int[width * height] 数组中,该数组使用BufferedImageGraphics.drawImage() 在实际屏幕上绘制。

我现在进行照明的方式是创建第二个int[width * height] 数组,该数组包含应从实际像素中减去的所有亮度。我尝试仅使用从 0f1f 的浮点数来表示 RGB 强度。

因此,例如,环境照明为 0.3f。我所做的是一个像素到像素的操作,对于将要绘制的每个像素,它的 RGB 值被分解,减少 70% (1f - 0.3f),重新组合成单​​个 int 并存储在辅助 int[width * height] 数组中.在将像素传输到 BufferedImage 时,我减去了二级数组中的相应值,得到了一个更暗的图像,正如预期的那样。

这是一个使图像变暗的示例,它工作正常,当实际点亮它们时出现问题:我给了播放器一个 lightRadius 和 3 个浅色分量浮点 (RGB)。在渲染播放器时,我还通过执行以下操作在辅助阵列中渲染它的光照:

int mask = subtractMask[xx + yy * width];

int mr = (mask >> 16) & 255;
int mg = (mask >> 8) & 255;
int mb = mask & 255;

mr -= (int) (dist * light.r * mr);
mg -= (int) (dist * light.g * mg);
mb -= (int) (dist * light.b * mb);

subtractMask[xx + yy * width] = mr << 16 | mg << 8 | mb;

其中 dist 是从0f1f 范围内的一个数字,它使光随着与光源的距离而衰减,light.r/g/b 是来自玩家的光的每个分量。 这段代码所做的基本上是“将一点点从像素中取出的光还给它”。如您所见,mr、mg 和 mb 变小(-=),然后组合回将从相应像素中减去的数字内,从而使减法的结果更大(更轻)。 对于白光,我得到了想要的结果:

问题是当我只使用蓝色分量(r = 0f,g = 0f,b = 1f)时,得到这个:

当然,这可以通过瓷砖的蓝色值非常少这一事实来解释,使环境光带走了一小部分,而灯光又将这一小部分返回(你可以看到最大的效果在玩家的裤子上,裤子是蓝色的)。 我仍然无法想到的是一种使照明独立于从像素中带走多少亮度以及以任何方式组合组件看起来都不错的方法(我对第二张图像的预期结果是亮度,例如在第一个,但颜色为蓝色)。那么如何实现这样的效果呢?

另外,为了使光照循环,我简单地计算了光照 x^2 + y^2

编辑:我想要的效果类似于 2D 游戏胫骨。这是棕色像素上的蓝光:

【问题讨论】:

  • 蓝色是RGB中最不发光的成分(在YUV色彩空间中计算Y的经典公式是R*0.299 + G*0.587 + B*0.114)。因此,如果您只使用蓝光并且仍希望获得与使用白光时相似的亮度,则您必须针对您使用较暗光源这一事实进行调整。
  • 对不起,我不知道 YUV 颜色空间的存在。我该如何做这样的更正?
  • 在您展示的示例中,大多数图像至少有一些蓝色成分,因此光线能够将其点亮。这只是物理学的一个事实,如果你有一个只反射红光和绿光的物体,而你用纯蓝光照亮它,你什么也得不到。
  • 是的,我就是这么想的。但是如何实现类似于我在上次编辑中添加的图像?那是蓝色光超过棕色,几乎没有蓝色。
  • 上传原始的、未更改的图像以供使用。

标签: java 2d pixel lighting


【解决方案1】:

我认为最好的方法是首先添加环境光和玩家光值,钳制到 [0...1] 范围,然后然后相乘像素值。

所以:

环境光:[ 0.3, 0.3, 0.3 ]
播放器灯光(在某个位置):[ 0.0, 0.0, 1.0 ]
总光照:[0.3, 0.3, 1.0 ]

原始像素值:[ 100, 200, 100 ]
输出像素值:[30,60,100]

如果你这样做,你也可以只用一个静态的 float[] 来表示每个像素的光量,只有在环境光或玩家光发生变化时才会改变它。然后,您无需计算每一帧的光,只需在整个图像上一次性应用它。

【讨论】:

  • 但我认为通过这样做,每一个带有少量蓝色成分(如绿草)的像素都不会亮起来,就像现在发生的那样。实际上,无论颜色如何,我都希望它们亮起来。这可能吗?
  • 一种选择是让您的播放器以蓝色为主,但也包含其他一些颜色。如果是我,我会让灯光在中心(玩家)始终为白色,但让红色和绿色分量褪色得更快,以便照亮区域的边缘带有蓝色。这往往会给人一个清晰的蓝光印象,同时使靠近玩家的物体仍然可以区分。
  • 我认为同样的问题会发生:我尝试了一些 r 和 g 的组合以及蓝色的 1f,我主要看到的只是 r 和 g 的影响,我认为我的方式'正在做的事情只是根据它们的原始颜色照亮像素......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多