我在純Java中創建2D自上而下的平鋪遊戲,現在我試圖實現一種照明方式。Java中的2D軟件照明問題
首先,我如何渲染一些細節:有一個屏幕類來處理所有的渲染。像素放在int[width * height]
陣列內,該陣列使用BufferedImage
和Graphics.drawImage()
在實際屏幕上繪製。
我現在正在照明的方式是通過創建第二個int[width * height]
數組來保存應從實際像素中減去的所有亮度。我嘗試使用浮動範圍從0f
到1f
來表示RGB強度。
因此,作爲一個例子,存在0.3f的環境照明。我所做的是像素到像素操作,其中對於將要繪製的每個像素,其RGB值將被分解,減少70%(1f - 0.3f),重新組合爲一個int並存儲在次要int[width * height]
陣列中。將像素傳輸到BufferedImage時,我會減去次級陣列中的相應值,並按預期得到較暗的圖像。
這是一個使圖像變暗的例子,它可以很好地工作,問題出現在實際點亮它們時:我給玩家一個lightRadius和三個淺色分量浮動(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是一個數字範圍從0f
到1f
這使得從源極和light.r/g/b
被遠處的光褪色來自玩家的光的每個組成部分。 這段代碼的功能基本上是「將一點像素從像素中提取出來」。正如你所看到的,mr,mg和mb被製作得較小( - =),然後在從相應像素中減去的數字內部組成,從而使得減法的結果變得更大(更輕)。 對於白光我獲得所需的結果:
問題是,當我只用藍色分量(R = 0F,G = 0F,B = 1F),得到這樣的:
當然,這可以通過瓦片具有非常小的藍色值的事實來解釋,使得環境光線佔據它的一小部分,並使得照明將其一小部分帶回(正如您可以看到的最大效果是在玩家的褲子上,這是藍色的)。 我仍然無法想到的一種方法是使照明不受像素帶走多少亮度的影響,以及以任何方式將各個組件合併在一起看起來不錯的東西(我期望得到的第二張圖像的結果是亮度像第一個一樣,但藍色)。那麼我怎麼能實現這樣的效果呢?
此外,爲了使照明循環,我只需計算一些光x^2 + y^2 < = radius^2,如果這句話是真的,像素應該點亮,執行我已經顯示的代碼之前。有更快的方法來計算這個嗎? (我在這個效果上損失了近50 FPS)。
編輯:我想要的效果就像2D遊戲Tibia。這是藍光在棕色像素:
藍色是RGB中最不亮的分量(在YUV色彩空間中計算Y的經典公式是R * 0.299 + G * 0.587 + B * 0.114)。因此,如果您只應用藍光並且仍然希望具有與使用白光時相似的亮度,則必須根據您使用較暗光源的事實進行調整。 – Michael 2013-03-19 20:29:20
對不起,但我並不知道YUV色彩空間的存在。我該怎麼做這樣的修正? – Thiago 2013-03-19 20:37:26
它看起來像你展示的例子,大多數圖像至少有一些藍色的成分,所以光線能夠點亮它。這只是一個物理學的事實,如果你有一個物體只反射紅光和綠光,而你用純藍光點亮它,你什麼也得不到。 – 2013-03-19 21:03:36