feat: added a camera with orthographic projection and did some work restructuring the comet_app to make the setup system optional. Input handling is moved to the app

This commit is contained in:
lisk77 2024-11-13 03:33:02 +01:00
parent 780365aeb8
commit 5a9f632e3a
22 changed files with 1173 additions and 349 deletions

View file

@ -1,9 +1,10 @@
[package]
name = "comet_renderer"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
[dependencies]
comet_ecs = { path = "../comet_ecs" }
comet_math = { path = "../comet_math" }
comet_resources = { path = "../comet_resources" }
comet_colors = { path = "../comet_colors" }

View file

@ -1,4 +1,4 @@
use comet_math::Point3;
use comet_math::{Point3, Vec2, Vec3};
#[rustfmt::skip]
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
@ -11,44 +11,30 @@ pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
const SAFE_FRAC_PI_2: f32 = std::f32::consts::FRAC_PI_2 - 0.0001;
pub struct Camera {
eye: cgmath::Point3<f32>,
target: cgmath::Point3<f32>,
up: cgmath::Vector3<f32>,
aspect: f32,
fovy: f32,
znear: f32,
zfar: f32,
zoom: f32,
dimension: Vec2,
position: Vec3
}
impl Camera {
pub fn new(
eye: cgmath::Point3<f32>,
target: cgmath::Point3<f32>,
up: cgmath::Vector3<f32>,
aspect: f32,
fovy: f32,
znear: f32,
zfar: f32,
zoom: f32,
dimension: Vec2,
position: Vec3
) -> Self {
Self {
eye,
target,
up,
aspect,
fovy,
znear,
zfar,
zoom,
dimension,
position
}
}
pub fn build_view_projection_matrix(&self) -> cgmath::Matrix4<f32> {
// 1.
let view = cgmath::Matrix4::look_at_rh(self.eye, self.target, self.up);
// 2.
let proj = cgmath::perspective(cgmath::Deg(self.fovy), self.aspect, self.znear, self.zfar);
let proj = cgmath::ortho(self.position.x() - self.dimension.x() / 2.0, self.position.x() + self.dimension.x() / 2.0, self.position.y() - self.dimension.y() / 2.0, self.position.y() + self.dimension.y() / 2.0, 1.0, 0.0);
// 3.
return OPENGL_TO_WGPU_MATRIX * proj * view;
return OPENGL_TO_WGPU_MATRIX * proj;
}
}

View file

@ -7,7 +7,6 @@ use std::sync::Arc;
use std::time::Instant;
use cgmath::num_traits::FloatConst;
use image::GenericImageView;
use log::info;
use wgpu::Color;
use wgpu::util::DeviceExt;
use winit::{
@ -16,9 +15,10 @@ use winit::{
};
use winit::dpi::Position;
use comet_colors::LinearRgba;
use comet_log::error;
use comet_ecs::{Component, ComponentSet, Render, Renderer2D, Transform2D, World};
use comet_log::*;
use comet_math;
use comet_math::{Mat4, Point3, Vec3};
use comet_math::{Mat4, Point3, Vec2, Vec3};
use comet_resources::{ResourceManager, texture, Vertex, Texture};
use comet_resources::texture_atlas::TextureRegion;
use crate::camera::{Camera, CameraUniform};
@ -67,10 +67,10 @@ pub struct Renderer<'a> {
diffuse_texture: texture::Texture,
diffuse_bind_group: wgpu::BindGroup,
resource_manager: ResourceManager,
/*camera: Camera,
camera: Camera,
camera_uniform: CameraUniform,
camera_buffer: wgpu::Buffer,
camera_bind_group: wgpu::BindGroup,*/
camera_bind_group: wgpu::BindGroup,
}
impl<'a> Renderer<'a> {
@ -199,64 +199,47 @@ impl<'a> Renderer<'a> {
label: Some("diffuse_bind_group"),
});
/*let camera = Camera::new(
// position the camera 1 unit up and 2 units back
// +z is out of the screen
(0.0, 1.0, 2.0).into(),
// have it look at the origin
(0.0, 0.0, 0.0).into(),
// which way is "up"
cgmath::Vector3::unit_y(),
config.width as f32 / config.height as f32,
45.0,
0.1,
100.0,
);
let camera = Camera::new(1.0, Vec2::new(2.0, 2.0), Vec3::new(0.0, 0.0, 0.0));
let mut camera_uniform = CameraUniform::new();
camera_uniform.update_view_proj(&camera);
let mut camera_uniform = CameraUniform::new();
camera_uniform.update_view_proj(&camera);
let camera_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
}
);
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let camera_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}
],
label: Some("camera_bind_group_layout"),
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
label: Some("camera_bind_group_layout"),
});
let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &camera_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: camera_buffer.as_entire_binding(),
}
],
label: Some("camera_bind_group"),
});*/
let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &camera_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: camera_buffer.as_entire_binding(),
}],
label: Some("camera_bind_group"),
});
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"),
bind_group_layouts: &[
&texture_bind_group_layout,
//&camera_bind_group_layout,
&camera_bind_group_layout,
],
push_constant_ranges: &[],
});
@ -347,10 +330,10 @@ impl<'a> Renderer<'a> {
diffuse_texture,
diffuse_bind_group,
resource_manager,
/*camera,
camera,
camera_uniform,
camera_buffer,
camera_bind_group,*/
camera_bind_group,
})
}
@ -380,10 +363,10 @@ impl<'a> Renderer<'a> {
((width/ self.config.width as f32) * 0.5, (height/ self.config.height as f32) * 0.5);
vec![
Vertex :: new ( [-bound_x, bound_y, 0.0], [0.0, 0.0] ),
Vertex :: new ( [-bound_x, -bound_y, 0.0], [0.0, 1.0] ),
Vertex :: new ( [ bound_x, -bound_y, 0.0], [1.0, 1.0]) ,
Vertex :: new ( [ bound_x, bound_y, 0.0], [1.0, 0.0] )
Vertex :: new ( [-bound_x, bound_y, 0.0], [0.0, 0.0], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [-bound_x, -bound_y, 0.0], [0.0, 1.0], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [ bound_x, -bound_y, 0.0], [1.0, 1.0], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [ bound_x, bound_y, 0.0], [1.0, 0.0], [0.0, 0.0, 0.0, 0.0] )
]
}
@ -401,10 +384,10 @@ impl<'a> Renderer<'a> {
((self.diffuse_texture.size.width as f32/ self.config.width as f32) * 0.5, (self.diffuse_texture.size.height as f32/ self.config.height as f32) * 0.5);
let vertices: Vec<Vertex> = vec![
Vertex :: new ( [-bound_x, bound_y, 0.0], [0.0, 0.0] ),
Vertex :: new ( [-bound_x, -bound_y, 0.0], [0.0, 1.0] ),
Vertex :: new ( [ bound_x, -bound_y, 0.0], [1.0, 1.0]) ,
Vertex :: new ( [ bound_x, bound_y, 0.0], [1.0, 0.0] )
Vertex :: new ( [-bound_x, bound_y, 0.0], [0.0, 0.0], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [-bound_x, -bound_y, 0.0], [0.0, 1.0], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [ bound_x, -bound_y, 0.0], [1.0, 1.0], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [ bound_x, bound_y, 0.0], [1.0, 0.0], [0.0, 0.0, 0.0, 0.0] )
];
/*let vertices: Vec<Vertex> = vec![
@ -494,8 +477,6 @@ impl<'a> Renderer<'a> {
paths.push(texture_path.clone() + path.unwrap().file_name().to_str().unwrap());
}
error!(format!("{:?}", paths));
self.set_texture_atlas(paths);
}
@ -572,10 +553,10 @@ impl<'a> Renderer<'a> {
((dim_x as f32/ self.config.width as f32) * 0.5, (dim_y as f32/ self.config.height as f32) * 0.5);
let vertices: &mut Vec<Vertex> = &mut vec![
Vertex :: new ( [-bound_x + position.x(), bound_y + position.y(), 0.0 + position.z()], [region.x0(), region.y0()] ),
Vertex :: new ( [-bound_x + position.x(), -bound_y + position.y(), 0.0 + position.z()], [region.x0(), region.y1()] ),
Vertex :: new ( [ bound_x + position.x(), -bound_y + position.y(), 0.0 + position.z()], [region.x1(), region.y1()] ) ,
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0 + position.z()], [region.x1(), region.y0()] )
Vertex :: new ( [-bound_x + position.x(), bound_y + position.y(), 0.0 + position.z()], [region.x0(), region.y0()], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [-bound_x + position.x(), -bound_y + position.y(), 0.0 + position.z()], [region.x0(), region.y1()], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [ bound_x + position.x(), -bound_y + position.y(), 0.0 + position.z()], [region.x1(), region.y1()], [0.0, 0.0, 0.0, 0.0] ) ,
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0 + position.z()], [region.x1(), region.y0()], [0.0, 0.0, 0.0, 0.0] )
];
let buffer_size = self.vertex_data.len() as u16;
@ -588,6 +569,45 @@ impl<'a> Renderer<'a> {
self.push_to_buffers(vertices, indices)
}
pub fn render_scene_2d(&mut self, world: &World) {
let entities = world.get_entities_with(ComponentSet::from_ids(vec![Renderer2D::type_id()]));
let mut vertex_buffer: Vec<Vertex> = Vec::new();
let mut index_buffer: Vec<u16> = Vec::new();
for entity in entities {
let renderer_component = world.get_component::<Renderer2D>(entity as usize);
let transform_component = world.get_component::<Transform2D>(entity as usize);
if renderer_component.is_visible() {
//renderer.draw_texture_at(renderer_component.get_texture(), Point3::new(transform_component.position().x(), transform_component.position().y(), 0.0));
let mut position = transform_component.position().clone();
position.set_x(position.x() / self.config().width as f32);
position.set_y(position.y() / self.config().height as f32);
let region = self.get_texture(renderer_component.get_texture().to_string());
let (dim_x, dim_y) = region.dimensions();
let (bound_x, bound_y) =
((dim_x as f32/ self.config().width as f32) * 0.5, (dim_y as f32/ self.config().height as f32) * 0.5);
let buffer_size = vertex_buffer.len() as u16;
vertex_buffer.append(&mut vec![
Vertex :: new ( [-bound_x + position.x(), bound_y + position.y(), 0.0], [region.x0(), region.y0()], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [-bound_x + position.x(), -bound_y + position.y(), 0.0], [region.x0(), region.y1()], [0.0, 0.0, 0.0, 0.0] ),
Vertex :: new ( [ bound_x + position.x(), -bound_y + position.y(), 0.0], [region.x1(), region.y1()], [0.0, 0.0, 0.0, 0.0] ) ,
Vertex :: new ( [ bound_x + position.x(), bound_y + position.y(), 0.0], [region.x1(), region.y0()], [0.0, 0.0, 0.0, 0.0] )
]);
index_buffer.append(&mut vec![
0 + buffer_size, 1 + buffer_size, 3 + buffer_size,
1 + buffer_size, 2 + buffer_size, 3 + buffer_size
]);
}
}
self.set_buffers(vertex_buffer, index_buffer);
}
pub fn window(&self) -> &Window {
&self.window
}
@ -606,10 +626,11 @@ impl<'a> Renderer<'a> {
}
}
pub fn update(&mut self) {
pub fn update(&mut self) -> f32 {
let now = Instant::now();
self.deltatime = now.duration_since(self.last_frame_time).as_secs_f32(); // Time delta in seconds
self.last_frame_time = now;
self.deltatime
}
pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
@ -642,7 +663,7 @@ impl<'a> Renderer<'a> {
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);
//render_pass.set_bind_group(1, &self.camera_bind_group, &[]);
render_pass.set_bind_group(1, &self.camera_bind_group, &[]);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
render_pass.draw_indexed(0..self.num_indices, 0, 0..1);

View file

@ -1,18 +1,20 @@
// Vertex shader
/*struct CameraUniform {
struct CameraUniform {
view_proj: mat4x4<f32>,
};
@group(1) @binding(0) // 1.
var<uniform> camera: CameraUniform;*/
var<uniform> camera: CameraUniform;
struct VertexInput {
@location(0) position: vec3<f32>,
@location(1) tex_coords: vec2<f32>,
@location(2) color: vec4<f32>,
}
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
@location(1) color: vec4<f32>,
}
@vertex
@ -21,7 +23,8 @@ fn vs_main(
) -> VertexOutput {
var out: VertexOutput;
out.tex_coords = model.tex_coords;
out.clip_position = /*camera.view_proj **/ vec4<f32>(model.position, 1.0);
out.color = model.color;
out.clip_position = camera.view_proj * vec4<f32>(model.position, 1.0);
return out;
}