1. 环境配置
1.1 下载对应插件
1.2 配置 GLSL-Linter 库
1.2.1 下载 VsCode 的 glsl 依赖包
https://github.com/KhronosGroup/glslang/releases
- 下载
glslang-master-windows-x64-Release.zip
1.2.2 在 VsCode 中配置路径
- 点击左下角齿轮,点击
Settings
- 打开界面后,点击左侧
Extensions
,选择GLSL linter configuration
- 设置路径
Glsl-linter:Validator Path
,指向glslangValidator.exe
- 按
Ctrl
+Shift
+P
打开设置(json),添加如下代码:
"glsl-linter.validatorPath": "D:\\WorkInstaller\\OpenGL\\glslang\\glslang\\bin\\glslangValidator.exe",
"glsl-linter.fileExtensions": {
".fs.glsl": "frag",
".vs.glsl": "vert",
".tes.glsl": "tese",
".tcs.glsl": "tesc",
".gs.glsl": "geom"
},
"shader-toy.enabledAudioInput": true
1.3 配置代码提示
输入 glsl
,进入配置界面:
在配置界面配置代码提示:
配置下载地址:
https://github.com/mdyshad0w/glslsnippets(已失效)
GLSL代码提示配置文本资源补档:
https://blog.csdn.net/weixin_44423708/article/details/135035641?spm=1001.2014.3001.5502
2. 从 ShaderToy 到 VsCode
具体参考 VsCode 上的 ShaderToy 插件提供的官方文档:
2.1 从 ShaderToy 上爬取资源
主要是爬取对应的纹理资源
脚本下载地址:
https://github.com/What-a-stupid-username/ShaderToyHelper
运行后在控制台输入对应网址或者ID号:
- 例如:
https://www.shadertoy.com/view/4dSBDt
或者4dSBDt
文件将直接下载至当前文件夹
注意修改对应的后缀:
- 比如说
code.txt
改为glsl
等等
2.2 配置通道的输入
在 ShaderToy
上的项目,每个项目会有若干个通道输入,例如:
2.2.1 纹理输入
图片输入
// 使用相对路径读取本地图片
#iChannel0 "./duck.png"
// 使用 url 读取线上图片资源
#iChannel1 "https://66.media.tumblr.com/tumblr_mcmeonhR1e1ridypxo1_500.jpg"
着色器输入
#iChannel0 "./buf B.glsl"
#iChannel1 "./buf C.glsl"
当前着色器的最后一帧作为输入
#iChannel0 "self"
Note :
- 纹理大小必须是 2 的幂次方
- 使用相对路径输入时,需要使用 VsCode 点开整个文件夹
2.2.2 Cubemap 输入
// 注意需要 {}
#iChannel0 "file://cubemaps/yokohama_{}.jpg"
// 声明通道0的纹理为 CubeMap 输入
#iChannel0::Type "CubeMap"
实际使用中 Cubemaps 可以指定为任何其他纹理(例如 .jpg
),通过包含通配符的路径和显式声明的类型的组合,识别出这个通道是一个 Cubemaps
通配符将通过替换以下任意集合中的值来解析
- [ ‘e’, ‘w’, ‘u’, ‘d’, ‘n’, ‘s’ ]
- [ ‘east’, ‘west’, ‘up’, ‘down’, ‘north’, ‘south’ ]
- [ ‘px’, ‘nx’, ‘py’, ‘ny’, ‘pz’, ‘nz’ ]
- [ ‘posx’, ‘negx’, ‘posy’, ‘negy’, ‘posz’, ‘negz’ ]
如果找不到这六个文件中的任何一个,则从第一个文件开始尝试下一个文件集
2.2.3 音频输入
#iChannel0 "./music/epic.mp3"
- 如果通道定义了音频输入,它将从文件扩展名中推断出来
- 通道将是一个 2×512 像素的纹理(高×宽),宽度可以通过
Audio Domain Size
设置来进行调整 - 第一行包含音频频谱,第二行包含其波形
Note :
- 默认情况下音频输入是禁用,需要手动去设置中启用
Enable Audio Input
2.2.4 输入的采样标准设置
在 VsCode 中进行如下设置
#iChannel0::MinFilter "NearestMipMapNearest"
#iChannel0::MagFilter "Nearest"
#iChannel0::WrapMode "Repeat"
2.2.5 键盘输入
在着色器前声明:
#iKeyboard
此时暴露给着色器以下功能:
bool isKeyPressed(int);
bool isKeyReleased(int);
bool isKeyDown(int);
bool isKeyToggled(int);
同时也提供一些变量与上述函数组合使用来查询键盘事件:
Key_A
to Key_Z
, Key_0
to Key_9
, Key_UpArrow
, Key_LeftArrow
, Key_Shift
2.3 导入其他的着色器
使用如下语法导入其他着色器作为库来使用:
#include "./some/shared/code.glsl"
#include "./shader_code.glsl"
#include "d:/some/global/code.glsl"
Note :
- 显然,这些着色器不允许定义
void main()
函数,只能定义一些常量和运算函数
2.4 Uniforms 变量
2.4.1 内置的 Uniforms 变量
iResolution
iGlobalTime
(also asiTime
)iTimeDelta
iFrame
iMouse
iMouseButton
iDate
iSampleRate
iChannelN
( N in [0, 9] )iChannelResolution[]
2.4.2 自定义的 Uniforms 变量
使用自定义的 Uniforms 变量定义那些直接在着色器中使用的 Uniforms 变量,给一个初始值以及一个范围
// 暴露一个滑动条来编辑该值
#iUniform float my_scalar = 1.0 in { 0.0, 5.0 }
// 这将显示一个步长为 0.2 的滑块
#iUniform float my_discreet_scalar = 1.0 in { 0.0, 5.0 } step 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 }
3. 与 ShaderToy 的兼容性
Example :
// 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);
}
其中做了如下替换:
gl_FragCoord
->fragCoord
gl_FragColor
->fragColor
其中 void main()
将委托给 void mainImage(out vec4, in vec2)
函数:
void main()
的定义是通过匹配/void\s+main\s*\(\s*\)\s*\{/g
找到的;- 除了定义扩展生成的定义以外,还需定义
void main()
,可以定义成void main(void)
。
例如,如果您的主定义将由预处理器处理掉,因此扩展不应该获取,那么这可能是必要的。
由于兼容性是通过一个简单的regex匹配实现的,所以它只是半可靠的。
如果只使用 shadertoy.com 网站执行诸如通过宏定义 mainImage
之类的操作时,您可能希望启用 “Shader Toy Strict Compatibility” 设置,该设置禁用使用定义 void main()
的着色器的功能,并且只允许以某种方式定义 mainImage
的着色器。
或者,您可以在着色器中使用 #StrictCompatibility
将此功能本地化为该着色器。
4. 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);
}