bwasty / vulkan-tutorial-rs

Rust version of https://github.com/Overv/VulkanTutorial
The Unlicense
694 stars 47 forks source link

Perhaps we should use cgmath instead of glm? #16

Closed nrayamajhee closed 5 years ago

nrayamajhee commented 5 years ago

I have been following this tutorial for the past couple of weeks and was almost sad that I would be stuck at chapter 20 without ever learning how to apply MVP transformations. Thanks @mcr431 for starting chapter 21.

But I was wondering if we can use cgmath instead of glm. Since the tutorial is significantly different from the C++ tutorial, I personally think we can benefit using cgmath instead of glm. I am new to rust and vulkan in general and am basing my argument solely on the fact that vulkano examples also use cgmath. It would be easier for a newcomer like me to navigate this fairly sparse set of vulkano tutorials if the math library in use was the same.

matthew-russo commented 5 years ago

@nrayamajhee Thanks! I have the rest of the sections in the pipeline with PRs submitted for all but the last one -- just working out some details on quality and consistency so they are easy to consume. Keep an eye out! I totally hear ya on library usage as I've spent a lot of time looking for relevant vulkano examples. In my personal projects I switched to cgmath due to better support and documentation so I'm familiar with it.

However, the reason I chose glm was for consistency with the original c++ vulkan tutorial, as the function calls are pretty much the exact same and I wanted to maintain as much similarity as possible. @bwasty do you have any opinions on the matter?

nrayamajhee commented 5 years ago

For example the teapot example from vulkano does sth like this:

    let elapsed = start_time.elapsed();
    let rotation = elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000.0;
    let rotation = Matrix3::from_angle_y(Rad(rotation as f32));

    let view = Matrix4::look_at(Point3::new(2.0,2.0, 2.0),Point3::new(0.0,0.0,0.0), Vector3::new(0.0,0.0,1.0));
    let scale = Matrix4::from_scale(0.01);

    let aspect_ratio = dimensions[0] as f32 /dimensions[1] as f32;
    let proj = cgmath::perspective(Rad(std::f32::consts::FRAC_PI_2),aspect_ratio,0.01,10.0);

    UniformBufferObject {
        model: Matrix4::from(rotation).into(),
        view: (view * scale).into(),
        proj: proj.into(),
    }

instead of:

        let duration = Instant::now().duration_since(start_time);
        let elapsed = (duration.as_secs() * 1000) + u64::from(duration.subsec_millis());

        let identity_matrix = glm::mat4(
            1.0, 0.0, 0.0, 0.0,
            0.0, 1.0, 0.0, 0.0,
            0.0, 0.0, 1.0, 0.0,
            0.0, 0.0, 0.0, 1.0,
        );

        let model = glm::ext::rotate(&identity_matrix, (elapsed as f32) * glm::radians(0.180), glm::vec3(0.0, 0.0, 1.00));

        let view = glm::ext::look_at(
            glm::vec3(2.0, 2.0, 2.0),
            glm::vec3(0.0, 0.0, 0.0),
            glm::vec3(0.0, 0.0, 1.0)
        );
        let mut proj = glm::ext::perspective(
            glm::radians(45.0,),
            dimensions[0] as f32 / dimensions[1] as f32,
            0.1,
            10.0
        );

        proj.c1.y *= -1.0;

UniformBufferObject { model, view, proj }
matthew-russo commented 5 years ago

Just for consistency of discussion as well I'm posting the c++ code that I was attempting to mirror:

    void updateUniformBuffer(uint32_t currentImage) {
        static auto startTime = std::chrono::high_resolution_clock::now();

        auto currentTime = std::chrono::high_resolution_clock::now();
        float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();

        UniformBufferObject ubo = {};
        ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
        ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
        ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 10.0f);
        ubo.proj[1][1] *= -1;

        ...
    }

Even if we were to switch to cgmath, I'd keep it as close to this structure as possible so it matches the original tutorial

nrayamajhee commented 5 years ago

Oh. Didn't see your PR. I was thinking you just got started. Thanks a ton! Looking forward to the rest of the tutorial.

bwasty commented 5 years ago

@mcr431 I actually overlooked this while reviewing since I wrote some C++ recently - I've always used cgmath in Rust so far and would definitely prefer it. Though I just saw that nalgebra has quite a few more stars now and amethyst hast switched to it recently, so that might be an alternative.

matthew-russo commented 5 years ago

I took a look at nalgebra’s documentation and read the amethyst issue. I’m good with switching to that over cgmath from a technical perspective.

The downside to this is that it’s still not what is used in the Vulkano docs which is the whole reason Nishan wanted the switch anyway? Cgmath recently switched maintainers and is now part of the Rust game dev github and actively managed with other projects like gfx I think so should be stable and maintained for a while. https://github.com/rustgd/cgmath/issues/468

bwasty commented 5 years ago

Similarity to the Vulkano examples is a good point, and cgmath does seem reasonably maintained, so I would go with it.

matthew-russo commented 5 years ago

Pr is here: https://github.com/bwasty/vulkan-tutorial-rs/pull/18. also updated all the future prs to use this so we wont need to deal with it later. Still need to go through them and test on other systems tho.

Thomspoon commented 5 years ago

Why not switch to nalgebra-glm?

matthew-russo commented 5 years ago

@Thomspoon I’m not really concerned with requiring a GLM-like interface. I originally went with glm-rs for consistency with the originally c++ tutorial. It’s my understanding that we went with Cgmath because it is used in other vulkano examples (and also gfx-rs examples) so it’s likely that if someone is searching for similar graphics material in rust, it will be most likely be using the same library.

I’m open to hearing an argument for nalgebra-glm though. Do we gain much by going with it?

Thomspoon commented 5 years ago

My only argument is nalgebra-glm remains consistent with the C++ tutorial, while retaining what nalgebra has to offer... Personally, I'd prefer if it either stayed the same (glm) or moved to nalgebra just to show what Rust has to offer. There are a few different flavors of the "vulkan-tutorial", but this one remains the closest to the original.

bwasty commented 5 years ago

I prefer the 'most used'/'most common' library to being perfectly consistent with C++ (cgmath and nalgebra are roughly equal - one has more stars, the other more downloads on crates.io). And the differences to glm aren't really that large as far as I see.