Skip to content

Renderer

Antonio Caggiano edited this page Oct 5, 2021 · 1 revision

If you find this page to be out of date, please report or update it.

The Renderer has a draw() method which does not submit any commands to the GPU yet, but put all objects that need to be drawn in certain lists within the Renderer.

Then it has a bunch of render methods which submit commands to the GPU according the objects lists:

  • render_shadow(model, target): it renderers a shadowmap onto a framebuffer depth attachment.
  • render_geometry(model, target): it renderers both color and depth onto a framebuffer which should be the so-called G-buffer.

The following two methods are used to blit a source attachment to another framebuffer color attachment:

  • blit_depth(source, target): it renders the depth attachment of the source onto the color attachment of the target.
  • blit_color(source, target): it renderers the color attachment written by the render_geometry() method onto the default framebuffer.

The Renderer has also a draw_gui() method which can be called after rendering/presenting and before calling swap_buffers().

Frame

The main graphics object (gfx) has a frame which is taken by the user for drawing. We can draw things on the frame and then we give it back to gfx for presenting it to screen.

// Pseudocode
let frame = gfx.next_frame();
renderer.draw(&scene, &frame.default_framebuffer);
gfx.present(frame);

Let us consider multiple framebuffers:

  1. shadowmap
  2. geometry (albedo, normal, depth)
  3. default

Let us introduce two new types:

struct CustomFramebuffer { textures, .., framebuffer }
struct DefaultFramebuffer { framebuffer }

And a trait implemented by both the previous structs.

trait DrawableOnto {
 fn get_framebuffer(&self) -> gl::Framebuffer;
}

The trait is used by the render/present methods to enable drawing on both custom framebuffers and default framebuffer.

impl Renderer {
  fn render_geometry<T: DrawableOnto>(scene: &Model, target: &T);
}

The blit methods borrows a CustomFramebuffer and blits it onto a DrawableOnto object, so that could be either another custom framebuffer or the default framebuffer.

impl Renderer {
  fn blit_depth<T: DrawableOnto>(&mut self, source: &CustomFramebuffer, target: &T);
  fn blit_color<T: DrawableOnto>(&mut self, source: &CustomFramebuffer, target: &T);
}

We probably just need a texture instead of the whole custom framebuffer.

Examples

let frame = gfx.next_frame();
renderer.draw(&scene);
renderer.render_shadow(&scene, &frame.shadow_buffer);
renderer.blit(&frame.shadow_buffer, &frame.default_framebuffer);
gfx.present(frame);
// Draw directly onto default framebuffer
renderer.draw(&scene);
renderer.render_geometry(&scene, &frame.default_framebuffer);
gfx.present(frame);
// Draw onto custom framebuffer, then blit to another custom framebuffer, then blit to default.
renderer.draw(&scene);
renderer.render_shadow(&scene, &frame.shadow_buffer);
renderer.blit_depth(&frame.shadow_buffer, &frame.geometry_buffer);
renderer.blit_color(&frame.geometry_buffer, &frame.default_framebuffer);
gfx.present(frame);
Clone this wiki locally