這篇教程是今日GitHub趨勢榜第一,一天便達(dá)到了1500星。主要介紹了通過使用Panda3D游戲引擎和OpenGL著色語言來為3D游戲添加紋理,法線貼圖,泛光,環(huán)境遮擋等等。教程內(nèi)容十分豐富,動圖也非常生動。
Shader,是運行在GPU上的程序,中文稱為著色器。它的主要用途是對三維物體進(jìn)行著色處理,對光與影進(jìn)行計算,以及控制紋理顏色的呈現(xiàn)等,最終,將游戲引擎中的幾何數(shù)據(jù)轉(zhuǎn)化為屏幕上的模型、場景以及特效。
吃雞、農(nóng)藥、戰(zhàn)地、塞爾達(dá)…都離不開著色器,著色器被譽為照亮虛擬世界的"魔法"。 著色器還可以用來做后期處理,類似PS。
著色程序是一整套編譯好并鏈接在一起的著色器的集合。著色器shader的編寫需要使用著色語言GL Shader Language(GLSL),GLSL的語法與C語言很類似。
著色器編程不光是對開發(fā)技能的考驗,更是對程序員想象力的挑戰(zhàn),以至于有說法稱會寫Shader的程序員是站在食物鏈頂端的人。想成為游戲開發(fā)高手,著色器編程是必備技能。
有興趣在3D游戲中添加紋理,光照,陰影,法線貼圖,環(huán)境光遮蔽了嗎?好極了!今天新智元為大家?guī)硪粋€Github項目,從零開始教會大家進(jìn)行3D游戲著色。
以下一系列著色技術(shù),都是具有高可移植的技巧,無論是Godot還是Unity都將適用。通過這些技術(shù),你的游戲視覺效果將提升到新的高度。
對于著色器之間的粘合劑,作者選擇了神器Panda3D游戲引擎和OpenGL著色語言(GLSL)。
Panda3D是一個強大的渲染引擎。核心渲染模塊基于C++開發(fā)。Panda3D提供了Python的腳本化實用接口。
本項目code在以下環(huán)境下測試通過。
Linux manjaro 4.9.135-1-MANJARO
OpenGL renderer string: GeForce GTX 970/PCIe/SSE2
OpenGL version string: 4.6.0 NVIDIA 410.73
g++ (GCC) 8.2.1 20180831
Panda3D 1.10.1-1
本文只對該repo做一個大致介紹,具體代碼及講解請參閱項目地址:
https://github.com/lettier/3d-game-shaders-for-beginners.git
運行示例代碼需要先build
如果你想運行示例代碼,首先要先build。根據(jù)不同平臺安裝對應(yīng)版本的Panda3D。其次,Clone項目repo,進(jìn)入目錄,開始編譯。
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/
編譯完成后執(zhí)行:
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/
編譯完成后執(zhí)行:
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坐標(biāo)系統(tǒng)
開始插手著色器代碼之前,需要對3D物體的坐標(biāo)系統(tǒng)有所了解。和在立體幾何的坐標(biāo)系意義,繪制3D物體也是需要x、y、z三個坐標(biāo)軸的值。
將定義好的坐標(biāo)軸的值轉(zhuǎn)換為實際繪制的坐標(biāo),需要經(jīng)過五個坐標(biāo)系統(tǒng)的轉(zhuǎn)換。
模型空間
相對于原點 (0,0,0) 而自定義的起始坐標(biāo)點。
世界空間
世界空間就是當(dāng)所有物體一起繪制、仍然相對于原點的、更大的一個坐標(biāo)系??梢苑乐鼓P统霈F(xiàn)扎堆兒情況。
觀察空間
將世界空間的坐標(biāo)轉(zhuǎn)化為攝像機的視角所觀察到的空間坐標(biāo)。
裁剪空間
根據(jù)我們的需要來裁剪一定范圍內(nèi)的物體,而在這個范圍之外的坐標(biāo)就會被忽略掉,實質(zhì)上還是進(jìn)行坐標(biāo)的操作。
屏幕空間
將坐標(biāo)投射到屏幕上。
渲染到紋理
渲染到紋理(Render To Texture, RTT)是現(xiàn)在很多特效里面都會用到的一項很基本的技術(shù),實現(xiàn)起來很簡單,也很重要。
渲染到紋理是為了實現(xiàn)一些特殊的效果,比如一個光滑的球體,它應(yīng)該是可以反射周圍環(huán)境的,這個時候就需要先渲染到紋理。
在此設(shè)置中,示例代碼執(zhí)行以下操作:
存儲幾何數(shù)據(jù)(如頂點位置或法線)供以后使用
存儲材料數(shù)據(jù)(如漫反射顏色)供以后使用
UV映射各種紋理(漫反射,普通,陰影等)
計算環(huán)境光,漫反射光,鏡面光和發(fā)光光
呈現(xiàn)霧
紋理和光照(Lighting)
紋理涉及使用UV坐標(biāo)將一些顏色或一些其他類型的矢量映射到片段。 U和V的范圍從0到1。每個頂點都獲得一個UV坐標(biāo),并在頂點著色器中輸出。
完成lighting涉及到計算和組合環(huán)境光、漫反射光、鏡面光和發(fā)射光方面。示例代碼使用Phong lighting。Diffuse代碼:
// ... float diffuseIntensity = max(dot(normal, unitLightDirection), 0.0); if (diffuseIntensity > 0) { // ... } // ...
法線貼圖
法線貼圖(英語:Normal mapping)是一種模擬凹凸處光照效果的技術(shù),是凸凹貼圖的一種實現(xiàn)。法線貼圖可以在不添加多邊形的前提下,為模型添加細(xì)節(jié)。常見的使用場景是為低多邊形模型改善外觀、添加細(xì)節(jié),此時的法線貼圖一般根據(jù)高多邊形模型或高度貼圖生成。
頂點代碼:
// ...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); // ...
描邊
描邊著色器需要一個輸入紋理,用于檢測邊緣中的顏色。此輸入紋理的候選者包括材質(zhì)的漫反射顏色、漫反射貼圖的顏色、頂點法線,甚至法線貼圖的顏色。
uniform struct { vec4 diffuse;} p3d_Material;out vec4 fragColor;void main() { vec3 diffuseColor = p3d_Material.diffuse.rgb; fragColor = vec4(diffuseColor, 1);}
霧化、全屏泛光
霧(fog,或在Blender中稱為mist)將霧氣效果添加到場景中,提供神秘感和柔化。
// ...uniform struct p3d_FogParameters { vec4 color ; float start ; float end ; } p3d_Fog;// ...
Panda3D提供了一個很好的數(shù)據(jù)結(jié)構(gòu),可以保存所有fog參數(shù),你也可以手動將其傳遞給著色器。
Bloom有時候也叫Glow效果,中文一般叫做“全屏泛光”,可以使得發(fā)光物體看起來更逼真。
屏幕空間環(huán)境光遮蔽(SSAO)
環(huán)境光遮蔽(AO,ambient occlusion),大致上指的是幾何物體的拐角處,因為受光不全面(被相鄰的面擋光/遮蔽),導(dǎo)致變暗。屏幕環(huán)境光遮蔽技術(shù)使用了屏幕空間場景的深度而不是真實的幾何體數(shù)據(jù)來確定遮蔽量。這一做法相對于真正的環(huán)境光遮蔽不但速度快,而且還能獲得很好的效果,使得它成為近似實時環(huán)境光遮蔽的標(biāo)準(zhǔn)。
下面動圖展示了用AO和沒用AO的區(qū)別。用了AO,物體拐角的地方會變暗看起來就更逼真。
景深
景深(英語:Depth of field, DOF)景深是指相機對焦點前后相對清晰的成像范圍。在光學(xué)中,尤其是錄影或是攝影,是一個描述在空間中,可以清楚成像的距離范圍。
雖然透鏡只能夠?qū)⒐饩鄣侥骋还潭ǖ木嚯x,遠(yuǎn)離此點則會逐漸模糊,但是在某一段特定的距離內(nèi),影像模糊的程度是肉眼無法察覺的,這段距離稱之為景深。
景深淺則模糊范圍大,虛化效果明顯。反之則虛化效果減弱。焦外代碼示例:
// ... vec4 result = 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; // ...色調(diào)分離和像素化
色調(diào)分離是指一幅圖像原本是由緊緊相鄰的漸變色階構(gòu)成,被數(shù)種突然的顏色轉(zhuǎn)變所代替。這一種突然的轉(zhuǎn)變,亦稱作“跳階”。色調(diào)分離其實就是用來制造分色效果。
將3D游戲像素化使他看起來很有趣,并可以節(jié)省時間,不必手動創(chuàng)建所有的像素藝術(shù)。和色調(diào)分離相結(jié)合,可以打造真正的復(fù)古外觀。
-
OpenGL
+關(guān)注
關(guān)注
1文章
85瀏覽量
29201 -
編程
+關(guān)注
關(guān)注
88文章
3565瀏覽量
93536 -
3D游戲
+關(guān)注
關(guān)注
0文章
10瀏覽量
10056
原文標(biāo)題:Github霸榜:從零開始學(xué)3D著色器編程
文章出處:【微信號:AI_era,微信公眾號:新智元】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論