zesterer / euc

A software rendering crate that lets you write shaders with Rust
Apache License 2.0
293 stars 18 forks source link

New Release/Further development #23

Open WannaBeKratos opened 1 year ago

WannaBeKratos commented 1 year ago

Is there a timeline for the merge of the rewrite branch ? Latest release was 1 year ago.

zesterer commented 1 year ago

Interesting you should mention this now, I've been doing a little work on it over the past week. There's just one non-trivial feature I'd like to add before it's ready to go: a line rasteriser. I'm happy to take contributions for it. Otherwise, I'll probably try to get round to it some time in the next week or two.

WannaBeKratos commented 1 year ago

-:( Unfortunately I'm not really familiar with graphics programming (just getting started :)), but i guess an implementation for line rasterizer based on the algorithm described in this presentation will suffice: Line Rasterization you said is not trivial, may I ask what challenges are you facing with the implementation?

zesterer commented 1 year ago

Oh, no challenges. I've just yet the find the time to do it. A simple implementation of Bresenham's algorithm will do just fine.

WannaBeKratos commented 1 year ago

Oke, I will Try to implement the Bresenham's algorithm for this package and submit a pull request this weekend 😃 hopefully i get somewhere.

zesterer commented 1 year ago

Thanks! You could probably duplicate most of triangles.rs and just swap out the inner loop with one that walks between each of the screen-space vertex coordinates. Thankfully, calculating barycentric coordinates for each point is relatively straightforward. I'm happy to help out & review, of course.

WannaBeKratos commented 1 year ago

I took your advice and copy most of the triangle.rs, but i do feel like i have bitten more than i can chew 🥲, you suggested to walk the screen space vertices, correct me if I'm wrong , but there are a maximum of 2 screen- space vertices(Points) ? Then while applying Bresenham's algorithm for the 2 points i need to emit fragments ?

zesterer commented 1 year ago

Yep. I'm happy to take it over if desired :)

WannaBeKratos commented 1 year ago

Was i close ? 😬 the initial part is just from triangle.rs, i added this loop for the vertices.

`;

        // Convert vertex coordinates to screen space
        let verts_screen = verts_euc.map(|euc| size * (euc.xy() * Vec2::new(0.5, -0.5) + 0.5));

        // Calculate change in vertex weights for each pixel
        //let weights_at = |p: Vec2<f32>| coords_to_weights * Vec3::new(p.x, p.y, 1.0);
        //let w_hom_origin = weights_at(Vec2::zero());
        //let w_hom_dx = (weights_at(Vec2::unit_x() * 1000.0) - w_hom_origin) / 1000.0;
        //let w_hom_dy = (weights_at(Vec2::unit_y() * 1000.0) - w_hom_origin) / 1000.0;

        // Iterate over screen-space vertex with Bresenham's algorithm

        let mut iter = verts_screen.iter();
        while let Some(vertex) = iter.next() {
            match iter.next() {
                Some(vertex2) => {
                    let mut x1 = vertex.x as i32;
                    let mut y1 = vertex.y as i32;

                    let mut x2 = vertex2.x as i32;
                    let mut y2 = vertex2.y as i32;

                    let dx = (x1.abs() - x2.abs()) as i32;
                    let dy = (y1.abs() - y2.abs()) as i32;

                    if (dx > dy) {
                        let mut pk = 2 * dy - dx;
                        for i in 0..dx {
                            if (x1 < x2) {
                                x1 += 1;
                            } else {
                                x1 -= 1;
                            }

                            if (pk < 0) {
                                //blitter.emit_fragment([x1, y1], get_v_data, z);
                                pk = pk + 2 * dy
                            } else {
                                if (y1 < y2) {
                                    y1 += 1;
                                } else {
                                    y1 -= 1;
                                }
                                pk = pk + 2 * dy - 2 * dx;
                            }
                        }
                    } else {
                        let mut pk = 2 * dy - dx;
                        for i in 0..dx {
                            if (x1 < x2) {
                                x1 += 1;
                            } else {
                                x1 -= 1;
                            }

                            if (pk < 0) {
                                //blitter.emit_fragment([y1, x1], get_v_data, z);
                                pk = pk + 2 * dy
                            } else {
                                if (y1 < y2) {
                                    y1 += 1;
                                } else {
                                    y1 -= 1;
                                }
                                pk = pk + 2 * dy - 2 * dx;
                            }
                        }
                    }
                }
                None => break,
            }
        }
    });
}`
zesterer commented 1 year ago

I think that's getting there, yes. Just need to deal with interpolating vertex data using barycentric (i.e: hom_) coordinates.

markusmoenig commented 1 year ago

I had a look at the refactor branch and it looks really nice. Hope it gets out in the near future.

I will probably use it to render low poly 3D scenes for my retro RPG Creator / Engine https://github.com/markusmoenig/Eldiron.

Software rendering makes it ultra-portable and for RPGs of the late 90s the current CPUs are more than fast enough, even on an iPhone, especially with multi-threading. Only thing I have to figure out is object based animations ... .

zesterer commented 1 year ago

Wow, sounds like a really fun project! I've used euc for similar stuff before.

Now that GATs are stable, I really have no excuse for not pushing the refactor branch forward.

I believe the only thing that's missing is a decent line rasteriser: if you happen to have a lot of experience here, I'd appreciate your input! The one in the master branch isn't great and it would be nice to have an upgrade on that.

markusmoenig commented 1 year ago

Thanks. No sorry, I am not a rasterizing expert ... .

btw; have you any experience with character animations and euc ? I.e. a Rust readable mesh format which supports animations (gltf ?) and executing transitions / morphing on the CPU ?

zesterer commented 1 year ago

I imagine would be much the same as on the GPU, albeit with a little less hassle (no need to load animation state into GPU buffers). There's definitely no reason as to why it would be any harder with euc than with an API like wgpu. In terms of loading those things, I suspect that taking a look at the work done on animations by the Bevy folks might provide some pointers.

markusmoenig commented 1 year ago

Talking about rasterization, the SoftGLRender C++ lib is under the MIT and seems to have quite a good line rasterizer at

src/Render/Software/RendererSoft.cpp