倉庫:https://gitee.com/mrxiao_com/2d_game_2
黑板:制作一些光場(Light Field)
當前的目標是為游戲添加光照系統,并已完成了法線映射(normal maps)的管道,但還沒有創建可以供這些正常映射采樣的光場。為了繼續推進,需要生成三個光場:上、中、下三個不同的環境貼圖(EnvMaps),以便能夠從中獲取周圍環境的光照數據。
具體來說:
-
光場的構建:
- 頂部和底部光場:這些光場相對容易構建,可以使用地面和天空的位圖來代表。地面圖將用作底部光場,天空圖作為頂部光場,主要工作是確保渲染器能夠保存并從未被遮擋的基礎層中提取數據。
- 中間光場:這個光場稍微復雜一些,需要考慮光的遮擋效應。如果有光源經過,應該能夠表現出光線穿過物體表面的效果,類似地,如果有物體阻擋光線,采樣到的光線就應該變暗。這個光場的實現會涉及一些更復雜的技術和算法,尤其是在計算遮擋和反射等方面。
-
目前的步驟:
- 生成頂部和底部的測試環境光貼圖,以確保系統的基本光照采樣工作正常。雖然還沒有實現復雜的遮擋和反射效果,但這些測試貼圖將幫助驗證正常映射的實現。
- 在頂部和底部光場上使用簡單的測試模式,以檢查是否能夠正確采樣并應用正常映射。
總的來說,當前工作重點是創建并調試這些基礎的光場貼圖,以便后續進一步完善光照和正常映射的系統,確保渲染效果能夠達到預期。
創建測試環境貼圖
在開發過程中,首先需要為環境貼圖(即光照場)分配空間。這些環境貼圖包括頂部、中部和底部貼圖,盡管目前尚不清楚這些貼圖的具體分辨率和內容(例如,頂部貼圖可能代表天空,但實際上可以是任何其他內容)。因此,將這些環境貼圖作為動態數據進行處理,它們會與地面緩沖區(ground buffers)一同管理,因為它們的性質是短暫的,隨著渲染器的發展,空間分配會逐步調整。
在實現過程中,需要為這些環境貼圖分配內存,并且考慮到光照的處理,這些貼圖的分辨率可以選擇一個較低的采樣率,而不是與其他內容保持相同的高分辨率。因此,應該先定義這些環境貼圖的寬度和高度,以便為后續的工作打下基礎。
接下來,初始化時,將這些環境貼圖的變量(例如頂部、中部和底部貼圖,以及它們的寬高)添加到相應的數據結構中,確保它們在渲染過程中能夠正確使用。
初始化環境貼圖
首先,設置了一個名為 TranState
的初始化狀態,用來初始化環境貼圖。接下來,環境貼圖的寬度和高度被設置為 512x256,雖然這些值是隨機選擇的,但它們決定了環境貼圖的分辨率。
為了簡化初始化過程,使用了一個循環來逐個初始化每個環境貼圖。具體來說,在循環中,首先獲取環境貼圖數組中的每個環境貼圖,并為其初始化不同的 LOD(Level of Detail)。這些 LOD 是相同貼圖的不同清晰度版本,逐級模糊,分辨率逐漸降低。
通過設置循環,首先處理頂層環境貼圖(索引 0),接著是中層和底層環境貼圖(索引 1 和 2)。另外,還考慮到了坐標系的方向,決定使用 “Z軸向上” 的方式,這樣可以保持與其他坐標系統一致,增加一致性和易于理解。
最后,在每一輪循環中,初始化的環境貼圖會根據對應的分辨率大小,逐漸變得更模糊,這樣可以生成一系列不同清晰度的環境貼圖版本,以供后續使用。
設置LOD(細節層次)選擇器
接下來,在初始化過程中,加入了另一個循環,用來處理每個 LOD(細節級別)索引。這個內層循環會根據環境貼圖的數量(此時設為 4)迭代,通過每一層 LOD。
在每一輪循環中,根據當前 LOD 索引來創建相應的環境貼圖。通過調用已定義的 MakeEmptyBitmap
函數,這個函數負責為每個 LOD 分配內存空間,并且將分配的內存推入暫存區(TransientArena)。這樣,環境貼圖的數據就能夠存儲在指定的內存區域。
為了支持不同細節級別的效果,首先創建最高分辨率的貼圖,然后每次迭代時,寬度和高度都會按比例縮小。具體來說,每次迭代時,寬度和高度會減半,從而生成一個逐漸模糊、分辨率遞減的級別(例如,初始分辨率、四分之一大小、再四分之一大小,依此類推)。這種方式會產生一系列從高到低的 LOD 地圖,確保每個級別的環境貼圖都有合適的分辨率。
通過這種方式,可以實現分層次的細節級別(LOD)管理,確保在渲染時根據需要使用不同清晰度的貼圖,以提高性能并保證渲染效果。
將貼圖傳遞給CoordinateSystem
在此階段,需要確保能夠正確地傳遞之前創建的環境貼圖(環境地圖)。之前這些環境貼圖并沒有被傳遞過來,而現在需要開始傳遞它們。這是一個直接的過程,只需要將環境貼圖按照順序傳遞即可。
首先,傳遞第一個環境貼圖(如頂部貼圖),然后是第二個貼圖(中間貼圖),最后是第三個貼圖(底部貼圖)。在代碼中,環境貼圖的順序需要符合預設的順序,即先是頂部貼圖,然后是中間貼圖,再到底部貼圖。
在傳遞這些貼圖時,確保與渲染組中的坐標系統一致,因此需要仔細檢查環境貼圖在傳遞時的順序,以確保與渲染設置相匹配。通過這種方式,環境貼圖可以正確地被使用在渲染過程中。
編譯并清理
有一些變量被錯誤地聲明為指針,這應該是一個錯誤,需要去掉指針聲明并進行修正。這樣修改之后,應該能夠順利編譯,并確保代碼正常工作。
這些修改有助于代碼結構的清晰,確保不同功能和模塊能夠適當地組織,避免潛在的問題,并且使代碼更加易于維護。
運行但沒有發生什么特別的事
目前,地圖中的內容只是垃圾數據,實際上它們目前只有零值,因為它們位于臨時緩沖區(transient arena)中,而該緩沖區在初始化時已經被清空。因此,當前不應有任何光照貢獻,這正是預期的結果。
接下來,目標是開始向這些地圖中填充實際內容,從而能夠開始從中進行采樣。首先,計劃將開始填充這些地圖,確保能夠正確地從中獲取數據并進行進一步的處理。
繪制環境貼圖
首先,需要在渲染過程中繪制這些環境圖,以確保它們確實包含預期的內容,而不是盲目地進行采樣。為了驗證這一點,首先在渲染調用之前,添加一些代碼以繪制至少是環境圖的頂級圖層。這樣可以確保已經正確填充了環境圖,并能夠正確地查看它們的內容。
由于粗糙度(roughness)用于決定選擇哪個LOD(細節層次),因此需要確認實際填入圖層的粗糙度值。在當前實現中,粗糙度值是用來決定選擇哪一層LOD的。例如,當粗糙度為零時,默認選擇的是頂層LOD。
為了繪制圖像,可以通過遍歷環境圖的每個地圖來繪制不同LOD的圖層。需要確保每個LOD圖層在屏幕上正確顯示,圖像的位置也需要通過重新定義X軸和Y軸的比例來確定。為了避免圖像重疊,可以根據實際LOD的寬高來調整顯示大小,確保它們能夠正確地顯示在屏幕上。
最后,繪制的圖層可能會出現顏色或透明度問題,需要調整顏色值,確保它們顯示為全亮度,避免任何顏色的影響。通過調整繪制位置,可以確保每個圖層正確顯示,并且在屏幕上能夠看到完整的環境圖。如果圖層的透明度不正確,可能會導致圖像無法正確顯示。
總之,這個過程的目的是確保環境圖正確地填充并渲染,以便可以進一步調試和驗證它們的使用。
準備環境貼圖
首先,在每一幀渲染開始時,清除并重新繪制環境圖,填充一些可以測試法線貼圖的內容。為了簡化測試,可以使用渲染組中的 DrawRectangle
調用,通過指定位圖并填充不同顏色來驗證法線貼圖效果。
具體來說,首先清除環境圖的頂層LOD,并填充該圖層。可以將底部填充為紅色,頂部填充為藍色,這樣通過法線貼圖的光照計算時,至少可以在物體的頂部和底部看到紅色和藍色的色調。
接下來,清除環境圖的頂層LOD,傳入相關參數(如 TranState
、EnvMapWidth
、EnvMapHeight
)進行清除,確保渲染的圖層沒有殘留內容。可以選擇清除為純紅色、純綠色和純藍色,代表不同的層次。清除綠色層可能是多余的,當前代碼可能未使用該層,這一點需要檢查并修正。
最后,轉換色彩格式時,可能需要將顏色從 uint32
轉換為 real32
,以確保渲染時顏色正確顯示。此時的清除操作完成,準備好進行后續的渲染和測試。
在游戲中查看
已經可以看到正在從環境貼圖中采樣了,但是出現了一個 bug,看起來是混合的方向被反轉了。具體來說,可以看到藍色區域有較為平滑的過渡效果,雖然可能還不是完全正確,但至少有一定的羽化效果,看起來沒有太硬的分界線。然而,紅色區域卻出現了明顯的硬邊界,這正是需要修正的問題,不符合預期效果。
注意到一些BUG
發現了兩個問題,第一個是混合的方向被反轉,導致藍色區域羽化效果正常,而紅色區域出現了硬邊界。第二個問題是地面和天空貼圖被翻轉了,地面貼圖應該在下方,但卻出現在上方,天空貼圖則相反。這個問題也需要解決。
這種問題的發現是通過調試代碼時采用的結構化藝術方法。通過用簡單的、易于區分的顏色(如紅色和藍色)來填充貼圖,能夠更清晰地看到哪里出錯,而不像直接用真實數據那樣難以分辨問題。結構化藝術幫助識別并修復渲染中的細微錯誤。計劃接下來可能用白色調試紋理替換當前的紋理,專注于查看球體法線貼圖的效果,而不受其他紋理的干擾。
查看如何修復底部貼圖的采樣
發現了一個問題,底部貼圖被錯誤地指定為上部貼圖,導致渲染結果不正確。檢查了法線圖的方向,發現法線的Y值在負方向時,被錯誤地判斷為底部貼圖。此問題可能是由于法線貼圖的坐標系問題引起的,當前的貼圖坐標系是從頂部到底部,而理想情況下應該使用從底部到頂部的坐標系。
考慮到大多數圖形API(如OpenGL)通常使用底部到頂部的坐標系,因此決定將貼圖的坐標系調整為從底部到頂部。這種調整需要盡快完成,因為在渲染過程中,坐標系問題可能會影響后續的計算和調試,因此需要盡早解決。
優先整理坐標系統
目前,坐標系問題尚未解決,但決定暫時跳過這一部分,先繼續進行渲染工作,直到更進一步處理坐標系問題。雖然當前坐標系存在問題,但實際采樣的部分并沒有錯誤,因此可以繼續進行。計劃在優化和進一步處理渲染時,首先對屏幕坐標系、世界坐標系和紋理坐標系進行統一,確保它們在整個系統中保持一致性。這一調整將在進一步推進之前進行,以避免后續出現更復雜的問題。
添加一些注釋
修復底部貼圖的采樣
在檢查底部紋理地圖時,發現出現了方向問題。原本的映射范圍應該是從負一到負零點五,但當前實現中出現了反向映射的問題。為了解決這個問題,需要調整坐標映射的方向,確保在零的位置應該是1,而不是0。通過對公式進行簡化和調整,可以正確地得到所需的結果。最終,通過調整公式,確保了映射的數值正確地從負一到負零點五之間變化,并成功修復了方向問題,達到了預期的漸變效果。
為環境貼圖實現棋盤格圖案
現在的目標是更準確地計算采樣位置,因為當前的采樣方法并不精確。為了測試這個問題,建議使用棋盤格紋理進行調試,這樣可以通過清晰的圖案幫助識別問題。計劃使用16像素的棋盤格模式,通過在每個LOD層上繪制這個棋盤格,來檢查紋理的采樣。
為了實現這一點,需要在代碼中定義棋盤格的寬度和高度,并通過遍歷每個LOD的x和y坐標,依次繪制每個格子。每個格子的最大和最小坐標由寬度和高度決定。為了簡化顏色的設置,將繪制矩形的函數修改為接受顏色值,顏色值包括紅、綠、藍和透明度。這樣可以直接傳遞顏色并且避免繁瑣的操作。
此外,還需要確保顏色值正確傳遞給每個矩形繪制函數,并更新了存儲顏色信息的結構,使得顏色數據傳遞更加簡潔和一致。最終,代碼將更高效且易于維護,因為減少了冗余的計算和數據傳遞。
實現ToV4
通常定義數學庫是為了快速地從一個向量類型轉換到另一個類型。比如,對于一個 v4
向量,定義一個 twoBefore
函數,可以接受一個 v3
(即 XYZ)和一個 W 分量。這個函數非常基礎,它的作用是將 v3
的 XYZ 分量和 W 分量直接傳遞給結果。這樣就能得到一個新的 v4
向量,結果的 XYZ 保持不變,而 W 則是傳入的 W 值。通過這種方式,可以快速在不同維度的向量之間進行轉換。
對于其他維度的向量,比如 v3
,也可以使用類似的方法進行定義和轉換。基本上,每個維度的向量都會有類似的函數來進行構造和轉換,這樣的實現非常簡潔且高效。
繼續棋盤格例程
在繪制棋盤格的過程中,首先需要為每個紋理地圖設置顏色。為了做到這一點,通過 LOD
獲取當前的顏色,并將其分配給地圖顏色。然后,為了繪制棋盤格,定義了一個 MapColor
,通過這個顏色來決定當前區域的顏色。在遍歷棋盤格時,通過判斷當前所在的棋盤格位置來決定是否將顏色設置為黑色。
棋盤格的最小點(MinP)和最大點(MaxP)可以通過 X
和 Y
坐標來確定,因為在繪制時,寬度和高度已經確定。為了正確地交替棋盤格的顏色,設置了一個 CheckerOn
變量,用來判斷當前方塊的顏色是地圖顏色還是黑色,并通過切換 CheckerOn
的狀態來實現這一效果。為了在每一行交替改變顏色,定義了一個 RowCheckerOn
變量,它決定了每一行的起始顏色。
同時,需要設置棋盤格的寬度和高度,這里暫時設定為 16x16
,不過也考慮到高度可能小于寬度,決定暫時調整為 8
。這個設置還沒有完全確定,最終效果會根據實際需求進行調整。
按alt+enter全屏好像不能固定全屏
在游戲中查看棋盤格
棋盤格已經繪制完成,看起來很棒。可以看到雙線性濾波正在生效,尤其是當樣本之間的紋理采樣時,產生了中間值,也就是在兩個采樣點之間的過渡效果。現在棋盤格已經被處理完了。
有趣的是,觀察到現在整個圖像沒有任何光照,這很奇怪,特別是因為推測這意味著紋理采樣的位置可能只選擇了一些黑色的像素。這個現象可能是因為沒有正確處理紋理坐標的計算,導致采樣結果不正確。因此,應該開始著手解決紋理坐標問題,確保能夠正確地從紋理圖中獲取像素值。
引入TestDiffuse和TestNormal
首先,決定不再使用樹的正常貼圖,而是創建一個測試用的位圖和正常貼圖。創建了 TestDiffuse
和 TestNormal
,其中 TestDiffuse
是一個顏色位圖,TestNormal
是一個球形正常貼圖。為了生成正常貼圖,選擇了一個球形正常貼圖,并設定了零粗糙度。接下來,創建了一個 256x256 的空位圖 TestDiffuse
,作為測試使用。
接著,使用 DrawRectangle
方法繪制矩形填充該位圖,并將顏色設置為中性灰色,這樣就可以觀察正常貼圖的效果了。
在代碼中,TreeNormal
不是 GameState
的成員,因此需要調整代碼中的變量名稱,改為 TestDiffuse
和 TestNormal
。此外,由于改變了位圖的大小,動態重載并不支持這一變化,因此需要處理這個問題。
其他修改是添加注釋
在游戲中查看并改變背景顏色
在開發過程中,原本使用的灰色與背景色相同,導致無法清晰地判斷圖形是否正確繪制。經過反思,這個灰色選擇顯然是一個疏忽。為了能更好地確認是否有繪制效果,決定調整顏色,以便能夠更容易地看到圖形。現在,當圖形正確繪制之后,可以觀察到其是否反映了預期的光照貢獻,尤其是在處理實際的反射和光照傳遞時。雖然時間緊迫,接下來的工作可能無法完成,但這一調整為后續的調試和開發提供了更清晰的視圖。
查看我們在SampleEnvironmentMap中的工作
在開發過程中,當前的實現并沒有處理如何正確地查找采樣位置,因此沒有得到預期的光照貢獻。當前系統只是簡單地選擇了地圖的上角,而沒有實際執行從地圖中查找和計算具體值的工作。為了解決這個問題,需要進行必要的操作,從地圖中獲取實際的值,并準確地進行計算,確保能夠正確反映光照的貢獻。這項工作將在后續完成。
使用法線查找環境貼圖
可以想象在地圖中選擇位置時,使用法線來確定位置。具體來說,可以從寬度開始,然后根據寬度選擇法線的 x 坐標。雖然這種方法并不完美,但它能提供一個簡單的思路,至少可以從中選擇出一些元素。這種方法并不是目標方案,但它提供了一個直觀的、易于理解的步驟,便于從中觀察和調試。
在游戲中查看
當前反射效果還沒有完全實現,實際上它只是在作為一種延遲紋理查找來使用。但至少可以確認,嘗試的方向是有效的。對于雙線性采樣的效果,經過重新思考,可能是合理的,因此目前這種方法應該是可行的。雖然目前的效果已經不錯,但暫時不打算深入研究如何正確進行采樣,因為現在并沒有足夠的時間來做這些細節工作。因此,可能需要暫時停止當前的進展。
接下來,計劃在稍后繼續處理實際的數學運算部分,尤其是采樣部分,可以留到第二天再繼續。同時,還需要考慮如何處理綠色范圍的相關問題,雖然目前還不清楚具體怎么做,但這部分工作肯定會需要大量的規劃和思考,因此要提前計劃好如何將這部分內容融入到整體中。
在MoveEntity函數中,你有兩個未使用的變量:NewPlayerP和OldPlayerP。你會刪除它們嗎?
有兩個變量 new player
和 old player
從未被使用,是否需要刪除它們呢?有些疑問是否將來可能會用到這兩個變量,特別是它們是否會在之后的工作中派上用場。不過,考慮到它們并未發揮作用,這部分代碼可能需要進行大幅刪除。如果確實需要刪除它們,完全可以這樣做。
這個方案能讓你看到水面反射星空嗎?
這個方案是否能讓一池水反射星空?關鍵在于如何處理這些地圖的分辨率。顯然,技術本身是能實現這一效果的,但在采樣過程中需要考慮許多因素。如果仔細考慮一下,可能會發現保持效果良好的過程中會有一些挑戰。例如,問題在于采樣時會遇到的一些困難,這可能會影響最終的視覺效果。
黑板:水面反射星空
當進行反射采樣時,尤其是水面反射星空時,問題在于反射的方向和法線。每次反射都會在不同的方向上產生不同的反彈,這些反彈會去采樣紋理圖,而這種采樣通常是稀疏的。因此,無法保證不會出現明顯的偽影。比如一個反彈可能會采樣到一個位置,而下一個反彈則可能跳躍到非常遠的地方,這就無法獲得期望的各向異性過濾效果,這對于水面反射的星空來說會導致不良效果。
在這種情況下,為了避免過于復雜的采樣問題,可能會選擇使用較低分辨率的紋理圖,這樣就不會用來進行高質量的反射,而更多是用于處理光照或光澤效果,而不是高質量的反射。
解決這種問題的常見做法是在3D中,通過從反射表面視角渲染場景,模擬類似的過程,但是否有其他復雜的技巧來避免這種糟糕的采樣結果并不明確。可能會使用各向異性過濾來改善紋理采樣,但它可能不足以完全解決問題。反射在3D中的問題可能也會面臨類似的困境,有時可能無法完全避免,導致反射效果中出現閃爍的偽影。因此,這種問題需要注意。
如果你想看到光照根據法線貼圖的球形形狀而扭曲,這是否只是修復從環境貼圖采樣時的數學部分,還是還有更多內容?
如果希望看到光照根據法線貼圖的球形形狀發生畸變,那么這實際上只是修正采樣部分數學計算的問題。明天進行修正時,應該能夠實現這種彎曲效果,直到那時,當前并沒有進行這一計算。因此,當前的效果并不表現為反射,原因是沒有在計算反射,這一點應該不會讓人感到意外。
擁有三個環境貼圖(頂部、中部、底部)相較于使用一個整體的環境貼圖有什么好處?
使用頂部、中部和底部等多個環境貼圖的好處在于,它們可以幫助處理空間的不同層次,尤其是與高度相關的內容。如果只使用一個環境貼圖,可能很難將高度信息融入其中,難以做到空間上的細節區分。因此,使用多個貼圖可以更好地表示不同的空間位置和高度。如果能夠找到一種方法將所有信息都從一個貼圖中提取出來,可能會更簡單,但目前并沒有想到這樣的方案。
黑板:預覽環境貼圖的工作方式
目前的思路是使用多個貼圖來處理不同的環境元素。首先,已經制作好了地面紋理,會將其放入場景中進行繪制。接著,為場景中的實體添加陰影,可以將陰影和地面紋理分成兩個不同的位圖來處理。然后,使用一個中間貼圖(包含光照信息)并將其中的光照信息添加到地面貼圖中,這樣就得到了一個包含光照和陰影的地面貼圖。接著,保留一個僅包含光照的中間貼圖和一個僅包含天空的頂部貼圖。
通過這種方法,地面貼圖會包含地面紋理、光照和陰影,中間貼圖僅包含光照信息,而頂部貼圖則包含天空元素。在進行采樣時,期望能夠通過這種方式獲取到需要的3D信息。通過這種多貼圖方式,可以實現對不同環境層次(如地面、光照、天空等)的處理,而單一的環境貼圖似乎很難做到這一點。
我不太明白底部貼圖的意義。地面是否會對地面上方的物體貢獻光照?
底部貼圖會將光照反射到地面上的物體上,這是因為現實中也是如此,地面反射的光線對位于地面上的物體外觀有重要影響。目標是嘗試將這種效果實現到游戲中。首先,計劃是添加所有三種貼圖,觀察它們的效果,如果發現其中某一個貼圖的效果不明顯,可以去掉,從而節省計算資源。因此,目標是先嘗試使用三種貼圖,如果效果不理想,可以刪除不必要的部分。如果最終只需要中間的貼圖,也可以只保留它,如果其他貼圖帶來良好的效果,則繼續保留。
對于每種環境貼圖,需要為每個物體設置對應的環境貼圖。
你會需要為每個“Z層”準備一組環境貼圖嗎?
在 Z 軸層級的處理上,計劃是讓這些層次以某種方式級聯。首先,從最低的地面層開始渲染,這將生成底部的環境貼圖。接著,我們需要處理天空貼圖,它本質上是上方地面層的反轉。接下來,通過使用地面貼圖的 Alpha 通道來確定位置,再將其與上層中間層的光照合成,得到上方光源照射到下層的區域。
在層次疊加的過程中,可以通過這種方式模擬光照的變化,使得從上方照射下來的光照能夠通過不同層次的合成展示出來。這是一種逐層渲染的方法,從底部開始渲染,然后逐步處理更高的層級。
此外,還可以考慮對過亮的部分進行處理,具體的做法可能會包括調整亮度,以避免場景中過亮的部分影響整體效果。
有沒有計劃對燈光進行過曝處理?(甚至是HDR?)
對于高動態范圍(HDR)效果,并不確定是否會實現。考慮到軟件環境中,可能無法有效地實現 HDR,因為使用浮點數(如 float16)可能難以處理。在考慮過亮效果時,可以通過使用中間緩沖區來模擬類似 bloom 的效果,但不太可能在軟件管線中實現真正的 HDR。
可能的解決方案包括嘗試使用一個額外的模糊緩沖區來增加一些 bloom 效果,但在當前的設置下,實際上并不認為能夠實現 HDR,尤其是在軟件管道中。
你能將所有燈光信息包含在一個5字節的位圖中嗎:0-255的吸收/反射比例,RGB的Alpha和散射?我想試試,但因為你警告過不要使用非32位對齊的結構,我感到有些猶豫。
可以將所有光照信息包含在一個五字節位圖中,其中包含 RGB 吸收率、反射率、縮放因子、透明度和散射效果。在嘗試這種方法時,可能會有一些猶豫,特別是考慮到非 32 位對齊的結構。然而,實際上,非 32 位對齊并不是一個嚴重的問題,因為這些數據本質上是作為像素值輸入的,因此可能能夠成功使用五字節格式。如果遇到問題,也可以通過將多個數據打包在一起,減少對齊問題的影響。
然而,關鍵問題在于如何處理法線信息。在這種方案中,法線的存儲似乎是一個需要解決的難題。
甚至只使用0-2的光照范圍也能得到很好的效果
可以通過將光照范圍從零到 255 映射到更高的亮度范圍來獲得更好的效果。例如,可以考慮將其映射到雙倍亮度等。這需要進一步思考和確認,尚不確定是否完全可行。
關于是否計劃進行相機層級的光照處理,目前還不確定。
你是否計劃做“相機級別”的光照效果,比如“眩暈手雷”之類的?
例如暈眩手雷這樣的效果,可以通過將屏幕覆蓋上某些效果或增加亮度來實現,這對系統來說非常容易做到。雖然不確定在當前的游戲中是否需要這些效果,但確實可以實現,而且并不復雜。如果可以不使用 alpha 通道,效果實現會更簡單。
如果不需要Alpha,你能否使用RGBE,其中E是所有通道的指數?
使用RGB加上指數(E)來處理每個通道的HDR會使管道處理變得復雜,尤其是在加載和重新打包E值時,這是一個麻煩的過程。雖然實現HDR是可能的,但不一定是可行的,考慮到當前有很多需要關注的問題,可能不值得嘗試做HDR。盡管如此,一旦渲染器的架構確定后,進行修改并非不可能,因此可以先實現非HDR版本,之后再考慮是否升級為HDR版本,關鍵是確保不會做出讓未來更改變得困難的決策。
飽和度覆蓋起來會很難嗎?
飽和度的疊加其實并不難。一個簡單的做法是通過拉取平均值來實現。例如,可以通過這種簡單的方法來處理飽和度疊加。
引入render_entry_saturation
飽和度的疊加可以通過一個簡單的后處理過程來實現。例如,可以添加一個渲染條目來調整飽和度值。通過這種方式,可以在最終的圖像上應用飽和度調整。具體做法是,在進行渲染時,添加一個飽和度參數,并在最終渲染輸出時循環遍歷每個像素并改變它們的飽和度。
為了實現這一點,可以在代碼中將目標緩沖區傳入并根據給定的飽和度值進行處理。這樣就可以在渲染過程中調整圖像的飽和度,通過修改像素的飽和度值來達到預期效果。
黑板:飽和度
可以通過將顏色從灰色的距離作為一個概念來理解飽和度調整。基本思路是將RGB值歸一化到0到1之間,然后計算它們的平均值(例如,R+G+B除以3)。接著,通過計算每個顏色與平均值的差異(即“delta”),根據飽和度值乘以這些差異,將顏色拉遠或拉近灰色。這種方法相對簡單,不需要進行復雜的顏色空間轉換(如HSV),也能達到調整飽和度的效果。
計算平均值和增量
為了實現飽和度調整,可以通過簡單的平均值方法來避免復雜的HSV轉換。首先,計算RGB值的平均值(例如R + G + B / 3),得到一個灰度值。為了提高灰度估算的準確度,可以考慮根據人的視覺感知,例如綠色比紅色和藍色更敏感,進行調整,但基本思路是通過RGB值計算出一個灰度值。
然后,計算每個顏色與平均值之間的差異(即“delta”),這個差異表示從灰色到原始顏色的距離。接著,可以通過將該差異乘以飽和度水平來調整顏色。如果飽和度水平為1.0,差異將完全恢復,飽和度為0時顏色變為灰色。
這樣的方法能夠在不進行復雜的顏色空間轉換的情況下調整飽和度,同時保留原始的透明度(Alpha通道)。
在游戲中查看,然后驅動它通過一個動畫參數
在上面的討論中,首先通過簡單的方式實現了圖像的去飽和化,圖像變為黑白。這種效果可以通過一個動畫參數來驅動,使得飽和度變化呈現動態效果。通過使用GameState->Time來控制飽和度的變化,可以讓飽和度周期性地從全色到無色之間轉換。這個效果的計算公式為:
GameState->Time * 0.5f + 0.5 * sin(GameState->Time)`,通過調整這個公式,可以實現飽和度隨時間的動態變化。
然而,這種實現方式并不是最準確的去飽和化方法。為了提高準確度,可以使用HSV顏色空間的快速轉換方法。雖然這種方法可能比當前的實現更精確,但也不一定是完美的,因此如果使用HSV轉換并返回到RGB空間,能夠達到更好的效果。
盡管當前的幀率非常低,且優化還不充分,但已經能看到飽和度的變化效果。
在這種方案中,光會從墻壁等地方水平反射嗎?
在這個方案中,討論了如何通過反射來處理光照,特別是在墻面等物體上實現水平方向的反射。重點是中間層的作用,這一層將用于獲取局部的反射效果,盡管目前并不確定這種方式的效果如何。中間層的目標是模擬光的反射,但對于這種方法的實際表現,尚未完全確定。
在2D光照的實現中,通常采用一些“黑科技”方法,效果的好壞取決于這些方法的調優程度。盡管不確定這種方式是否會有效,但會繼續嘗試看看能否從中得到預期的結果。
太棒了!現在我們可以過度飽和了
可以通過增加飽和度值來實現過度飽和的效果。通過調整該值,可以看到圖像的顏色變得更加飽和。此時,飽和度的增大會使顏色偏離正常范圍,從而產生過飽和的視覺效果。