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

graphics!: separate texture binding from the Bindings struct #521

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bbogdan-ov
Copy link
Contributor

Warning

This PR will break most of the existing code

This PR aims to make MINIQUAD api more flexible by separating texture binding to its own method RenderingBackend::apply_images

Why?

Sometimes i need to use the same buffer bindings (vertex and index buffers) for different sprites for example (because they all are quads), but creating a new Bindings for each sprite just to change their texture is tedious.

This is especially frustrating when, for example, you need to load hundreds of .png files and create a texture for each of them. This can also lead to relatively huge memory usage and poor performance, as you need to allocate and store a vector of buffer IDs + another buffer ID for each texture.

Migration

 struct Stage {
     // ...
 }
 impl Stage {
     fn new() -> Stage {
         let my_texture_1: TextureId = /* load texture... */;
         let my_texture_2: TextureId = /* load texture... */;

         // `images` field was removed from the `Bindings` struct
         let my_bindings = Bindings {
             vertex_buffers: /* ... */,
             index_buffers: /* ... */,
-            images: vec![my_texture_1, my_texture_2],
         }

         // ...

         Stage {
             // ...
             my_bindings,

             // You'd better store these textures as separate variables:
+            my_texture_1,
+            my_texture_2,
         }
     }
 }
 impl EventHandler for Stage {
     // ...

     fn draw(&mut self) {
         // ...

         self.ctx.apply_bindings(self.my_bindings);
         // Now you need to explicitly apply textures
+        self.ctx.apply_images(&[self.my_texture_1, self.my_texture_2]);

         self.ctx.draw(0, 6, 1);
     }
 }

Example

This code is significantly simplified for clarity

Initialization:

let bindings = Bindings {
    vertex_buffers: /* ... */,
    index_buffer: /* ... */,
};

// Storing each texture in a separate variable
let texture1: TextureId = /* load texture... */;
let texture2: TextureId = /* load texture... */;

// All other steps are the same as before (e.g. creating pipeline or shader)
// ...

Drawing logic:

pub fn draw_sprite(&mut self, x: i32, y: i32, texture: &TextureId) {
    self.ctx.apply_pipeline(&self.pipeline);
    self.ctx.apply_bindings(&self.bindings);

    self.ctx.apply_image(texture);
    // If i need to apply multiple textures:
    // self.context.apply_images(&[texture, texture_n, ...]);

    self.ctx.apply_uniforms(/* ... */);

    self.ctx.draw(0, 6, 1);
}

Drawing sprites:

fn draw(&mut self) {
    // ...

    self.draw_sprite(10, 10, &texture1);
    self.draw_sprite(60, 10, &texture2);

    // I can draw as many sprites as i want:
    // self.draw_sprite(0, 0, &texture_n);
}

Result:

image

P.S.

Thanks for your time!

Hopefully this PR will be merged, but as I said earlier, it will break most of the existing code.

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.

1 participant