render work

This commit is contained in:
core 2025-03-08 13:29:30 -05:00
parent cb0b3f5993
commit 13aa62ecbc
11 changed files with 183 additions and 146 deletions

5
.idea/wxbox.iml generated
View file

@ -12,6 +12,11 @@
<sourceFolder url="file://$MODULE_DIR$/wxbox_client_wasm/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/wxbox_common/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/wxbox_web/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/crates/client/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/crates/common/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/crates/grib2/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/crates/pal/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/crates/tiler/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />

5
Cargo.lock generated
View file

@ -828,9 +828,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
version = "1.21.0"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
dependencies = [
"bytemuck_derive",
]
@ -5106,6 +5106,7 @@ dependencies = [
name = "wxbox-client"
version = "0.1.0"
dependencies = [
"bytemuck",
"console_error_panic_hook",
"eframe",
"egui",

View file

@ -13,6 +13,7 @@ egui = "0.31"
poll-promise = "0.3"
ehttp = "0.5"
image = "0.25"
bytemuck = "1.22"
[target.'cfg(target_arch = "wasm32")'.dependencies]
tracing-web = "0.1"

View file

@ -94,7 +94,7 @@
}
}
</style>
<link rel="modulepreload" href="/wxbox-client-5fe4727443779190.js" crossorigin="anonymous" integrity="sha384-A3JOZ15bmE6xydSHdMZU5eIbrIJ8XY/DNJ5CtuoUisRN+ij0kXCl7eikCAcPsitl"><link rel="preload" href="/wxbox-client-5fe4727443779190_bg.wasm" crossorigin="anonymous" integrity="sha384-9sLtaYmgcP7scAP05eP73dWDxb1P/1C+pS93pBTkZLNTsrnwri+zXI/1NrlJBm9z" as="fetch" type="application/wasm"></head>
<link rel="modulepreload" href="/wxbox-client-b2e1a3e7de3c6850.js" crossorigin="anonymous" integrity="sha384-nDqexAJ4zOC1UgJKvlu7tZO/Xu13qGp8nhmNPBCjCZhoWJ2FIphBbxmj+dwXs9Uw"><link rel="preload" href="/wxbox-client-b2e1a3e7de3c6850_bg.wasm" crossorigin="anonymous" integrity="sha384-Qv6lJAdZwj0oPiGat7p3dWQwZr1TtBEsq1J/pIPFPRI4IcAQ2r5ulP2rCVt+eFeN" as="fetch" type="application/wasm"></head>
<body>
<!-- The WASM code will resize the canvas dynamically -->
@ -111,8 +111,8 @@
<script type="module">
import init, * as bindings from '/wxbox-client-5fe4727443779190.js';
const wasm = await init({ module_or_path: '/wxbox-client-5fe4727443779190_bg.wasm' });
import init, * as bindings from '/wxbox-client-b2e1a3e7de3c6850.js';
const wasm = await init({ module_or_path: '/wxbox-client-b2e1a3e7de3c6850_bg.wasm' });
window.wasmBindings = bindings;

View file

@ -197,25 +197,24 @@ function debugString(val) {
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
function __wbg_adapter_32(arg0, arg1, arg2) {
wasm.closure1003_externref_shim(arg0, arg1, arg2);
}
function takeFromExternrefTable0(idx) {
const value = wasm.__wbindgen_export_1.get(idx);
wasm.__externref_table_dealloc(idx);
return value;
}
function __wbg_adapter_32(arg0, arg1) {
const ret = wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h3a79313ab83803af_multivalue_shim(arg0, arg1);
function __wbg_adapter_35(arg0, arg1) {
const ret = wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h099b1487e92de126_multivalue_shim(arg0, arg1);
if (ret[1]) {
throw takeFromExternrefTable0(ret[0]);
}
}
function __wbg_adapter_35(arg0, arg1, arg2) {
wasm.closure786_externref_shim(arg0, arg1, arg2);
}
function __wbg_adapter_40(arg0, arg1, arg2) {
wasm.closure1466_externref_shim(arg0, arg1, arg2);
wasm.closure1689_externref_shim(arg0, arg1, arg2);
}
/**
@ -551,6 +550,12 @@ function __wbg_get_imports() {
imports.wbg.__wbg_deleteTexture_eaf729f97b59aaf4 = function(arg0, arg1) {
arg0.deleteTexture(arg1);
};
imports.wbg.__wbg_deleteVertexArrayOES_0de32bd8adddeecb = function(arg0, arg1) {
arg0.deleteVertexArrayOES(arg1);
};
imports.wbg.__wbg_deleteVertexArray_cff2c6ab55f2c8b6 = function(arg0, arg1) {
arg0.deleteVertexArray(arg1);
};
imports.wbg.__wbg_deltaMode_b2e9bb0dca5cf196 = function(arg0) {
const ret = arg0.deltaMode;
return ret;
@ -600,12 +605,6 @@ function __wbg_get_imports() {
const ret = arg0.done;
return ret;
};
imports.wbg.__wbg_drawArrays_01e26acf05821932 = function(arg0, arg1, arg2, arg3) {
arg0.drawArrays(arg1 >>> 0, arg2, arg3);
};
imports.wbg.__wbg_drawArrays_32d97bfaf282c738 = function(arg0, arg1, arg2, arg3) {
arg0.drawArrays(arg1 >>> 0, arg2, arg3);
};
imports.wbg.__wbg_drawElements_28e4f5037fe8c665 = function(arg0, arg1, arg2, arg3, arg4) {
arg0.drawElements(arg1 >>> 0, arg2, arg3 >>> 0, arg4);
};
@ -1614,20 +1613,20 @@ function __wbg_get_imports() {
const ret = false;
return ret;
};
imports.wbg.__wbindgen_closure_wrapper3076 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 783, __wbg_adapter_32);
imports.wbg.__wbindgen_closure_wrapper3632 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1004, __wbg_adapter_32);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper3078 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 783, __wbg_adapter_35);
imports.wbg.__wbindgen_closure_wrapper3634 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1004, __wbg_adapter_35);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper3080 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 783, __wbg_adapter_35);
imports.wbg.__wbindgen_closure_wrapper3636 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1004, __wbg_adapter_32);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper5619 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1467, __wbg_adapter_40);
imports.wbg.__wbindgen_closure_wrapper6213 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1690, __wbg_adapter_40);
return ret;
};
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {

View file

@ -7,7 +7,7 @@ use crate::map::osm::OSMBaselayer;
use crate::map::tiles::{LayerManager, LayerSource};
pub struct App {
map: Arc<Mutex<Map>>
map: Map
}
impl App {
@ -16,7 +16,7 @@ impl App {
layer_manager.layers.insert(0, OSMBaselayer::SOURCE_ID);
Self {
map: Arc::new(Mutex::new(Map::new(layer_manager, cc).unwrap())),
map: Map::new(layer_manager, cc).unwrap(),
}
}
}
@ -31,16 +31,13 @@ impl eframe::App for App {
egui::CentralPanel::default()
.show(ctx, |ui| {
{
let map = self.map.clone();
map.lock().unwrap().custom_painting(&ctx, ui);
}
self.map.custom_painting(&ctx, ui);
});
}
fn on_exit(&mut self, gl: Option<&glow::Context>) {
if let Some(gl) = gl {
self.map.lock().unwrap().render.lock().unwrap().destroy(gl);
self.map.render.lock().unwrap().destroy(gl);
}
}
}

View file

@ -10,7 +10,7 @@ use image::{DynamicImage, ImageReader};
use poll_promise::Promise;
use tracing::{debug, warn};
use crate::map::osm::OSMBaselayer;
use crate::map::render::MapRender;
use crate::map::render::{ExtraRenderOptions, MapRender};
use crate::map::tiles::{LayerManager, LayerSource, Tile};
pub struct Map {
@ -18,7 +18,8 @@ pub struct Map {
pub lat: f64,
pub long: f64,
pub zoom: f64,
pub render: Arc<Mutex<MapRender>>
pub render: Arc<Mutex<MapRender>>,
pub options: ExtraRenderOptions
}
impl Map {
@ -29,7 +30,9 @@ impl Map {
lat: 35.227085,
long: -80.843124,
zoom: 12.0,
render: Arc::new(Mutex::new(MapRender::new(gl)?))
render: Arc::new(Mutex::new(MapRender::new(gl)?)),
options: ExtraRenderOptions {
}
})
}
pub fn process_input(&mut self, ctx: &egui::Context, ui: &mut Ui, rect: Rect, response: egui::Response) {
@ -180,9 +183,10 @@ impl Map {
self.process_input(ctx, ui, rect, response);
let tileset = self.load_tiles(ctx, rect.width() as usize, rect.height() as usize);
let render = self.render.clone();
let options = self.options;
let cb = egui_glow::CallbackFn::new(move |_info, painter| {
let tileset = tileset.clone();
render.lock().unwrap().paint(painter.gl(), tileset);
render.lock().unwrap().paint(painter.gl(), tileset, options);
});
ui.painter().add(egui::PaintCallback {
rect,

View file

@ -0,0 +1,10 @@
#version 300 es
precision mediump float; // floats: medium precision
out vec4 FragColor;
in vec2 texCoord;
uniform sampler2D tex;
void main() {
FragColor = texture(tex, texCoord);
}

View file

@ -1,9 +1,16 @@
use tracing::{debug, warn};
use std::io::Cursor;
use std::mem;
use glow::{Buffer, HasContext, PixelUnpackData, Program, Texture, VertexArray};
use image::{DynamicImage, EncodableLayout, ImageReader};
use tracing::{debug, error, warn};
use crate::map::Tileset;
pub struct MapRender {
program: glow::Program,
vertex_buffer: glow::Buffer,
vbo: Buffer,
vao: VertexArray,
ebo: Buffer,
shader_program: Program,
test_texture: Texture,
}
#[allow(unsafe_code)]
@ -14,8 +21,6 @@ impl MapRender {
let shader_version = egui_glow::ShaderVersion::get(gl);
unsafe {
let program = gl.create_program().expect("Cannot create program");
if !shader_version.is_new_shader_interface() {
warn!(
"Custom 3D painting hasn't been ported to {:?}",
@ -24,86 +29,75 @@ impl MapRender {
return None;
}
let (vertex_shader_source, fragment_shader_source) = (
r#"
layout(location = 0) in vec2 pos;
const vec4 colors[6] = vec4[6](
vec4(1.0, 0.0, 0.0, 1.0),
vec4(0.0, 1.0, 0.0, 1.0),
vec4(0.0, 0.0, 1.0, 1.0),
vec4(1.0, 0.0, 0.0, 1.0),
vec4(0.0, 1.0, 0.0, 1.0),
vec4(0.0, 0.0, 1.0, 1.0)
);
out vec4 v_color;
void main() {
v_color = colors[gl_VertexID];
gl_Position = vec4(pos, 0.0, 1.0);
}
"#,
r#"
precision mediump float;
in vec4 v_color;
out vec4 out_color;
void main() {
out_color = v_color;
}
"#,
);
let vbo = gl.create_buffer().unwrap();
let ebo = gl.create_buffer().unwrap();
let vao = gl.create_vertex_array().unwrap();
let shader_sources = [
(glow::VERTEX_SHADER, vertex_shader_source),
(glow::FRAGMENT_SHADER, fragment_shader_source),
];
let shaders: Vec<_> = shader_sources
.iter()
.map(|(shader_type, shader_source)| {
let shader = gl
.create_shader(*shader_type)
.expect("Cannot create shader");
gl.shader_source(
shader,
&format!(
"{}\n{}",
shader_version.version_declaration(),
shader_source
),
);
gl.compile_shader(shader);
assert!(
gl.get_shader_compile_status(shader),
"Failed to compile custom_3d_glow {shader_type} ({} {}): {}",
glow::VERTEX_SHADER,
glow::FRAGMENT_SHADER,
gl.get_shader_info_log(shader)
);
gl.attach_shader(program, shader);
shader
})
.collect();
gl.link_program(program);
assert!(
gl.get_program_link_status(program),
"{}",
gl.get_program_info_log(program)
);
for shader in shaders {
gl.detach_shader(program, shader);
gl.delete_shader(shader);
let vertex_shader = gl.create_shader(glow::VERTEX_SHADER).unwrap();
gl.shader_source(vertex_shader, include_str!("vertex.glsl"));
gl.compile_shader(vertex_shader);
if !gl.get_shader_compile_status(vertex_shader) {
// shader compilation failed
error!("vertex shader compilation failed: {}", gl.get_shader_info_log(vertex_shader));
return None;
}
let vertex_buffer = gl.create_buffer().expect("Cannot create vertex buffer");
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer));
gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, (2 * size_of::<f32>()) as i32, 0);
gl.enable_vertex_attrib_array(0);
let fragment_shader = gl.create_shader(glow::FRAGMENT_SHADER).unwrap();
gl.shader_source(fragment_shader, include_str!("frag.glsl"));
gl.compile_shader(fragment_shader);
if !gl.get_shader_compile_status(fragment_shader) {
// shader compilation failed
error!("fragment shader compilation failed: {}", gl.get_shader_info_log(fragment_shader));
return None;
}
let shader_program = gl.create_program().unwrap();
gl.attach_shader(shader_program, vertex_shader);
gl.attach_shader(shader_program, fragment_shader);
gl.link_program(shader_program);
if !gl.get_program_link_status(shader_program) {
error!("linking shader failed: {}", gl.get_program_info_log(shader_program));
}
gl.use_program(Some(shader_program));
gl.delete_shader(vertex_shader);
gl.delete_shader(fragment_shader);
let test_img = ImageReader::new(Cursor::new(include_bytes!("../../0.png"))).with_guessed_format().unwrap().decode().unwrap();
let test_img_rgb8 = test_img.flipv().into_rgb8();
let w = test_img_rgb8.width();
let h = test_img_rgb8.height();
let raw = test_img_rgb8.into_raw();
let test_texture = gl.create_texture().unwrap();
gl.bind_texture(glow::TEXTURE_2D, Some(test_texture));
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::REPEAT as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32);
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::NEAREST as i32);
gl.tex_image_2d(
glow::TEXTURE_2D,
0,
glow::RGB as i32,
w as i32,
h as i32,
0,
glow::RGB,
glow::UNSIGNED_BYTE,
PixelUnpackData::Slice(Some(&raw)),
);
gl.generate_mipmap(glow::TEXTURE_2D);
gl.uniform_1_i32(
gl.get_uniform_location(shader_program, "tex").as_ref(),
0
);
Some(Self {
program,
vertex_buffer
vbo,
shader_program,
vao,
ebo,
test_texture,
})
}
}
@ -111,46 +105,62 @@ impl MapRender {
pub fn destroy(&self, gl: &glow::Context) {
use glow::HasContext as _;
unsafe {
gl.delete_program(self.program);
gl.delete_program(self.shader_program);
gl.delete_buffer(self.vbo);
gl.delete_vertex_array(self.vao);
}
}
pub fn paint(&self, gl: &glow::Context, tileset: Tileset) {
pub fn paint(&self, gl: &glow::Context, tileset: Tileset, options: ExtraRenderOptions) {
use glow::HasContext as _;
let verticies: &[f32] = &[
// X Y Z S T
0.5, 0.5, 0.0, 1.0, 1.0, // top right
0.5, -0.5, 0.0, 1.0, 0.0, // bottom right
-0.5, -0.5, 0.0, 0.0, 0.0, // bottom left
-0.5, 0.5, 0.0, 0.0, 1.0, // top left
];
let indicies: &[u32] = &[
0, 1, 3,
1, 2, 3
];
unsafe {
gl.use_program(Some(self.program));
gl.clear_color(0.5, 0.1, 0.1, 1.0);
gl.clear(glow::COLOR_BUFFER_BIT);
gl.bind_vertex_array(Some(self.vao));
gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vbo));
gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, bytemuck::cast_slice(verticies), glow::DYNAMIC_DRAW);
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.ebo));
gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, bytemuck::cast_slice(indicies), glow::DYNAMIC_DRAW);
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, (5 * mem::size_of::<f32>()) as i32, 0);
gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, (5 * mem::size_of::<f32>()) as i32, 3 * mem::size_of::<f32>() as i32);
gl.enable_vertex_attrib_array(0);
gl.enable_vertex_attrib_array(1);
gl.use_program(Some(self.shader_program));
gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_2D, Some(self.test_texture));
let tiles = tileset.tiles.lock().unwrap();
for tile in tiles.iter() {
let mut data = vec![];
// A-B
// | |
// C-D
// ABC
// BDC
// a: (sp_xclip, sp_yclip)
// b: (ep_xclip, sp_yclip)
// c: (sp_xclip, ep_yclip)
// d: (ep_xclip, ep_yclip)
// sp_xclip sp_yclip ep_xclip sp_yclip sp_xclip ep_yclip // ABC
// ep_xclip sp_yclip ep_xclip ep_yclip sp_xclip ep_yclip // BDC
debug!("A {:?} - B {:?}", (tile.sp_xclip, tile.sp_yclip), (tile.ep_xclip, tile.sp_yclip));
debug!("C {:?} - D {:?}", (tile.sp_xclip, tile.ep_yclip), (tile.ep_xclip, tile.ep_yclip));
//let raw_data = [tile.sp_xclip, tile.sp_yclip, tile.ep_xclip, tile.sp_yclip, tile.sp_xclip, tile.ep_yclip, tile.ep_xclip, tile.sp_yclip, tile.ep_xclip, tile.ep_yclip, tile.sp_xclip, tile.ep_yclip];
gl.bind_vertex_array(Some(self.vao));
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.ebo));
let raw_data = [1.0f32, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0];
for v in &raw_data {
data.extend(v.to_be_bytes());
}
gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, &data, glow::DYNAMIC_DRAW);
gl.draw_arrays(glow::TRIANGLES, 0, 3);
}
gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0);
}
}
}
#[derive(Copy, Clone)]
pub struct ExtraRenderOptions {
}

View file

@ -0,0 +1,10 @@
#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
texCoord = aTexCoord;
}