miye 0.1.2

A simple, lightweight .obj model renderer.
Documentation
use crate::models::Model;
use crate::state::State;
use std::ops::Range;

pub fn draw(state: &mut State) {
    let frame = state.surface.get_current_texture().unwrap();

    let view = frame
        .texture
        .create_view(&wgpu::TextureViewDescriptor::default());

    let mut encoder = state
        .device
        .create_command_encoder(&wgpu::CommandEncoderDescriptor {
            label: Some("Command Encoder"),
        });

    state.camera_uniform.update_view_proj(&state.camera);
    state.queue.write_buffer(
        &state.camera_buffer,
        0,
        bytemuck::cast_slice(&[state.camera_uniform]),
    );

    {
        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
            label: Some("Vertex Render Pass"),
            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                view: &view,
                resolve_target: None,
                ops: wgpu::Operations {
                    load: wgpu::LoadOp::Clear(wgpu::Color::WHITE),
                    store: wgpu::StoreOp::Store,
                },
            })],
            depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
                view: &state.depth_texture.view,
                depth_ops: Some(wgpu::Operations {
                    load: wgpu::LoadOp::Clear(1.0),
                    store: wgpu::StoreOp::Store,
                }),
                stencil_ops: None,
            }),
            timestamp_writes: None,
            occlusion_query_set: None,
        });

        render_pass.set_bind_group(0, &state.camera_bind_group, &[]);
        render_pass.set_pipeline(&state.render_pipeline);
        for i in &state.instances {
            render_pass.draw_model(&i.model);
        }
    }

    state.queue.submit(Some(encoder.finish()));
    frame.present();
}

pub trait DrawModel<'a> {
    fn draw_mesh(&mut self, mesh: &'a crate::models::Mesh, material: &'a crate::models::Material);
    fn draw_mesh_instanced(
        &mut self,
        mesh: &'a crate::models::Mesh,
        instances: Range<u32>,
        material: &'a crate::models::Material,
    );
    fn draw_model(&mut self, model: &'a Model);
    fn draw_model_instanced(&mut self, model: &'a Model, instances: Range<u32>);
}

impl<'a, 'b> DrawModel<'b> for wgpu::RenderPass<'a>
where
    'b: 'a,
{
    fn draw_mesh(&mut self, mesh: &'b crate::models::Mesh, material: &'a crate::models::Material) {
        self.draw_mesh_instanced(mesh, 0..1, material)
    }

    fn draw_mesh_instanced(
        &mut self,
        mesh: &'b crate::models::Mesh,
        instances: Range<u32>,
        material: &'b crate::models::Material,
    ) {
        self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
        self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
        self.set_bind_group(1, &material.bind_group, &[]);
        self.draw_indexed(0..mesh.num_elements, 0, instances);
    }

    fn draw_model(&mut self, model: &'b Model) {
        self.draw_model_instanced(model, 0..1);
    }

    fn draw_model_instanced(&mut self, model: &'b Model, instances: Range<u32>) {
        for mesh in &model.mesh {
            let material = &model.material[mesh.material];
            self.draw_mesh_instanced(mesh, instances.clone(), material);
        }
    }
}