From b558c59903754c1c88984f8faf53b47125061434 Mon Sep 17 00:00:00 2001 From: core Date: Fri, 28 Mar 2025 12:21:48 -0400 Subject: [PATCH] start render refactor --- .../client/src/assets/shaders/fragment.glsl | 2 + crates/client/src/assets/shaders/vertex.glsl | 2 + crates/client/src/rendering/mod.rs | 361 ++++-------------- crates/client/src/rendering/renderer.rs | 297 ++++++++++++++ crates/client/src/wasm/websocket.rs | 2 +- 5 files changed, 369 insertions(+), 295 deletions(-) create mode 100644 crates/client/src/rendering/renderer.rs diff --git a/crates/client/src/assets/shaders/fragment.glsl b/crates/client/src/assets/shaders/fragment.glsl index 321831091406c5c711c30cc53cb29b2ee544c178..24afa3e85185c5f980134aca513260c9ef3fd165 100644 --- a/crates/client/src/assets/shaders/fragment.glsl +++ b/crates/client/src/assets/shaders/fragment.glsl @@ -1,3 +1,5 @@ +#version 300 es + precision mediump float; in vec2 v_pos; diff --git a/crates/client/src/assets/shaders/vertex.glsl b/crates/client/src/assets/shaders/vertex.glsl index ec48884ea20940532c38f26f23a87ff04936f7d3..be35d37600c9e3dc8feb00e605a91c11b369e9f2 100644 --- a/crates/client/src/assets/shaders/vertex.glsl +++ b/crates/client/src/assets/shaders/vertex.glsl @@ -1,3 +1,5 @@ +#version 300 es + precision mediump float; in vec2 pos; diff --git a/crates/client/src/rendering/mod.rs b/crates/client/src/rendering/mod.rs index d657d812c3ca01eeeaf1fee943a28e273284bb6e..a8acca861f34bdbc4ab8b9bfc213d10bf77c9ece 100644 --- a/crates/client/src/rendering/mod.rs +++ b/crates/client/src/rendering/mod.rs @@ -1,4 +1,6 @@ use std::collections::HashMap; +use std::mem; +use std::mem::swap; use std::num::NonZeroU32; use std::sync::Arc; @@ -43,42 +45,31 @@ use crate::platform::websocket::Ws; use crate::ui::{draw_ui, init_ui}; use assets::AssetLoader; use crate::networking::websocket::Websocket; +use crate::rendering::MaybeRenderer::{Initialized, Initializing}; +use crate::rendering::renderer::{RenderCreateContext, Renderer}; pub mod assets; +mod renderer; + +enum MaybeRenderer { + Uninitialized(RenderCreateContext), + Initializing, + Initialized(Renderer) +} -#[derive(Default)] pub struct App { window: Option, world: World, + renderer: MaybeRenderer, - program: Option, - vertex_array: Option, - vertex_buffer: Option, - element_buffer: Option, #[cfg(not(target_arch = "wasm32"))] gl_surface: Option>, #[cfg(not(target_arch = "wasm32"))] gl_context: Option, - egui_glow: Option, gl: Option>, - textures: HashMap, - - send_packet_events: Events, - recv_packet_events: Events, - planet_types: HashMap, // (world entity, server id) - - up: bool, - down: bool, - left: bool, - right: bool, - - mouse_pos: PhysicalPosition, } -const VERTICES: [f32; 16] = [ - -1.0, -1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, -]; -const INDICES: [u32; 6] = [0, 1, 2, 2, 3, 0]; + impl App { pub fn new( @@ -87,10 +78,18 @@ impl App { recv_packet_events: Events, ) -> Self { Self { + window: None, world, - send_packet_events, - recv_packet_events, - ..Default::default() + renderer: MaybeRenderer::Uninitialized(RenderCreateContext { + send_packet_events, + recv_packet_events, + planet_types: Default::default(), + }), + #[cfg(not(target_arch = "wasm32"))] + gl_context: None, + #[cfg(not(target_arch = "wasm32"))] + gl_surface: None, + gl: None, } } } @@ -210,87 +209,7 @@ impl ApplicationHandler for App { (Arc::new(gl), "#version 300 es") }; - unsafe { - let shaders = [ - ( - "vertex", - include_str!("../assets/shaders/vertex.glsl"), - glow::VERTEX_SHADER, - ), - ( - "fragment", - include_str!("../assets/shaders/fragment.glsl"), - glow::FRAGMENT_SHADER, - ), - ]; - let program = gl.create_program().expect("Failed to create program"); - - for (name, source, shader_type) in shaders { - let shader = gl - .create_shader(shader_type) - .expect("Failed to create vertex shader"); - gl.shader_source(shader, &format!("{}\n{}", shader_version, source)); - gl.compile_shader(shader); - if !gl.get_shader_compile_status(shader) { - tracing::error!( - "error in {} shader: {}", - name, - gl.get_shader_info_log(shader) - ); - } - gl.attach_shader(program, shader); - gl.delete_shader(shader); - } - gl.link_program(program); - - gl.use_program(Some(program)); - - let vertex_array = gl - .create_vertex_array() - .expect("Failed to create vertex array"); - gl.bind_vertex_array(Some(vertex_array)); - let vertex_buffer = gl.create_buffer().expect("Failed to create vertex buffer"); - gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer)); - let element_buffer = gl.create_buffer().expect("Failed to create element buffer"); - gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(element_buffer)); - gl.buffer_data_u8_slice( - glow::ARRAY_BUFFER, - std::slice::from_raw_parts(VERTICES.as_ptr() as *const u8, size_of_val(&VERTICES)), - glow::STATIC_DRAW, - ); - gl.buffer_data_u8_slice( - glow::ELEMENT_ARRAY_BUFFER, - std::slice::from_raw_parts(INDICES.as_ptr() as *const u8, size_of_val(&INDICES)), - glow::STATIC_DRAW, - ); - gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, 4 * size_of::() as i32, 0); - gl.enable_vertex_attrib_array(0); - gl.vertex_attrib_pointer_f32( - 1, - 2, - glow::FLOAT, - false, - 4 * size_of::() as i32, - 2 * size_of::() as i32, - ); - gl.enable_vertex_attrib_array(1); - - gl.clear_color(0.1, 0.1, 0.1, 1.0); - gl.viewport( - 0, - 0, - window.inner_size().width as i32, - window.inner_size().height as i32, - ); - gl.enable(glow::BLEND); - gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA); - - self.program = Some(program); - self.vertex_array = Some(vertex_array); - self.vertex_buffer = Some(vertex_buffer); - self.element_buffer = Some(element_buffer); - } #[cfg(target_arch = "wasm32")] web_sys::window().unwrap().set_onresize(Some( Closure::::new(move |_| { @@ -322,11 +241,14 @@ impl ApplicationHandler for App { .unchecked_ref(), )); - let egui_glow = egui_glow::EguiGlow::new(event_loop, gl.clone(), None, None, true); + let mut rcc = Initializing; + swap(&mut self.renderer, &mut rcc); + let MaybeRenderer::Uninitialized(rcc) = rcc else { unreachable!() }; - init_ui(egui_glow.egui_ctx.clone()); + let renderer = unsafe { Renderer::new(gl.clone(), event_loop, rcc) }; + + self.renderer = Initialized(renderer); - self.egui_glow = Some(egui_glow); self.gl = Some(gl); } fn window_event( @@ -335,14 +257,13 @@ impl ApplicationHandler for App { _window_id: winit::window::WindowId, event: winit::event::WindowEvent, ) { - let event_response = self - .egui_glow - .as_mut() - .unwrap() - .on_window_event(self.window.as_ref().unwrap(), &event); - if event_response.consumed { - return; + let Initialized(renderer) = &mut self.renderer else {return}; + let Some(window) = &self.window else { return }; + + if renderer.egui_glow.on_window_event(window, &event).consumed { + return; // egui ate it } + match event { WindowEvent::CloseRequested => { event_loop.exit(); @@ -358,13 +279,13 @@ impl ApplicationHandler for App { let mut camera = self.world.get_resource_mut::().unwrap(); camera.width = size.width; camera.height = size.height; - +/* unsafe { self.gl .as_ref() .unwrap() .viewport(0, 0, size.width as i32, size.height as i32); - } + }*/ } WindowEvent::MouseWheel { delta, .. } => { let mut camera = self.world.get_resource_mut::().unwrap(); @@ -386,57 +307,57 @@ impl ApplicationHandler for App { match event.state { ElementState::Pressed => match key { KeyCode::KeyW => { - self.up = true; + renderer.up = true; matched = true; } KeyCode::KeyS => { - self.down = true; + renderer.down = true; matched = true; } KeyCode::KeyA => { - self.left = true; + renderer.left = true; matched = true; } KeyCode::KeyD => { - self.right = true; + renderer.right = true; matched = true; } _ => matched = false, }, ElementState::Released => match key { KeyCode::KeyW => { - self.up = false; + renderer.up = false; matched = true; } KeyCode::KeyS => { - self.down = false; + renderer.down = false; matched = true; } KeyCode::KeyA => { - self.left = false; + renderer.left = false; matched = true; } KeyCode::KeyD => { - self.right = false; + renderer.right = false; matched = true; } _ => matched = false, }, } if matched { - self.send_packet_events + renderer.send_packet_events .send(SendPacket(Packet::PlayerInput { - up: self.up, - down: self.down, - left: self.left, - right: self.right, + up: renderer.up, + down: renderer.down, + left: renderer.left, + right: renderer.right, })); } } PhysicalKey::Unidentified(_) => {} // unsupported } } - WindowEvent::CursorMoved { position, .. } => self.mouse_pos = position, + WindowEvent::CursorMoved { position, .. } => renderer.mouse_pos = position, WindowEvent::MouseInput { state, button, .. } => { let button = match button { MouseButton::Left => ButtonType::Left, @@ -459,9 +380,9 @@ impl ApplicationHandler for App { let camera = self.world.get_resource::().unwrap(); let view = camera.to_cursor_matrix(); let pos = - view * Vector3::new(self.mouse_pos.x as f32, self.mouse_pos.y as f32, 1.0); + view * Vector3::new(renderer.mouse_pos.x as f32, renderer.mouse_pos.y as f32, 1.0); let pos = pos / pos.z; - self.send_packet_events + renderer.send_packet_events .send(SendPacket(Packet::PlayerMouseInput { x: pos.x, y: pos.y, @@ -473,185 +394,37 @@ impl ApplicationHandler for App { } } fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + let Initialized(renderer) = &mut self.renderer else { return }; + let Some(window) = &self.window else { return }; + let mut ws = self .world .get_resource_mut::() .expect("Failed to get Ws resource"); #[cfg(target_arch = "wasm32")] while let Ok(Some(packet)) = ws.receiver.try_next() { - self.recv_packet_events.send(RecvPacket(packet)); + renderer.recv_packet_events.send(RecvPacket(packet)); } #[cfg(not(target_arch = "wasm32"))] while let Ok(packet) = ws.receiver.try_recv() { - self.recv_packet_events.send(RecvPacket(packet)); + renderer.recv_packet_events.send(RecvPacket(packet)); } - self.send_packet_events.update(); - self.recv_packet_events.update(); + renderer.send_packet_events.update(); + renderer.recv_packet_events.update(); process_packets( &mut self.world, - &mut self.send_packet_events, - &mut self.recv_packet_events, - &mut self.planet_types, + &mut renderer.send_packet_events, + &mut renderer.recv_packet_events, + &mut renderer.planet_types, ); let gl = self.gl.as_ref().unwrap(); - - let player = self.world.query_filtered::<&Transform, With>(); - - self.egui_glow - .as_mut() - .unwrap() - .run(self.window.as_ref().unwrap(), |ctx| { - draw_ui(ctx, &mut self.world, &mut self.send_packet_events); - }); - - let camera = self.world.get_resource::().unwrap(); - let x_scale = camera.zoom / camera.width as f32 * 2.0; - let y_scale = camera.zoom / camera.height as f32 * 2.0; - let view = &[ - x_scale, - 0.0, - 0.0, - camera.x * x_scale, - 0.0, - y_scale, - 0.0, - camera.y * y_scale, - 0.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - ]; - - let mut sprite_query = self.world.query::<(&Transform, &mut Texture)>(); - - let mut sprites = Vec::new(); - for (transform, texture) in sprite_query.iter(&self.world) { - sprites.push((transform, texture)); - } - unsafe { - gl.clear(glow::COLOR_BUFFER_BIT); - gl.use_program(self.program); - gl.bind_vertex_array(self.vertex_array); - gl.bind_buffer(glow::ARRAY_BUFFER, self.vertex_buffer); - gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, self.element_buffer); - gl.active_texture(glow::TEXTURE0); - - let view_loc = gl.get_uniform_location(self.program.unwrap(), "view"); - let model_loc = gl.get_uniform_location(self.program.unwrap(), "model"); - - gl.uniform_matrix_4_f32_slice(view_loc.as_ref(), true, view); - - if !self.textures.contains_key("starfield.svg") { - let assets = self.world.resource::(); - match assets.get("starfield.svg") { - Some(image) => { - let texture_object = gl - .create_texture() - .expect("Failed to create texture object"); - gl.bind_texture(glow::TEXTURE_2D, Some(texture_object)); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MIN_FILTER, - glow::LINEAR_MIPMAP_LINEAR as i32, - ); - gl.tex_image_2d( - glow::TEXTURE_2D, - 0, - glow::RGBA as i32, - image.width as i32, - image.height as i32, - 0, - glow::RGBA, - glow::UNSIGNED_BYTE, - PixelUnpackData::Slice(Some(&image.bytes)), - ); - gl.generate_mipmap(glow::TEXTURE_2D); - - self.textures - .insert("starfield.svg".to_string(), texture_object); - } - None => {} - } - } - if self.textures.contains_key("starfield.svg") { - gl.bind_texture( - glow::TEXTURE_2D, - self.textures.get("starfield.svg").copied(), - ); - - let camera = self.world.get_resource::().unwrap(); - let x = -(camera.x + camera.x.signum() * 200.0) + camera.x % 400.0; - let y = -(camera.y + camera.y.signum() * 200.0) + camera.y % 400.0; - let x_range = camera.width as f32 / camera.zoom / 400.0; - let y_range = camera.height as f32 / camera.zoom / 400.0; - for i in ((-x_range / 2.0) as i32 - 1)..=((x_range / 2.0) as i32 + 1) { - for j in ((-y_range / 2.0) as i32 - 1)..=((y_range / 2.0) as i32 + 1) { - let model = - Translation3::new(x + (i * 400) as f32, y + (j * 400) as f32, 0.0) - .to_homogeneous() - * Scale3::new(200.0, 200.0, 1.0).to_homogeneous(); - gl.uniform_matrix_4_f32_slice(model_loc.as_ref(), false, model.as_slice()); - gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0); - } - } - } - - for (transform, texture) in sprites { - if !self.textures.contains_key(&texture.name) { - let assets = self.world.resource::(); - let image = match assets.get(texture.name.clone()) { - Some(t) => t, - None => continue, - }; - - let texture_object = gl - .create_texture() - .expect("Failed to create texture object"); - gl.bind_texture(glow::TEXTURE_2D, Some(texture_object)); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MIN_FILTER, - glow::LINEAR_MIPMAP_LINEAR as i32, - ); - gl.tex_image_2d( - glow::TEXTURE_2D, - 0, - glow::RGBA as i32, - image.width as i32, - image.height as i32, - 0, - glow::RGBA, - glow::UNSIGNED_BYTE, - PixelUnpackData::Slice(Some(&image.bytes)), - ); - gl.generate_mipmap(glow::TEXTURE_2D); - - self.textures.insert(texture.name.clone(), texture_object); - } - // now the texture must exist - - let model = transform.to_matrix(); - let model = model.as_slice(); - gl.uniform_matrix_4_f32_slice(model_loc.as_ref(), false, model); - - gl.bind_texture(glow::TEXTURE_2D, self.textures.get(&texture.name).copied()); - gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0); - } + renderer.draw(gl, window, &mut self.world); } - self.egui_glow - .as_mut() - .unwrap() - .paint(self.window.as_ref().unwrap()); - #[cfg(not(target_arch = "wasm32"))] self.gl_surface .as_ref() @@ -663,8 +436,8 @@ impl ApplicationHandler for App { .world .get_resource_mut::() .expect("Failed to get Ws resource"); - let mut send_event_cursor = self.send_packet_events.get_cursor(); - for event in send_event_cursor.read(&self.send_packet_events) { + let mut send_event_cursor = renderer.send_packet_events.get_cursor(); + for event in send_event_cursor.read(&renderer.send_packet_events) { ws.send_packet(event.0.clone()); } diff --git a/crates/client/src/rendering/renderer.rs b/crates/client/src/rendering/renderer.rs new file mode 100644 index 0000000000000000000000000000000000000000..351999591b3d82e8861c904a7274929eecb501d6 --- /dev/null +++ b/crates/client/src/rendering/renderer.rs @@ -0,0 +1,297 @@ +use std::collections::HashMap; +use std::sync::Arc; +use bevy_ecs::entity::Entity; +use bevy_ecs::event::Events; +use bevy_ecs::prelude::With; +use bevy_ecs::world::World; +use egui::Window; +use egui_glow::EguiGlow; +use glow::PixelUnpackData; +use nalgebra::{Scale3, Translation3}; +use winit::dpi::PhysicalPosition; +use winit::event_loop::ActiveEventLoop; +use starkingdoms_common::PlanetType; +use crate::components::{Camera, Player, RecvPacket, SendPacket, Texture, Transform}; +use crate::ui::draw_ui; +use crate::rendering::assets::AssetLoader; + +pub struct Renderer { + program: glow::Program, + vertex_array: glow::VertexArray, + vertex_buffer: glow::Buffer, + element_buffer: glow::Buffer, + pub egui_glow: EguiGlow, + textures: HashMap, + pub(crate) send_packet_events: Events, + pub(crate) recv_packet_events: Events, + pub(crate) planet_types: HashMap, // (world entity, server id) + + pub(crate) up: bool, + pub(crate) down: bool, + pub(crate) left: bool, + pub(crate) right: bool, + + pub(crate) mouse_pos: PhysicalPosition, +} + +pub struct RenderCreateContext { + pub send_packet_events: Events, + pub recv_packet_events: Events, + pub planet_types: HashMap +} + +const VERTICES: [f32; 16] = [ + -1.0, -1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, +]; +const INDICES: [u32; 6] = [0, 1, 2, 2, 3, 0]; + +impl Renderer { + pub unsafe fn new(gl: Arc, event_loop: &ActiveEventLoop, ctx: RenderCreateContext) -> Self { + use glow::HasContext as _; + + let shaders = [ + ( + "vertex", + include_str!("../assets/shaders/vertex.glsl"), + glow::VERTEX_SHADER, + ), + ( + "fragment", + include_str!("../assets/shaders/fragment.glsl"), + glow::FRAGMENT_SHADER, + ), + ]; + let program = gl.create_program().expect("Failed to create program"); + + for (name, source, shader_type) in shaders { + let shader = gl + .create_shader(shader_type) + .expect("Failed to create vertex shader"); + gl.shader_source(shader, source); + gl.compile_shader(shader); + if !gl.get_shader_compile_status(shader) { + tracing::error!( + "error in {} shader: {}", + name, + gl.get_shader_info_log(shader) + ); + } + gl.attach_shader(program, shader); + gl.delete_shader(shader); + } + gl.link_program(program); + + gl.use_program(Some(program)); + + let vertex_array = gl + .create_vertex_array() + .expect("Failed to create vertex array"); + gl.bind_vertex_array(Some(vertex_array)); + let vertex_buffer = gl.create_buffer().expect("Failed to create vertex buffer"); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer)); + let element_buffer = gl.create_buffer().expect("Failed to create element buffer"); + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(element_buffer)); + gl.buffer_data_u8_slice( + glow::ARRAY_BUFFER, + std::slice::from_raw_parts(VERTICES.as_ptr() as *const u8, size_of_val(&VERTICES)), + glow::STATIC_DRAW, + ); + gl.buffer_data_u8_slice( + glow::ELEMENT_ARRAY_BUFFER, + std::slice::from_raw_parts(INDICES.as_ptr() as *const u8, size_of_val(&INDICES)), + glow::STATIC_DRAW, + ); + + gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, 4 * size_of::() as i32, 0); + gl.enable_vertex_attrib_array(0); + gl.vertex_attrib_pointer_f32( + 1, + 2, + glow::FLOAT, + false, + 4 * size_of::() as i32, + 2 * size_of::() as i32, + ); + gl.enable_vertex_attrib_array(1); + + gl.clear_color(0.1, 0.1, 0.1, 1.0); + gl.enable(glow::BLEND); + gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA); + + + let egui_glow = EguiGlow::new(event_loop, gl.clone(), None, None, true); + + crate::ui::init_ui(egui_glow.egui_ctx.clone()); + + Self { + program, + vertex_array, + vertex_buffer, + element_buffer, + egui_glow, + textures: HashMap::new(), + send_packet_events: ctx.send_packet_events, + recv_packet_events: ctx.recv_packet_events, + planet_types: ctx.planet_types, + left: false, + right: false, + up: false, + down: false, + mouse_pos: Default::default(), + } + } + + pub unsafe fn draw(&mut self, gl: &glow::Context, window: &winit::window::Window, world: &mut World) { + use glow::HasContext as _; + + let player = world.query_filtered::<&Transform, With>(); + + // draw the UI + self.egui_glow + .run(window, |ctx| { + draw_ui(ctx, &mut *world, &mut self.send_packet_events); + }); + + let camera = world.get_resource::().unwrap(); + let x_scale = camera.zoom / camera.width as f32 * 2.0; + let y_scale = camera.zoom / camera.height as f32 * 2.0; + let view = &[ + x_scale, + 0.0, + 0.0, + camera.x * x_scale, + 0.0, + y_scale, + 0.0, + camera.y * y_scale, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + ]; + + let mut sprite_query = world.query::<(&Transform, &mut Texture)>(); + + let mut sprites = Vec::new(); + for (transform, texture) in sprite_query.iter(&world) { + sprites.push((transform, texture)); + } + + gl.clear(glow::COLOR_BUFFER_BIT); + gl.use_program(Some(self.program)); + gl.bind_vertex_array(Some(self.vertex_array)); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vertex_buffer)); + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.element_buffer)); + gl.active_texture(glow::TEXTURE0); + + let view_loc = gl.get_uniform_location(self.program, "view"); + let model_loc = gl.get_uniform_location(self.program, "model"); + + gl.uniform_matrix_4_f32_slice(view_loc.as_ref(), true, view); + + if !self.textures.contains_key("starfield.svg") { + let assets = world.resource::(); + match assets.get("starfield.svg") { + Some(image) => { + let texture_object = gl + .create_texture() + .expect("Failed to create texture object"); + gl.bind_texture(glow::TEXTURE_2D, Some(texture_object)); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR_MIPMAP_LINEAR as i32, + ); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::RGBA as i32, + image.width as i32, + image.height as i32, + 0, + glow::RGBA, + glow::UNSIGNED_BYTE, + PixelUnpackData::Slice(Some(&image.bytes)), + ); + gl.generate_mipmap(glow::TEXTURE_2D); + + self.textures + .insert("starfield.svg".to_string(), texture_object); + } + None => {} + } + } + if self.textures.contains_key("starfield.svg") { + gl.bind_texture( + glow::TEXTURE_2D, + self.textures.get("starfield.svg").copied(), + ); + + let camera = world.get_resource::().unwrap(); + let x = -(camera.x + camera.x.signum() * 200.0) + camera.x % 400.0; + let y = -(camera.y + camera.y.signum() * 200.0) + camera.y % 400.0; + let x_range = camera.width as f32 / camera.zoom / 400.0; + let y_range = camera.height as f32 / camera.zoom / 400.0; + for i in ((-x_range / 2.0) as i32 - 1)..=((x_range / 2.0) as i32 + 1) { + for j in ((-y_range / 2.0) as i32 - 1)..=((y_range / 2.0) as i32 + 1) { + let model = + Translation3::new(x + (i * 400) as f32, y + (j * 400) as f32, 0.0) + .to_homogeneous() + * Scale3::new(200.0, 200.0, 1.0).to_homogeneous(); + gl.uniform_matrix_4_f32_slice(model_loc.as_ref(), false, model.as_slice()); + gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0); + } + } + } + + for (transform, texture) in sprites { + if !self.textures.contains_key(&texture.name) { + let assets = world.resource::(); + let image = match assets.get(texture.name.clone()) { + Some(t) => t, + None => continue, + }; + + let texture_object = gl + .create_texture() + .expect("Failed to create texture object"); + gl.bind_texture(glow::TEXTURE_2D, Some(texture_object)); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR_MIPMAP_LINEAR as i32, + ); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::RGBA as i32, + image.width as i32, + image.height as i32, + 0, + glow::RGBA, + glow::UNSIGNED_BYTE, + PixelUnpackData::Slice(Some(&image.bytes)), + ); + gl.generate_mipmap(glow::TEXTURE_2D); + + self.textures.insert(texture.name.clone(), texture_object); + } + // now the texture must exist + + let model = transform.to_matrix(); + let model = model.as_slice(); + gl.uniform_matrix_4_f32_slice(model_loc.as_ref(), false, model); + + gl.bind_texture(glow::TEXTURE_2D, self.textures.get(&texture.name).copied()); + gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0); + } + + // paint UI + self.egui_glow + .paint(window); + } +} \ No newline at end of file diff --git a/crates/client/src/wasm/websocket.rs b/crates/client/src/wasm/websocket.rs index ab38cbdeed854059cf0241b8982fcdd0e39d5be5..77fcd31e2e0c93a7a5d5f4122d0685f81bbdd456 100644 --- a/crates/client/src/wasm/websocket.rs +++ b/crates/client/src/wasm/websocket.rs @@ -35,7 +35,7 @@ impl Websocket for Ws { window.location().hostname().unwrap(), PORT ))*/ - let ws = WebSocket::new("ws://100.64.0.45:3000").expect("Couldn't connect to server"); + let ws = WebSocket::new("ws://localhost:3000").expect("Couldn't connect to server"); let (packet_sender, receiver) = unbounded(); //let packet_sender = Rc::new(RwLock::new(packet_sender)); let (sender, packet_receiver) = unbounded();