From 22f6c83d59bccf5eba67980c6191b709d3c815d3 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Thu, 31 Dec 2020 14:35:30 -0800 Subject: [PATCH] WebGL fixes after disabling threaded chunk builder (#451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At this point, the UI renders in the browser through WebGL, with no GL errors. Progress towards #446 🕸️ Web support * main: enable render loop on wasm, disable events_loop on wasm for now Allow for testing rendering on WebGL * chunk_builder: disable on wasm due to no threads on wasm Chunks will not be correctly rendered, but other parts of the program now can be tested instead of crashing in std::thread * chunk_frag: glBindFragDataLocation is only on native, WebGL 2 uses in-shader specification layout(location=), which works on native in OpenGL 4.1 but we're on OpenGL 3.2 - see https://www.khronos.org/opengl/wiki/Fragment_Shader#Output_buffers * std_or_web: always fail File::open() to avoid servers.json empty string JSON parse failing * www: update installation instructions * render: fix apparent TEXTURE_MAX_LEVEL -> TEXTURE_MAG_FILTER typo * render: correct type for internalFormat DEPTH_COMPONENT24 Valid combinations of format, type, and internalFormat are listed at https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf#page=124&zoom=100,168,206. We had UNSIGNED_BYTE for DEPTH_COMPONENT24, but only UNSIGNED_INT is a valid type for this internal format. Fixes texImage: Mismatched internalFormat and format/type: 0x81a6 and 0x1902/0x1401 and fixes the subsequent GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT error. * render: gl::MULTISAMPLE (0x809d) is not available on WebGL Fixes WebGL warning: enabled: cap: Invalid enum value 0.bootstrap.js line 11 > eval:851:21 * gl: replace set_float_multi_raw with a safer set_float_multi Removes use of passing raw pointers in set_float_multi_raw parameters Instead, casts raw pointers to flatten, similar to set_matrix_multi Fixes uniform setter: (uniform colorMul[0]) values length (1) must be a positive integer multiple of size of . * render: model: send BYTE to id attrib, fixes type mismatch Fixes drawElementsInstanced: Vertex attrib 0 requires data of type INT, but is being supplied with type UINT --- src/chunk_builder.rs | 5 +++++ src/gl/mod.rs | 9 ++++++--- src/main.rs | 8 ++++---- src/render/mod.rs | 20 +++++++++++++------- src/render/model.rs | 6 ++---- src/render/shaders/chunk_frag.glsl | 8 ++++++-- std_or_web/src/lib.rs | 2 +- www/README.md | 5 +++-- 8 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/chunk_builder.rs b/src/chunk_builder.rs index cc63af9..78d299a 100644 --- a/src/chunk_builder.rs +++ b/src/chunk_builder.rs @@ -10,8 +10,13 @@ use std::sync::mpsc; use std::sync::{Arc, RwLock}; use std::thread; +#[cfg(not(target_arch = "wasm32"))] const NUM_WORKERS: usize = 8; +// TODO: threads or web workers on wasm +#[cfg(target_arch = "wasm32")] +const NUM_WORKERS: usize = 0; + pub struct ChunkBuilder { threads: Vec<(mpsc::Sender, thread::JoinHandle<()>)>, free_builders: Vec<(usize, Vec, Vec)>, diff --git a/src/gl/mod.rs b/src/gl/mod.rs index 91f8d52..4a7d4b1 100644 --- a/src/gl/mod.rs +++ b/src/gl/mod.rs @@ -213,6 +213,7 @@ pub type Type = u32; pub const UNSIGNED_BYTE: Type = gl::UNSIGNED_BYTE; pub const UNSIGNED_SHORT: Type = gl::UNSIGNED_SHORT; pub const UNSIGNED_INT: Type = gl::UNSIGNED_INT; +pub const BYTE: Type = gl::BYTE; pub const SHORT: Type = gl::SHORT; pub const FLOAT: Type = gl::FLOAT; @@ -587,9 +588,11 @@ impl Uniform { } } - #[allow(clippy::missing_safety_doc)] - pub unsafe fn set_float_multi_raw(&self, data: *const f32, len: usize) { - glow_context().uniform_4_f32_slice(Some(&self.0), std::slice::from_raw_parts(data, len)); + pub fn set_float_multi(&self, v: &[[f32; 4]]) { + unsafe { + glow_context() + .uniform_4_f32_slice(Some(&self.0), &*(v as *const [[f32; 4]] as *const [f32; 4])) + } } pub fn set_matrix4(&self, m: &::cgmath::Matrix4) { diff --git a/src/main.rs b/src/main.rs index 0788855..3365b97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -278,8 +278,8 @@ fn main2() { let canvas = canvas.dyn_into::().unwrap(); let webgl2_context = canvas .get_context("webgl2") - .unwrap() - .unwrap() + .expect("Failed to get WebGL2 context") + .expect("Failed to create WebGL2 context, is WebGL2 support enabled? (https://get.webgl.org/webgl2/)") .dyn_into::() .unwrap(); ( @@ -399,7 +399,6 @@ fn main2() { let mut last_resource_version = 0; - /* TODO: fix move of winit_window #[cfg(target_arch = "wasm32")] render_loop.run(move |running: &mut bool| { tick_all( @@ -413,8 +412,9 @@ fn main2() { ); println!("render_loop"); }); - */ + // TODO: enable events_loop for wasm, too, fix borrow with render_loop + #[cfg(not(target_arch = "wasm32"))] events_loop.run(move |event, _event_loop, control_flow| { #[cfg(target_arch = "wasm32")] { diff --git a/src/render/mod.rs b/src/render/mod.rs index b1cc157..a507b23 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -316,6 +316,7 @@ impl Renderer { gl::active_texture(0); self.gl_texture.bind(gl::TEXTURE_2D_ARRAY); + #[cfg(not(target_arch = "wasm32"))] gl::enable(gl::MULTISAMPLE); let time_offset = self.sky_offset * 0.9; @@ -453,6 +454,8 @@ impl Renderer { gl::enable(gl::DEPTH_TEST); gl::depth_mask(true); gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + + #[cfg(not(target_arch = "wasm32"))] gl::disable(gl::MULTISAMPLE); self.ui.tick(width, height); @@ -809,7 +812,7 @@ impl TransInfo { None, ); accum.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); - accum.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, gl::LINEAR); + accum.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR); trans.texture_2d(gl::COLOR_ATTACHMENT_0, gl::TEXTURE_2D, &accum, 0); let revealage = gl::Texture::new(); @@ -825,7 +828,7 @@ impl TransInfo { None, ); revealage.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); - revealage.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, gl::LINEAR); + revealage.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR); trans.texture_2d(gl::COLOR_ATTACHMENT_1, gl::TEXTURE_2D, &revealage, 0); let trans_depth = gl::Texture::new(); @@ -837,16 +840,19 @@ impl TransInfo { height, gl::DEPTH_COMPONENT24, gl::DEPTH_COMPONENT, - gl::UNSIGNED_BYTE, + gl::UNSIGNED_INT, None, ); trans_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); - trans_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, gl::LINEAR); + trans_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR); trans.texture_2d(gl::DEPTH_ATTACHMENT, gl::TEXTURE_2D, &trans_depth, 0); chunk_shader.program.use_program(); - gl::bind_frag_data_location(&chunk_shader.program, 0, "accum"); - gl::bind_frag_data_location(&chunk_shader.program, 1, "revealage"); + #[cfg(not(target_arch = "wasm32"))] // bound with layout(location=) + { + gl::bind_frag_data_location(&chunk_shader.program, 0, "accum"); + gl::bind_frag_data_location(&chunk_shader.program, 1, "revealage"); + } gl::check_framebuffer_status(); gl::draw_buffers(&[gl::COLOR_ATTACHMENT_0, gl::COLOR_ATTACHMENT_1]); @@ -879,7 +885,7 @@ impl TransInfo { height, gl::DEPTH_COMPONENT24, gl::DEPTH_COMPONENT, - gl::UNSIGNED_BYTE, + gl::UNSIGNED_INT, None, ); fb_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); diff --git a/src/render/model.rs b/src/render/model.rs index 983d247..d7831bd 100644 --- a/src/render/model.rs +++ b/src/render/model.rs @@ -114,7 +114,7 @@ impl Manager { v.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 36, 28) } if let Some(v) = collection.shader.id { - v.vertex_pointer_int(1, gl::UNSIGNED_BYTE, 36, 32) + v.vertex_pointer_int(1, gl::BYTE, 36, 32) } let mut model = Model { @@ -283,9 +283,7 @@ impl Manager { v.set_matrix4_multi(&model.matrix) } if let Some(v) = &collection.shader.color_mul { - unsafe { - v.set_float_multi_raw(model.colors.as_ptr() as *const _, model.colors.len()) - } + v.set_float_multi(&model.colors) } gl::draw_elements(gl::TRIANGLES, model.count, self.index_type, 0); } diff --git a/src/render/shaders/chunk_frag.glsl b/src/render/shaders/chunk_frag.glsl index ee3d5cd..46c560c 100644 --- a/src/render/shaders/chunk_frag.glsl +++ b/src/render/shaders/chunk_frag.glsl @@ -7,12 +7,16 @@ in float vAtlas; in vec3 vLighting; #ifndef alpha +#ifdef ES +layout(location = 2) out vec4 fragColor; +#else out vec4 fragColor; +#endif #else #ifdef ES -layout(location = 1) out vec4 accum; -layout(location = 2) out float revealage; +layout(location = 0) out vec4 accum; +layout(location = 1) out float revealage; #else out vec4 accum; out float revealage; diff --git a/std_or_web/src/lib.rs b/std_or_web/src/lib.rs index 7182cf9..0c8b339 100644 --- a/std_or_web/src/lib.rs +++ b/std_or_web/src/lib.rs @@ -19,7 +19,7 @@ cfg_if! { pub fn open>(path: P) -> Result { println!("File open {}", path.as_ref().to_str().unwrap()); - Ok(File{}) + Err(std::io::Error::new(std::io::ErrorKind::Other, "No files exist on web")) } } diff --git a/www/README.md b/www/README.md index 7fb6258..59512c3 100644 --- a/www/README.md +++ b/www/README.md @@ -12,7 +12,8 @@ To build for wasm32-unknown-unknown, run in the top-level directory (not www): ```sh rustup target add wasm32-unknown-unknown cargo install wasm-bindgen-cli -wasm-pack build +cargo install wasm-pack +wasm-pack build --dev ``` or: @@ -27,7 +28,7 @@ After building the Rust app, run the NodeJS web server as follows: ```sh cd pkg -npm link +sudo npm link cd .. cd www npm link stevenarella