#macos #着色器 #金属 #克隆 #支持 #输入 #shader-toy

app xixixao/shader_roy

Rust语言编写的ShaderToy克隆,目前支持macOS。

1个不稳定版本

0.1.0 2021年2月7日

#730 in 图形API

24 星级 & 3 关注者

27KB
661

ShaderRoy

Rust语言编写的ShaderToy克隆,目前支持macOS。

Demo Youtube Video

功能

  1. cargo run <rust项目目录>将在macOS中显示一个窗口,其中包含一个Metal框架的片段着色器
  2. 您可以通过编辑和保存Rust项目源代码(在VS code或其他编辑器中)来更改片段着色器输出,窗口将实时更新。
  3. 您使用Rust编写着色器,但它被编译为Metal着色语言(C++的变体)。
  4. 在着色器源代码中,您可以引用constINPUT结构,它为每一帧提供输入,类似于ShaderToy中的输入统一变量。尽管Metal没有像WebGL那样的全局统一变量的概念,您仍然不需要将这些值作为参数传递给函数。
  5. 您可以使用mod <name>use <name>::*来将着色器分散到多个文件中。
  6. 当窗口开启时,您可以从命令行暂停、重新启动,甚至运行另一个着色器文件。

说明

  1. 克隆此仓库
  2. 运行cargo run raymarching_eyes
  3. 编辑examples/raymarching_eyes.rs

为什么用Rust作为着色器源代码?更好的语法、更好的编辑器集成,以及这是一项有趣的黑客技巧。它应该感觉就像编写Rust(感觉非常棒!)一样。与ShaderToy不同,Rust类型检查器会立即警告大多数可能犯的错误。

Metal着色Rust语言

通常您将编写与C++ Metal着色语言API非常相似的Rust代码,除了少数差异。

INPUT结构在shader_roy_metal_sl_interface中进行了文档说明。

API MSL (C++) Rust
标量类型
float foo() {
  return 3.0;
}

使用与Metal类型相对应的标准Rust类型。

fn foo() -> f32 {
  3.0
}
向量类型
void foo(float3 a, uint2 b) {}

使用泛型Vec类型。它的默认类型参数是f32,以便于使用。

fn foo(a: Vec3, b: Vec2<u32>) {}
构造函数

向量构造函数(如float4等)可以接受任意数量的向量/标量参数,只要它们组合成正确长度的向量。

auto x = float2(1.0);
float4(x, x);

uint2(0, 0);

在Rust中,这些紧随类型名称之后。您需要将它们作为方法调用。

let x = 1.0.vec2();
(x, x).vec4();

vec2u32(0, 0);
访问构造函数

向量组件选择构造函数(如xxy等)允许组件的排列和/或重复。

auto pos = float2(1.0, 2.0);
auto foo = pos.yyxy;
// => float4(2.0, 2.0, 1.0, 2.0)

在Rust中,您需要将它们作为方法调用。

let pos = (1.0, 2.0).vec2();
let foo = pos.yyxy();
// => (2.0, 2.0, 1.0, 2.0).vec4()
函数
min(x, y);

数学、几何和常见函数需要作为方法调用。

x.min(y)
重命名函数
clamp(x, 0.3, 0.4);
length(x);
length_squared(x);
normalize(x);
faceforward(x, incident, surface);
reflect(x, normal);
refract(x, normal, eta);
fmin(x, y);
fmax(x, y);

名称遵循vek

x.clamped(0.3, 0.4);
x.magnitude();
x.magnitude_squared();
x.normalized();
x.face_forward(incident, surface);
x.reflected(normal);
x.refracted(normal, eta);
x.min(y);
x.max(y);
具有不同参数顺序的方法
mix(0.3, 0.4, a);
smoothstep(0.3, 0.4, x);
step(0.3, x);

当一个参数与其他参数不同时,它用作方法调用的接收者。

a.mix(0.3, 0.4);
x.smoothstep(0.3, 0.4);
x.step(0.3);

限制

模块

目前,只有与主文件位于同一目录的模块将被监视。只支持同一目录中的文件用于mod <name>,不支持<name>/mod.rs。对modpath属性没有支持。

let绑定

变量不能被重新声明。(目前

构造函数

在Rust中,我们可以使用单个泛型vec2构造函数来表示所有的Vec2。但这将需要实际使用rustc将构造函数编译为具体的Metal C++构造函数。为了使事情更简单,这里的Rust绑定要求直接指定构造函数(vec2bool -> bool2)。

开发

打印编译后的着色器而不打开窗口

cargo test -- --nocapture

依赖关系

~5–14MB
~167K SLoC