我正在用纯Java创建一个2D自上而下的平铺游戏,现在我正在尝试实现一种照明方式。
首先,我将如何渲染一些细节:有一个处理所有渲染的屏幕类。像素放在int[width * height]
数组中,使用BufferedImage
和Graphics.drawImage()
在实际屏幕上绘制。
我现在正在进行照明的方式是创建第二个int[width * height]
数组,该数组保存应从实际像素中减去的所有亮度。我尝试仅使用从0f
到1f
的浮点数来表示RGB强度。
因此,作为一个例子,环境照明为0.3f。我所做的是像素到像素操作,对于每个要绘制的像素,其RGB值被分解,减少70%(1f-0.3f),重新组合成单个int并存储在次要{{1}内数组。将像素传输到BufferedImage时,我会按照预期减去辅助数组中的相应值并获得更暗的图像。
这是使图像变暗的一个例子,它工作正常,实际点亮它时会出现问题:我给了玩家一个lightRadius和3个浅色组件浮点数(RGB)。在渲染播放器时,我还通过执行以下操作在辅助阵列中渲染它的光照:
int[width * height]
其中dist是一个从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;
到0f
的数字,它使光线与光源的距离逐渐消失,1f
是来自光源的光的每个组成部分。播放器。
这段代码的作用基本上是“将一些像素中的光线反射回来”。如您所见,mr,mg和mb变得更小( - =),然后在将从相应像素中减去的数字内部组合,从而使减法的结果更大(更亮)。
对于白光,我得到了理想的结果:
问题是我只使用蓝色成分(r = 0f,g = 0f,b = 1f),得到这个:
当然,这可以通过以下事实来解释:瓷砖具有非常小的蓝色值,使得环境光占据了它的一小部分并且使得照明将其中的一小部分带回来(如您所见)效果是玩家的裤子,这是蓝色的)。 我仍然无法想到的是一种使照明不依赖于从像素中消除多少亮度的方法,以及在任何方式下组合组件的简单看起来很好的东西(我期望第二张图像的结果是亮度像在第一个,但有色蓝色)。那我怎么能实现这样的效果呢?
另外,为了使照明变成圆形,我只是计算一些光x ^ 2 + y ^ 2 <= radius ^ 2,其中如果这句话为真,则像素应该点亮,执行我已经显示的代码之前。有更快的计算方法吗? (这个效果让我失去了近50 FPS。)
编辑:我想要的效果就像2D游戏Tibia。这是棕色像素上的蓝光:
答案 0 :(得分: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]
如果你这样做,你也可以只有一个静态浮点[]来表示每个像素的光量,只有当环境光或球员灯变化时才会改变它。然后,您不需要为每个帧计算光线,只需在整个图像上一次性应用它。