use tracing::{debug, warn}; use crate::map::Tileset; pub struct MapRender { program: glow::Program, vertex_buffer: glow::Buffer, } #[allow(unsafe_code)] impl MapRender { pub fn new(gl: &glow::Context) -> Option { use glow::HasContext as _; 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 {:?}", shader_version ); 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 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_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::()) as i32, 0); gl.enable_vertex_attrib_array(0); Some(Self { program, vertex_buffer }) } } pub fn destroy(&self, gl: &glow::Context) { use glow::HasContext as _; unsafe { gl.delete_program(self.program); } } pub fn paint(&self, gl: &glow::Context, tileset: Tileset) { use glow::HasContext as _; unsafe { gl.use_program(Some(self.program)); 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]; 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); } } } }