summaryrefslogtreecommitdiff
path: root/src/context.rs
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2024-03-03 00:10:10 -0500
committerLLLL Colonq <llll@colonq>2024-03-03 00:10:10 -0500
commit070108cf09b1b561613b6eea04723afbbb464507 (patch)
tree01503df63f16ef6ef4ab4a37b24305286bb2477c /src/context.rs
Initial commit (new winit)
Diffstat (limited to 'src/context.rs')
-rw-r--r--src/context.rs156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/context.rs b/src/context.rs
new file mode 100644
index 0000000..5328d4d
--- /dev/null
+++ b/src/context.rs
@@ -0,0 +1,156 @@
+use wasm_bindgen::JsCast;
+use winit::platform::web::WindowExtWebSys;
+use glow::HasContext;
+
+#[link(wasm_import_module = "./helpers.js")]
+extern {
+ fn js_track_resized_setup();
+ fn js_poll_resized() -> bool;
+}
+
+// pub const RENDER_WIDTH: f32 = 640.0;
+// pub const RENDER_HEIGHT: f32 = 360.0;
+// pub const RENDER_WIDTH: f32 = 320.0;
+// pub const RENDER_HEIGHT: f32 = 180.0;
+pub const RENDER_WIDTH: f32 = 240.0;
+pub const RENDER_HEIGHT: f32 = 160.0;
+
+pub fn compute_upscale(windoww: u32, windowh: u32) -> u32 {
+ let mut ratio = 1;
+ loop {
+ if (RENDER_WIDTH as u32) * ratio > windoww
+ || (RENDER_HEIGHT as u32) * ratio > windowh
+ {
+ break;
+ }
+ ratio += 1;
+ }
+ (ratio - 1).max(1)
+}
+
+pub struct Context {
+ pub window: winit::window::Window,
+ pub gl: glow::Context,
+ pub emptyvao: glow::VertexArray,
+ pub performance: web_sys::Performance,
+}
+
+impl Context {
+ pub fn new(window: winit::window::Window) -> Self {
+ let gl = web_sys::window()
+ .and_then(|win| win.document())
+ .and_then(|doc| {
+ let dst = doc.get_element_by_id("oubliette-parent")?;
+ let canvas = web_sys::Element::from(window.canvas().expect("failed to find canvas"));
+ dst.append_child(&canvas).ok()?;
+ let c = canvas.dyn_into::<web_sys::HtmlCanvasElement>().ok()?;
+ let webgl2_context = c.get_context("webgl2").ok()??
+ .dyn_into::<web_sys::WebGl2RenderingContext>().ok()?;
+ Some(glow::Context::from_webgl2_context(webgl2_context))
+ })
+ .expect("couldn't add canvas to document");
+ unsafe {
+ gl.clear_color(0.1, 0.1, 0.1, 1.0);
+ gl.clear_depth_f32(1.0);
+
+ gl.enable(glow::DEPTH_TEST);
+ gl.depth_func(glow::LEQUAL);
+
+ gl.enable(glow::BLEND);
+ gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
+
+ gl.enable(glow::STENCIL_TEST);
+
+ gl.cull_face(glow::FRONT);
+ }
+
+ let emptyvao = unsafe {
+ gl.create_vertex_array().expect("failed to initialize vao")
+ };
+
+ unsafe { js_track_resized_setup(); }
+
+
+ Self {
+ window,
+ gl,
+ emptyvao,
+ performance: web_sys::window().expect("failed to find window")
+ .performance().expect("failed to get performance"),
+ }
+ }
+
+ pub fn maximize_canvas(&self) {
+ web_sys::window()
+ .and_then(|win| win.document())
+ .and_then(|doc| {
+ let inner_size = {
+ let browser_window = doc.default_view()
+ .or_else(web_sys::window)
+ .unwrap();
+ winit::dpi::LogicalSize::new(
+ browser_window.inner_width().unwrap().as_f64().unwrap(),
+ browser_window.inner_height().unwrap().as_f64().unwrap(),
+ )
+ };
+ self.window.canvas().unwrap().set_width(inner_size.width as _);
+ self.window.canvas().unwrap().set_height(inner_size.height as _);
+ let _ = self.window.request_inner_size(inner_size);
+ Some(())
+ })
+ .expect("failed to resize canvas");
+ }
+
+ pub fn resize_necessary(&self) -> bool {
+ unsafe {
+ js_poll_resized()
+ }
+ }
+
+ pub fn clear_color(&self, color: glam::Vec4) {
+ unsafe {
+ self.gl.clear_color(color.x, color.y, color.z, color.w);
+ }
+ }
+
+ pub fn clear_depth(&self) {
+ unsafe {
+ self.gl.clear(glow::DEPTH_BUFFER_BIT);
+ }
+ }
+
+ pub fn clear(&self) {
+ unsafe {
+ self.gl.stencil_mask(0xff);
+ self.gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT | glow::STENCIL_BUFFER_BIT);
+ }
+ }
+
+ pub fn begin_stencil(&self) {
+ unsafe {
+ self.gl.stencil_func(glow::ALWAYS, 1, 0xff);
+ self.gl.stencil_op(glow::KEEP, glow::KEEP, glow::REPLACE);
+ }
+ }
+
+ pub fn use_stencil(&self) {
+ unsafe {
+ self.gl.stencil_func(glow::EQUAL, 1, 0xff);
+ self.gl.stencil_op(glow::KEEP, glow::KEEP, glow::KEEP);
+ }
+ }
+
+ pub fn end_stencil(&self) {
+ unsafe {
+ self.gl.stencil_func(glow::ALWAYS, 1, 0xff);
+ self.gl.stencil_op(glow::KEEP, glow::KEEP, glow::KEEP);
+ }
+ }
+
+ pub fn render_no_geometry(&self) {
+ unsafe {
+ self.gl.bind_vertex_array(Some(self.emptyvao));
+ self.gl.draw_arrays(glow::TRIANGLE_STRIP, 0, 4);
+ }
+ }
+}