3GAL4KPRWFKBWY2AT4YE53JHQGT6H46UEKUPIT4CHKZY3NSVLHZAC QTBM4XITUDUC3645V26MOLQZLTXGAI5KRHHMRKKPBUYKTF66OQIQC OM6475B3O4T22Z22CPMOW4AN54JWQ34HXPMIV26MLRXRIKKBSTAAC L6RIUKGLJZLAOKFGUDTZKBPP4HUBPEZAKHJEQHO34WFF62AB2ZIQC X5EMQBC4BFNJOOHS2QMF4UB4QH6JKSALK6RXLK6B7SP6MNYSAP6QC GROTV3H2V6BHU5CA7WSLVYDCWAR7GHUP5JV2QOGPLJ6N3553T4MAC LJD76LBNKTWSAHLRGL7EXNMM5HYRSOD6VXWYQSX2XVK7TQROTZ6QC GHIHJCWBCGFZI4AG66L7WG4WKJ467DXFBRBNLT4ZULSN7ZVBJI6AC EEO6C4YSWFW3JOZ3JH6K7X4TKAUTVJD53CQNYZHI2QY6REGEXUCAC 7CBRRVV3GLVLBHNPQNRHSA2ZCLHIMCHFEMWMZNOICY2OZLB7DGPAC KMU4E426CB2NDRJEK7B4GSL22P62CJPPZRK45X3JV5WP5NIBIGRQC MT6IBX7SGLE26XIFZY53WYNHSJZMSDVDRJP3VYPXIQ4DKY75XVXAC BTZ5WJPNRJ4Y3JB77XZXQWDZV2SJ4WBMSYPITUYOWSR4GLRHU4GAC OGNLZ5CUNFD7X43S4VTMCCEMJA2R76O35XACIR7AUBHPGME27E3AC O5P6HCPWGMGJBFJEMC3SYQJ5OEW2AQV4KEJCMRVTTS3K6M45Z3BAC SSJKQR6X6L2KUJI2YPLMBQU3PTR2RYAQQR6N35MDMOCOTV6ZDUEAC 6YVIIRYC6FQP7ET7AMJHG4XCIDI4KIJMOKUDAUMVBLYFEULRDQEAC 42S2A7MCAEX5QBEWP72MK3HBY3FCANOPVHLUPWK4FIZZ3NMIOQ4AC Q6Z5IQJ3SUI7BUJCKT377EPIRO7UVZFI7UB74ZEEGTCTUKC7WGKQC WQIQA2TNWNSNGKQC22XPTECAZEWG6PG5QWQECUVXDUQRSCV6RUZQC PAOLWMH7TLJLNAWBJBWP7KB7YGDFUPASMTFU33KZ3QW5JXJMPXCAC DKGUNP6LG3DJ35VMHU42K3VJO5JJ5UVYI4PLM72HO5ZNAQ4P366AC KID2E3YKLHUFPHWYYGRQZTX73THWMAXQWPT5XZEJJO46BCQD27HQC N7AJTLSWYZDDPB3JDCRGZVLGX7GCUMHYQB4OAKNETMDHENAZAJCQC 7B5SB3V7YC4HKFX6PIX6IHJ4U3BKYLD5EBMEY6O5FQ7YGN4VVI4AC ER6ZNH7MRH3CT66LQR72NYUXOTC2NDKHHDV72VBUHSJGE2VNUXCAC AGYP6KTCCMVHH2CJ3XA6NYNTTX22MJKGZJ4FTFNET35CEZIKV5MAC DZPGVVKGX6QS4HX5GVF3DR3UZAV2EOMMVRUDEGTR2OPJVDG3FNXQC HTDZ53HWD4X3DSFZX7MMC7DPFJNHQPGBVLJD2S325SQRRVIQ3CLAC DOR7S6M2PZ5FQ7TFGWIK7FUFUZENXKU4G42I5HQITODPBBEJB4YQC L5SVCVPJMJPDARA4H43U5INQMAKHUIB5PUP55IDRKAPQDB35MXZQC 34CROJEM52NB7TGBCGGMIYAQ2AZUI44FWO25MGYYUSCMHLCLJNAQC BYFMGWJ5ZPXZTCIFDHP66KK7JTEKT2NO7HR2XY7T5WRAAG3L5WYQC ELBXLSZ3LKHEXX7T7FU2EE6UTZI2QXUTV4ZM66PGSKVLHSHXQVWAC ERVDDYMSDOMRHCJYLXDFGE34YV26TKAWL6NFA2ELPUW6ECN5AOBQC use crate::{screen::{Camera, RenderError, RenderInput, RenderOptions, Screen},text::{TextSystem, TextSystemData},};use winit::{event::{ElementState, KeyEvent, WindowEvent},keyboard::{Key, NamedKey},window::Window,};screen: Screen,}let mut camera = Camera::default();let mut render_options = RenderOptions::default();// The *only* time we need to manually do this, all others should use extract_view!let mut view = GameView {camera: &mut camera,render_options: &mut render_options,// executor: &mut executor,};initial_scene.on_enter(&mut view);let egui = egui::Context::default();let egui_winit =egui_winit::State::new(egui.clone(), egui::ViewportId::ROOT, &window, None, None);let screen = Screen::new(window).await?;Ok(Self {egui,egui_winit,screen,scene_library,current_scene: initial_scene,// systemsshow_debug: false,internal_state: GameState {camera,render_options,},text: TextSystem::new()?,})}}pub fn screen(&self) -> &Screen {&self.screen}pub fn screen_mut(&mut self) -> &mut Screen {&mut self.screen}/// Runs egui codeegui_winit::update_viewport_info(self.egui_winit.egui_input_mut().viewports.get_mut(&egui::ViewportId::ROOT).unwrap(),&self.egui,self.screen.window(),);let input = self.egui_winit.take_egui_input(self.screen.window());let full_output = self.egui.run(input, |ctx| {egui::Window::new("Debug Tools").open(&mut self.show_debug).show(ctx, |ui| {ui.horizontal(|ui| {let mut vsync = self.screen.is_vsync();let text = if vsync { "yes" } else { "no" };ui.label("VSync");ui.toggle_value(&mut vsync, text);self.screen.vsync(vsync);});ui.add(egui::Slider::new(&mut self.internal_state.render_options.gamma, 0.0..=2.0).text("Gamma"),);});let mut view = extract_view!(self);self.current_scene.gui_egui(ctx, &mut view)});let prims = self.egui.tessellate(full_output.shapes.clone(), full_output.pixels_per_point);(full_output, prims)}/// Returns true if the event was handled#[cfg(debug_assertions)]if matches!(event,WindowEvent::KeyboardInput {event: KeyEvent {logical_key: Key::Named(NamedKey::F1),state: ElementState::Pressed,repeat: false,..},..}) {self.show_debug = !self.show_debug;return true;}if self.egui_winit.on_window_event(self.screen.window(), event).consumed{return true;}self.current_scene.input(event, &mut view)}puffin::profile_function!();// Run any in-progress tasks from the async executor// self.executor.run_until_stall(&mut self.internal_state);if let Some(reference) = self.current_scene.update(dt, &mut view) {let new_scene = self.scene_library.get_scene(&mut view, reference);self.current_scene.on_exit(&mut view);self.current_scene = new_scene;self.current_scene.on_enter(&mut view);}}puffin::profile_function!();// Any resources only used for the rendering process go herelet camera_text_data = camera_text_data_info.iter().map(|(buf, mapper)| mapper.produce(buf)).collect();let world_text_data = world_text_data_info.iter().map(|(buf, mapper)| mapper.produce(buf)).collect();// Build the renderer inputlet input = RenderInput {paint_jobs: &paint_jobs,textures_delta: &egui_output.textures_delta,font_system: &mut self.text.fonts,swash_cache: &mut self.text.swash,camera_text_data,world_text_data,};self.screen.render(input)}}// methods here might query the world to produce// rendering data ready for Screen to usecamera: &mut self.internal_state.camera,render_options: &self.internal_state.render_options,let world_text_data_info: Vec<_> =self.text.produce_world(&text_data).into_iter().collect();let camera_text_data_info: Vec<_> =self.text.produce_camera(&text_data).into_iter().collect();self.text.prepare(&text_data);let (egui_output, paint_jobs) = self.gui_egui();let text_data = TextSystemData::extract();pub fn render(&mut self) -> Result<(), RenderError> {let mut view = extract_view!(self);pub fn update(&mut self, dt: std::time::Duration) {let mut view = extract_view!(self);pub fn input(&mut self, event: &WindowEvent) -> bool {self.egui_winit.handle_platform_output(self.screen.window(), full_output.platform_output.clone());pub fn gui_egui(&mut self) -> (egui::FullOutput, Vec<egui::ClippedPrimitive>) {pub async fn create_surface(&mut self) -> color_eyre::Result<()> {self.screen.create_surface().awaitlet mut initial_scene = scene_library.get_scene(&mut view, ModeReference::Init);impl Game {pub async fn new(window: Window) -> color_eyre::Result<Self> {let scene_library = ModeLibrary;egui: egui::Context,egui_winit: egui_winit::State,internal_state: GameState,// executor: Cosync<GameState<S>>,// systemstext: TextSystem,// internal controlsshow_debug: bool,}pub struct GameState {pub camera: Camera,pub render_options: RenderOptions,}pub camera: &'a mut Camera,pub render_options: &'a mut RenderOptions,}macro_rules! extract_view {GameView {camera: &mut $game.internal_state.camera,render_options: &mut $game.internal_state.render_options,// executor: &mut $game.executor,}};($game: expr) => {// pub executor: &'a mut Cosync<GameState<S>>,pub struct GameView<'a> {scene_library: ModeLibrary,current_scene: Box<dyn Mode + Send>,pub struct Game {use self::mode::{Mode, ModeLibrary, ModeReference};mod mode;
fn meets_thresh(color: vec4<f32>) -> bool {// stack overflow magic \sqrt{0.299\cdot r^{2}+0.587\cdot g^{2}+0.114\cdot b^{2}}let brightness = sqrt(dot(color.rgb * color.rgb, vec3<f32>(0.299, 0.587, 0.114)));return brightness > 0.1;}const PI = 3.14159265359;const STD_DEV: f32 = 50.0;
let strength = 3.0;var added: vec4<f32>;// let offset = vec2<f32>(textureOffset.x, textureOffset.y);// Turns out this might be a cool astigmatism shader, gotta remember thatlet offset_y = vec2<f32>(0.0, textureOffset.y);let offset_x = vec2<f32>(textureOffset.x, 0.0);for(var i: u32 = 0; i < 9; i++) {let new_color_a = textureSample(t_world, s_world, t_tex_coords + offset_x * f32(i));let new_color_b = textureSample(t_world, s_world, t_tex_coords - offset_x * f32(i));if (meets_thresh(new_color_a)) {// result += vec4<f32>(new_color_a.rgb * weight[i], 0);added += vec4<f32>(new_color_a.rgb, 1.0 / strength) * weight_calc(i) * strength;}if (meets_thresh(new_color_b)) {// result += vec4<f32>(new_color_b.rgb * weight[i], 0);added += vec4<f32>(new_color_b.rgb, 1.0 / strength) * weight_calc(i) * strength;}let new_color_c = textureSample(t_world, s_world, t_tex_coords + offset_y * f32(i));let new_color_d = textureSample(t_world, s_world, t_tex_coords - offset_y * f32(i));if (meets_thresh(new_color_c)) {// result += vec4<f32>(new_color_a.rgb * weight[i], 0);added += vec4<f32>(new_color_c.rgb, 1.0 / strength) * weight_calc(i) * strength;}if (meets_thresh(new_color_d)) {// result += vec4<f32>(new_color_b.rgb * weight[i], 0);added += vec4<f32>(new_color_d.rgb, 1.0 / strength) * weight_calc(i) * strength;}let new_color_e = textureSample(t_world, s_world, t_tex_coords + offset_x * f32(i) + offset_y * f32(i));let new_color_f = textureSample(t_world, s_world, t_tex_coords + offset_x * f32(i) - offset_y * f32(i));if (meets_thresh(new_color_e)) {// result += vec4<f32>(new_color_a.rgb * weight[i], 0);added += vec4<f32>(new_color_e.rgb, 1.0 / strength) * weight_calc(i) * strength;}if (meets_thresh(new_color_f)) {// result += vec4<f32>(new_color_b.rgb * weight[i], 0);added += vec4<f32>(new_color_f.rgb, 1.0 / strength) * weight_calc(i) * strength;}let new_color_g = textureSample(t_world, s_world, t_tex_coords + offset_x * f32(i) + offset_y * f32(i));let new_color_h = textureSample(t_world, s_world, t_tex_coords - offset_x * f32(i) + offset_y * f32(i));if (meets_thresh(new_color_g)) {// result += vec4<f32>(new_color_a.rgb * weight[i], 0);added += vec4<f32>(new_color_g.rgb, 1.0 / strength) * weight_calc(i) * strength;}if (meets_thresh(new_color_h)) {// result += vec4<f32>(new_color_b.rgb * weight[i], 0);added += vec4<f32>(new_color_h.rgb, 1.0 / strength) * weight_calc(i) * strength;}}// We do it this weird way, cuz the world texture is *not* HDR atmlet hdr = result + added;let sdr = hdr::aces_tone_map(hdr.rgb);// Map gamma while, we're at itresult = vec4<f32>(pow(sdr, vec3<f32>(render_options.gamma)), hdr.a);// return in.color;// return in.color * textureSample(t_world, s_world, in.tex_coords);
glyphon_to_world: (glam::Affine3A::from_translation(glam::Vec3::new(-(WORLD_HALF_EXTENTS.x as f32),-(WORLD_HALF_EXTENTS.y as f32),0.0,)) * glam::Affine3A::from_scale(glam::Vec3::new(2.0 * WORLD_HALF_EXTENTS.x as f32,2.0 * WORLD_HALF_EXTENTS.y as f32,1.0,))).inverse(),
let attrs = Attrs::new().family(glyphon::Family::Name("Poiret One"));
let srgb_red: palette::Srgb<u8> = palette::named::WHITE.into_format();let (r, g, b) = srgb_red.into_components();let color = glyphon::Color::rgb(r, g, b);let attrs = Attrs::new().family(glyphon::Family::Name("Poiret One")).color(color);
-1.0 * WORLD_HALF_EXTENTS.x as f32,1.0 * WORLD_HALF_EXTENTS.x as f32,-1.0 * WORLD_HALF_EXTENTS.y as f32,1.0 * WORLD_HALF_EXTENTS.y as f32,
-0.5 * self.world_width as f32,0.5 * self.world_width as f32,-0.5 * self.world_height as f32,0.5 * self.world_height as f32,