17 个不稳定版本 (3 个破坏性更新)
新 0.4.0 | 2024 年 8 月 7 日 |
---|---|
0.3.3 | 2024 年 7 月 9 日 |
0.2.8 | 2024 年 6 月 5 日 |
0.2.6 | 2024 年 5 月 9 日 |
0.1.2 | 2023 年 11 月 2 日 |
#65 in 图形 API
188 每月下载次数
用于 tweak_runner
405KB
4K SLoC
库 Tweak Shader
Tweak Shader 库为交互式屏幕着色器格式提供了渲染和簿记上下文。它允许用户创建类似于 ShaderToy 或 ISF 着色器的着色器,并具有可运行时调整的自定义统一变量。该库支持图像,以及各种其他类型,包括颜色、浮点数、整数、2D 点等。该库的设计和功能受到了 ISF(交互式着色器格式)项目的影响。
使用方法
use tweak_shader::RenderContext;
use wgpu::TextureFormat;
let src = r#"
#version 450
#pragma tweak_shader(version=1.0)
layout(location = 0) out vec4 out_color;
#pragma input(float, name="foo", default=0.0, min=0.0, max=1.0)
#pragma input(float, name="bar")
#pragma input(float, name="baz", default=0.5)
layout(set = 0, binding = 0) uniform Inputs {
float foo;
float bar;
float baz;
};
void main()
{
out_color = vec4(foo, bar, baz, 1.0);
}
"#;
let format = TextureFormat::Rgba8UnormSrgb;
let device = // your wgpu::Device here;
let queue = // your wgpu::Queue here;
let render_context = RenderContext::new(isf_shader_source, format, &device, &queue).unwrap();
// Congratulations! You now have a 255x255 blue square.
let output = render_context.render_to_vec(&queue, &device, 255, 255);
有效的文档约定如下。
输入类型
输入约定提供了有关着色器输入的信息,包括类型、名称和可选属性,如默认值、最小和最大界限、标签和有效值。
约定类型 | 基础类型 | 字段 | 描述 |
---|---|---|---|
float | float | name, min, max, default | 单个 float 输入 |
int | int | name, min, max, default, labels, values | 单个 int 输入,可选的标签和有效值列表 |
bool | int | name, default | 布尔值,由 int(0 - false,1 - true)表示,这是由于 Naga 相关原因。 |
Point | vec2 | name, min, max, default | 2D 点。 |
Color | vec4 | name, default | 具有直接 alpha 的颜色输入。 |
Image | Texture2d | name | 用于加载图像或图像序列的空闲纹理槽。 |
以下是一些示例
- 浮点输入
#pragma input(float, name="foo", default=0.0, min=0.0, max=1.0)
- 带有标签的整数输入
#pragma input(int, name="mode", default=0, values=[0, 1, 2], labels=["A", "B", "C"])
- 图像输入
#pragma input(image, name="input_image", path="./demo.png")
layout(set=1, binding=1) uniform sampler default_sampler;
layout(set=1, binding=2) uniform texture2D input_image;
每个输入约定对应于着色器代码中的统一变量,其中 name
字段指定匹配的全局统一值或映射到输入的纹理名称中的结构体字段。
采样器配置
采样器编译指令允许您配置采样器绑定的采样模式。
// Sampler pragmas must be of the form
// #pragma sampler(name='foo', linear|nearest, <clamp|repeat|mirror>)
#pragma sampler(name='linear_sampler', linear, mirror)
layout(set=1, binding=1) uniform sampler linear_sampler;
工具块
微调着色器库允许您有效地使用工具块访问特定的统一或推送常量字段。以下是如何使用工具块的示例
#pragma utility_block(ShaderInputs)
layout(push_constant) uniform ShaderInputs {
float time; // shader playback time (in seconds)
float time_delta; // elapsed time since the last frame in seconds
float frame_rate; // estimated number of frames per second
uint frame_index; // frame count
vec4 mouse; // ShaderToy mouse scheme
vec4 date; // [year, month, day, seconds]
vec3 resolution; // viewport resolution in pixels, [width, height, aspect ratio]
uint pass_index; // updated to reflect the current render pass index
};
您可以使用 #pragma utility_block
来访问专用工具函数的成员,例如 RenderContext::update_time
和 RenderContext::update_resolution
。字段名称在块之间可能不同,它们通过偏移量访问。
额外的渲染通道和持久缓冲区
您可以使用 #pragma pass
编译指令定义额外的渲染通道并指定每个通道的输出目标。以下是如何创建额外通道的示例
#pragma pass(0, persistent, target="single_pixel", height=1, width=1)
layout(set=0, binding=1) uniform sampler default_sampler;
layout(set=0, binding=2) uniform texture2D single_pixel;
#pragma pass
编译指令允许您添加在主通道之前按其索引顺序运行的通道。如果指定了 target
,则通道将写入映射到指定变量的上下文管理的纹理。您还可以指定输出纹理的 height
和 width
;否则,默认为渲染目标的尺寸。
计算着色器专用编译指令
计算着色器有独特的约束和一些独特的编译指令来管理存储纹理。
阶段
#pragma stage("compute")
// default
#pragma stage("fragment")
阶段编译指令可以用来告诉上下文这是一个计算着色器,它不会自行推断。
目标
目标编译指令创建一个可写入的存储纹理。在设备设置期间启用适当的标志后,应该能够将目标分配为 readwrite
或 writeonly
。此外,除非格式说明符与渲染上下文相匹配,否则这些目标将无法验证。
// must be of the form:
// #pragma target(name="foo", <persistent>, <width=k>, <height=k>)
#pragma target(name="output_image")
layout(rgba8, set=0, binding=1) uniform writeonly image2D output_image;
中继
由于在Web上目标仅限于写入,我们需要使用多个通道来从中读取,这是通过在每个通道之后将只写纹理复制到普通纹理来实现的。为此,我们包括了 relay
编译指令。
// Relays must be of the form
// #pragma relay(name="foo", target="bar" <persistent>, <width=k>, <height=k>)
// this means that in compute shaders, specifying persistence
// and size of a renderpass is illegal.
#pragma pass(0)
#pragma relay(name="relay", target="relay_target")
layout(rgba8, set=0, binding=1) uniform writeonly image2D relay;
layout(set=0, binding=2) uniform texture2D relay_target;
依赖项
~11-42MB
~667K SLoC