Github霸榜:從零開始學3D著色器編程

2021-01-08 新智元

新智元原創

來源:Github

編輯:元子

【新智元導讀】這篇教程是今日GitHub趨勢榜第一,一天便達到了1500星。主要介紹了通過使用Panda3D遊戲引擎和OpenGL著色語言來為3D遊戲添加紋理,法線貼圖,泛光,環境遮擋等等。教程內容十分豐富,動圖也非常生動。

Shader,是運行在GPU上的程序,中文稱為著色器。它的主要用途是對三維物體進行著色處理,對光與影進行計算,以及控制紋理顏色的呈現等,最終,將遊戲引擎中的幾何數據轉化為屏幕上的模型、場景以及特效。

吃雞、農藥、戰地、塞爾達…都離不開著色器,著色器被譽為照亮虛擬世界的"魔法"。 著色器還可以用來做後期處理,類似PS。

著色程序是一整套編譯好並連結在一起的著色器的集合。著色器shader的編寫需要使用著色語言GL Shader Language(GLSL),GLSL的語法與C語言很類似。

著色器編程不光是對開發技能的考驗,更是對程式設計師想像力的挑戰,以至於有說法稱會寫Shader的程式設計師是站在食物鏈頂端的人。想成為遊戲開發高手,著色器編程是必備技能。

有興趣在3D遊戲中添加紋理,光照,陰影,法線貼圖,環境光遮蔽了嗎?好極了!今天新智元為大家帶來一個Github項目,從零開始教會大家進行3D遊戲著色。

以下一系列著色技術,都是具有高可移植的技巧,無論是Godot還是Unity都將適用。通過這些技術,你的遊戲視覺效果將提升到新的高度。

對於著色器之間的粘合劑,作者選擇了神器Panda3D遊戲引擎和OpenGL著色語言(GLSL)。

Panda3D是一個強大的渲染引擎。核心渲染模塊基於C++開發。Panda3D提供了Python的腳本化實用接口。

本項目code在以下環境下測試通過。

Linux manjaro 4.9.135-1-MANJAROOpenGL renderer string: GeForce GTX 970/PCIe/SSE2OpenGL version string: 4.6.0 NVIDIA 410.73g++ (GCC) 8.2.1 20180831Panda3D 1.10.1-1

本文只對該repo做一個大致介紹,具體代碼及講解請參閱項目地址:

https://github.com/lettier/3d-game-shaders-for-beginners.git

運行示例代碼需要先build

如果你想運行示例代碼,首先要先build。根據不同平臺安裝對應版本的Panda3D。其次,Clone項目repo,進入目錄,開始編譯。

Linux:

g++\ -c main.cxx \ -o 3d-game-shaders-for-beginners.o \ -std=gnu++11 \ -O2 \ -I/usr/include/python2.7/ \ -I/usr/include/panda3d/

編譯完成後執行:

g++\ 3d-game-shaders-for-beginners.o \ -o 3d-game-shaders-for-beginners \ -L/usr/lib/panda3d \ -lp3framework \ -lpanda \ -lpandafx \ -lpandaexpress \ -lp3dtoolconfig \ -lp3dtool \ -lp3pystub \ -lp3direct \ -lpthread

Mac:

clang++\ -c main.cxx \ -o 3d-game-shaders-for-beginners.o \ -std=gnu++11 \ -g \ -O2 \ -I/usr/include/python2.7/ \ -I/Developer/Panda3D/include/

編譯完成後執行:

clang++\ 3d-game-shaders-for-beginners.o \ -o 3d-game-shaders-for-beginners \ -L/Developer/Panda3D/lib \ -lp3framework \ -lpanda \ -lpandafx \ -lpandaexpress \ -lp3dtoolconfig \ -lp3dtool \ -lp3pystub \ -lp3direct \ -lpthread

坐標系統

開始插手著色器代碼之前,需要對3D物體的坐標系統有所了解。和在立體幾何的坐標系意義,繪製3D物體也是需要x、y、z三個坐標軸的值。

將定義好的坐標軸的值轉換為實際繪製的坐標,需要經過五個坐標系統的轉換。

模型空間

相對於原點 (0,0,0) 而自定義的起始坐標點。

世界空間

世界空間就是當所有物體一起繪製、仍然相對於原點的、更大的一個坐標系。可以防止模型出現扎堆兒情況。

觀察空間

將世界空間的坐標轉化為攝像機的視角所觀察到的空間坐標。

裁剪空間

根據我們的需要來裁剪一定範圍內的物體,而在這個範圍之外的坐標就會被忽略掉,實質上還是進行坐標的操作。

屏幕空間

將坐標投射到屏幕上。

渲染到紋理

渲染到紋理(Render To Texture, RTT)是現在很多特效裡面都會用到的一項很基本的技術,實現起來很簡單,也很重要。

渲染到紋理是為了實現一些特殊的效果,比如一個光滑的球體,它應該是可以反射周圍環境的,這個時候就需要先渲染到紋理。

在此設置中,示例代碼執行以下操作:

存儲幾何數據(如頂點位置或法線)供以後使用存儲材料數據(如漫反射顏色)供以後使用UV映射各種紋理(漫反射,普通,陰影等)計算環境光,漫反射光,鏡面光和發光光呈現霧

紋理和光照(Lighting)

紋理涉及使用UV坐標將一些顏色或一些其他類型的矢量映射到片段。 U和V的範圍從0到1。每個頂點都獲得一個UV坐標,並在頂點著色器中輸出。

完成lighting涉及到計算和組合環境光、漫反射光、鏡面光和發射光方面。示例代碼使用Phong lighting。Diffuse代碼:

// ...float diffuseIntensity = max(dot(normal, unitLightDirection), 0.0);if (diffuseIntensity > 0) {// ... }// ...

法線貼圖

法線貼圖(英語:Normal mapping)是一種模擬凹凸處光照效果的技術,是凸凹貼圖的一種實現。法線貼圖可以在不添加多邊形的前提下,為模型添加細節。常見的使用場景是為低多邊形模型改善外觀、添加細節,此時的法線貼圖一般根據高多邊形模型或高度貼圖生成。

頂點代碼:

// ...uniform mat3 p3d_NormalMatrix;// ...in vec3 p3d_Normal;// ...in vec3 p3d_Binormal;in vec3 p3d_Tangent;// ... vertexNormal = normalize(p3d_NormalMatrix * p3d_Normal); binormal = normalize(p3d_NormalMatrix * p3d_Binormal); tangent = normalize(p3d_NormalMatrix * p3d_Tangent);// ...

描邊

描邊著色器需要一個輸入紋理,用於檢測邊緣中的顏色。此輸入紋理的候選者包括材質的漫反射顏色、漫反射貼圖的顏色、頂點法線,甚至法線貼圖的顏色。

uniformstruct {vec4diffuse;}p3d_Material;outvec4 fragColor;voidmain() {vec3diffuseColor = p3d_Material.diffuse.rgb;fragColor = vec4(diffuseColor, 1);}

霧化、全屏泛光

霧(fog,或在Blender中稱為mist)將霧氣效果添加到場景中,提供神秘感和柔化。

// ...uniform structp3d_FogParameters { vec4 color ; float start ; float end ; } p3d_Fog;// ...

Panda3D提供了一個很好的數據結構,可以保存所有fog參數,你也可以手動將其傳遞給著色器。

Bloom有時候也叫Glow效果,中文一般叫做「全屏泛光」,可以使得發光物體看起來更逼真。

屏幕空間環境光遮蔽(SSAO)

環境光遮蔽(AO,ambient occlusion),大致上指的是幾何物體的拐角處,因為受光不全面(被相鄰的面擋光/遮蔽),導致變暗。屏幕環境光遮蔽技術使用了屏幕空間場景的深度而不是真實的幾何體數據來確定遮蔽量。這一做法相對於真正的環境光遮蔽不但速度快,而且還能獲得很好的效果,使得它成為近似實時環境光遮蔽的標準。

下面動圖展示了用AO和沒用AO的區別。用了AO,物體拐角的地方會變暗看起來就更逼真。

景深

景深(英語:Depth of field, DOF)景深是指相機對焦點前後相對清晰的成像範圍。在光學中,尤其是錄影或是攝影,是一個描述在空間中,可以清楚成像的距離範圍。

雖然透鏡只能夠將光聚到某一固定的距離,遠離此點則會逐漸模糊,但是在某一段特定的距離內,影像模糊的程度是肉眼無法察覺的,這段距離稱之為景深。

景深淺則模糊範圍大,虛化效果明顯。反之則虛化效果減弱。焦外代碼示例:

//...vec4result = vec4(0);for(int i = 0; i < size2; ++i) {x = size - xCount;y = yCount - size;result+=texture(blurTexture,texCoord+vec2(x * separation, y * separation));xCount-= 1;if(xCount < countMin) { xCount = countMax; yCount -= 1; }}result = result / size2;//...

色調分離和像素化

色調分離是指一幅圖像原本是由緊緊相鄰的漸變色階構成,被數種突然的顏色轉變所代替。這一種突然的轉變,亦稱作「跳階」。色調分離其實就是用來製造分色效果。

將3D遊戲像素化使他看起來很有趣,並可以節省時間,不必手動創建所有的像素藝術。和色調分離相結合,可以打造真正的復古外觀。

參考連結:

https://github.com/lettier/3d-game-shaders-for-beginners.git

相關焦點

  • 編程入門先學什麼?零經驗的人學編程難嗎
    「編程入門先學什麼」這是所有想了解編程行業都擔心的一個問題,「零經驗的人學編程難嗎」這是所有想進入編程行業都需要關注的一個問題。一聽編程兩個字很多人都在退縮了,有很多的同學是非常的想知道,編程入門先學什麼,零經驗的人學編程難不難,小編整理了相關信息,希望會對大家有所幫助!
  • 著色器語言,圖形計算量身定做、支持3D特效
    著色器是運行在GPU上的小程序,它是使用著色器語言GLSL編寫的。前面的文章中已經介紹了基於OpenGL如何畫出三角形和長方形,在這個過程中說明了著色器程序的創建、編譯和連結。著色器程序上則需要附著上頂點著色器、片段著色器。而頂點著色器、片段著色器是採用著色器語言編寫的。
  • 《Re:從零開始的異世界生活》霸氣屠榜,三大榜單,全榜第一
    自從《Re:從零開始的異世界生活》第一季出現之後,就陸續打破各種異世界穿越番的記錄,而在本次《Re:從零開始的異世界生活》第二季開播之後,這部作品也是再次成為本次新番作品中的霸權番!在放出的三個榜單中,《Re:從零開始的異世界生活》霸權屠榜,三大榜單,全榜第一!動漫新番人氣排行榜榜第一個榜單來自於本周的動漫新番人氣排行榜。
  • 《Re:從零開始的異世界生活》霸氣屠榜,三大榜單,全榜第一!
    在放出的三個榜單中,《Re:從零開始的異世界生活》霸權屠榜,三大榜單,全榜第一!動漫新番人氣排行榜榜第一個榜單來自於本周的動漫新番人氣排行榜。在本次的榜單中,菜月昴成功的碾壓了上周霸榜的桐人,成為了本周男性角色人氣排行榜的榜首。而且在目前更新的《Re:從零開始的異世界生活》第二季中,菜月昴將獨自一人完成本次的「聖域篇」,而這一章也是《Re:從零開始的異世界生活》故事中最為精彩的一部分。
  • 零基礎學編程應該怎麼開始?
    萬事開頭難,開始學編程前我們總會考慮到各方面的原因,難度?能學會嗎?學多久?怎麼學?等等,但是很少去關注自己的學習需求,比如自己的學習環境和學習效率等。所以學習前,我們需要深刻地認識自己,看自己處於什麼時期。
  • 學編程不止是為做程式設計師,編程貓小火箭學員家長:學編程,是培養思維...
    學編程不止是為做程式設計師,編程貓小火箭學員家長:學編程,是培養思維的好方式 2020年03月25日 10:26作者:網絡編輯:王動
  • 零基礎想學電腦編程技術,有哪些經驗可以借鑑
    網際網路行業發展迅猛,已經深入我們生活的方方面面,一般來說程式設計師剛畢業就能比某些行業的同屆畢業高几倍的工資,於是越來越多的人開始轉行到IT領域,程式設計師也不再基於計算機科學或軟體工程等個別專業的畢業生,其他非計算機相關專業的,像學物理、數學、自動化,甚至英語、藝術或歷史的,也都投入的程式設計師的行列。
  • 拒絕內卷,從不讓孩子學少兒編程開始
    01在b站上,一位叫vita的小學生,從去年8月開始,持續發布編程教學視頻,奶聲奶氣地講解信息加密、信息傳輸中的安全隱患等編程知識。熱度最高的一個視頻,播放量達221萬,vita很快成為少年網紅。vita今年9歲,上三年級。
  • 上古語言從入門到精通:COBOL教程登上GitHub熱榜
    上周,機器之心曾經介紹過美國新澤西州州長急聘 COBOL 程式設計師的這件事,很多人表示:「在大學裡還真學過 COBOL,但現在書都扔了。」雖然是一門「上古語言」,但銀行等機構都還在用。因此,有人表示想學習一下。畢竟,「選擇程式設計師這門職業,就意味著終生學習。」
  • 從零基礎能學會編程嗎?
    能夠讀懂0和1,就已經學會了編程首先聲明,我不是託也不是為XX培訓機構做廣告,我會從我自己的一個經歷告訴那些想學習編程的人,零基礎能否會學編程。我只有高中畢業,畢業後做了2年的模具學徒,然後參加了軟體研發的培訓機構學習編程。在這之前,我的電腦基礎就是高中的學習到的TT,然後做學徒時,見過的autocad軟體,玩遊戲的經驗吧。一定要講一下為什麼要去學習軟體編程,因為模具學不會,經常被說,臉皮比較薄。
  • 學編程的十大誤區:看看你中招了沒?
    我們學一樣技能,光是努力是不夠的,還要避免一些誤區,學習編程更是如此。如果你在學編程的過程中存在一些誤區,你的學編程之路就會事倍功半,甚至會從「入門」學到「放棄」。了解並避免一些學習編程中的誤區,有助於你更好的學習編程。
  • 網絡安全發展大勢所趨,10後都開始學編程了!
    重慶重慶《關於加強中小學編程教育的通知》文件中,明確規定小學編程教育3~6年級累計不少於36課時、初中階段編程教育累計不少於36課時,並配有專門的編程教師。隨著近年信息化的快速發展,網絡安全越來越重要,而編程是網絡安全一切的基礎,不僅學校,家長、社會培訓機構也都在有意識地培養未成年人的編程思維。10後都開始學編程了!9歲的10後女孩李妍自學編程製作的快閃作品,在青年創作大賽上大放異彩。
  • 次世代3d遊戲建模,零基礎的小白可以學嗎?
    次世代3d遊戲建模,零基礎、沒有美術基礎可以學嗎?首先需要明確的是無基礎是可以學習的,如果你自學能力較強,可以上上網課;如果自學能力和自律能力較弱,建議去參加專業培訓。
  • Scratch、Python學哪個?兒童編程怎麼學?全面解析編程(下)
    怎麼學編程1.學習的順序問題前面已經講到編程課程主要是Scratch、Python、C++、機器人類編程。建議可以先學Scratch,然後再學習Python,根據具體的學習結果,再決定是否學習信息奧賽或機器人。Scratch入門比較容易,趣味性強,並且可以學習基本的編程思想和方法,為後續的更專業的語言學習打下基礎。如果孩子對編程感興趣,那麼可以考慮系統的學習Python,Python語言語法簡潔。相比其他程式語言也比較容易入門,提供相關課程的培訓機構也比較多,網上也有很多相關的學習資源。
  • Scratch、Python學哪個?兒童編程怎麼學?全面解析編程(中)
    為什麼要學習編程?前文已經介紹了編程是什麼,有哪些可以學的程式語言。其實在學習編程之前,家長最關心的應該是為什麼要學習編程?學了編程孩子會有什麼收穫?接下來我們來討論這兩個問題。多數家長讓孩子學編程的原因可能有以下幾個:別的孩子都在學,我的孩子也不能落下收到編程培訓的廣告信息學校開設了相關的基礎課程,想再深入學習
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python視頻教程 2020年07月08日 11:00作者:黃頁編輯:黃頁
  • 大學生學編程需要什麼基礎?多久能學會呢
    眾所周知現在的程式設計師都是高薪工作,很多人會通過自學或培訓去獲得一些編程知識,那「學編程需要什麼基礎呢?」大學生學編程需要什麼基礎?多久能學會在學習編程的大軍中有相當一部分人是零基礎前來學習的,因此很多人在學習之前肯定會有這樣的疑問:「學編程需要什麼基礎?」
  • 8歲學編程已經晚了?6個網站讓你在家教孩子學編程
    少兒編程,有必要學嗎?從幾歲開始?  少兒編程的火熱的市場催生了大大小小、良莠不齊的培訓班,有的培訓班甚至在網上買幾套課程解碼,租個房子請幾個老師就開始招生,並且根據齊魯壹點報導,有的少兒編程培訓機構還打著「學編程——參加比賽——拿到好成績——升學有保證」的旗號招生,並且宣稱3歲就可以開始學編程了,8歲都有點晚了。
  • 我今年30歲了,現在才開始學編程,會不會太晚?
    時常收到類似這樣的問題我30歲了,現在才開始學編程,會不會太晚?28歲了,想轉行學編程,不知會不會太晚?不知道從什麼時候開始,焦慮這個詞開始在社交圈裡蔓延。甚至有人開始販賣焦慮,說程式設計師是吃青春飯的,程式設計師過了35歲了就沒有企業要了。其實不然,筆者身邊有不少35歲的同事,有的還40歲多歲了,還堅持在一線編碼上,也都過得還不錯。年齡從來不是學習的阻礙,編程也是一樣,如果你想從 30 歲開始學習編程,不妨先看看日本一位 82 歲的老奶奶的故事。
  • 使命召喚戰區怎麼刪除著色器 著色器刪除方法
    ———————————————————————————————————— 使命召喚戰區怎麼刪除著色器?著色器刪除要注意些什麼?著色器刪除有什麼技巧嗎?