Mewa 用户指南/使用自定义着色器扩展 Mewa
本章解释如何使用自定义 GLSL 着色器扩展 Mewa。在 Mewa 中,GLSL 着色器由一个节点持有。
Mewa 的核心是一个脚本引擎,它执行 Mewa 脚本文件。Mewa 脚本是具有 .mw 文件扩展名的文本文件。节点是通过执行脚本创建的。
可用的脚本在 节点菜单 中列出。菜单中显示的名称是脚本的文件名。单击菜单条目将执行相应的脚本。
在创建 Mewa 节点时,最好查看示例并修改它们。Mewa 脚本文件位于 脚本目录 中。打开任何脚本文件,应用一些更改并执行它以观察结果。
让我们从一个简单的脚本开始。
在这个示例中,我们将创建一个脚本,它将生成一个名为 MyImage 的新节点。要创建脚本,请创建一个名为 MyImage.mw 的新文本文件,并将下面的文本粘贴到该文件中。
// this is a mewa script that creates a node with a custom shader
shaderSource = "
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 col = 0.5 + 0.5*cos( iTime + fragCoord.xyx + vec3(0,2,4) );
fragColor = vec4(col,1.0);
}";
addShaderNode("MyImage", shaderSource);
上面的 Mewa 脚本文件包含 GLSL 着色器代码(在引号内)和一个 Mewa API 调用以创建 Mewa 节点。
着色器代码实现 mainImage() 函数。此函数对每个像素调用一次。fragCoord 参数包含像素坐标(以归一化坐标表示)。fragCoord 值始终介于 0 到 1 之间,并覆盖整个视口。每个像素的输出颜色存储在 fragColor 中。
变量 iTime 是 Mewa 提供的一个 输入变量。
现在让我们安装它并运行它。
Mewa 脚本文件位于一个目录中,我们称之为 脚本目录。它的位置取决于 Mewa 运行的平台。
要查找 脚本目录,请在 Mewa 的主窗口中单击 。将打开一个常规信息窗口,显示 脚本目录。
要运行我们新创建的脚本,请通过单击节点按钮 打开 节点菜单。将显示位于 脚本目录 中的所有脚本的列表。
节点菜单中显示的名称是脚本的文件名。要启动我们脚本的执行,请单击 MyImage 条目。一个名为 MyImage0 的节点将添加到节点图中。单击输出按钮(节点右侧的方形按钮)将打开输出窗口,显示我们节点的输出。见下图截图。
以下是 Mewa 向所有着色器提供的所有输入变量的列表
类型 | 名称 | 描述 |
---|---|---|
vec3 | iResolution | 视口分辨率(以像素为单位)。z 是纵横比(宽度/高度) |
float | iTime | 播放时间(以秒为单位) |
int | iFrame | 播放帧号 |
vec3 | iChannelResolution0, iChannelResolution1 | 每个通道的输入纹理分辨率。z 是纵横比(宽度/高度) |
sampler2D | iChannel0, iChannel1 | 输入通道 |
vec4 | iChannelRect0, iChannelRect1 | 纹理坐标中的通道矩形。矩形以 vec4( 左,右,下,上 ) 表示。 |
在我们上面创建的 示例 中,结果节点没有输入。
要生成一个接受输入图像的着色器节点,我们将变量 iChannel0 引入我们的着色器源代码。
现在让我们创建一个名为 MyFilter.mw 的新文本文件,其内容如下
shaderSource = "
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 col = texture2D(iChannel0, fragCoord).rgb;
fragColor = vec4(col,1.0);
}";
node = addShaderNode("MyFilter", shaderSource);
node.setRenderArea( "iChannel0" );
将 MyFilter.mw 文件放在脚本目录中,并从节点菜单中运行它。
MyFilter 节点现在提供了 1 个输入和 1 个输出。
着色器只是将输入纹理渲染到其输出中。
现在我们已经有一个运行着色器的节点,让我们向着色器添加一个输入变量,并使用 GUI 控件更改其值。
下面的脚本将输入变量 uNumber 添加到着色器源代码中,并添加一个 uiControl 来控制 uNumber 变量的值。
shaderSource = "
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 col = texture2D(iChannel0, fragCoord).rgb;
col.r = uNumber; // uNumber is a variable of type float
fragColor = vec4(col,1.0);
}";
myNode = newShaderNode("MyFilter", shaderSource);
myNode.setRenderArea( "iChannel0" );
// Slider control
uiControl = node.addFloatControl("uNumber", 0.5);
uiControl.setText("MyControl");
uiControl.setStep(0.01);
uiControl.setRange(0, 1);
脚本的最后 4 行设置了 GUI 控件。
addFloatControl 创建 GUI 小部件并将其添加到节点参数窗口。它的参数是着色器源代码中使用的变量名,它的第二个参数是它的初始值。
GUI 控件通过节点参数在 Mewa 中可见。要打开节点参数,请单击节点右侧的圆形按钮。
更改参数值并在输出窗口中观察结果。
在构建节点图时,平移/缩放图像是一个常见的操作,能够限制图像矩形内的着色器处理区域对于防止渲染整个视口非常重要。
根据节点的用例,我们必须选择 3 个选项中的 1 个
- "iResolution"
- 主函数 mainImage( fragColor, fragCoord ) 接受 2 个输入参数,其中 fragCoord 始终从 0 到 1,并覆盖整个视口。
- 用于通过计算每个像素的颜色来生成过程图像。
- "iChannel0"
- 在此选项中,着色器仅处理图像 iChannel0 覆盖的区域。主函数 mainImage( fragColor, fragCoord ) 接受 2 个输入参数,其中 fragCoord 包含输入图像的纹理坐标。fragCoord 范围不一定从 0 开始到 1 结束,但它将在 0 和 1 限制内的任何范围内。
- 用于对图像应用图像处理滤镜
- "iChannel0+iChannel1"
- 主函数 mainImage( fragColor, fragCoord0, fragCoord1 ) 接受 3 个输入参数,其中 fragCoord0 和 fragCoord1 是 2 个输入图像的纹理坐标
- 用于混合/合并 2 个输入图像
所选选项使用 setRenderArea() 函数设置。
有关如何使用 "iChannel0+iChannel1" 选项的示例,请参见位于您的 脚本目录 中的 OverlayBlend.mw 脚本。
ShaderToy 是一个浏览器内的着色器开发环境。在 ShaderToy 中开发的着色器只需稍作修改即可轻松在 Mewa 中使用。
Mewa 着色器与 ShaderToy 着色器之间存在一些差异
- 在 main() 函数中传递的 fragColor 参数保存像素值。在 Mewa 中,fragColor 包含归一化像素值,范围在 0 到 1 之间。
- ShaderToy 使用 texture 函数来获取输入纹理的颜色,而 Mewa 使用 GLSL 函数 texture2D。
脚本可以在 Mewatools WebStore 中发布,这是一个 Mewa 附加组件的在线存储库。