Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: next #299

Draft
wants to merge 58 commits into
base: develop
Choose a base branch
from
Draft

WIP: next #299

wants to merge 58 commits into from

Conversation

Nazariglez
Copy link
Owner

@Nazariglez Nazariglez commented Dec 2, 2023

This is the next version of notan. We can consider it a rework, addressing some of the flaws, but also leaving behind some bad design decisions.

To merge this we need to reach a feature pair status, the API may change in some cases:

  • Window Manager
  • Asset Loading
  • Mouse Support
  • Touch Support
  • Keyboard Support
  • Draw2D API
  • Low Graphics API
  • Shader Cross Compilation
  • EGUI Support
  • Native WGPU Support
  • Web && WebGL Support
  • Web && WGPU Support

Then we can aim to get some extras, but they are not required:

  • Multiple window support
  • iOS Support
  • Android Support
  • OpenGL Support?
  • Gamepad Support

@Nazariglez
Copy link
Owner Author

Nazariglez commented Dec 3, 2023

Each example must be made on its own commit, and that commit must be referenced on this PR. Allowing users to check the diff easily as a guide for migrating.


Edit: I am thinking that this can be tricky if it's an iterative change, because the API can evolve a bit while this PR lands, but I'll try to do my best.

@Nazariglez
Copy link
Owner Author

I added a checklist with things that must be done. Some of them are going to change quite a bit, so I am going to create separate PRs for those features or just leave comments to discuss the changes.

I am trying to keep the soul of the project without changes. However, some things must go, like graphics extensions, they are handy but too limiting (ie: we cannot use draw2d on EGUI because that design does not work with the borrow checker, etc...). This will make some things more verbose for the user, but not that much. We will see.

I want to do this in a way that works for me and for others as well, so I am not going to click the merge button until we're sure this is what we want to do with Notan.

@Nazariglez Nazariglez added this to the Next milestone Jun 8, 2024
@Nazariglez
Copy link
Owner Author

Quick update on this, I am experimenting almost full-time in another repo with a new API for Notan. I really like the API made here, I do think it's elegant and functional, however it has still some issues and is not very ergonomic when dealing with plugins (egui paint callback, etc...). I hope to have something working and translated this repo soon. A sneak peak (this can still change):

gfx_clear.rs

use rkit::gfx::{self, Color, Renderer};
use rkit::time;

fn main() {
    rkit::init().on_update(update).run().unwrap()
}

fn update() {
    let t = time::elapsed_f32();
    let color = Color::rgb(t.cos(), t.sin(), 1.0);

    let mut renderer = Renderer::new();
    renderer.begin_pass().clear_color(color);

    gfx::render_to_frame(&renderer).unwrap();
}

gfx_triangle.rs

use rkit::gfx::{self, Buffer, Color, RenderPipeline, Renderer, VertexFormat, VertexLayout};

// language=wgsl
const SHADER: &str = r#"
struct VertexInput {
    @location(0) position: vec2<f32>,
    @location(1) color: vec3<f32>,
};

struct VertexOutput {
    @builtin(position) position: vec4<f32>,
    @location(0) color: vec3<f32>,
};

@vertex
fn vs_main(
    model: VertexInput,
) -> VertexOutput {
    var out: VertexOutput;
    out.color = model.color;
    out.position = vec4<f32>(model.position - 0.5, 0.0, 1.0);
    return out;
}

@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    return vec4<f32>(in.color, 1.0);
}
"#;

struct State {
    pip: RenderPipeline,
    vbo: Buffer,
}

impl State {
    fn new() -> Result<Self, String> {
        let pip = gfx::create_render_pipeline(SHADER)
            .with_vertex_layout(
                VertexLayout::new()
                    .with_attr(0, VertexFormat::Float32x2)
                    .with_attr(1, VertexFormat::Float32x3),
            )
            .build()?;

        #[rustfmt::skip]
        let vertices: &[f32] = &[
            0.5, 1.0,   1.0, 0.0, 0.0,
            0.0, 0.0,   0.0, 1.0, 0.0,
            1.0, 0.0,   0.0, 0.0, 1.0,
        ];

        let vbo = gfx::create_vertex_buffer(vertices).build()?;
        Ok(Self { pip, vbo })
    }
}

fn main() {
    rkit::init_with(|| State::new().unwrap())
        .on_update(update)
        .run()
        .unwrap()
}

fn update(s: &mut State) {
    let mut renderer = Renderer::new();
    renderer
        .begin_pass()
        .clear_color(Color::rgb(0.1, 0.2, 0.3))
        .pipeline(&s.pip)
        .buffers(&[&s.vbo])
        .draw(0..3);

    gfx::render_to_frame(&renderer).unwrap();
}

@Nazariglez
Copy link
Owner Author

Nazariglez commented Sep 17, 2024

Working on Draw2D API:

draw_triangle.rs

use rkit::draw::draw_2d;
use rkit::gfx::{self, Color};
use rkit::math::vec2;

fn main() -> Result<(), String> {
    rkit::init().on_update(update).run()
}

fn update(s: &mut ()) {
    let mut draw = draw_2d();
    draw.clear(Color::rgb(0.1, 0.2, 0.3));
    draw.triangle(vec2(400.0, 100.0), vec2(100.0, 500.0), vec2(700.0, 500.0));
    gfx::render_to_frame(&draw).unwrap();
}

draw_sprite.rs

use rkit::app::window_size;
use rkit::draw::{draw_2d, Sprite};
use rkit::gfx::{self, Color};

struct State {
    sprite: Sprite,
}

impl State {
    fn new() -> Result<Self, String> {
        let sprite = draw::create_sprite()
            .from_image(include_bytes!("assets/ferris.png"))
            .build()?;

        Ok(Self { sprite })
    }
}

fn main() -> Result<(), String> {
    rkit::init_with(|| State::new().unwrap())
        .on_update(update)
        .run()
}

fn update(s: &mut State) {
    let pos = window_size() * 0.5 - s.sprite.size() * 0.5;

    let mut draw = draw_2d();
    draw.clear(Color::rgb(0.1, 0.2, 0.3));
    draw.image(&s.sprite).position(pos);
    gfx::render_to_frame(&draw).unwrap();
}

I am trying to keep the API as similar as possible but improving (or trying) some parts.

Related to this, WGPU is a different beast, and I am not sure yet how to manage blending and masking in a easy way, so I am still experimenting a lot with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants