KodeLife | Shader 實時編輯預覽的強大工具使用實踐

語言: CN / TW / HK

經常有朋友在群裡面問想學習 Shader 有什麼工具可以推薦?

今天它來了~~~

推薦一款強大的 Shader 實時編輯預覽的工具 —— KodeLife

對,它的名字就叫做 KodeLife ,可別看成 KobeLife 了,一個字母之差完全就是兩個概念。

KodeLife 的官網地址如下:

hexler.net/products/ko…

貼一張主頁封面圖:

有需要的同學可以去官網下載安裝,它是需要購買 License 的,不過可以免費使用兩個月。


KodeLife 的編輯功能

首次開啟 KodeLife 會載入並演示預設的 Shader 程式碼效果。

編輯區就是我們寫 Shader 程式碼的地方,背後的畫面就是實時預覽的效果。這畫面效果是會隨著時間不斷改變的,這裡只是靜態圖看不到而已。

首次開啟可能會被這個效果給嚇唬到,畢竟這畫面五顏六色而且還閃來閃去,其實很多東西都可以去掉的,一個簡單的例子會更容易上手一些。

如下圖:

看到這中間打鉤的三個選項了嘛,它們分別是 OpenGL 渲染不同階段對應的著色器,由於我們都是用 OpenGL ES ,它是 OpenGL 的子集,一些功能都被移除了,所以下面這些 Shader 都是用不到的。

簡單介紹一下它們的名字:

  • Tess Control

    • 全名:Tessellation Control Shader
    • 中文名:曲面細分著色器
  • Tess Eval

    • 全名:Tessellation Control Shader
    • 中文名:細分計算著色器
  • Geometry

    • 全名:Geometry Shader
    • 中文名:幾何著色器

拋開這三個不看,那麼剩下的標籤頁就是 VertexFragment ,分別是頂點著色器和片段著色器,這應該很熟悉了。


KodeLife 使用實踐

接下來我們就要新建一個 Shader 進行編寫。

File 裡面有兩種 New 新建檔案的型別。

其中第二個 New From Template 就會按照 Shadertoy 或者 The Book of Shaders 的示例來載入 Shader 模板工程。

溫馨提示:

Shadertoy 是非常有名的 Shader 學習網站,上面有著絢麗的 Shader 效果,並且有原始碼供學習,就是網站開啟速度太慢了。

The Book of Shaders 是一本非常有名的 Shader 入門學習書籍,講解的示例簡單易學。

這裡我們按照 The Book of Shaders 提供的模板新建一個工程來編寫程式碼。

下面是工程建好後對應的程式碼和效果。

它自帶了三個 unifrom 變數:

  • u_resolution
    • 影象的解析度
  • u_mouse
    • 滑鼠點的位置
  • u_time
    • 時間

可以在 Shader 去利用這個三個變數,它們的輸入值是由 KodeLife 來保證的,在右側可以檢視並修改這變數的具體值。

  • 數字 0 區域:

    • Shader 效果的預覽區域
  • 數字 1 區域:

    • 開關控制是否使用下面的屬性內容
    • 檢視當前的屬性,比如檢視並編輯影象解析度的
    • 指定 Clear Color 時的顏色
  • 數字 2 區域:

    • 時間變數,可以在裡面控制時間的開始和停止
    • 可以調整時間變化的速
    • 可以調整時間變化的起始和結束值,並在該區域內迴圈
  • 數字 3 區域:

    • 顯示圖片的解析度
  • 數字 4 區域:

    • 設定滑鼠的點選區域
    • 在數字 4 的右側區域內點選滑鼠,改變滑鼠區域值
    • 可以單獨設定 X 和 Y 值,也可以設定是否要歸一化操作

以上就是 KodeLife 進行 Shader 編寫的操作部分了,相信你也已經知道要如何操作了。

如果使用 Shadertoy 提供的模板,它自帶的變數會多一點,但都大同小異了,而且這都不是重點,重點還是如何使用這些變數進行創作。

所以接下來就是發揮想象力進行 Shader 的開發了。


KodeLife Shader 編寫實踐

提供兩個簡單例子,演示一下在 KodeLife 中編寫程式碼實現網格效果。

程式碼如下:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {

    vec2 fragcoord = vec2(gl_FragCoord.xy / u_resolution);
    vec3 bgColor = vec3(1.0,1.0,1.0);
    vec3 pixelColor = bgColor;
    vec3 gridColor = vec3(0.5,0.5,0.5);
    
    const float width = 0.1;
    const float minWidth = 0.003;
    for(float i = 0.0; i < 1.0; i+=width){
        if (mod(fragcoord.x,width) < minWidth || mod(fragcoord.y,width) < minWidth){
            pixelColor = gridColor;
        }
    }
    
    gl_FragColor = vec4(pixelColor,1.0);
}
複製程式碼

效果如下:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    
    vec2 r = vec2(gl_FragCoord.xy - 0.5 * u_resolution);
    vec2 fragcoord = 2.0 * r.xy / u_resolution;
    
    vec3 bgColor = vec3(1.0,1.0,1.0);
    vec3 pixelColor = bgColor;
    vec3 gridColor = vec3(0.5,0.5,0.5);
    vec3 axesColor = vec3(1.0,0.0,0.0);
    
    const float width = 0.1;
    const float minWidth = 0.008;
    for(float i = 0.0; i < 1.0; i+=width){
        if (mod(fragcoord.x,width) < minWidth || mod(fragcoord.y,width) < minWidth){
            pixelColor = gridColor;
        }
    }
    
    if (abs(fragcoord.x) < 0.008 || abs(fragcoord.y) < 0.008){
        pixelColor = axesColor;
    }
    
    
    gl_FragColor = vec4(pixelColor,1.0);
}
複製程式碼

效果如下:

把程式碼複製貼上到 KodeLife 中執行就能看到效果了。

這兩個效果的區別就是在於中間座標軸繪製了,你能從程式碼中看到有何不同嗎?

在後續的文章再來講解如何編寫 Shader 吧~~~

能力不足,經驗有限,文中有何不對的地方歡迎批評指正,也可以加我微信 ezglumes 交流~~