WebGL fixes after disabling threaded chunk builder (#451)

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 <enum 0x809d> 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 <enum 0x8b52>.

* 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
This commit is contained in:
iceiix 2020-12-31 14:35:30 -08:00 committed by GitHub
parent b7bd59f75f
commit 22f6c83d59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 23 deletions

View File

@ -10,8 +10,13 @@ use std::sync::mpsc;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::thread; use std::thread;
#[cfg(not(target_arch = "wasm32"))]
const NUM_WORKERS: usize = 8; const NUM_WORKERS: usize = 8;
// TODO: threads or web workers on wasm
#[cfg(target_arch = "wasm32")]
const NUM_WORKERS: usize = 0;
pub struct ChunkBuilder { pub struct ChunkBuilder {
threads: Vec<(mpsc::Sender<BuildReq>, thread::JoinHandle<()>)>, threads: Vec<(mpsc::Sender<BuildReq>, thread::JoinHandle<()>)>,
free_builders: Vec<(usize, Vec<u8>, Vec<u8>)>, free_builders: Vec<(usize, Vec<u8>, Vec<u8>)>,

View File

@ -213,6 +213,7 @@ pub type Type = u32;
pub const UNSIGNED_BYTE: Type = gl::UNSIGNED_BYTE; pub const UNSIGNED_BYTE: Type = gl::UNSIGNED_BYTE;
pub const UNSIGNED_SHORT: Type = gl::UNSIGNED_SHORT; pub const UNSIGNED_SHORT: Type = gl::UNSIGNED_SHORT;
pub const UNSIGNED_INT: Type = gl::UNSIGNED_INT; pub const UNSIGNED_INT: Type = gl::UNSIGNED_INT;
pub const BYTE: Type = gl::BYTE;
pub const SHORT: Type = gl::SHORT; pub const SHORT: Type = gl::SHORT;
pub const FLOAT: Type = gl::FLOAT; pub const FLOAT: Type = gl::FLOAT;
@ -587,9 +588,11 @@ impl Uniform {
} }
} }
#[allow(clippy::missing_safety_doc)] pub fn set_float_multi(&self, v: &[[f32; 4]]) {
pub unsafe fn set_float_multi_raw(&self, data: *const f32, len: usize) { unsafe {
glow_context().uniform_4_f32_slice(Some(&self.0), std::slice::from_raw_parts(data, len)); 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<f32>) { pub fn set_matrix4(&self, m: &::cgmath::Matrix4<f32>) {

View File

@ -278,8 +278,8 @@ fn main2() {
let canvas = canvas.dyn_into::<web_sys::HtmlCanvasElement>().unwrap(); let canvas = canvas.dyn_into::<web_sys::HtmlCanvasElement>().unwrap();
let webgl2_context = canvas let webgl2_context = canvas
.get_context("webgl2") .get_context("webgl2")
.unwrap() .expect("Failed to get WebGL2 context")
.unwrap() .expect("Failed to create WebGL2 context, is WebGL2 support enabled? (https://get.webgl.org/webgl2/)")
.dyn_into::<web_sys::WebGl2RenderingContext>() .dyn_into::<web_sys::WebGl2RenderingContext>()
.unwrap(); .unwrap();
( (
@ -399,7 +399,6 @@ fn main2() {
let mut last_resource_version = 0; let mut last_resource_version = 0;
/* TODO: fix move of winit_window
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
render_loop.run(move |running: &mut bool| { render_loop.run(move |running: &mut bool| {
tick_all( tick_all(
@ -413,8 +412,9 @@ fn main2() {
); );
println!("render_loop"); 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| { events_loop.run(move |event, _event_loop, control_flow| {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {

View File

@ -316,6 +316,7 @@ impl Renderer {
gl::active_texture(0); gl::active_texture(0);
self.gl_texture.bind(gl::TEXTURE_2D_ARRAY); self.gl_texture.bind(gl::TEXTURE_2D_ARRAY);
#[cfg(not(target_arch = "wasm32"))]
gl::enable(gl::MULTISAMPLE); gl::enable(gl::MULTISAMPLE);
let time_offset = self.sky_offset * 0.9; let time_offset = self.sky_offset * 0.9;
@ -453,6 +454,8 @@ impl Renderer {
gl::enable(gl::DEPTH_TEST); gl::enable(gl::DEPTH_TEST);
gl::depth_mask(true); gl::depth_mask(true);
gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
#[cfg(not(target_arch = "wasm32"))]
gl::disable(gl::MULTISAMPLE); gl::disable(gl::MULTISAMPLE);
self.ui.tick(width, height); self.ui.tick(width, height);
@ -809,7 +812,7 @@ impl TransInfo {
None, None,
); );
accum.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); 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); trans.texture_2d(gl::COLOR_ATTACHMENT_0, gl::TEXTURE_2D, &accum, 0);
let revealage = gl::Texture::new(); let revealage = gl::Texture::new();
@ -825,7 +828,7 @@ impl TransInfo {
None, None,
); );
revealage.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); 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); trans.texture_2d(gl::COLOR_ATTACHMENT_1, gl::TEXTURE_2D, &revealage, 0);
let trans_depth = gl::Texture::new(); let trans_depth = gl::Texture::new();
@ -837,16 +840,19 @@ impl TransInfo {
height, height,
gl::DEPTH_COMPONENT24, gl::DEPTH_COMPONENT24,
gl::DEPTH_COMPONENT, gl::DEPTH_COMPONENT,
gl::UNSIGNED_BYTE, gl::UNSIGNED_INT,
None, None,
); );
trans_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); 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); trans.texture_2d(gl::DEPTH_ATTACHMENT, gl::TEXTURE_2D, &trans_depth, 0);
chunk_shader.program.use_program(); chunk_shader.program.use_program();
gl::bind_frag_data_location(&chunk_shader.program, 0, "accum"); #[cfg(not(target_arch = "wasm32"))] // bound with layout(location=)
gl::bind_frag_data_location(&chunk_shader.program, 1, "revealage"); {
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::check_framebuffer_status();
gl::draw_buffers(&[gl::COLOR_ATTACHMENT_0, gl::COLOR_ATTACHMENT_1]); gl::draw_buffers(&[gl::COLOR_ATTACHMENT_0, gl::COLOR_ATTACHMENT_1]);
@ -879,7 +885,7 @@ impl TransInfo {
height, height,
gl::DEPTH_COMPONENT24, gl::DEPTH_COMPONENT24,
gl::DEPTH_COMPONENT, gl::DEPTH_COMPONENT,
gl::UNSIGNED_BYTE, gl::UNSIGNED_INT,
None, None,
); );
fb_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR); fb_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR);

View File

@ -114,7 +114,7 @@ impl Manager {
v.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 36, 28) v.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 36, 28)
} }
if let Some(v) = collection.shader.id { 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 { let mut model = Model {
@ -283,9 +283,7 @@ impl Manager {
v.set_matrix4_multi(&model.matrix) v.set_matrix4_multi(&model.matrix)
} }
if let Some(v) = &collection.shader.color_mul { if let Some(v) = &collection.shader.color_mul {
unsafe { v.set_float_multi(&model.colors)
v.set_float_multi_raw(model.colors.as_ptr() as *const _, model.colors.len())
}
} }
gl::draw_elements(gl::TRIANGLES, model.count, self.index_type, 0); gl::draw_elements(gl::TRIANGLES, model.count, self.index_type, 0);
} }

View File

@ -7,12 +7,16 @@ in float vAtlas;
in vec3 vLighting; in vec3 vLighting;
#ifndef alpha #ifndef alpha
#ifdef ES
layout(location = 2) out vec4 fragColor;
#else
out vec4 fragColor; out vec4 fragColor;
#endif
#else #else
#ifdef ES #ifdef ES
layout(location = 1) out vec4 accum; layout(location = 0) out vec4 accum;
layout(location = 2) out float revealage; layout(location = 1) out float revealage;
#else #else
out vec4 accum; out vec4 accum;
out float revealage; out float revealage;

View File

@ -19,7 +19,7 @@ cfg_if! {
pub fn open<P: AsRef<Path>>(path: P) -> Result<File> { pub fn open<P: AsRef<Path>>(path: P) -> Result<File> {
println!("File open {}", path.as_ref().to_str().unwrap()); 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"))
} }
} }

View File

@ -12,7 +12,8 @@ To build for wasm32-unknown-unknown, run in the top-level directory (not www):
```sh ```sh
rustup target add wasm32-unknown-unknown rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli cargo install wasm-bindgen-cli
wasm-pack build cargo install wasm-pack
wasm-pack build --dev
``` ```
or: or:
@ -27,7 +28,7 @@ After building the Rust app, run the NodeJS web server as follows:
```sh ```sh
cd pkg cd pkg
npm link sudo npm link
cd .. cd ..
cd www cd www
npm link stevenarella npm link stevenarella