{"id":13822317,"url":"https://github.com/Nazariglez/notan","last_synced_at":"2025-05-16T15:33:57.205Z","repository":{"id":37023181,"uuid":"213882019","full_name":"Nazariglez/notan","owner":"Nazariglez","description":"Cross-platform multimedia layer ","archived":false,"fork":false,"pushed_at":"2024-04-06T13:45:10.000Z","size":27902,"stargazers_count":723,"open_issues_count":13,"forks_count":51,"subscribers_count":12,"default_branch":"develop","last_synced_at":"2024-04-14T09:51:19.310Z","etag":null,"topics":["crates","game-2d","game-development","gamedev","multimedia-library","rust"],"latest_commit_sha":null,"homepage":"https://nazariglez.github.io/notan-web/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Nazariglez.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-10-09T09:55:11.000Z","updated_at":"2024-04-25T21:30:13.491Z","dependencies_parsed_at":"2023-11-25T23:26:20.314Z","dependency_job_id":"e6ccde31-2858-49be-807d-48c2f3e8e9ef","html_url":"https://github.com/Nazariglez/notan","commit_stats":{"total_commits":923,"total_committers":17,"mean_commits":"54.294117647058826","dds":0.06608884073672805,"last_synced_commit":"cb72b39e948161a1babb69d0edcf3a7f61a0cc99"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nazariglez%2Fnotan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nazariglez%2Fnotan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nazariglez%2Fnotan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nazariglez%2Fnotan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Nazariglez","download_url":"https://codeload.github.com/Nazariglez/notan/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225033840,"owners_count":17410519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crates","game-2d","game-development","gamedev","multimedia-library","rust"],"created_at":"2024-08-04T08:01:54.388Z","updated_at":"2025-05-16T15:33:57.199Z","avatar_url":"https://github.com/Nazariglez.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eNotan\u003c/h1\u003e\n\u003cdiv align=\"center\"\u003e\n \u003cstrong\u003e\n     Portable Multimedia Layer\n \u003c/strong\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003ca href=\"https://giphy.com/gifs/LvPqA4mRfjemAOrRNz\"\u003e\n  \u003cimg src=\"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExaHVvMDJ4b21vaHdpd3k0aDc4MzZtZnl4eDZ5NDVzMnNuNTEycHF1NCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/LvPqA4mRfjemAOrRNz/giphy.gif\" height=\"150px\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://giphy.com/gifs/HB5c3gYSdqGdywEi5C\"\u003e\n  \u003cimg src=\"https://media.giphy.com/media/HB5c3gYSdqGdywEi5C/giphy.gif\" height=\"150px\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://giphy.com/gifs/iFjqxAWZRQkOuA6Xk0\"\u003e\n  \u003cimg src=\"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExaGEweXhvMHZoY3NsMWEweGpvcHN0eDdibmM3c2JzcHEyYmhrM2EzcyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/iFjqxAWZRQkOuA6Xk0/giphy.gif\" height=\"150px\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://giphy.com/gifs/uZvbmYdbknganNfijt\"\u003e\n  \u003cimg src=\"https://media.giphy.com/media/uZvbmYdbknganNfijt/giphy.gif\" height=\"150px\"\u003e\n\u003c/a\u003e\n\n\u003c/div\u003e\n\n**Notan** is a simple and portable layer, designed to make your own multimedia apps on top of it\nwithout worrying too much about platform-specific code.\n\nThe main goal is to provide a set of APIs and tools that can be used to create your project in an ergonomic manner without\nenforcing any structure or pattern, always trying to stay out of your way.\n\n## Community\n\n- [Discord](https://discord.gg/rH3nP7neeu): Join us!\n\n## Status\n\nNotan is in slow maintenance mode. I'm focusing on other projects for now.  \nFor more details -\u003e [Notan 1.x and Next Steps](https://github.com/nazariglez/notan/issues/354)\n\n## Examples\n\n- [Online demos](https://nazariglez.github.io/notan-web/).\n\n#### Do you want to open a window?\n\n[Window Open](https://nazariglez.github.io/notan-web/examples/window_open.html)\n\n```rust\nuse notan::prelude::*;\n\n#[notan_main]\nfn main() -\u003e Result\u003c(), String\u003e {\n    notan::init().build()\n}\n```\n\n#### Do you want to draw a triangle?\n\n[Draw Triangle](https://nazariglez.github.io/notan-web/examples/draw_triangle.html)\n\n```rust\nuse notan::prelude::*;\nuse notan::draw::*;\n\n#[notan_main]\nfn main() -\u003e Result\u003c(), String\u003e {\n    notan::init().draw(draw)\n        .add_config(DrawConfig)\n        .build()\n}\n\nfn draw(gfx: \u0026mut Graphics) {\n    let mut draw = gfx.create_draw();\n    draw.clear(Color::BLACK);\n    draw.triangle((400.0, 100.0), (100.0, 500.0), (700.0, 500.0));\n    gfx.render(\u0026draw);\n}\n```\n\n#### How about render the triangle directly?\n\n[Renderer Triangle](https://nazariglez.github.io/notan-web/examples/renderer_triangle.html)\n\n```rust\nuse notan::prelude::*;\n\n//language=glsl\nconst VERT: ShaderSource = notan::vertex_shader! {\n    r#\"\n    #version 450\n    layout(location = 0) in vec2 a_pos;\n    layout(location = 1) in vec3 a_color;\n\n    layout(location = 0) out vec3 v_color;\n\n    void main() {\n        v_color = a_color;\n        gl_Position = vec4(a_pos - 0.5, 0.0, 1.0);\n    }\n    \"#\n};\n\n//language=glsl\nconst FRAG: ShaderSource = notan::fragment_shader! {\n    r#\"\n    #version 450\n    precision mediump float;\n\n    layout(location = 0) in vec3 v_color;\n    layout(location = 0) out vec4 color;\n\n    void main() {\n        color = vec4(v_color, 1.0);\n    }\n    \"#\n};\n\n#[derive(AppState)]\nstruct State {\n    clear_options: ClearOptions,\n    pipeline: Pipeline,\n    vbo: Buffer,\n}\n\n#[notan_main]\nfn main() -\u003e Result\u003c(), String\u003e {\n    notan::init_with(setup).draw(draw).build()\n}\n\nfn setup(gfx: \u0026mut Graphics) -\u003e State {\n    let clear_options = ClearOptions::color(Color::new(0.1, 0.2, 0.3, 1.0));\n\n    let vertex_info = VertexInfo::new()\n        .attr(0, VertexFormat::Float32x2)\n        .attr(1, VertexFormat::Float32x3);\n\n    let pipeline = gfx\n        .create_pipeline()\n        .from(\u0026VERT, \u0026FRAG)\n        .with_vertex_info(\u0026vertex_info)\n        .build()\n        .unwrap();\n\n    #[rustfmt::skip]\n    let vertices = [\n        0.5, 1.0,   1.0, 0.2, 0.3,\n        0.0, 0.0,   0.1, 1.0, 0.3,\n        1.0, 0.0,   0.1, 0.2, 1.0,\n    ];\n\n    let vbo = gfx\n        .create_vertex_buffer()\n        .with_info(\u0026vertex_info)\n        .with_data(\u0026vertices)\n        .build()\n        .unwrap();\n\n    State {\n        clear_options,\n        pipeline,\n        vbo,\n    }\n}\n\nfn draw(gfx: \u0026mut Graphics, state: \u0026mut State) {\n    let mut renderer = gfx.create_renderer();\n\n    renderer.begin(Some(state.clear_options));\n    renderer.set_pipeline(\u0026state.pipeline);\n    renderer.bind_buffer(\u0026state.vbo);\n    renderer.draw(0, 3);\n    renderer.end();\n\n    gfx.render(\u0026renderer);\n}\n```\n\n#### Looking for more examples?\n\nSure! Check the [examples folder](examples). You will find there a few of them for any matter, like rendering, windowing, input, etc...\n\n## Installation\n\nAdd `notan` to your project from [crates.io](https://crates.io). The `main` branch should always be the latest version on `crates.io`.\n\n## WebAssembly\n\nWe treat the web as a first class citizen. WebAssembly compilation is dead simple, we recommend to just use [trunk](https://trunkrs.dev/).\nYou only need to add an `index.html` file to your project and run `trunk serve` to see it working.\n\nHere is a simple `index.html` file as an example:\n\n```html\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eNotan App\u003c/title\u003e\n    \u003cmeta content=\"text/html;charset=utf-8\" http-equiv=\"Content-Type\" /\u003e\n    \u003cmeta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" /\u003e\n    \u003cmeta\n      name=\"viewport\"\n      content=\"minimal-ui, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"\n    /\u003e\n    \u003cmeta name=\"apple-mobile-web-app-capable\" content=\"yes\" /\u003e\n    \u003cstyle\u003e\n      html,\n      body {\n        width: 100%;\n        height: 100%;\n        padding: 0;\n        margin: 0;\n        background-color: #252526;\n      }\n\n      * {\n        outline: none;\n      }\n\n      body {\n        display: flex;\n        align-items: safe center;\n        justify-content: safe center;\n      }\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ccanvas id=\"notan_app\"\u003e\u003c/canvas\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nHowever, you can also use [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) or [wasm-pack](https://rustwasm.github.io/wasm-pack/).\n\n## How it works\n\nIs quite simple, **Notan** defines a set of APIs for different things (like windows, graphics, inputs, audio, etc...) as a \"core\".\nBelow this \"core\" exists the `backends`, which are crates that add support for any platform managing the platform-specific\ncode and translating it to our \"core\" APIs. Anybody should be able to create and use a custom backend easily.\nAnd, on top of the \"core\" we can build more ergonomic APIs that are usable with any backend made for Notan.\n\nThen the final user only needs to worrying to build their apps on top of Notan and it should be fine no matter the compilation target.\nOf course, there are still things to have in mind if you want to target different targets, writing portable code can be tricky sometimes\nbut Notan should help with most of them.\n\n## Supported platforms\n\n- Web Browsers (`wasm32`) - WebGL2\n- Window - OpenGL 3.3\n- MacOS - OpenGL 3.3\n- Linux - OpenGL 3.3\n\nThe current graphics backend in place for these platforms is using [glow.rs](https://github.com/grovesNL/glow) which allow us to target WebGl2, GL and GL ES easily.\n\n## Performance\n\nPeople love to see performance numbers and benchmarks (I love it too), but the truth is that any\nbenchmark or numbers worth nothing without the full context of how these numbers were calculated.\n\nWe didn't check (_yet_) about which parts of the code can be changed to improve the performance.\nIs not an easy task to keep in balance a good API, small boilerplate, and been performant.\nHowever, this is something that we try to accomplish with this project since the idea was born.\n\n**Notan** try to give to the user a simple to build things, and the performance will depend on a lot of factors, user's code included.\n\nLet's see a simple example, the 2D Draw API is built on top of the Graphics API, it has plenty of room for improvements,\nbut I got some decent numbers on my machine running the example [draw_bunnymark](examples/draw_bunnymark.rs).\n\nOn a Macbook (2.3Hz i9 - 16GB RAM):\n\n- Native: 85000 Bunnies at 60FPS\n- Chrome: 78000 Bunnies at 60FPS\n\nOn a high-end Desktop with Archlinux:\n\n- Native: 205000 Bunnies at 60FPS\n- Chrome: 131000 Bunnies at 60FPS\n\nLet's keep in mind that the conditions for `bunnymark` are very unlikely to see in a real project.\nHowever, it's widely used to test the performance in 2D Draw APIs.\n\n## Integration\n\nNotan is designed to be as modular as possible. It's flexible enough to allow change how the event life cycle works with\na plugin (i.e: [FpsLimit](crates/notan_extra/src/fps_limit.rs)), or to allow us to draw custom things easily on top of the\ngraphics API using _Graphic Extensions_ (i.e: [egui](crates/notan_egui) or [draw](crates/notan_draw)).\n\nEven any backend can be easily _plugged-in_ from the code just using `init_with_backend`.\n\nWe include some of these plugins or graphics extensions behind feature flags, as a part of the project.\nHowever, everybody can create their own plugins or extension to extend Notan.\n\n## Why?\n\nI have been looking since ever for a project that allows me to create multimedia apps (games in my case) with just one codebase,\nnot been too much opinionated about how to do it, with multiple platforms support and treating the web as a first-class citizen.\n\nI felt that it was a tricky thing to find until I found [Haxe](https://haxe.org/) and [Kha](https://kha.tech/), the perfect match.\nHowever, I did not like a few things about the build system, the lack of tools and IDEs, and how the language itself does some things.\nSo, after a while I decided to start looking again, and I saw that **Rust** had a great **WebAssembly** compiler among other targets,\nand check all those boxes.\n\nFor the last three years, I have been working on this project in different repositories with different names and multiple \"start-over\" times.\nIt was my place to learn Rust and OpenGL, you can say that it was my sandbox and my hobby.\n\nHowever, I feel that it could be useful for more people than me in the current state.\n\nThe name **Notan** comes from `not an engine`. The main purpose of the project is to be used as foundation providing\na basic but useful set of features.\n\nThey are:\n\n- Platform abstraction (desktop, mobile, etc...)\n- Windowing\n- Graphics rendering\n- Text rendering\n- Draw 2D API\n- Audio\n- Input (Keyboard, mouse, etc...)\n- Simple UI via egui\n\nEverything else, like particles, physics, etc..., is out of the scope of the project\nand can be added via external crates, plugins or extensions. Although we can always talk\nif you think that something should be part of the project.\n\n## So... what's next?\n\nImproving the project step by step, aiming for a more mature and better APIs, fixes, better platform support, more graphics backends etc...\n\n## License\n\nThis project is licensed under either of [Apache License, Version\n2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT), at your option.\n\n## Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in this project by you, as defined in the Apache 2.0 license,\nshall be dual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNazariglez%2Fnotan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNazariglez%2Fnotan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNazariglez%2Fnotan/lists"}