【Shader学习随笔】00 - ShaderToy到VsCode

1. 环境配置

1.1 下载对应插件

screenShot.png

screenShot.png

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

screenShot.png

  • 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 配置代码提示

screenShot.png

输入 glsl ,进入配置界面:

screenShot.png

在配置界面配置代码提示:

screenShot.png

配置下载地址:

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 上的项目,每个项目会有若干个通道输入,例如:

screenShot.png

screenShot.png

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

screenShot.png

2.2.4 输入的采样标准设置

screenShot.png

在 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 导入其他的着色器

screenShot.png

使用如下语法导入其他着色器作为库来使用:

#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 as iTime)
  • 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);
}
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值