stevenarella/src/render/model.rs

499 lines
15 KiB
Rust
Raw Normal View History

2016-03-27 18:31:57 -04:00
use super::glsl;
use super::shaders;
use crate::format::{self, Component};
use crate::gl;
use crate::model::BlockVertex;
use crate::shared::Direction;
use crate::types::hash::FNVHash;
use byteorder::{NativeEndian, WriteBytesExt};
use cgmath::{Matrix4, Point3, SquareMatrix};
2016-03-27 18:31:57 -04:00
use collision::{self, Frustum, Sphere};
use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use std::sync::{Arc, RwLock};
pub struct Manager {
collections: Vec<Collection>,
index_buffer: gl::Buffer,
index_type: gl::Type,
max_index: usize,
}
pub const DEFAULT: CollectionKey = CollectionKey(0);
pub const SUN: CollectionKey = CollectionKey(1);
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct CollectionKey(usize);
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModelKey(CollectionKey, usize);
impl Manager {
pub fn new(greg: &glsl::Registry) -> Manager {
let mut m = Manager {
collections: vec![],
index_buffer: gl::Buffer::new(),
index_type: gl::UNSIGNED_SHORT,
max_index: 0,
};
m.add_collection(
&greg.get("model_vertex"),
&greg.get("model_frag"),
gl::SRC_ALPHA,
gl::ONE_MINUS_SRC_ALPHA,
2016-03-27 18:31:57 -04:00
);
m.add_collection(
&greg.get("sun_vertex"),
&greg.get("sun_frag"),
gl::SRC_ALPHA,
gl::ONE_FACTOR,
2016-03-27 18:31:57 -04:00
);
m
}
pub fn add_collection(
&mut self,
vert: &str,
frag: &str,
blend_s: gl::Factor,
blend_d: gl::Factor,
) -> CollectionKey {
2016-03-27 18:31:57 -04:00
let collection = Collection {
shader: ModelShader::new_manual(vert, frag),
models: HashMap::with_hasher(BuildHasherDefault::default()),
blend_s,
blend_d,
2016-03-27 18:31:57 -04:00
next_id: 0,
};
self.collections.push(collection);
CollectionKey(self.collections.len())
}
pub fn get_model(&mut self, key: ModelKey) -> Option<&mut Model> {
let collection = &mut self.collections[(key.0).0];
collection.models.get_mut(&key)
}
pub fn create_model(&mut self, ckey: CollectionKey, parts: Vec<Vec<Vertex>>) -> ModelKey {
let array = gl::VertexArray::new();
array.bind();
self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
let buffer = gl::Buffer::new();
buffer.bind(gl::ARRAY_BUFFER);
let mut model = {
let collection = &mut self.collections[ckey.0];
collection.shader.program.use_program();
if let Some(v) = collection.shader.position {
v.enable()
}
if let Some(v) = collection.shader.texture_info {
v.enable()
}
if let Some(v) = collection.shader.texture_offset {
v.enable()
}
if let Some(v) = collection.shader.color {
v.enable()
}
if let Some(v) = collection.shader.id {
v.enable()
}
if let Some(v) = collection.shader.position {
v.vertex_pointer(3, gl::FLOAT, false, 36, 0)
}
if let Some(v) = collection.shader.texture_info {
v.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 36, 12)
}
if let Some(v) = collection.shader.texture_offset {
v.vertex_pointer_int(3, gl::SHORT, 36, 20)
}
if let Some(v) = collection.shader.color {
v.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 36, 28)
}
if let Some(v) = collection.shader.id {
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
2020-12-31 17:35:30 -05:00
v.vertex_pointer_int(1, gl::BYTE, 36, 32)
}
2016-03-27 18:31:57 -04:00
let mut model = Model {
// For culling only
x: 0.0,
y: 0.0,
z: 0.0,
radius: 0.0,
// Per a part
matrix: Vec::with_capacity(parts.len()),
colors: Vec::with_capacity(parts.len()),
block_light: 15.0,
sky_light: 15.0,
array,
buffer,
2016-03-27 18:31:57 -04:00
buffer_size: 0,
count: 0,
verts: vec![],
};
for (i, part) in parts.into_iter().enumerate() {
model.matrix.push(Matrix4::identity());
model.colors.push([1.0, 1.0, 1.0, 1.0]);
for mut pp in part {
pp.id = i as u8;
model.verts.push(pp);
}
}
model
};
Self::rebuild_model(&mut model);
2016-04-09 16:49:39 -04:00
if self.max_index < model.count as usize {
let (data, ty) = super::generate_element_buffer(model.count as usize);
2016-03-27 18:31:57 -04:00
self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
self.index_buffer
.set_data(gl::ELEMENT_ARRAY_BUFFER, &data, gl::DYNAMIC_DRAW);
2016-04-09 16:49:39 -04:00
self.max_index = model.count as usize;
2016-03-27 18:31:57 -04:00
self.index_type = ty;
}
let collection = &mut self.collections[ckey.0];
let key = ModelKey(ckey, collection.next_id);
collection.next_id += 1;
collection.models.insert(key, model);
key
}
pub fn remove_model(&mut self, key: ModelKey) {
let collection = &mut self.collections[(key.0).0];
collection.models.remove(&key);
}
fn rebuild_model(model: &mut Model) {
model.array.bind();
2016-04-09 16:49:39 -04:00
model.count = ((model.verts.len() / 4) * 6) as i32;
2016-03-27 18:31:57 -04:00
let mut buffer = Vec::with_capacity(36 * model.verts.len());
for vert in &model.verts {
let _ = buffer.write_f32::<NativeEndian>(vert.x);
let _ = buffer.write_f32::<NativeEndian>(vert.y);
let _ = buffer.write_f32::<NativeEndian>(vert.z);
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_x() as u16);
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_y() as u16);
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_width() as u16);
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_height() as u16);
let _ = buffer.write_i16::<NativeEndian>(
((vert.texture.get_width() as f64) * 16.0 * vert.texture_x) as i16,
);
let _ = buffer.write_i16::<NativeEndian>(
((vert.texture.get_height() as f64) * 16.0 * vert.texture_y) as i16,
);
2016-03-27 18:31:57 -04:00
let _ = buffer.write_i16::<NativeEndian>(vert.texture.atlas as i16);
let _ = buffer.write_i16::<NativeEndian>(0);
let _ = buffer.write_u8(vert.r);
let _ = buffer.write_u8(vert.g);
let _ = buffer.write_u8(vert.b);
let _ = buffer.write_u8(vert.a);
let _ = buffer.write_u8(vert.id);
let _ = buffer.write_u8(0);
let _ = buffer.write_u8(0);
let _ = buffer.write_u8(0);
}
model.buffer.bind(gl::ARRAY_BUFFER);
if buffer.len() < model.buffer_size {
model.buffer.re_set_data(gl::ARRAY_BUFFER, &buffer);
} else {
model
.buffer
.set_data(gl::ARRAY_BUFFER, &buffer, gl::DYNAMIC_DRAW);
2016-03-27 18:31:57 -04:00
model.buffer_size = buffer.len();
}
}
pub fn rebuild_models(
&mut self,
version: usize,
textures: &Arc<RwLock<super::TextureManager>>,
) {
2016-03-27 18:31:57 -04:00
for collection in &mut self.collections {
for model in collection.models.values_mut() {
2016-03-27 18:31:57 -04:00
for vert in &mut model.verts {
vert.texture = if vert.texture.version == version {
vert.texture.clone()
} else {
let mut new = super::Renderer::get_texture(textures, &vert.texture.name);
2016-03-27 18:31:57 -04:00
new.rel_x = vert.texture.rel_x;
new.rel_y = vert.texture.rel_y;
new.rel_width = vert.texture.rel_width;
new.rel_height = vert.texture.rel_height;
new.is_rel = vert.texture.is_rel;
new
};
}
Self::rebuild_model(model);
}
}
}
pub fn draw(
&mut self,
frustum: &Frustum<f32>,
perspective_matrix: &Matrix4<f32>,
camera_matrix: &Matrix4<f32>,
light_level: f32,
sky_offset: f32,
) {
2016-03-27 18:31:57 -04:00
gl::enable(gl::BLEND);
for collection in &self.collections {
collection.shader.program.use_program();
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.perspective_matrix {
v.set_matrix4(perspective_matrix)
}
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.camera_matrix {
v.set_matrix4(camera_matrix)
}
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.texture {
v.set_int(0)
}
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.sky_offset {
v.set_float(sky_offset)
}
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.light_level {
v.set_float(light_level)
}
2016-03-27 18:31:57 -04:00
gl::blend_func(collection.blend_s, collection.blend_d);
2016-04-02 20:26:31 -04:00
for model in collection.models.values() {
if model.radius > 0.0
&& frustum.contains(&Sphere {
center: Point3::new(model.x, -model.y, model.z),
radius: model.radius,
}) == collision::Relation::Out
{
2016-03-27 18:31:57 -04:00
continue;
}
model.array.bind();
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.lighting {
v.set_float2(model.block_light, model.sky_light)
}
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.model_matrix {
v.set_matrix4_multi(&model.matrix)
}
Use web-sys for web backend (#444) A small step for #446 🕸️ Web support, use web-sys to interface to the web. Previously, we would try to use glutin on the web, which is not supported; now glutin is only used on native: fixes #171 could not find Context in platform_impl. winit is still used on both, but the GL context is created with web-sys and glow (on the web), and created with glutin and used with glow (on native). stdweb is no longer used, being replaced by web-sys. Substantial refactoring to allow reusing the code between web/native: * settings: use VirtualKeyCode from winit, not reexported from glutin * std_or_web: remove broken localstoragefs/stdweb, add File placeholder * render: disable skin_thread on wasm since we don't have threads * gl: use glow types in gl wrapper (integers in native, but Web*Key in web) * gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't * gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web * gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper * glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2 * shaders: add explicit float/int type conversions, required for WebGL * shaders: specify mediump precision, required for WebGL * shaders: specify fragment shader output locations for WebGL * main: refactor handle_window_event to take a winit window, not glutin context * main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this) * main: use winit events in handle_window_event not reexported glutin events * main: refactor game loop handling into tick_all() * main: create winit window for WebGL, and use winit_window from glutin * main: restore console_error_panic_hook, mistakingly removed in (#260) * main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web * www: index.js: fix wasm import path * www: npm update, npm audit fix * www: update readme to link to status on #446 🕸️ Web support
2020-12-26 16:42:37 -05:00
if let Some(v) = &collection.shader.color_mul {
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
2020-12-31 17:35:30 -05:00
v.set_float_multi(&model.colors)
}
2016-04-09 16:49:39 -04:00
gl::draw_elements(gl::TRIANGLES, model.count, self.index_type, 0);
2016-03-27 18:31:57 -04:00
}
}
gl::disable(gl::BLEND);
}
}
struct Collection {
shader: ModelShader,
models: HashMap<ModelKey, Model, BuildHasherDefault<FNVHash>>,
blend_s: gl::Factor,
blend_d: gl::Factor,
next_id: usize,
}
pub struct Model {
// For culling only
pub x: f32,
pub y: f32,
pub z: f32,
pub radius: f32,
// Per a part
pub matrix: Vec<Matrix4<f32>>,
pub colors: Vec<[f32; 4]>,
pub block_light: f32,
pub sky_light: f32,
array: gl::VertexArray,
buffer: gl::Buffer,
buffer_size: usize,
2016-04-09 16:49:39 -04:00
count: i32,
2016-03-27 18:31:57 -04:00
pub verts: Vec<Vertex>,
}
#[derive(Clone)]
pub struct Vertex {
pub x: f32,
pub y: f32,
pub z: f32,
pub texture: super::Texture,
pub texture_x: f64,
pub texture_y: f64,
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
pub id: u8,
}
init_shader! {
Program ModelShader {
vert = "model_vertex",
frag = "model_frag",
attribute = {
optional position => "aPosition",
optional texture_info => "aTextureInfo",
optional texture_offset => "aTextureOffset",
optional color => "aColor",
optional id => "id",
2016-03-27 18:31:57 -04:00
},
uniform = {
optional perspective_matrix => "perspectiveMatrix",
optional camera_matrix => "cameraMatrix",
optional model_matrix => "modelMatrix",
optional texture => "textures",
optional light_level => "lightLevel",
optional sky_offset => "skyOffset",
optional lighting => "lighting",
optional color_mul => "colorMul",
2016-03-27 18:31:57 -04:00
},
}
}
2016-03-28 09:15:21 -04:00
// Helper methods
pub fn append_box(
verts: &mut Vec<Vertex>,
x: f32,
y: f32,
z: f32,
w: f32,
h: f32,
d: f32,
textures: [Option<super::Texture>; 6],
2016-03-28 09:15:21 -04:00
) {
append_box_texture_scale(
verts,
x,
y,
z,
w,
h,
d,
textures,
[
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
],
);
2016-03-28 09:15:21 -04:00
}
pub fn append_box_texture_scale(
verts: &mut Vec<Vertex>,
x: f32,
y: f32,
z: f32,
w: f32,
h: f32,
d: f32,
textures: [Option<super::Texture>; 6],
texture_scale: [[f64; 2]; 6],
) {
2016-03-28 09:15:21 -04:00
for dir in Direction::all() {
let tex = textures[dir.index()].clone();
if tex.is_none() {
continue;
}
let tex = tex.unwrap();
for vert in BlockVertex::face_by_direction(dir) {
2016-03-28 09:15:21 -04:00
let (rr, gg, bb) = if dir == Direction::West || dir == Direction::East {
(
(255.0 * 0.8) as u8,
(255.0 * 0.8) as u8,
(255.0 * 0.8) as u8,
)
2016-03-28 09:15:21 -04:00
} else {
(255, 255, 255)
};
verts.push(Vertex {
x: vert.x * w + x,
y: vert.y * h + y,
z: vert.z * d + z,
texture: tex.clone(),
texture_x: (vert.toffsetx as f64) * texture_scale[dir.index()][0],
2016-04-04 17:08:24 -04:00
texture_y: (vert.toffsety as f64) * texture_scale[dir.index()][1],
2016-03-28 09:15:21 -04:00
r: rr,
g: gg,
b: bb,
a: 255,
id: 0,
});
}
}
}
2016-04-07 16:30:20 -04:00
pub struct FormatState<'a> {
pub offset: f32,
pub width: f32,
pub text: Vec<Vertex>,
pub renderer: &'a mut super::Renderer,
pub y_scale: f32,
pub x_scale: f32,
}
impl<'a> FormatState<'a> {
2016-04-07 16:30:20 -04:00
pub fn build(&mut self, c: &Component, color: format::Color) {
match *c {
format::Component::Text(ref txt) => {
2016-04-07 16:30:20 -04:00
let col = FormatState::get_color(&txt.modifier, color);
self.append_text(&txt.text, col);
let modi = &txt.modifier;
if let Some(ref extra) = modi.extra {
for e in extra {
self.build(e, col);
}
}
}
}
}
fn append_text(&mut self, txt: &str, color: format::Color) {
let (rr, gg, bb) = color.to_rgb();
for ch in txt.chars() {
if ch == ' ' {
self.offset += 6.0 * self.x_scale;
continue;
}
let texture = self.renderer.ui.character_texture(ch);
let w = self.renderer.ui.size_of_char(ch) as f32;
for vert in crate::model::BlockVertex::face_by_direction(Direction::North) {
2016-04-07 16:30:20 -04:00
self.text.push(Vertex {
x: vert.x * self.x_scale * w - (self.offset + w * self.x_scale),
y: vert.y * self.y_scale + 2.1 / 16.0,
z: -0.6 / 16.0,
texture: texture.clone(),
texture_x: vert.toffsetx as f64,
texture_y: vert.toffsety as f64,
r: rr,
g: gg,
b: bb,
a: 255,
id: 0,
});
}
self.offset += (w + 2.0) * self.x_scale;
}
if self.offset > self.width {
self.width = self.offset;
}
}
fn get_color(modi: &format::Modifier, color: format::Color) -> format::Color {
modi.color.unwrap_or(color)
}
}