I(lO9_HQvozqukfcSu@)7iv
zd@64Q|1XnWBDllK+UsAZf32j`9?TlkGV^B9JTTLD0A3c6Z
z#FFV$fy6AE3)Ou_?~}-87$6IhHOUQ0M^9V&ml9^wDHw*q;bAa*7siuGSd?GWBus6V
zgd>|LacR#I;^rE0HjC5KQ8U0(M6;(SuJk<%%j8QKkH`6_kZHi-68#5X75+I5kCOaj
zk}Hk)t{!j>zHwnoJI;j8RyZ?PxXsFA`%O&AnfjPfzBj3zytPFcWpQ%uV`KPE)AZcu
zX)o-EE{-Q5-r0i+{TI{EXjZDYX&!x>
zdD!H=lDJx6E|1>Sr#Ex5mmLW)&hG2Z!Dd%(FKfyoudf=+!+k@yuCy=NR6KpK@%ggn
zq=^N8R@>|v4F9}zOXB?4ZlBa!lubSMwyyV*v@hZ8)%LRP)Yz8IZiol#>BgR24SWcF
zFG<4zKfJK{*TCp=S=yISmp<6*63&+F4QcAatEV?R1w*L6CCv`NsgKRB-CnNNcjB4z
zx-`7qUfjP2PCho@!to)tFEQr(OULiFEd2D}lcp9NpXd*vFI+j`zlHGMJQvFDFG|?^
z3wilI*sm1<&ubF6Ge7Zg-j;x4!_k+(@4a&1wj=Q+9ES~b_a&_cwp(NHI}#K4-jt9}
zJpR7qr|ROnC80Mlj^7>K;m7=r-(B6of7E&RbSD>_Joa;6!Z&9w=Ef%Oj~G6c`~?TH
BZ(RTY
literal 0
HcmV?d00001
diff --git a/src/renderer/bidimensional/transform.rs b/src/renderer/bidimensional/transform.rs
index a5a3884..0690d55 100644
--- a/src/renderer/bidimensional/transform.rs
+++ b/src/renderer/bidimensional/transform.rs
@@ -1,33 +1,35 @@
+use crate::renderer::bidimensional::gl_representations::{create_glmat4, GlUniform};
+use ultraviolet::{Isometry3, Rotor3, Similarity3, Vec3};
+
#[derive(Default, Debug, Copy, Clone)]
pub struct Position2D {
pub x: f32,
- pub y: f32
+ pub y: f32,
}
#[derive(Debug)]
pub struct Transform2D {
pub(crate) position: Position2D,
pub(crate) scale: f32,
- pub(crate) angle: f32
+ pub(crate) angle: f32,
}
-impl Default for Transform2D{
+impl Default for Transform2D {
fn default() -> Self {
Self {
position: Default::default(),
scale: 1.0,
- angle: 0.0
+ angle: 0.0,
}
}
}
impl Transform2D {
-
- pub fn new(position: Position2D, scale: f32, angle: f32) -> Self{
+ pub fn new(position: Position2D, scale: f32, angle: f32) -> Self {
Self {
position,
scale,
- angle
+ angle,
}
}
@@ -41,4 +43,24 @@ impl Transform2D {
}
}
+impl From<&Transform2D> for GlUniform {
+ fn from(transform: &Transform2D) -> Self {
+ let mut transform_rotate = Isometry3::identity();
+ transform_rotate.append_translation(Vec3 {
+ x: transform.position.x,
+ y: transform.position.y,
+ z: 1.0,
+ });
+ transform_rotate.prepend_rotation(Rotor3::from_rotation_xy(transform.angle).normalized());
+
+ let mut scale = Similarity3::identity();
+ scale.append_scaling(transform.scale);
+ let mut transform_rotate = transform_rotate.into_homogeneous_matrix();
+ let mut scale = scale.into_homogeneous_matrix();
+ GlUniform {
+ trans: create_glmat4(&mut transform_rotate),
+ scale: create_glmat4(&mut scale),
+ }
+ }
+}
diff --git a/src/renderer/bidimensional/triangle.rs b/src/renderer/bidimensional/triangle.rs
index f3df9b6..c541fbe 100644
--- a/src/renderer/bidimensional/triangle.rs
+++ b/src/renderer/bidimensional/triangle.rs
@@ -1,186 +1,60 @@
-use miniquad::{Context, Buffer, BufferType, Bindings, Shader, Pipeline, BufferLayout, VertexAttribute, VertexFormat};
-use crate::renderer::bidimensional::gl_representations::{ColoredGlVertex, GlVec2, GlColor, GlUniform, create_glmat4, TexturedGlVertex};
-use crate::renderer::bidimensional::material::{Material2D, Texture2D};
-use ultraviolet::{Isometry3, Similarity3, Vec4, Vec3, Rotor3, Rotor2, Similarity2, Vec2, Mat4};
-use crate::renderer::bidimensional::renderer::Renderable2D;
-use crate::renderer::bidimensional::transform::{Transform2D, Position2D};
-use image::{GenericImageView};
-use crate::renderer::color::Color;
+use wgpu::{BindGroupLayout, Device, RenderPipeline, SwapChainDescriptor};
+
+use crate::renderer::bidimensional::gl_representations::TexturedGlVertex;
+
+use crate::renderer::bidimensional::transform::Position2D;
pub struct Triangle {
pub vertices: [Position2D; 3],
pub uvs: Option<[Position2D; 3]>,
}
-impl Triangle {
- pub fn render_colored(&self, context: &mut Context, transform: &Transform2D, color: &Color) -> (Pipeline, Bindings){
- let color: GlColor = color.into();
- let vertices: [ColoredGlVertex; 3] = [
- ColoredGlVertex { pos: GlVec2::from(&self.vertices[0]), color: color.clone() },
- ColoredGlVertex { pos: GlVec2::from(&self.vertices[1]), color: color.clone() },
- ColoredGlVertex { pos: GlVec2::from(&self.vertices[2]), color },
- ];
-
- let vertex_buffer = Buffer::immutable(context, BufferType::VertexBuffer, &vertices);
- let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
- let index_buffer = Buffer::immutable(context, BufferType::IndexBuffer, &indices);
-
- let bindings = Bindings {
- vertex_buffers: vec![vertex_buffer],
- index_buffer,
- images: vec![],
- };
-
- let shader = Shader::new(context, shader::VERTEX_COLORED, shader::FRAGMENT_COLORED, shader::meta(vec![])).unwrap();
-
- let pipeline = Pipeline::new(
- context,
- &[BufferLayout::default()],
- &[
- VertexAttribute::new("pos", VertexFormat::Float2),
- VertexAttribute::new("color", VertexFormat::Float4),
- ],
- shader,
- );
-
- (pipeline, bindings)
-
- }
-
- pub fn render_textured(&self, context: &mut Context, transform: &Transform2D, texture: &Texture2D) -> (Pipeline, Bindings){
- let uvs = self.uvs.unwrap_or_else(|| {
- log::error!("No uv map found for shape with Texture2D material. Using default positions.");
- [Position2D { x: 0.0, y: 0.0 }; 3]
- });
- let vertices: [TexturedGlVertex; 3] = [
- TexturedGlVertex { pos: GlVec2::from(&self.vertices[0]), uv: GlVec2::from(&uvs[0]) },
- TexturedGlVertex { pos: GlVec2::from(&self.vertices[1]), uv: GlVec2::from(&uvs[1]) },
- TexturedGlVertex { pos: GlVec2::from(&self.vertices[2]), uv: GlVec2::from(&uvs[2]) },
- ];
- let vertex_buffer = Buffer::immutable(context, BufferType::VertexBuffer, &vertices);
- let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
- let index_buffer = Buffer::immutable(context, BufferType::IndexBuffer, &indices);
-
- let bindings = Bindings {
- vertex_buffers: vec![vertex_buffer],
- index_buffer,
- images: vec![miniquad::Texture::from_rgba8(context, texture.width, texture.height, &texture.bytes)],
- };
-
- let shader = Shader::new(context, shader::VERTEX_TEXTURED, shader::FRAGMENT_TEXTURED, shader::meta(vec!["tex".to_string()])).unwrap();
-
- let pipeline = Pipeline::new(
- context,
- &[BufferLayout::default()],
- &[
- VertexAttribute::new("pos", VertexFormat::Float2),
- VertexAttribute::new("uv", VertexFormat::Float2),
- ],
- shader,
- );
-
- (pipeline, bindings)
- }
-}
-
-impl Renderable2D for Triangle {
- fn render(&self, context: &mut Context, material: Option<&Material2D>, transform: &Transform2D) {
- let (pipeline, bindings) = match material.expect("Render function must not be called without a material") {
- Material2D::Color(color) => self.render_colored(context, transform, &color),
- Material2D::Texture(texture) => self.render_textured(context, transform, &texture)
- };
-
- context.apply_pipeline(&pipeline);
- context.apply_bindings(&bindings);
-
- let mut transform_rotate = Isometry3::identity();
- transform_rotate.append_translation(Vec3 {
- x: transform.position.x,
- y: transform.position.y,
- z: 1.0,
- });
- transform_rotate.prepend_rotation(Rotor3::from_rotation_xy(transform.angle).normalized());
-
- let mut scale = Similarity3::identity();
- scale.append_scaling(transform.scale);
-
- let mut transform_rotate = transform_rotate.into_homogeneous_matrix();
- let mut scale = scale.into_homogeneous_matrix();
-
- context.apply_uniforms(&GlUniform { offset: (0., 0.), trans: create_glmat4(&mut transform_rotate), scale: create_glmat4(&mut scale) });
-
- context.draw(0, 3, 1);
- }
-}
-
-
-mod shader {
- use miniquad::*;
-
- pub const VERTEX_TEXTURED: &str =
- r#"
- #version 330 core
- in vec2 pos;
- in vec2 uv;
-
- uniform mat4 trans;
- uniform mat4 scale;
- uniform vec2 offset;
-
- out lowp vec2 texcoord;
- void main() {
- gl_Position = (trans * vec4(pos, 0, 1)) * scale;
- texcoord = uv;
- }
- "#;
-
- pub const VERTEX_COLORED: &str =
- r#"
- #version 330 core
- in vec2 pos;
- in vec4 color;
-
- uniform mat4 trans;
- uniform mat4 scale;
- uniform vec2 offset;
-
- out lowp vec4 color_lowp;
- void main() {
- gl_Position = (trans * vec4(pos, 0, 1)) * scale;
- color_lowp = color;
- }
- "#;
-
- pub const FRAGMENT_COLORED: &str =
- r#"
- #version 330 core
- in lowp vec4 color_lowp;
- out vec4 FragColor;
- void main() {
- FragColor = color_lowp;
- }
- "#;
-
- pub const FRAGMENT_TEXTURED: &str =
- r#"
- #version 330 core
- in lowp vec2 texcoord;
- out vec4 FragColor;
- uniform sampler2D tex;
- void main() {
- FragColor = texture(tex, texcoord);
- }
- "#;
-
- pub fn meta(images: Vec) -> ShaderMeta {
- ShaderMeta {
- images,
- uniforms: UniformBlockLayout {
- uniforms: vec![
- UniformDesc::new("offset", UniformType::Float2),
- UniformDesc::new("trans", UniformType::Mat4),
- UniformDesc::new("scale", UniformType::Mat4)],
- },
- }
- }
+pub(crate) fn triangle_pipeline(
+ device: &Device,
+ sc_desc: &SwapChainDescriptor,
+ texture_bind_group_layout: &BindGroupLayout,
+ transform_bind_group_layout: &BindGroupLayout,
+) -> RenderPipeline {
+ let vs_module = device.create_shader_module(&wgpu::include_spirv!("shaders/shader.vert.spv"));
+ let fs_module = device.create_shader_module(&wgpu::include_spirv!("shaders/shader.frag.spv"));
+
+ let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: Some("Basic triangle pipeline layout"),
+ bind_group_layouts: &[texture_bind_group_layout, transform_bind_group_layout],
+ push_constant_ranges: &[],
+ });
+
+ let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+ label: Some("Triangle render pipeline"),
+ layout: Some(&render_pipeline_layout),
+ vertex: wgpu::VertexState {
+ module: &vs_module,
+ entry_point: "main",
+ buffers: &[TexturedGlVertex::desc()],
+ },
+ fragment: Some(wgpu::FragmentState {
+ module: &fs_module,
+ entry_point: "main",
+ targets: &[wgpu::ColorTargetState {
+ format: sc_desc.format,
+ alpha_blend: wgpu::BlendState::REPLACE,
+ color_blend: wgpu::BlendState::REPLACE,
+ write_mask: wgpu::ColorWrite::ALL,
+ }],
+ }),
+ primitive: wgpu::PrimitiveState {
+ topology: wgpu::PrimitiveTopology::TriangleList,
+ strip_index_format: None,
+ front_face: wgpu::FrontFace::Ccw,
+ cull_mode: wgpu::CullMode::Back,
+ polygon_mode: wgpu::PolygonMode::Fill,
+ },
+ depth_stencil: None,
+ multisample: wgpu::MultisampleState {
+ count: 1,
+ mask: !0,
+ alpha_to_coverage_enabled: false,
+ },
+ });
+ render_pipeline
}
diff --git a/src/renderer/color.rs b/src/renderer/color.rs
index 08da577..8fb5a56 100644
--- a/src/renderer/color.rs
+++ b/src/renderer/color.rs
@@ -9,13 +9,16 @@ pub struct Color {
/// Blue value of the color
b: u8,
/// Alpha value of the color
- a: f32
+ a: f32,
}
impl Color {
pub fn new(r: u8, g: u8, b: u8, a: f32) -> Self {
- assert!(a <= 1. && a >= 0., "Alpha value must be between 0.0 and 1.0");
- Self { r,g,b,a }
+ assert!(
+ a <= 1. && a >= 0.,
+ "Alpha value must be between 0.0 and 1.0"
+ );
+ Self { r, g, b, a }
}
pub fn new_rgb(r: u8, g: u8, b: u8) -> Self {
@@ -46,13 +49,13 @@ impl Color {
}
}
-impl Into for &Color{
+impl Into for &Color {
fn into(self) -> GlColor {
- GlColor{
+ GlColor {
r: self.r as f32 / 255.,
g: self.g as f32 / 255.,
b: self.b as f32 / 255.,
- a: self.a
+ a: self.a,
}
}
-}
\ No newline at end of file
+}
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index fd65c3a..157ca9c 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -1,33 +1,41 @@
pub mod bidimensional;
pub mod color;
-use miniquad::Context;
-use legion::{World, Resources};
+pub mod renderer_state;
+use legion::World;
+use crate::renderer::bidimensional::scion2d::Scion2D;
+use wgpu::{CommandEncoder, Device, Queue, SwapChainDescriptor, SwapChainTexture};
/// Trait to implement in order to create a renderer to use in a `Scion` application
pub trait ScionRenderer {
- /// The draw method is called each frame
- fn draw(&mut self, context: &mut Context, world: &mut World, resource: &mut Resources);
+ fn update(
+ &mut self,
+ world: &mut World,
+ device: &Device,
+ sc_desc: &SwapChainDescriptor,
+ queue: &mut Queue,
+ );
+ fn render(&mut self, world: &mut World, frame: &SwapChainTexture, encoder: &mut CommandEncoder);
}
/// Type of renderer to use to render the game.
pub enum RendererType {
Scion2D,
- Custom(Box)
+ Custom(Box),
}
-impl Default for RendererType{
+impl Default for RendererType {
fn default() -> Self {
RendererType::Scion2D
}
}
-impl RendererType{
- pub(crate) fn into_boxed_renderer(self) -> Box{
- match self{
- RendererType::Scion2D => { Box::new(bidimensional::renderer::Scion2D) }
- RendererType::Custom(boxed) => { boxed }
+impl RendererType {
+ pub(crate) fn into_boxed_renderer(self) -> Box {
+ match self {
+ RendererType::Scion2D => Box::new(Scion2D::default()),
+ RendererType::Custom(boxed) => boxed,
}
}
-}
\ No newline at end of file
+}
diff --git a/src/renderer/renderer_state.rs b/src/renderer/renderer_state.rs
new file mode 100644
index 0000000..84edb9c
--- /dev/null
+++ b/src/renderer/renderer_state.rs
@@ -0,0 +1,96 @@
+use winit::event::WindowEvent;
+use winit::window::Window;
+
+use crate::renderer::ScionRenderer;
+use legion::{Resources, World};
+
+pub struct RendererState {
+ surface: wgpu::Surface,
+ device: wgpu::Device,
+ queue: wgpu::Queue,
+ sc_desc: wgpu::SwapChainDescriptor,
+ swap_chain: wgpu::SwapChain,
+ size: winit::dpi::PhysicalSize,
+ scion_renderer: Box,
+}
+
+impl RendererState {
+ pub(crate) async fn new(window: &Window, scion_renderer: Box) -> Self {
+ let size = window.inner_size();
+ let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
+ let surface = unsafe { instance.create_surface(window) };
+ let adapter = instance
+ .request_adapter(&wgpu::RequestAdapterOptions {
+ power_preference: wgpu::PowerPreference::default(),
+ compatible_surface: Some(&surface),
+ })
+ .await
+ .unwrap();
+
+ let (device, queue) = adapter
+ .request_device(
+ &wgpu::DeviceDescriptor {
+ features: wgpu::Features::empty(),
+ limits: wgpu::Limits::default(),
+ label: None,
+ },
+ None, // Trace path
+ )
+ .await
+ .unwrap();
+
+ let sc_desc = wgpu::SwapChainDescriptor {
+ usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
+ format: adapter.get_swap_chain_preferred_format(&surface),
+ width: size.width,
+ height: size.height,
+ present_mode: wgpu::PresentMode::Fifo,
+ };
+ let swap_chain = device.create_swap_chain(&surface, &sc_desc);
+
+ Self {
+ surface,
+ device,
+ queue,
+ sc_desc,
+ swap_chain,
+ size,
+ scion_renderer,
+ }
+ }
+
+ pub(crate) fn resize(&mut self, new_size: winit::dpi::PhysicalSize) {
+ self.size = new_size;
+ self.sc_desc.width = new_size.width;
+ self.sc_desc.height = new_size.height;
+ self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
+ }
+
+ pub(crate) fn _input(&mut self, _event: &WindowEvent) -> bool {
+ //todo!()
+ false
+ }
+
+ pub(crate) fn update(&mut self, world: &mut World) {
+ self.scion_renderer
+ .update(world, &self.device, &self.sc_desc, &mut self.queue);
+ }
+
+ pub(crate) fn render(
+ &mut self,
+ world: &mut World,
+ _resources: &mut Resources,
+ ) -> Result<(), wgpu::SwapChainError> {
+ let frame = self.swap_chain.get_current_frame()?.output;
+ let mut encoder = self
+ .device
+ .create_command_encoder(&wgpu::CommandEncoderDescriptor {
+ label: Some("Render Encoder"),
+ });
+
+ self.scion_renderer.render(world, &frame, &mut encoder);
+ self.queue.submit(std::iter::once(encoder.finish()));
+
+ Ok(())
+ }
+}
diff --git a/src/utils/file.rs b/src/utils/file.rs
index c86bd80..6a26d10 100644
--- a/src/utils/file.rs
+++ b/src/utils/file.rs
@@ -1,23 +1,29 @@
use std::fs::File;
-use std::path::{Path};
-use std::io::{Read};
-use std::{path, io, env};
+use std::io::Read;
+use std::path::Path;
+use std::{env, io, path};
pub struct FileReaderError {
- msg: String
+ _msg: String,
}
-pub fn read_file(path: &Path) -> Result, FileReaderError>{
+pub fn read_file(path: &Path) -> Result, FileReaderError> {
let mut file = match File::open(path) {
Ok(file) => file,
- Err(e) => return Err(FileReaderError{ msg: e.to_string() })
+ Err(e) => {
+ return Err(FileReaderError {
+ _msg: e.to_string(),
+ })
+ }
};
let mut buffer = Vec::new();
let read_result = file.read_to_end(&mut buffer);
return match read_result {
Ok(_) => Ok(buffer),
- Err(e) => Err(FileReaderError{ msg: e.to_string()})
- }
+ Err(e) => Err(FileReaderError {
+ _msg: e.to_string(),
+ }),
+ };
}
pub fn app_base_path() -> Result {
@@ -25,8 +31,11 @@ pub fn app_base_path() -> Result {
return Ok(path::PathBuf::from(manifest_dir));
}
- return match env::current_exe(){
+ return match env::current_exe() {
Ok(path) => Ok(path),
- Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Failed to find an application root"))
- }
+ Err(_) => Err(io::Error::new(
+ io::ErrorKind::Other,
+ "Failed to find an application root",
+ )),
+ };
}
diff --git a/src/utils/logger.rs b/src/utils/logger.rs
index e15281b..ccf4611 100644
--- a/src/utils/logger.rs
+++ b/src/utils/logger.rs
@@ -1,8 +1,8 @@
use log::debug;
use std::io;
-use fern::colors::ColoredLevelConfig;
use crate::config::logger_config::LoggerConfig;
+use fern::colors::ColoredLevelConfig;
/// Logging utility provided by Scion
pub(crate) struct Logger;
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 4b4347e..11e3560 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -1,4 +1,4 @@
+pub mod file;
pub mod logger;
pub mod time;
pub mod window;
-pub mod file;
diff --git a/src/utils/window.rs b/src/utils/window.rs
index 880af5b..48292e3 100644
--- a/src/utils/window.rs
+++ b/src/utils/window.rs
@@ -3,14 +3,14 @@
#[derive(Default, Debug)]
pub struct WindowDimensions {
width: f32,
- height: f32
+ height: f32,
}
impl WindowDimensions {
- pub fn new(screen_size: (f32, f32)) -> Self{
- Self{
+ pub fn new(screen_size: (f32, f32)) -> Self {
+ Self {
width: screen_size.0,
- height: screen_size.1
+ height: screen_size.1,
}
}
@@ -30,4 +30,4 @@ impl WindowDimensions {
pub fn height(self) -> f32 {
self.height
}
-}
\ No newline at end of file
+}