diff --git a/assets/shaders/pixel.fs b/assets/shaders/pixel.fs index b3a1f3d..7e576a9 100644 --- a/assets/shaders/pixel.fs +++ b/assets/shaders/pixel.fs @@ -8,27 +8,43 @@ in vec4 fragColor; uniform sampler2D texture0; uniform vec4 colDiffuse; +// Time fed from CPU +uniform float time = 0.0; + // Output fragment color out vec4 finalColor; // Viewport dimensions -const float renderWidth = 1080; -const float renderHeight = 720; +const vec2 viewport = vec2(1080.0, 720.0); // Pixel scaling -uniform float pixelWidth = 2.0; -uniform float pixelHeight = 2.0; +const vec2 pixelScale = vec2(2.0, 2.0); void main() { - float dx = pixelWidth * (1.0 / renderWidth); - float dy = pixelHeight * (1.0 / renderHeight); - vec2 coord = vec2(dx * floor(fragTexCoord.x / dx), dy * floor(fragTexCoord.y / dy)); + // Calculate the distance to merge pixels + float dx = pixelScale.x * (1.0 / viewport.x); + float dy = pixelScale.y * (1.0 / viewport.y); - vec3 tc = texture(texture0, coord).rgb; + // Get the base UV coordinate of the pixel + vec2 baseUV = fragTexCoord; + + // Use a wave function to translate the pixel UV + float X = baseUV.x*0.5+time; + float Y = baseUV.y*0.25+time; + baseUV.y += cos(X+Y)*0.0025*cos(Y); + baseUV.x += sin(X-Y)*0.012*sin(Y); + // Calculate a UV for this new blocky pixel + vec2 pixelatedUV = vec2(dx * floor(baseUV.x / dx), dy * floor(baseUV.y / dy)); + + // Rebuild the texture with the new UVs + vec3 tc = texture(texture0, pixelatedUV).rgb; + + // Apply a color filter tc = tc + vec3(0, 0.05, 0.15); + // Build the final pixel finalColor = vec4(tc, 1.0); -} +} \ No newline at end of file diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs index 77b855a..99cd752 100644 --- a/src/logic/ingame/mod.rs +++ b/src/logic/ingame/mod.rs @@ -19,12 +19,17 @@ pub enum InGameState { pub struct InGameScreen { current_state: InGameState, + shader_time_var_location: i32, } impl InGameScreen { - pub fn new() -> Self { + pub unsafe fn new(game_core: &GameCore) -> Self { Self { current_state: InGameState::SWIMMING, + shader_time_var_location: raylib::ffi::GetShaderLocation( + *game_core.resources.pixel_shader, + rstr!("time").as_ptr(), + ), } } @@ -65,7 +70,12 @@ impl InGameScreen { width: game_core.resources.background_back.width as f32, height: game_core.resources.background_back.height as f32, }, - Rectangle::new(0.0,0.0, (game_core.resources.background_back.width * 2) as f32, (game_core.resources.background_back.height * 2) as f32), + Rectangle::new( + 0.0, + 0.0, + (game_core.resources.background_back.width * 2) as f32, + (game_core.resources.background_back.height * 2) as f32, + ), Vector2 { x: 0.0, y: 0.0 }, 0.0, Color::WHITE, @@ -78,7 +88,12 @@ impl InGameScreen { width: game_core.resources.background_front.width as f32, height: game_core.resources.background_front.height as f32, }, - Rectangle::new(0.0 ,0.0, (game_core.resources.background_front.width * 2) as f32,(game_core.resources.background_front.height * 2) as f32), + Rectangle::new( + 0.0, + 0.0, + (game_core.resources.background_front.width * 2) as f32, + (game_core.resources.background_front.height * 2) as f32, + ), Vector2 { x: 0.0, y: 0.0 }, 0.0, Color::WHITE, @@ -251,13 +266,19 @@ impl Screen for InGameScreen { } } + // Update the shader's internal time + game_core + .resources + .pixel_shader + .set_shader_value(self.shader_time_var_location, draw_handle.get_time() as f32); + // Render the 2D context via the ripple shader { let mut shader_context = draw_handle.begin_shader_mode(&game_core.resources.pixel_shader); // Blit the texture - shader_context.draw_texture_rec( + shader_context.draw_texture_pro( &game_core.resources.shader_texture, Rectangle { x: 0.0, @@ -265,7 +286,14 @@ impl Screen for InGameScreen { width: game_core.resources.shader_texture.width() as f32, height: (game_core.resources.shader_texture.height() as f32) * -1.0, }, + Rectangle { + x: -10.0, + y: -10.0, + width: win_width as f32 + 20.0, + height: win_height as f32 + 20.0, + }, Vector2::zero(), + 0.0, Color::WHITE, ); } diff --git a/src/logic/pausemenu.rs b/src/logic/pausemenu.rs index 375dec5..7b627f0 100644 --- a/src/logic/pausemenu.rs +++ b/src/logic/pausemenu.rs @@ -125,7 +125,7 @@ impl Screen for PauseMenuScreen { draw_handle.draw_text( "Credits:\n\t- @ewpratten\n\t- @rsninja722\n\t- @wm-c\n\t- @catarinaburghi", (win_width / 2) - (SCREEN_PANEL_SIZE.x as i32 / 2) + 10, - (win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 120, + (win_height / 2) - (SCREEN_PANEL_SIZE.y as i32 / 2) + 170, 20, Color::BLACK, ); diff --git a/src/main.rs b/src/main.rs index c4822d3..e4982fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,16 @@ mod world; use gamecore::{GameCore, GameProgress, GameState}; use lib::{utils::profiler::GameProfiler, wrappers::audio::player::AudioPlayer}; use log::info; -use logic::{gameend::GameEndScreen, ingame::InGameScreen, loadingscreen::LoadingScreen, mainmenu::MainMenuScreen, pausemenu::PauseMenuScreen, screen::Screen, shop::ShopScreen, winscreen::{self, WinScreen}}; +use logic::{ + gameend::GameEndScreen, + ingame::InGameScreen, + loadingscreen::LoadingScreen, + mainmenu::MainMenuScreen, + pausemenu::PauseMenuScreen, + screen::Screen, + shop::ShopScreen, + winscreen::{self, WinScreen}, +}; use raylib::prelude::*; use world::{load_world_colliders, World}; @@ -69,10 +78,13 @@ fn main() { let mut loading_screen = LoadingScreen::new(); let mut main_menu_screen = MainMenuScreen::new(); let mut pause_menu_screen = PauseMenuScreen::new(); - let mut ingame_screen = InGameScreen::new(); + let mut ingame_screen; + unsafe { + ingame_screen = InGameScreen::new(&game_core); + } let mut game_end_screen = GameEndScreen::new(); let mut shop_screen = ShopScreen::new(); - let mut win_screen = WinScreen::new(); + let mut win_screen = WinScreen::new(); // Main rendering loop while !raylib.window_should_close() { @@ -117,12 +129,12 @@ fn main() { &mut audio_system, &mut game_core, ), - GameState::WinGame => win_screen.render( + GameState::WinGame => win_screen.render( &mut draw_handle, &raylib_thread, &mut audio_system, &mut game_core, - ) + ), }; // If needed, update the global state