Shader 魔法的學習之路(1):簡介與“Hello World!”


3樓貓 發佈時間:2022-05-12 09:14:32 作者:mnikn Language

這系列的教程我們會從零講解 shader 編程,如何用 shader 做一些酷炫的效果。
不過在此之前,我們先簡單介紹一下 shader 是什麼。

Shader 是什麼?能吃嗎?

我不想講那些太學術官方的解釋,一句話概括:Shader 是系統給你的一系列鉤子函數,主要用在圖形上,你可以在上面的鉤子函數基於像素級別改變甚至創造圖形。

Shader 的使用場景

可以到Shadertoy看下別人用 shader 創造的東西。
有人可能會問,這些東西為什麼不直接通過繪圖軟件或者動畫軟件搞出來,而非要用 shader 實現呢?
舉個例子:大家有玩過遊戲吧(沒玩過那就去玩),一些遊戲中當鼠標移到可交互的物品,為了看起來更顯眼,這些物品會有邊緣的高光,當鼠標移出去又恢復原狀。這系列的場景的存在,要求我們要有動態修改圖形的能力。

Shader 編程的一些基礎概念和術語

下面的術語和概念在之後的教程中會反覆提及,這裡先預習一下,看不懂也沒關係,後面會再提。
概念:
  • 圖形學渲染流水線:一個圖形需要經過多道工藝渲染出來,每項工藝接受上一條工藝的產物進行進一步的加功,這樣每道工藝互不相干形成了流水線,我們關注的 shader 就是其中的一道工藝。詳細介紹:點擊跳轉
術語:
  • fragment shader:處理每個像素的繪製顏色、方式的 shader
  • vetex shader:處理像素要在哪裡繪製的 shader
  • uv:畫布所有的像素點,整體表現為一個 0 到 1 分佈的矩陣
  • 零點:座標系的 (0,0) 點,本系列教程採用 webgl,默認零點在左下角

教程的一些參考和說明

這系列教程大部分思路和實現均來自Youtube視頻“Shadertoy for absolute beginners”,教程很不錯,建議去看一下。
本人目前也還在根據上述的視頻學習 shader,水平有限難免有錯誤,如果有什麼說得不對的歡迎指正。

Hello World!

接下來初步嘗試下 shader 編程。
由於 shader 編程在不同平臺的編寫形式不同,根據語法分為 glsl 和 hlsl,根據引擎分為:opengl、webgl、directx 和其他我不知道的引擎,一些遊戲引擎又會針對 shader 做一些封裝:Unity、UE、Godot。
這系列的教程不會詳細講不同平臺的區別,雖然不同平臺的函數、變量甚至語法可能都有差異,不過思路是共通的,本系列的代碼均使用 webgl,而且為了方便快速體驗 shader 編程,我們會在一個封裝好的平臺
Shadertoy 上去寫代碼,如果你已經有熟悉的平臺,例如 Unity,可以自己根據文中代碼進行實踐。

先來個 Hello World?不,我直接藍屏!

對於 shader 編程來說,畫個 hello world 還挺麻煩的,所以我們直接先畫個藍屏吧!
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { fragColor = vec4(0.0, 0.0, 1.0 ,1.0); }
一句核心代碼就實現了藍屏,我們逐步看下上面的代碼寫的是什麼意思。
首先我們定義了一個叫 mainImage 的函數,由於 shadertoy 做了一些封裝,其實這個和傳統的 shader 編程稍微有點不同。傳統的 shader 編程這個函數應該叫 fragment,也被叫為 fragment shader ,也沒有接受入參和出參。這個函數可以認為是系統給我們的鉤子函數,繪製每個像素時都會調用這個函數,具體的執行時機由系統決定。
然後就是一句核心代碼 fragColor = vec4(0.0, 0.0, 1.0 ,1.0)fragColor 是 webgl 的內置變量,表示當前像素的顏色。
後面的 vec4(0.0, 0.0, 1.0, 1.0)vec4 可以先看作是一個存了四個值的數據結構,變體還有 vec3vec2,裡面的值類型都是 float(浮點數),vec3 存的就是三個值,以此類推。
我們給 vec4 設置的值是 (0.0, 0.0, 1.0, 1.0),因為這個值是賦給 fragColor 的,那這個值就表示的是顏色值,顏色值用 rgba 表示,所以這個值的意思是紅色、綠色的值都為 0,藍色和 alpha 值為 1.0,所以最終展現了藍色。

再來個黃屏!

那如果我想要表現的是黃色,那要怎麼做呢?根據顏色混合的原理,黃色=紅色+綠色,所以我們這樣設置:
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { fragColor = vec4(1.0, 1.0, 0.0 ,1.0); }
一個像《電馭叛客2077》跳票通知的東西就出來啦!
這篇文章的內容目前為止沒講太多東西,主要是先讓大家熟悉一下,接下來就開始正式地繪製一些常規的圖案了。
本次文章的作業是,讓屏幕顯示出呼倫貝爾大草原的顏色。

© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com