#macos #metal #支持 #克隆 #着色器 #源码 #着色器玩具

xixixao/rust_to_metal_sl

ShaderToy的Rust克隆,目前支持MacOS

1个不稳定版本

0.1.0 2021年2月7日

#457图形API

24 星级 & 3 关注者

25KB
733 代码行

ShaderRoy

ShaderToy的Rust克隆,目前支持MacOS。

Demo Youtube Video

功能

  1. cargo run <rust项目目录> 在单个MacOS窗口中显示一个 Metal 框架 片段着色器
  2. 您可以通过编辑并保存Rust项目源代码(在VS code或其他编辑器中)来更改片段着色器输出,窗口将实时更新。
  3. 您在Rust中编写着色器,但它会被编译成 Metal着色语言(C++的变体)
  4. 在着色器源代码中,您可以引用 const INPUT 结构,它为每个帧提供输入,类似于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语言

通常,您将编写的Rust代码将非常类似于C++ Metal着色语言API,但有一些差异。

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。目前对path属性在mod上的支持也不存在。

Let绑定

变量不能重新声明。(目前如此)

构造函数

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

开发

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

cargo test -- --nocapture

依赖项

~7.5MB
~166K SLoC