feat: added Color trait to the comet_colors crate to make parameters simpler

This commit is contained in:
lisk77 2025-03-18 16:52:49 +01:00
parent b2578f7673
commit 7dc17fb435
13 changed files with 100 additions and 132 deletions

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Hsla { pub struct Hsla {
@ -98,4 +98,10 @@ impl Hsla {
pub fn to_oklcha(&self) -> Oklcha { pub fn to_oklcha(&self) -> Oklcha {
self.to_oklaba().to_oklcha() self.to_oklaba().to_oklcha()
} }
}
impl Color for Hsla {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsla, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Hsva { pub struct Hsva {
@ -96,4 +96,10 @@ impl Hsva {
pub fn to_oklcha(&self) -> Oklcha { pub fn to_oklcha(&self) -> Oklcha {
self.to_oklaba().to_oklcha() self.to_oklaba().to_oklcha()
} }
}
impl Color for Hsva {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hsva, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsla, Hsva, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Hwba { pub struct Hwba {
@ -159,4 +159,10 @@ impl Hwba {
self.to_oklaba().to_oklcha() self.to_oklaba().to_oklcha()
} }
}
impl Color for Hwba {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hsva, Hwba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsla, Hsva, Hwba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Laba { pub struct Laba {
@ -140,4 +140,10 @@ impl Laba {
pub fn to_hsla(&self) -> Hsla { pub fn to_hsla(&self) -> Hsla {
self.to_hsva().to_hsla() self.to_hsva().to_hsla()
} }
}
impl Color for Laba {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hsva, Hwba, Laba, LinearRgba, Oklaba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsla, Hsva, Hwba, Laba, LinearRgba, Oklaba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Lcha { pub struct Lcha {
@ -90,4 +90,10 @@ impl Lcha {
self.to_hsva().to_hsla() self.to_hsva().to_hsla()
} }
}
impl Color for Lcha {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -19,4 +19,8 @@ mod xyza;
mod laba; mod laba;
mod lcha; mod lcha;
mod oklaba; mod oklaba;
mod oklcha; mod oklcha;
pub trait Color {
fn to_wgpu(&self) -> wgpu::Color;
}

View file

@ -1,5 +1,5 @@
use wgpu::Color; use wgpu;
use crate::{sRgba, Hsla, Hsva, Hwba, Laba, Lcha, Oklaba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsla, Hsva, Hwba, Laba, Lcha, Oklaba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct LinearRgba { pub struct LinearRgba {
@ -123,9 +123,11 @@ impl LinearRgba {
pub fn to_hsla(&self) -> Hsla { pub fn to_hsla(&self) -> Hsla {
self.to_hsva().to_hsla() self.to_hsva().to_hsla()
} }
}
pub fn to_wgpu(&self) -> Color { impl Color for LinearRgba {
Color { fn to_wgpu(&self) -> wgpu::Color {
wgpu::Color {
r: self.red as f64, r: self.red as f64,
g: self.green as f64, g: self.green as f64,
b: self.blue as f64, b: self.blue as f64,

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklcha, Xyza}; use crate::{sRgba, Color, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklcha, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Oklaba { pub struct Oklaba {
@ -110,4 +110,10 @@ impl Oklaba {
pub fn to_hsla(&self) -> Hsla { pub fn to_hsla(&self) -> Hsla {
self.to_hsva().to_hsla() self.to_hsva().to_hsla()
} }
}
impl Color for Oklaba {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Xyza}; use crate::{sRgba, Color, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Xyza};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Oklcha { pub struct Oklcha {
@ -89,4 +89,10 @@ impl Oklcha {
pub fn to_hsla(&self) -> Hsla { pub fn to_hsla(&self) -> Hsla {
self.to_hsva().to_hsla() self.to_hsva().to_hsla()
} }
}
impl Color for Oklcha {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{math::Vec4, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza}; use crate::{math::Vec4, Color, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Xyza};
/// sRGB representation of color /// sRGB representation of color
/// There are two variants: `sRgba<u8>` and `sRgba<f32>` /// There are two variants: `sRgba<u8>` and `sRgba<f32>`
@ -342,4 +342,16 @@ impl sRgba<f32> {
self.alpha self.alpha
) )
} }
}
impl Color for sRgba<f32> {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
}
impl Color for sRgba<u8> {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,4 +1,4 @@
use crate::{sRgba, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha}; use crate::{sRgba, Color, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Xyza { pub struct Xyza {
@ -106,4 +106,10 @@ impl Xyza {
pub fn to_hsla(&self) -> Hsla { pub fn to_hsla(&self) -> Hsla {
self.to_hsva().to_hsla() self.to_hsva().to_hsla()
} }
}
impl Color for Xyza {
fn to_wgpu(&self) -> wgpu::Color {
self.to_linear().to_wgpu()
}
} }

View file

@ -1,10 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use winit::window::Window; use winit::window::Window;
use comet_colors::LinearRgba; use comet_colors::Color;
pub trait Renderer: Sized + Send + Sync { pub trait Renderer: Sized + Send + Sync {
async fn new(window: Arc<Window>, clear_color: Option<LinearRgba>) -> Self; async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Self;
fn size(&self) -> PhysicalSize<u32>; fn size(&self) -> PhysicalSize<u32>;
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>); fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>);
fn update(&mut self) -> f32; fn update(&mut self) -> f32;

View file

@ -2,12 +2,12 @@ use std::iter;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use wgpu::{BufferUsages, Color, ShaderModule}; use wgpu::{BufferUsages, ShaderModule};
use wgpu::naga::ShaderStage; use wgpu::naga::ShaderStage;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use winit::window::Window; use winit::window::Window;
use comet_colors::LinearRgba; use comet_colors::{ Color, LinearRgba };
use comet_ecs::{Camera, Camera2D, Component, Position2D, Render, Render2D, Transform2D, Scene}; use comet_ecs::{Camera, Camera2D, Component, Position2D, Render, Render2D, Transform2D, Scene};
use comet_log::{debug, info}; use comet_log::{debug, info};
use comet_math::{Point3, Vec2, Vec3}; use comet_math::{Point3, Vec2, Vec3};
@ -28,13 +28,13 @@ pub struct Renderer2D<'a> {
pipelines: Vec<wgpu::RenderPipeline>, pipelines: Vec<wgpu::RenderPipeline>,
render_pass: Vec<RenderPassInfo>, render_pass: Vec<RenderPassInfo>,
last_frame_time: Instant, last_frame_time: Instant,
deltatime: f32, delta_time: f32,
vertex_buffer: wgpu::Buffer, vertex_buffer: wgpu::Buffer,
vertex_data: Vec<Vertex>, vertex_data: Vec<Vertex>,
index_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer,
index_data: Vec<u16>, index_data: Vec<u16>,
num_indices: u32, num_indices: u32,
clear_color: Color, clear_color: wgpu::Color,
diffuse_texture: Texture, diffuse_texture: Texture,
diffuse_bind_group_layout: wgpu::BindGroupLayout, diffuse_bind_group_layout: wgpu::BindGroupLayout,
diffuse_bind_group: wgpu::BindGroup, diffuse_bind_group: wgpu::BindGroup,
@ -46,7 +46,7 @@ pub struct Renderer2D<'a> {
} }
impl<'a> Renderer2D<'a> { impl<'a> Renderer2D<'a> {
pub async fn new(window: Arc<Window>, clear_color: Option<LinearRgba>) -> Renderer2D<'a> { pub async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Renderer2D<'a> {
let vertex_data: Vec<Vertex> = vec![]; let vertex_data: Vec<Vertex> = vec![];
let index_data: Vec<u16> = vec![]; let index_data: Vec<u16> = vec![];
@ -107,13 +107,13 @@ impl<'a> Renderer2D<'a> {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"), label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(&vertex_data), contents: bytemuck::cast_slice(&vertex_data),
usage: wgpu::BufferUsages::VERTEX | BufferUsages::COPY_DST, usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
}); });
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"), label: Some("Index Buffer"),
contents: bytemuck::cast_slice(&index_data), contents: bytemuck::cast_slice(&index_data),
usage: wgpu::BufferUsages::INDEX | BufferUsages::COPY_DST usage: BufferUsages::INDEX | BufferUsages::COPY_DST
}); });
let num_indices = index_data.len() as u32; let num_indices = index_data.len() as u32;
@ -170,7 +170,7 @@ impl<'a> Renderer2D<'a> {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"), label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]), contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
}); });
let camera_bind_group_layout = let camera_bind_group_layout =
@ -261,7 +261,7 @@ impl<'a> Renderer2D<'a> {
let clear_color = match clear_color { let clear_color = match clear_color {
Some(color) => color.to_wgpu(), Some(color) => color.to_wgpu(),
None => Color { None => wgpu::Color {
r: 0.0, r: 0.0,
g: 0.0, g: 0.0,
b: 0.0, b: 0.0,
@ -279,7 +279,7 @@ impl<'a> Renderer2D<'a> {
pipelines, pipelines,
render_pass: vec![], render_pass: vec![],
last_frame_time: Instant::now(), last_frame_time: Instant::now(),
deltatime: 0.0, delta_time: 0.0,
vertex_buffer, vertex_buffer,
vertex_data, vertex_data,
index_buffer, index_buffer,
@ -298,7 +298,7 @@ impl<'a> Renderer2D<'a> {
} }
pub fn dt(&self) -> f32 { pub fn dt(&self) -> f32 {
self.deltatime self.delta_time
} }
pub fn config(&self) -> &wgpu::SurfaceConfiguration { pub fn config(&self) -> &wgpu::SurfaceConfiguration {
@ -340,28 +340,6 @@ impl<'a> Renderer2D<'a> {
pub fn apply_shader(&mut self, shader: &str) { pub fn apply_shader(&mut self, shader: &str) {
let shader_module = self.graphic_resource_manager.get_shader( let shader_module = self.graphic_resource_manager.get_shader(
((Self::get_project_root().unwrap().as_os_str().to_str().unwrap().to_string() + "\\resources\\shaders\\").as_str().to_string() + shader).as_str()).unwrap(); ((Self::get_project_root().unwrap().as_os_str().to_str().unwrap().to_string() + "\\resources\\shaders\\").as_str().to_string() + shader).as_str()).unwrap();
let texture_bind_group_layout = self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: None,
},
],
label: Some("texture_bind_group_layout"),
});
let camera_bind_group_layout = self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { let camera_bind_group_layout = self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry { entries: &[wgpu::BindGroupLayoutEntry {
binding: 0, binding: 0,
@ -380,7 +358,7 @@ impl<'a> Renderer2D<'a> {
self.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { self.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"), label: Some("Render Pipeline Layout"),
bind_group_layouts: &[ bind_group_layouts: &[
&texture_bind_group_layout, &self.diffuse_bind_group_layout,
&camera_bind_group_layout, &camera_bind_group_layout,
], ],
push_constant_ranges: &[], push_constant_ranges: &[],
@ -742,13 +720,13 @@ impl<'a> Renderer2D<'a> {
self.vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { self.vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Updated Vertex Buffer"), label: Some("Updated Vertex Buffer"),
contents: bytemuck::cast_slice(&self.vertex_data), contents: bytemuck::cast_slice(&self.vertex_data),
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
}); });
self.index_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { self.index_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Updated Index Buffer"), label: Some("Updated Index Buffer"),
contents: bytemuck::cast_slice(&self.index_data), contents: bytemuck::cast_slice(&self.index_data),
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
}); });
self.num_indices = self.index_data.len() as u32; self.num_indices = self.index_data.len() as u32;
@ -780,7 +758,7 @@ impl<'a> Renderer2D<'a> {
} }
/// A function to draw text at a given position. /// A function to draw text at a given position.
pub fn draw_text_at(&mut self, text: &str, font: String, size: f32, position: Point3) { pub fn draw_text_at(&mut self, text: &str, font: String, size: f32, position: Point3, color: impl Color) {
self.set_font_atlas(font.clone()); self.set_font_atlas(font.clone());
let screen_position = Point3::new(position.x()/self.config.width as f32, position.y()/self.config.height as f32, position.z()); let screen_position = Point3::new(position.x()/self.config.width as f32, position.y()/self.config.height as f32, position.z());
@ -841,7 +819,6 @@ impl<'a> Renderer2D<'a> {
position = i; position = i;
} }
} }
position position
} }
@ -949,81 +926,6 @@ impl<'a> Renderer2D<'a> {
self.set_buffers(vertex_buffer, index_buffer); self.set_buffers(vertex_buffer, index_buffer);
} }
/*pub fn render_scene_2d(&mut self, world: &World) {
let cameras = world.get_entities_with(ComponentSet::from_ids(vec![Camera2D::type_id()]));
if cameras == vec![] {
return;
}
let (camera_position, camera_component) = self.setup_camera(cameras, world);
let mut visible_entities: Vec<usize> = vec![];
for entity in world.get_entities_with(ComponentSet::from_ids(vec![Transform2D::type_id(), Render2D::type_id()])) {
let entity_id = entity as usize;
if !camera_component
.in_view_frustum(*camera_position, *world.get_component::<Transform2D>(entity_id).unwrap().position())
{
continue;
}
match world.get_component::<Render2D>(entity_id) {
Some(render) => {
if !render.is_visible() {
continue;
}
if let Some(cam) = world.get_component::<Camera2D>(entity_id) {
continue;
}
visible_entities.push(entity_id);
}
None => {
continue;
}
}
}
let mut vertex_buffer: Vec<Vertex> = Vec::new();
let mut index_buffer: Vec<u16> = Vec::new();
//debug!("Visible entities: {:?}", visible_entities);
for entity in visible_entities {
let renderer_component = world.get_component::<Render2D>(entity);
let transform_component = world.get_component::<Transform2D>(entity);
if renderer_component.unwrap().is_visible() {
let mut position = transform_component.unwrap().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_region(renderer_component.unwrap().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);
}*/
fn sort_entities_by_position(&self, entity_data: Vec<(usize, Position2D)>) -> Vec<usize> { fn sort_entities_by_position(&self, entity_data: Vec<(usize, Position2D)>) -> Vec<usize> {
let mut sorted_entities: Vec<usize> = vec![]; let mut sorted_entities: Vec<usize> = vec![];
@ -1124,9 +1026,9 @@ impl<'a> Renderer2D<'a> {
pub fn update(&mut self) -> f32 { pub fn update(&mut self) -> f32 {
let now = Instant::now(); let now = Instant::now();
self.deltatime = now.duration_since(self.last_frame_time).as_secs_f32(); // Time delta in seconds self.delta_time = now.duration_since(self.last_frame_time).as_secs_f32(); // Time delta in seconds
self.last_frame_time = now; self.last_frame_time = now;
self.deltatime self.delta_time
} }
pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> { pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
@ -1174,7 +1076,7 @@ impl<'a> Renderer2D<'a> {
impl<'a> Renderer for Renderer2D<'a> { impl<'a> Renderer for Renderer2D<'a> {
async fn new(window: Arc<Window>, clear_color: Option<LinearRgba>) -> Renderer2D<'a> { async fn new(window: Arc<Window>, clear_color: Option<impl Color>) -> Renderer2D<'a> {
Self::new(window, clear_color).await Self::new(window, clear_color).await
} }