GameDesign 板


LINE

這篇是 Ray Marching 相關系列的最後一篇, 接著看緣份吧,因為越寫越不『超』新手了。 今天我為這篇文章寫的 shader 在這: https://youtu.be/P4wCIKMwYlE
沒錯,有顏色了,這次的主題就是光, 與如何讓物件疊加的方法。 (畫面裏面有『四個』球) 其實要我寫『光』的教學文,我感覺超心虛的。 我微積分學的不好,很多東西我只會抄, 一堆相關公式文章wiki根本看不懂在說三隻小貓的。 別說我自己寫了, 我還希望有哪個大師寫給我看勒。Orz 所以... 這篇真的是新手文囉。 [基本知識] 這篇『不會』說到像是用 Game Engine 或是 Blender, 先做幾個多邊形,然後擺個光源調個強度, 再改一改材質就做會出來的效果。 這篇是新手文,不是大學電腦繪圖課。:> 這篇會講的是體積光 (Volumetric Light)。 體積光是甚麼?體積光也有人叫他 God Light,長這樣: https://i.ebayimg.com/images/g/mggAAOSwShpZc31P/s-l500.jpg
早期的電腦繪圖,光影效果只出現在實際存在的鋼體上。 像是實心的球表面有光暗反射散射等等的效果, 影子也只會出現在實體的地面上, 那些也就是我上面說的大學電腦繪圖課會教的東西。 但體積光,就像上面那個天使要降臨前的光束, 是在空無一物的空氣中出現的。 這種東西就像讓光有體積,或是把光當作物體一樣看待, 所以就叫體積光。 我們之前二個 shader, 不都有假定世界任何一個點都有密度嗎? 只要有密度,就能被光照到, 而且密度不是 1,光就能透過去, 並照到下一個點 (ray marching)。 這概念其實就是體積光。 再換個說法,現實中看的到體積光,是因為空氣中有粉塵, 粉塵多寡就代表了該點為中心的某個範圍的密度, 所以是很符合物理現實的。 除了體積光,還需要知道一些光的基本常識: 1. 反射 (Reflection) 就國中物理的入射光反射光那些東西, 這篇 shader 沒用到,再用 GPU 都要燒起來了。 2 吸收 (Absortion) 光射到一個物體,某些波長會被吸收變成熱量之類的, 沒被吸收然後反射的部分就是顏色。 3. 透射 (Transmittance) 光可以穿過透明物體,不過會有耗損 (被反射或被吸收了) 所以,Reflection + Absortion + Transmittance = 1.0 透射就是等等程式裡的密度, 程式中的光的顏色則是代表了吸收的概念。 大家國中物理一定都學得很好, 所以我們開始看程式吧!(笑) [程式] 程式在這: https://www.shadertoy.com/view/fdycD3 基本邏輯都是繼承前二篇的,所以看不懂可以先翻前面的看。 [世界構成] func 跟之前長的一樣 void world( vec3 pos, out distance, out density ) 這次世界有四個球,ball_1 ~ ball_4。 雖然前一個範例也有 sky/river 二個物體, 但二者沒有任何交集,顏色只是加起來而已。 這是世界的四個球是有重疊的, 這種情況,密度和最短距離要用正確的方法算。 最短距離: 先分別算 pos 對四顆球的最短距離, 然後在四個數字中取最小的。 min( min( min( dis1, dis2 ), dis3 ), dis4 ); 密度: 二種算法, 一種是四個球的密度取最大值。 一種是把四個值加起來。 沒有好壞,是疊加處的感覺不同。 我的感覺是透明度越低的,越適合最大值,反之是疊加值。 二種在程式中都有寫,可以試試。 [用 ray marching 算顏色] raymarch() 現在不是回傳該方向的總密度, 而是直接回傳該方向的總顏色了。 vec4 raymarch( in vec3 ro, in vec3 rd ) 要怎麼算某個方向的總顏色呢? 總顏色跟總密度一樣, 是 raymarch 的路徑上所有的採樣點的顏色的總和, 密度高的點顏色佔的比例高,密度低的比例低, 比例的高底是放在 color.a 的透明度裡面。 計算方法跟總密度的算法幾乎一樣。 color.a *= 0.4; // 跟範例 (六) 把密度調低在加的意思一樣 color.rgb *= color.a; // 照透明度調淡顏色 color_sum += color * (1.0 - color_sum.a); 那要怎麼算出各別的採樣點的顏色呢? 假設採樣點位置是 pos, 首先,我們有個光源位置: LIGHT_POS = vec3( -2.1, -2.6, 1.2 ), 接著我們可以算出採樣點到光源的方向向量。 然後從採樣點出發, 往光源方向 ray marching 前進某距離, 再算出 pos 到光源的該距離的總密度 t。 t 代表 Transmittance (透射率), 密度高的路線,光比較不容易射到 pos, 密度低的路線,光比較容易射到 pos, 若 t = 0,光線可以沒有任何耗損直接射到 pos。 也就是說, t 越高,光的影響越低, t 越低,光的影響越高。 假設光的顏色是 light_color, 我們就依照透射率比例,加光的顏色加在原本該點的顏色上, 如此就是下面 code 的意思: t = lightmarch( pos, LIGHT_POS ); vec3 light_color = vec3(1.0,0.6,0.3); vec3 ambient_color = vec3(0.91,0.98,1.05); color.rgb = color.rgb * (light_color*(1.0-t) + ambient_color); 那... ambient color 是甚麼? 如果有用 Blender 或任何的遊戲引擎做過 3D 遊戲都應該用過, 這是 "如果沒有任何光源時,物體的基本自體發光"。 你可以把 ambient_color = vec3(0.0), 然後就會發現光照不到的地方都變全黑了。 在做 3D 遊戲時, 有 ambient color 其實不太好, 因為不好控制光源效果。 比較好的做法是多放幾個光源, 像 direction light 之類的, 但這只是 shader 範例,所以別在意這個了。 [最佳化] 我們一直都沒討論最佳化的問題, 但當你在做光影時,最佳化的問題是避免不了的。 像是我這個範例,在瀏覽器的 WebGL 跑, 若你拿幾千塊的手機或是平板, fps 我猜就 10 上下吧。XD 那要怎麼辦呢? 首先,我們真的需要對畫面上所有的方向做 ray marching 嗎? 像前一個例子,做天空時,畫面下半部的點可以通通不做 ray march, 做河流時,畫面上半部也是一樣,馬上就可以減少一半的計算。 而以這個四球例子,一般要先算 ro/rd 是否有和任何物體相交, 有相交再做 ray marching。 甚麼? 怎麼知道一條 ro/rd 的光線有沒有和四顆球相交? wiki 公式和證明: https://bit.ly/39AgCMz 看不懂在寫三隻小貓?顆顆,寫成 code 是這樣: // i remember its from Duke in shadertoy, // but i can't find the origin post, sorry bool inter(v3 ro,v3 rd,v3 pos,f radius,v3 pt) { v3 pos2ro = (ro - pos); float b = dot(pos2ro, rd); float c = dot(pos2ro, pos2ro) - radius*radius; float d = b*b - c; pt = ro + rd*(-b - sqrt(d));//第一個交點 return d >= 0.0; } 不是我寫的,給你參考。 還有,光源的 ray marching 採樣 可是直接讓計算次數以倍數成長的, 到底採樣幾次,才會達到你預期的效果? 還是只採樣最遠的那個採樣點, 然後照比例算透射率就好? 然後,我們真的需要這麼逼真的表面嗎? 不用的話,減少 ray marching 採樣次數, 然後調整 noise 參數找到可接受的就好, 像前一個大河的例子, 從 40 次降到 20 次其實也還行。 最後,如果這不是遊戲的主要重點, 我們是不是該手動降低 fps, 把資源留給遊戲前景呢? 作法只是不用每次都在 main 裏叫 ray marching, 加個 timer 減少畫面的更新。 [結語] 連寫了三篇 ray marching,算是把基本的都講完了。 靠這三篇的基礎,也可以在遊戲中做出很炫的東西了。 美麗的夜空、磅礡的大雨、 深海的景象、宇宙、爆炸、通通都做得出來。 但做得出來跟做的漂不漂亮是二回事就是了, 美感是很吃天份的 (我就沒有), 請多看看其他神人的作品吧。 --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.228.104.110 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/GameDesign/M.1655700635.A.0DF.html ※ 編輯: meowyih (61.228.104.110 臺灣), 06/20/2022 13:37:10
1F:推 kyushu: 感謝分享,收藏ing 06/20 19:15
2F:推 NciscalA: 推推 06/21 09:36
3F:推 kindamark: 推 06/21 12:46
4F:推 eugenelinrmx: 推分享 06/21 22:59







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:BabyMother站內搜尋

TOP