java - Java 中的 2D 软件光照问题

标签 java 2d pixel lighting

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

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

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

因此,作为示例,环境光照为 0.3f。我所做的是像素到像素操作,其中对于将要绘制的每个像素,其 RGB 值被分解,减少 70% (1f - 0.3f),重新组合回单个 int 并存储在辅助 int 内[宽度 * 高度] 数组。当将像素传输到 BufferedImage 时,我减去辅助数组内的相应值并得到较暗的图像,如预期的那样。

这是一个使图像变暗的示例,效果很好,但实际点亮它们时出现问题:我给了玩家一个 lightRadius 和 3 个光颜色分量 float (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 变小(-=),然后组合回要从相应像素中减去的数字内,从而使减法结果更大(更轻)。 对于白光,我得到了所需的结果:

While light with 50 pixel radius

问题是当我只使用蓝色分量(r = 0f,g = 0f,b = 1f)时,得到:Blue Light with the same 50 pixel radius

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

此外,为了使照明呈圆形,我只需计算一些光 x^2 + y^2 <= radius^2 ,如果这句话为真,则像素应该亮起,执行我之前展示的代码。有没有更快的方法来计算这个? (在此效果下我损失了近 50 FPS)。

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

最佳答案

我认为最好的方法是首先添加环境光和玩家光值,限制在 [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[] 来表示每个像素的光量,仅在环境光或玩家光发生变化时才更改它。然后,您不需要计算每一帧的光线,只需将其一次性应用到整个图像即可。

关于java - Java 中的 2D 软件光照问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15507949/

相关文章:

2d - 屏幕坐标到等距坐标

2d - 碰撞检测使该游戏在检查与多个平台的碰撞时卡住

algorithm - 如何使用用户输入的涂鸦在多边形上添加新线段

java - 我的 JComponents 占用了太多像素

c - Windows 控制台像素

Java 图像质量 (JPEG)

java - Java程序在Windows上运行时不显示Unicode字符

java - 如何通过IP地址与另一台机器连接?

Java力场继承

java - 如何将 PostgreSQL 驱动程序 (jar) 添加到使用 liberty-maven-plugin 创建的 open-liberty microprofile fat jar?