M crates/client/Cargo.toml => crates/client/Cargo.toml +4 -2
@@ 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"
M crates/client/index.html => crates/client/index.html +2 -1
@@ 35,5 35,6 @@
}
window.addEventListener('load', run);
</script>
+ <canvas id="canvas"></canvas>
</body>
-</html>>
\ No newline at end of file
+</html>
M crates/client/src/lib.rs => crates/client/src/lib.rs +9 -0
@@ 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();
}
A crates/client/src/rendering/init.rs => crates/client/src/rendering/init.rs +0 -0
A crates/client/src/rendering/mod.rs => crates/client/src/rendering/mod.rs +119 -0
@@ 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<Window>,
+ program: glow::Program,
+ vertex_array: glow::VertexArray,
+ vertex_buffer: glow::Buffer,
+ gl: Option<glow::Context>,
+}
+
+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::<web_sys::HtmlCanvasElement>()
+ .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::<web_sys::WebGl2RenderingContext>()
+ .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::<f32>() 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();
+ }
+ _ => {}
+ }
+ }
+}
A crates/client/src/shaders/fragment.glsl => crates/client/src/shaders/fragment.glsl +9 -0
@@ 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);
+}
A crates/client/src/shaders/vertex.glsl => crates/client/src/shaders/vertex.glsl +10 -0
@@ 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);
+}