From 6c494c3c6ee4ef0257b1d5409fd2b6c64bb86277 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Tue, 18 Mar 2025 23:29:07 -0500 Subject: [PATCH] triangl, but pixelated --- crates/client/Cargo.toml | 6 +- crates/client/index.html | 3 +- crates/client/src/lib.rs | 9 ++ crates/client/src/rendering/init.rs | 0 crates/client/src/rendering/mod.rs | 119 ++++++++++++++++++++++++ crates/client/src/shaders/fragment.glsl | 9 ++ crates/client/src/shaders/vertex.glsl | 10 ++ 7 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 crates/client/src/rendering/init.rs create mode 100644 crates/client/src/rendering/mod.rs create mode 100644 crates/client/src/shaders/fragment.glsl create mode 100644 crates/client/src/shaders/vertex.glsl diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index b91c58d9e38ebba65476497b692e2873cc8a7f57..57275532aeea99ee95da21f7450ead500ad72105 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -12,12 +12,11 @@ tracing = "0.1" # Log system tracing-subscriber = "0.3" # Log layers bevy_ecs = "0.15" egui = "0.30" -wgpu = { version = "23", features = ["webgl"] } winit = "0.30" +glow = "0.16.0" thiserror = "2" image = "0.25" egui-winit = { version = "0.30", default-features = false, features = ["links", "wayland", "x11"] } -egui-wgpu = "0.30" web-time = "1" futures = "0.3" nalgebra = "0.33" @@ -26,6 +25,7 @@ serde = "1" serde_json = "1" crossbeam = "0.8.4" resvg = "0.44.0" +bytemuck = "1.22.0" # WASM dependencies [target.'cfg(target_arch = "wasm32")'.dependencies] @@ -41,3 +41,5 @@ poll-promise = { version = "0.3.0", features = ["web"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] pollster = "0.4" tungstenite = "0.26.1" +glutin-winit = "0.5.0" +glutin = "0.32.2" diff --git a/crates/client/index.html b/crates/client/index.html index 020158094f93fea3ab3d4b396ebe72ccaf0f74db..af3bfac5df36fadeb5bc69804ec9429cef95d126 100644 --- a/crates/client/index.html +++ b/crates/client/index.html @@ -35,5 +35,6 @@ } window.addEventListener('load', run); + - \ No newline at end of file + diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 393e42b86fd909e016ad2160086cb0351666ebaf..007c0c7cbcee464f7d7f67367e05ea623c10d307 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -1,4 +1,6 @@ +use rendering::App; use tracing::info; +use winit::event_loop::{ControlFlow, EventLoop}; #[cfg(target_arch = "wasm32")] #[path = "wasm/mod.rs"] @@ -7,6 +9,8 @@ pub mod platform; #[path = "native/mod.rs"] pub mod platform; +pub mod rendering; + // Hi, you've found the real main function! This is called AFTER platform-specific initialization code. pub fn start() { info!( @@ -20,4 +24,9 @@ pub fn start() { ); info!("Creating the ECS world..."); + + let event_loop = EventLoop::new().unwrap(); + event_loop.set_control_flow(ControlFlow::Poll); + + event_loop.run_app(&mut App::default()).unwrap(); } diff --git a/crates/client/src/rendering/init.rs b/crates/client/src/rendering/init.rs new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/crates/client/src/rendering/mod.rs b/crates/client/src/rendering/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..eb5edbf39d2e50f9493913f7b66e8a27ef35339f --- /dev/null +++ b/crates/client/src/rendering/mod.rs @@ -0,0 +1,119 @@ +use glow::HasContext; +use wasm_bindgen::JsCast; +use winit::{application::ApplicationHandler, dpi::LogicalSize, event::WindowEvent, event_loop::ActiveEventLoop, platform::web::{WindowAttributesExtWebSys, WindowExtWebSys}, raw_window_handle::HasWindowHandle, window::{Window, WindowAttributes}}; + +pub mod init; + +#[derive(Default)] +pub struct App { + window: Option, + program: glow::Program, + vertex_array: glow::VertexArray, + vertex_buffer: glow::Buffer, + gl: Option, +} + +const VERTICES: [f32; 6] = [ + 0.0, 1.0, + -1.0, -1.0, + 1.0, -1.0, +]; + +impl ApplicationHandler for App { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + #[cfg(target_arch = "wasm32")] + let attributes = { + let document = web_sys::window().unwrap().document().unwrap(); + let canvas = document.get_element_by_id("canvas").unwrap(); + let canvas = canvas.dyn_into::() + .map_err(|_| ()).unwrap(); + Window::default_attributes() + .with_title("StarKingdoms.TK") + .with_canvas(Some(canvas)) + }; + #[cfg(not(target_arch = "wasm32"))] + let attributes = { + Window::default_attributes().with_title("StarKingdoms.TK"); + }; + self.window = Some(event_loop.create_window(attributes).unwrap()); + let window = self.window.as_ref().unwrap(); + #[cfg(target_arch = "wasm32")] + let context = window.canvas().unwrap().get_context("webgl2") + .unwrap().unwrap() + .dyn_into::() + .unwrap(); + #[cfg(not(target_arch = "wasm32"))] + unsafe { + } + let (gl, shader_version) = (glow::Context::from_webgl2_context(context), "#version 300 es"); + unsafe { + let vertex_shader = gl.create_shader(glow::VERTEX_SHADER).expect("Failed to create vertex shader"); + let fragment_shader = gl.create_shader(glow::FRAGMENT_SHADER).expect("Failed to create fragment shader"); + + let vertex_source = include_str!("../shaders/vertex.glsl"); + let fragment_source = include_str!("../shaders/fragment.glsl"); + + gl.shader_source(vertex_shader, &format!("{}\n{}", shader_version, vertex_source)); + gl.compile_shader(vertex_shader); + if !gl.get_shader_compile_status(vertex_shader) { + tracing::error!("error in vertex shader: {}", gl.get_shader_info_log(vertex_shader)); + } + gl.shader_source(fragment_shader, &format!("{}\n{}", shader_version, fragment_source)); + gl.compile_shader(fragment_shader); + if !gl.get_shader_compile_status(fragment_shader) { + tracing::error!("error in fragment shader: {}", gl.get_shader_info_log(fragment_shader)); + } + + let program = gl.create_program().expect("Failed to create program"); + gl.attach_shader(program, vertex_shader); + gl.attach_shader(program, fragment_shader); + gl.link_program(program); + + gl.delete_shader(vertex_shader); + gl.delete_shader(fragment_shader); + + 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)); + gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, + std::slice::from_raw_parts(VERTICES.as_ptr() as *const u8, 6*4), + glow::STATIC_DRAW); + + gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, 2*std::mem::size_of::() as i32, 0); + gl.enable_vertex_attrib_array(0); + + gl.clear_color(1.0, 1.0, 1.0, 1.0); + + self.program = program; + self.vertex_array = vertex_array; + self.vertex_buffer = vertex_buffer; + } + self.gl = Some(gl); + } + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: winit::window::WindowId, + event: winit::event::WindowEvent, + ) { + match event { + WindowEvent::Resized(size) => { + } + WindowEvent::RedrawRequested => { + let window = self.window.as_ref().unwrap(); + let gl = self.gl.as_ref().unwrap(); + + unsafe { + gl.clear(glow::COLOR_BUFFER_BIT); + gl.draw_arrays(glow::TRIANGLES, 0, 3); + } + + window.request_redraw(); + } + _ => {} + } + } +} diff --git a/crates/client/src/shaders/fragment.glsl b/crates/client/src/shaders/fragment.glsl new file mode 100644 index 0000000000000000000000000000000000000000..8ce360beba624581798995d67c5145617f4775f0 --- /dev/null +++ b/crates/client/src/shaders/fragment.glsl @@ -0,0 +1,9 @@ +precision mediump float; + +in vec2 v_pos; + +out vec4 color; + +void main() { + color = vec4(v_pos+1.0f, 0.0f, 1.0f); +} diff --git a/crates/client/src/shaders/vertex.glsl b/crates/client/src/shaders/vertex.glsl new file mode 100644 index 0000000000000000000000000000000000000000..21fc4129c43636abbf467b44fb62a23ba7a81473 --- /dev/null +++ b/crates/client/src/shaders/vertex.glsl @@ -0,0 +1,10 @@ +precision mediump float; + +in vec2 pos; + +out vec2 v_pos; + +void main() { + v_pos = pos; + gl_Position = vec4(v_pos, 0.0, 1.0); +}