安利一個 Visual Studio Code 的 Shader 插件【免費】|8月更文挑戰

Visual Studio Code - Shader Toy

這個擴展能夠在 VSCode 中查看 GLSL 着色器的 WebGL 實時預覽,經過提供 「Show GLSL Preview」 命令能夠達到相似於訪問 shadertoy.com 的效果。node

要運行該命令,能夠打開 「Command Palette」 並輸入「 Shader Toy: Show GLSL Preview 」,或者在文本編輯器中右鍵單擊並從上下文菜單中選擇 「Shader Toy: Show GLSL Preview」 。git

運行該命令將視圖分割並顯示一個應用了您的着色器的全屏四方的視圖。您的片斷着色器的入口點是 void main() ,或者若是前者不可用,那麼入口點則是 void mainImage(vec4 out,vec2 in) ,其中第一個參數是輸出顏色,第二個參數是片斷屏幕位置。github

另外一個可用的命令是 「Shader Toy: Show Static GLSL Preview」 ,它將打開一個預覽,但不會對變化的編輯器做出反應。能夠一次打開任意數量的編輯視圖,這使得依賴於多個通道的着色器能夠被一個惟一的工做流進行編輯。瀏覽器

特色

Uniforms 變量

目前,iResolutioniGlobalTime(也稱 iTime)、iTimeDeltaiFrameiMouseiMouseButtoniDateiSampleRateiChannelN (其中 N 在 [0,9] 區間內)和 iChannelResolution[] 都是可用的 uniform 變量。安全

紋理輸入

紋理通道 iChannelN 能夠經過在着色器頂部插入以下形式的代碼來定義服務器

#iChannel0 "file://duck.png"
#iChannel1 "https://66.media.tumblr.com/tumblr_mcmeonhR1e1ridypxo1_500.jpg"
#iChannel2 "file://other/shader.glsl"
#iChannel2 "self"
#iChannel4 "file://music/epic.mp3"
複製代碼

以上代碼演示了markdown

  1. 使用本地和遠程圖像做爲紋理(注意,紋理大小是 2 的冪次是你一般須要遵照的規範);
  2. 使用另外一個着色器結果做爲紋理;
  3. 經過指定 self 使用這個着色器的最後一幀;
  4. 使用音頻輸入。

注意,要使用本地輸入的相對路徑,您必須在可視代碼中打開一個文件夾。app

紋理示例爲了影響紋理的採樣行爲,使用如下語法:編輯器

#iChannel0::MinFilter "NearestMipMapNearest"
#iChannel0::MagFilter "Nearest"
#iChannel0::WrapMode "Repeat"
複製代碼

注意,由於 WebGL 標準,許多選項只能在寬度和高度都是 2 的冪次狀況下工做。函數

立方貼圖輸入

Cubemaps 能夠指定爲任何其餘紋理,事實上,它們是 Cubemaps 的路徑包含通配符和它們的類型被顯式聲明的組合。

#iChannel0 "file://cubemaps/yokohama_{}.jpg" // 注意 '{}'
#iChannel0::Type "CubeMap"
複製代碼

通配符將經過替換下列集合中的任何值來解析

  • [ 'e', 'w', 'u', 'd', 'n', 's' ],
  • [ 'east', 'west', 'up', 'down', 'north', 'south' ],
  • [ 'px', 'nx', 'py', 'ny', 'pz', 'nz' ] or
  • [ 'posx', 'negx', 'posy', 'negy', 'posz', 'negz' ].

若是找不到這六個文件中的任何一個,就從下一個集合的第一個開始嘗試。

音頻輸入(實驗性的)

注意: 默認狀況下音頻輸入是禁用的,更改設置 「Enable Audio Input」 來啓用它。

不支持音頻輸入從內部_Visual Studio代碼,由於ffmpeg不是附帶Visual Studio代碼,因此您必須生成一個獨立的版本和主機本地服務器可以加載本地文件(或擺弄你的瀏覽器安全設置)若是您想要在着色器使用音頻的話。若是您的通道定義了音頻輸入,它將從文件擴展名中推斷出來。通道將是一個 2 像素高和 512 像素寬的紋理,寬度能夠經過「Audio Domain Size」 設置來調整。第一行包含音頻頻譜,第二行包含其波形。

鍵盤輸入

若是你想使用鍵盤輸入,你能夠在着色器前加上 #iKeyboard。這將暴露給你的着色器如下功能:

bool isKeyPressed(int);
bool isKeyReleased(int);
bool isKeyDown(int);
bool isKeyToggled(int);
複製代碼

此外,它還將暴露從 Key_AKey_Z、從 Key_0Key_9Key_UpArrowKey_LeftArrowKey_Shift 等變量。使用這些常量和上面提到的函數來查詢鍵盤的狀態。

引用其餘(include)着色器

你也能夠經過一個標準的 c 類語法來包括其餘文件到你的着色器中:

#include "some/shared/code.glsl"
#include "other/local/shader_code.glsl"
#include "d:/some/global/code.glsl"
複製代碼

注意:這些着色器不能定義void main() 函數,所以只能用於工具函數、常量定義等。

自定義 Uniforms 變量 (實驗性的,易變的)

使用自定義 uniform 變量定義那些直接在你的着色器中使用的 uniform 變量,給一個初始值以及一個可選的範圍。

#iUniform float my_scalar = 1.0 in { 0.0, 5.0 }                   // 這將暴露一個滑動條來編輯該值
#iUniform float my_discreet_scalar = 1.0 in { 0.0, 5.0 } step 0.2 // 步長爲 0.2

#iUniform float other_scalar = 5.0                                // 這將公開一個文本字段以給出任意值
#iUniform vec2 position_in_2d = vec2(1.0) // 暴露兩個文本字段
#iUniform color3 my_color = color3(1.0)                           // 這將是一個可編輯的顏色選擇器
#iUniform vec4 other_color = vec4(1.0) in { 0.0, 1.0 }            // 這將暴露四個滑塊
複製代碼

與 Shadertoy.com 的兼容性

下面是一個從 shadertoy.com 移植的 shader 的例子:

// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// Created by S.Guillitte
void main() {
  float time = iGlobalTime * 1.0;
  vec2 uv = (gl_FragCoord.xy / iResolution.xx - 0.5) * 8.0;
  vec2 uv0 = uv;
  float i0 = 1.0;
  float i1 = 1.0;
  float i2 = 1.0;
  float i4 = 0.0;
  for (int s = 0; s < 7; s++) {
    vec2 r;
    r = vec2(cos(uv.y * i0 - i4 + time / i1), sin(uv.x * i0 - i4 + time / i1)) / i2;
    r += vec2(-r.y, r.x) * 0.3;
    uv.xy += r;

    i0 *= 1.93;
    i1 *= 1.15;
    i2 *= 1.7;
    i4 += 0.05 + 0.1 * time * i1;
  }
  float r = sin(uv.x - time) * 0.5 + 0.5;
  float b = sin(uv.y + time) * 0.5 + 0.5;
  float g = sin((uv.x + uv.y + sin(time * 0.5)) * 0.5) * 0.5 + 0.5;
  gl_FragColor = vec4(r, g, b, 1.0);
}
複製代碼

注意,與 shadertoy.com 相比,gl_FragCoord 代替了 fragCoord, gl_FragColor 代替了原始演示中的 fragColor。可是,對於插入一個簡單的 void main() 有一個基本的支持,它將委託給一個 void mainImage(vec4 out,vec2 in) 函數。void main() 的定義是經過匹配 regex /void\s+main\s (\s)\s*{/g** 找到的,所以,若是除了擴展生成的定義以外還須要定義 void main() ,則能夠將其定義爲 void main(void) 。例如,若是您的 main 定義將被預處理器處理掉,並所以擴展不接受該定義,則可能有必要這麼作。

英文原文:Note that compared to shadertoy.com gl_FragCoord replaces fragCoord and gl_FragColor replaces fragColor in the original demo. There is however a rudimentary support for inserting a trivial void main() which will delegate to a void mainImage(out vec4, in vec2) function. The definition of void main() is found by matching the regex /void\s+main\s*(\s*)\s*{/g, thus if you require to define void main() in addition to the extension generating a definition you may define it as void main(void). This might be necessary, for example, if your main definition would be processed away by the preprocessor and should thus not be picked up by the extension.

glslify 的集成

您能夠在設置中啓用對 glslify 的支持,可是由於 glslify 不支持轉換先後的行映射,因此只要啓用了設置,就會遺憾地禁用錯誤上的行號。使用 glslify 容許爲您的着色器使用 node.js 風格的模塊系統:

#pragma glslify: snoise = require('glsl-noise/simplex/2d')

float noise(in vec2 pt) {
    return snoise(pt) * 0.5 + 0.5;
}

void main () {
    float r = noise(gl_FragCoord.xy * 0.01);
    float g = noise(gl_FragCoord.xy * 0.01 + 100.0);
    float b = noise(gl_FragCoord.xy * 0.01 + 300.0);
    gl_FragColor = vec4(r, g, b, 1);
}
複製代碼

GLSL 預覽交互

該擴展在GLSL預覽中提供了一個暫停按鈕來中止時間的前進。與此相結合,您可使用 GLSL 預覽中提供的屏幕快照按鈕來捕獲和保存幀。默認狀況下,保存的屏幕截圖的分辨率與 GLSL 預覽的分辨率相同的,不過有一個設置容許用戶使用任意值覆蓋該分辨率。最後,擴展提供了一個關於着色器性能和內存消耗的淺顯視圖。

錯誤高亮

該擴展還支持在文本編輯器中突出顯示編譯錯誤,對於單個着色器也是如此,對於多個通道的也是如此。它經過在文本編輯器中直接顯示做爲診斷的錯誤,以及在 GLSL 預覽窗口中以可理解的格式顯示錯誤,並容許用戶與錯誤消息交互跳轉到相關行,並在必要時打開相關文件來實現:

要求

  • 一個支持 WebGL 的顯卡.

已知的問題

  • 目前某些着色器的性能不是很好,緣由正在調查中
  • 帶有來自遠程源的音頻的着色器目前不能正常工做,這是VSCode方面的一個問題,將在 Electron 6 發佈時修復。
  • 彷佛有一個很是罕見的錯誤,致使音頻輸入聲音損壞。

Todo

  • 獲得更多的反饋;

  • 在不可移植的版本中禁用音頻;

Cubemap 採樣。

貢獻

任何形式的貢獻都是受歡迎和鼓勵的。

GitHub 項目頁面

Visual Studio 商店地址

Release Notes

(略)

英文原文

相關文章
相關標籤/搜索