#windowing #gamedev #graphics-api #graphics #engine

notan

一个简单易用的可移植多媒体层,可轻松创建应用程序或游戏

23 个不稳定版本 (11 个破坏性更新)

0.12.1 2024年6月8日
0.12.0 2024年2月19日
0.11.0 2023年10月18日
0.9.5 2023年4月18日
0.2.1 2022年3月29日

#63 in GUI

Download history 156/week @ 2024-04-29 207/week @ 2024-05-06 206/week @ 2024-05-13 226/week @ 2024-05-20 138/week @ 2024-05-27 275/week @ 2024-06-03 194/week @ 2024-06-10 169/week @ 2024-06-17 136/week @ 2024-06-24 13/week @ 2024-07-01 34/week @ 2024-07-08 80/week @ 2024-07-15 94/week @ 2024-07-22 179/week @ 2024-07-29 72/week @ 2024-08-05 114/week @ 2024-08-12

每月468次下载
4 个工具包 中使用

MIT/Apache

1MB
7K SLoC

Notan

可移植多媒体层

Notan 是一个简单且可移植的层,旨在让您在上面轻松创建自己的多媒体应用程序,而无需过多关注特定平台的代码。

主要目标是提供一套 API 和工具,可以以舒适的方式使用它们来创建项目,而无需强制任何结构或模式,始终尽量不干扰您。

社区

示例

你想打开一个窗口吗?

窗口打开

use notan::prelude::*;

#[notan_main]
fn main() -> Result<(), String> {
    notan::init().build()
}

你想画一个三角形吗?

绘制三角形

use notan::prelude::*;
use notan::draw::*;

#[notan_main]
fn main() -> Result<(), String> {
    notan::init().draw(draw)
        .add_config(DrawConfig)
        .build()
}

fn draw(gfx: &mut Graphics) {
    let mut draw = gfx.create_draw();
    draw.clear(Color::BLACK);
    draw.triangle((400.0, 100.0), (100.0, 500.0), (700.0, 500.0));
    gfx.render(&draw);
}

直接渲染这个三角形怎么样?

渲染器三角形

use notan::prelude::*;

//language=glsl
const VERT: ShaderSource = notan::vertex_shader! {
    r#"
    #version 450
    layout(location = 0) in vec2 a_pos;
    layout(location = 1) in vec3 a_color;

    layout(location = 0) out vec3 v_color;

    void main() {
        v_color = a_color;
        gl_Position = vec4(a_pos - 0.5, 0.0, 1.0);
    }
    "#
};

//language=glsl
const FRAG: ShaderSource = notan::fragment_shader! {
    r#"
    #version 450
    precision mediump float;

    layout(location = 0) in vec3 v_color;
    layout(location = 0) out vec4 color;

    void main() {
        color = vec4(v_color, 1.0);
    }
    "#
};

#[derive(AppState)]
struct State {
    clear_options: ClearOptions,
    pipeline: Pipeline,
    vbo: Buffer,
}

#[notan_main]
fn main() -> Result<(), String> {
    notan::init_with(setup).draw(draw).build()
}

fn setup(gfx: &mut Graphics) -> State {
    let clear_options = ClearOptions::color(Color::new(0.1, 0.2, 0.3, 1.0));

    let vertex_info = VertexInfo::new()
        .attr(0, VertexFormat::Float32x2)
        .attr(1, VertexFormat::Float32x3);

    let pipeline = gfx
        .create_pipeline()
        .from(&VERT, &FRAG)
        .with_vertex_info(&vertex_info)
        .build()
        .unwrap();

    #[rustfmt::skip]
    let vertices = [
        0.5, 1.0,   1.0, 0.2, 0.3,
        0.0, 0.0,   0.1, 1.0, 0.3,
        1.0, 0.0,   0.1, 0.2, 1.0,
    ];

    let vbo = gfx
        .create_vertex_buffer()
        .with_info(&vertex_info)
        .with_data(&vertices)
        .build()
        .unwrap();

    State {
        clear_options,
        pipeline,
        vbo,
    }
}

fn draw(gfx: &mut Graphics, state: &mut State) {
    let mut renderer = gfx.create_renderer();

    renderer.begin(Some(state.clear_options));
    renderer.set_pipeline(&state.pipeline);
    renderer.bind_buffer(&state.vbo);
    renderer.draw(0, 3);
    renderer.end();

    gfx.render(&renderer);
}

需要更多示例吗?

当然!请检查示例文件夹。您将找到一些示例,涵盖渲染、窗口、输入等各个方面...

安装

crates.ionotan 添加到您的项目中。主分支应始终是 crates.io 上的最新版本。

WebAssembly

我们将网络视为一等公民。WebAssembly 编译非常简单,我们建议您使用 trunk。您只需将一个 index.html 文件添加到您的项目中,并运行 trunk serve 来查看它的工作情况。

以下是一个简单的 index.html 文件作为示例

<html>
    <head>
        <title>Notan App</title>
        <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport"
              content="minimal-ui, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <style>
            html, body {
                width: 100%;
                height: 100%;
                padding: 0;
                margin: 0;
                background-color: #252526;
            }

            * {
                outline: none;
            }

            body {
                display: flex;
                align-items: center;
                justify-content: center;
            }
        </style>
    </head>
    <body>
        <canvas id="notan_canvas"></canvas>
    </body>
</html>

但是,您也可以使用 wasm-bindgenwasm-pack

工作原理

非常简单,Notan 定义了一组用于不同事物的 API(如窗口、图形、输入、音频等)作为“核心”。在这个“核心”下面存在的是 backends,它们是 crate,为任何平台添加支持,管理特定平台的代码,并将其转换为我们的“核心”API。任何人都可以轻松地创建和使用自定义后端。而且,在“核心”之上,我们可以构建更易于使用的 API,这些 API 可以与为 Notan 制作的任何后端一起使用。

然后最终用户只需担心在 Notan 之上构建他们的应用程序即可,无论编译目标如何,都应该是没有问题的。当然,如果您想针对不同的目标,仍然需要考虑一些事情,编写可移植的代码有时可能会有点棘手,但 Notan 应该能帮助解决其中的大部分问题。

支持的平台

  • Web 浏览器(《tt class="src-rs">wasm32》) - WebGL2
  • 窗口 - OpenGL 3.3
  • MacOS - OpenGL 3.3
  • Linux - OpenGL 3.3

这些平台当前使用的图形后端是 glow.rs,它使我们能够轻松地针对 WebGL2、GL 和 GL ES。

性能

人们喜欢看到性能数据和基准测试(我也很喜欢),但事实是,如果没有完整的计算上下文,任何基准测试或数据都毫无意义。

我们还没有检查(尚未)代码的哪些部分可以更改以改善性能。保持良好的 API、小的样板代码和良好的性能之间的平衡并不是一件容易的事情。然而,这正是我们从项目一开始就试图实现的事情。

Notan 努力为用户提供简单构建事物的工具,性能将取决于许多因素,包括用户的代码。

让我们看一个简单的例子,2D 绘图 API 是在图形 API 之上构建的,它有很多改进的空间,但我在我的机器上运行示例 draw_bunnymark 时获得了一些不错的数字。

在 Macbook(2.3Hz i9 - 16GB RAM)上

  • 本地:85000 只兔子在 60FPS
  • Chrome:78000 只兔子在 60FPS

在高端桌面电脑上(Archlinux)

  • 本地:205000 只兔子在 60FPS
  • Chrome:131000 只兔子在 60FPS

请记住,bunnymark 的条件在真实项目中很少见。然而,它被广泛用于测试 2D 绘图 API 的性能。

集成

Notan 被设计成尽可能模块化。它足够灵活,允许使用插件更改事件生命周期(例如:FpsLimit),或者允许我们使用 图形扩展(例如:eguidraw)在图形 API 上轻松绘制自定义内容。

任何后端都可以通过使用 init_with_backend 仅在代码中轻松地 插入

我们把这些插件或图形扩展包含在项目的一部分中,作为功能标志。然而,每个人都可以创建他们自己的插件或扩展来扩展 Notan。

为什么?

我一直寻找一个项目,可以让我使用一个代码库创建多媒体应用程序(我的情况是游戏),不拘泥于如何实现,支持多个平台,并将 Web 视为第一公民。

我一直觉得找到合适的东西很棘手,直到我发现了 HaxeKha,这对完美的组合。然而,我对构建系统的一些方面并不满意,比如工具和IDE的缺乏,以及语言本身的一些操作。所以,过了一段时间后,我决定再次寻找,我发现 Rust 在其他目标中有一个出色的 WebAssembly 编译器,并且满足所有这些条件。

在过去三年里,我在不同的仓库中以不同的名字多次“从头开始”工作在这个项目上。这是我学习 Rust 和 OpenGL 的地方,可以说这是我沙盒和爱好。

然而,我认为在当前状态下,这个项目可能比对我更有用。

Notan 这个名字来自 not an engine。项目的核心目的是作为一个基础,提供一组基本但有用的功能。

它们包括:

  • 平台抽象(桌面、移动等)
  • 窗口管理
  • 图形渲染
  • 文本渲染
  • 2D 绘图 API
  • 音频
  • 输入(键盘、鼠标等)
  • 简单的 UI 通过 egui

其他一切,如粒子、物理等,都不在项目的范围内,可以通过外部crate、插件或扩展添加。尽管如此,如果您认为某些内容应该成为项目的一部分,我们总是可以讨论。

那么,接下来是什么?

逐步改进项目,目标是更加成熟和更好的API、修复、更好的平台支持、更多图形后端等...

许可证

该项目根据您的选择,受 Apache License, Version 2.0MIT 许可证 的许可。

贡献

除非您明确声明,否则您根据 Apache 2.0 许可证定义的任何旨在包含在本项目中的有意贡献,都应如上所述双许可,不附加任何额外条款或条件。

依赖

~9–51MB
~1M SLoC