Gotta move

This commit is contained in:
Hazel Layne Aranda 2021-03-09 15:51:45 -05:00
parent f3617e61bc
commit c155390e22
Signed by: hazelra
GPG key ID: 09213F100E5E4E67
8 changed files with 218 additions and 123 deletions

View file

@ -8,8 +8,8 @@ uniform sampler2D texture;
uniform vec2 screen_resolution; uniform vec2 screen_resolution;
uniform vec2 curvature = vec2(3.0, 3.0); uniform vec2 curvature = vec2(3.0, 3.0);
uniform vec2 scanline_opacity = vec2(1.0, 1.0); uniform vec2 scanline_opacity = vec2(0.5, 0.5);
uniform float brightness = 3.0; uniform float brightness = 2.0;
out vec4 f_color; out vec4 f_color;

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

153
src/assets.rs Normal file
View file

@ -0,0 +1,153 @@
use std::collections::HashMap;
use glium::{
texture::{RawImage2d, SrgbTexture2d},
Display, Program,
};
use glob::glob;
pub type Textures = HashMap<String, SrgbTexture2d>;
#[derive(Debug)]
pub struct TextureAtlas {
pub texture: SrgbTexture2d,
rects: HashMap<String, glium::Rect>,
width: u32,
height: u32,
}
pub struct AtlasUVs {
pub bottom_left: [f32; 2],
pub bottom_right: [f32; 2],
pub top_left: [f32; 2],
pub top_right: [f32; 2],
}
impl TextureAtlas {
fn new(display: &Display) -> TextureAtlas {
log::info!("Loading textures");
let paths = glob("assets/textures/**/*.png").unwrap();
let items = paths.map(|entry| {
let path = entry.unwrap();
let image = image::open(&path).unwrap().to_rgba8();
let image_dimensions = image.dimensions();
let image = image.into_raw();
let name_path = path
.with_extension("")
.strip_prefix("assets/textures/")
.unwrap()
.to_owned();
let mut name = String::new();
for part in name_path.iter() {
name.push_str(part.to_str().unwrap());
name.push(':');
}
name.pop();
crunch::Item::new(
(name, image),
image_dimensions.0 as usize,
image_dimensions.1 as usize,
crunch::Rotation::None,
)
});
log::info!("Packing textures into atlas");
let (width, height, items) = crunch::pack_into_po2(4096, items).unwrap();
let items = items.into_iter().map(|entry| {
let rect = glium::Rect {
left: entry.0.x as u32,
bottom: entry.0.y as u32,
width: entry.0.w as u32,
height: entry.0.h as u32,
};
let name = entry.1 .0;
let image = entry.1 .1;
(name, image, rect)
});
let mut atlas = TextureAtlas {
texture: SrgbTexture2d::empty(display, width as u32, height as u32).unwrap(),
rects: HashMap::new(),
width: width as u32,
height: height as u32,
};
for (name, image, rect) in items {
atlas.texture.write(
rect,
RawImage2d::from_raw_rgba_reversed(&image, (rect.width, rect.height)),
);
atlas.rects.insert(name, rect);
}
atlas
}
pub fn get_uv(&self, name: String) -> AtlasUVs {
let rect = self.rects.get(&name).unwrap();
AtlasUVs {
bottom_left: Self::coord_to_uv(
rect.left,
rect.bottom + rect.height,
self.width,
self.height,
),
bottom_right: Self::coord_to_uv(
rect.left + rect.width,
rect.bottom + rect.height,
self.width,
self.height,
),
top_left: Self::coord_to_uv(rect.left, rect.bottom, self.width, self.height),
top_right: Self::coord_to_uv(
rect.left + rect.width,
rect.bottom,
self.width,
self.height,
),
}
}
fn coord_to_uv(x: u32, y: u32, width: u32, height: u32) -> [f32; 2] {
[x as f32 / width as f32, (y as f32 / height as f32)]
}
}
pub type Shaders = HashMap<String, Program>;
fn load_shaders(display: &Display) -> Shaders {
log::info!("Loading shaders.");
let mut shaders: Shaders = Shaders::new();
for entry in glob("assets/shaders/*").unwrap() {
if let Ok(path) = entry {
// Operate only on directories
if path.is_file() {
continue;
}
let vert_source = std::fs::read_to_string(path.join("vert.glsl")).unwrap();
let frag_source = std::fs::read_to_string(path.join("frag.glsl")).unwrap();
let program = Program::from_source(display, &vert_source, &frag_source, None).unwrap();
let name = path.file_name().unwrap().to_str().unwrap().to_owned();
shaders.insert(name.to_string(), program);
log::info!("Loaded shader {:?} from {:?}.", name, path);
}
}
shaders
}
pub struct Assets {
pub texture_atlas: TextureAtlas,
pub shaders: Shaders,
}
impl Assets {
pub fn new(display: &Display) -> Assets {
Assets {
texture_atlas: TextureAtlas::new(display),
shaders: load_shaders(display),
}
}
}

View file

@ -1,21 +1,24 @@
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use anymap::AnyMap; use anymap::AnyMap;
use assets::{Assets, Shaders};
use cgmath::Matrix3; use cgmath::Matrix3;
use glium::{ use glium::{
glutin, index::PrimitiveType, texture::Texture2d, uniform, Display, Frame, IndexBuffer, glutin, index::PrimitiveType, texture::Texture2d, uniform, Display, Frame, IndexBuffer,
Surface, VertexBuffer, Surface, VertexBuffer,
}; };
use glium_glyph::{glyph_brush::Section, GlyphBrush}; use glium_glyph::{
glyph_brush::{rusttype::Font, Section},
GlyphBrush,
};
use glutin::{ use glutin::{
event::{Event, WindowEvent}, event::{Event, WindowEvent},
event_loop::ControlFlow, event_loop::ControlFlow,
}; };
use resources::Shaders;
use simplelog::{TermLogger, TerminalMode}; use simplelog::{TermLogger, TerminalMode};
use state::GameState; use state::GameState;
pub mod resources; pub mod assets;
pub mod state; pub mod state;
const TIMESTEP: f32 = 1.0 / 20.0; const TIMESTEP: f32 = 1.0 / 20.0;
@ -41,7 +44,7 @@ struct State {
current_state: Box<dyn GameState>, current_state: Box<dyn GameState>,
next_state: Option<Box<dyn GameState>>, next_state: Option<Box<dyn GameState>>,
resources: AnyMap, resources: Assets,
} }
impl State { impl State {
@ -83,12 +86,11 @@ impl State {
}; };
// Set initial state // Set initial state
let current_state = Box::new(state::TestState); let current_state = Box::new(state::TestState { time: 0.0 });
let next_state = None; let next_state = None;
// The resources map // The resources map
let mut resources = AnyMap::new(); let resources = Assets::new(display);
resources::load_resources(display, &mut resources);
// Package it all together UwU // Package it all together UwU
State { State {
@ -130,7 +132,7 @@ impl State {
let render_indices = let render_indices =
IndexBuffer::new(display, PrimitiveType::TriangleStrip, &[1, 2, 0, 3 as u16]).unwrap(); IndexBuffer::new(display, PrimitiveType::TriangleStrip, &[1, 2, 0, 3 as u16]).unwrap();
let program = self.resources.get::<Shaders>().unwrap().get("crt").unwrap(); let program = self.resources.shaders.get("crt").unwrap();
let mut scale = (1.0, 1.0); let mut scale = (1.0, 1.0);
if self.screen_scale.0 < self.screen_scale.1 { if self.screen_scale.0 < self.screen_scale.1 {
@ -143,7 +145,7 @@ impl State {
let uniforms = uniform! { let uniforms = uniform! {
matrix: cgmath::conv::array3x3(scale_matrix), matrix: cgmath::conv::array3x3(scale_matrix),
texture: self.render_texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest), texture: self.render_texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
screen_resolution: [SCREEN_WIDTH, SCREEN_HEIGHT], screen_resolution: [SCREEN_HEIGHT, SCREEN_HEIGHT],
/*curvature: [3.0, 3.0 as f32], /*curvature: [3.0, 3.0 as f32],
scanline_opacity: [0.5, 0.5 as f32], scanline_opacity: [0.5, 0.5 as f32],
brightness: 2.0 as f32,*/ brightness: 2.0 as f32,*/
@ -180,6 +182,11 @@ fn main() {
Display::new(wb, cb, &event_loop).unwrap() Display::new(wb, cb, &event_loop).unwrap()
}; };
// For font rendering
let dejavu = std::fs::read("assets/fonts/DejaVuSans.ttf").unwrap();
let fonts = vec![Font::from_bytes(dejavu).unwrap()];
let mut glyph_brush = GlyphBrush::new(&display, fonts);
// The main state of program or whatever // The main state of program or whatever
let mut state = State::new(&display); let mut state = State::new(&display);
@ -220,7 +227,6 @@ fn main() {
state.render(&display, &mut target); state.render(&display, &mut target);
// Draw the FPS Indicator // Draw the FPS Indicator
let glyph_brush = state.resources.get_mut::<GlyphBrush>().unwrap();
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: &format!("FPS: {:?}", state.current_fps), text: &format!("FPS: {:?}", state.current_fps),
screen_position: (0.0, 0.0), screen_position: (0.0, 0.0),

View file

@ -1,74 +0,0 @@
use std::collections::HashMap;
use anymap::AnyMap;
use glium::{texture::SrgbTexture2d, Display, Program};
use glium_glyph::{glyph_brush::rusttype::Font, GlyphBrush};
use glob::glob;
pub type Textures = HashMap<String, SrgbTexture2d>;
pub type Shaders = HashMap<String, Program>;
// Set up and load all global resources.
pub fn load_resources(display: &Display, resources: &mut AnyMap) {
// Load images
log::info!("Loading textures");
let mut textures: Textures = HashMap::new();
for entry in glob("assets/textures/**/*.png").unwrap() {
use image::io::Reader;
if let Ok(path) = entry {
let image = Reader::open(&path).unwrap().decode().unwrap().to_rgba8();
let image_dimensions = image.dimensions();
let image = glium::texture::RawImage2d::from_raw_rgba_reversed(
&image.into_raw(),
image_dimensions,
);
let texture = SrgbTexture2d::new(display, image).unwrap();
let name_path = path
.with_extension("")
.strip_prefix("assets/textures/")
.unwrap()
.to_owned();
let mut name = String::new();
for part in name_path.iter() {
name.push_str(part.to_str().unwrap());
name.push(':');
}
name.pop();
textures.insert(name.to_string(), texture);
log::info!("Loaded texture {:?} from {:?}.", name, path);
}
}
resources.insert(textures);
// Load shaders
log::info!("Loading shaders.");
let mut shaders: HashMap<String, Program> = HashMap::new();
for entry in glob("assets/shaders/*").unwrap() {
if let Ok(path) = entry {
// Operate only on directories
if path.is_file() {
continue;
}
let vert_source = std::fs::read_to_string(path.join("vert.glsl")).unwrap();
let frag_source = std::fs::read_to_string(path.join("frag.glsl")).unwrap();
let program = Program::from_source(display, &vert_source, &frag_source, None).unwrap();
let name = path.file_name().unwrap().to_str().unwrap().to_owned();
shaders.insert(name.to_string(), program);
log::info!("Loaded shader {:?} from {:?}.", name, path);
}
}
resources.insert(shaders);
// Set up font stuff
let dejavu = std::fs::read("assets/fonts/DejaVuSans.ttf").unwrap();
let fonts = vec![Font::from_bytes(dejavu).unwrap()];
let glyph_brush = GlyphBrush::new(display, fonts);
log::info!("Set up font.");
resources.insert(glyph_brush);
}

View file

@ -4,26 +4,22 @@ use glium::{framebuffer::SimpleFrameBuffer, glutin::event::Event, Display, Frame
mod test_state; mod test_state;
pub use test_state::TestState; pub use test_state::TestState;
use crate::assets::Assets;
pub trait GameState { pub trait GameState {
fn input(&mut self, resources: &mut AnyMap, event: &Event<()>); fn input(&mut self, assets: &Assets, event: &Event<()>);
fn update(&mut self, resources: &mut AnyMap, dt: f32) -> Option<Box<dyn GameState>>; fn update(&mut self, assets: &Assets, dt: f32) -> Option<Box<dyn GameState>>;
fn render(&mut self, resources: &mut AnyMap, display: &Display, target: &mut SimpleFrameBuffer); fn render(&mut self, assets: &Assets, display: &Display, target: &mut SimpleFrameBuffer);
} }
pub struct DummyState; pub struct DummyState;
impl GameState for DummyState { impl GameState for DummyState {
fn update(&mut self, _resourcess: &mut AnyMap, _dt: f32) -> Option<Box<dyn GameState>> { fn update(&mut self, _assets: &Assets, _dt: f32) -> Option<Box<dyn GameState>> {
None None
} }
fn input(&mut self, _resources: &mut AnyMap, _event: &Event<()>) {} fn input(&mut self, _assets: &Assets, _event: &Event<()>) {}
fn render( fn render(&mut self, _assets: &Assets, _display: &Display, _target: &mut SimpleFrameBuffer) {}
&mut self,
_resources: &mut AnyMap,
_display: &Display,
_target: &mut SimpleFrameBuffer,
) {
}
} }

View file

@ -2,24 +2,26 @@ use glium::{
framebuffer::SimpleFrameBuffer, implement_vertex, index::PrimitiveType, uniform, framebuffer::SimpleFrameBuffer, implement_vertex, index::PrimitiveType, uniform,
uniforms::Sampler, IndexBuffer, Surface, VertexBuffer, uniforms::Sampler, IndexBuffer, Surface, VertexBuffer,
}; };
use resources::Shaders;
use crate::resources::{self, Textures}; use crate::assets::Assets;
use super::GameState; use super::GameState;
pub struct TestState; pub struct TestState {
pub time: f32,
}
impl GameState for TestState { impl GameState for TestState {
fn input(&mut self, resources: &mut anymap::AnyMap, event: &glium::glutin::event::Event<()>) {} fn input(&mut self, assets: &Assets, event: &glium::glutin::event::Event<()>) {}
fn update(&mut self, resources: &mut anymap::AnyMap, dt: f32) -> Option<Box<dyn GameState>> { fn update(&mut self, assets: &Assets, dt: f32) -> Option<Box<dyn GameState>> {
self.time += 0.0;
None None
} }
fn render( fn render(
&mut self, &mut self,
resources: &mut anymap::AnyMap, assets: &Assets,
display: &glium::Display, display: &glium::Display,
target: &mut SimpleFrameBuffer, target: &mut SimpleFrameBuffer,
) { ) {
@ -33,24 +35,46 @@ impl GameState for TestState {
implement_vertex!(Vertex, position, tex_coords); implement_vertex!(Vertex, position, tex_coords);
let tex_coords = crate::assets::AtlasUVs {
top_left: [0.0, 0.0],
top_right: [1.0, 0.0],
bottom_left: [0.0, 1.0],
bottom_right: [1.0, 1.0],
};
let tex_coords = assets
.texture_atlas
.get_uv("backgrounds:grass-hills".to_string());
VertexBuffer::new( VertexBuffer::new(
display, display,
&[ &[
Vertex { Vertex {
position: [-1.0, -1.0], position: [-1.0, -1.0],
tex_coords: [0.0, 0.0], tex_coords: [
(tex_coords.top_left[0] - self.time.sin() / 8.0),
tex_coords.top_left[1],
],
}, },
Vertex { Vertex {
position: [-1.0, 1.0], position: [-1.0, 1.0],
tex_coords: [0.0, 1.0], tex_coords: [
(tex_coords.bottom_left[0] - self.time.sin() / 8.0),
tex_coords.bottom_left[1],
],
}, },
Vertex { Vertex {
position: [1.0, 1.0], position: [1.0, 1.0],
tex_coords: [1.0, 1.0], tex_coords: [
(tex_coords.bottom_right[0] / 2.0 - self.time.sin() / 8.0),
tex_coords.bottom_right[1],
],
}, },
Vertex { Vertex {
position: [1.0, -1.0], position: [1.0, -1.0],
tex_coords: [1.0, 0.0], tex_coords: [
(tex_coords.top_right[0] / 2.0 - self.time.sin() / 8.0),
tex_coords.top_right[1],
],
}, },
], ],
) )
@ -60,23 +84,13 @@ impl GameState for TestState {
let index_buffer = let index_buffer =
IndexBuffer::new(display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap(); IndexBuffer::new(display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();
let program = resources.get::<Shaders>().unwrap().get("basic").unwrap(); let program = assets.shaders.get("basic").unwrap();
let texture = resources
.get::<Textures>()
.unwrap()
.get("tiles:dirt")
.unwrap();
let uniforms = uniform! { let uniforms = uniform! {
/*matrix: [ matrix: cgmath::conv::array3x3(
[1.0,0.0,0.0], cgmath::Matrix3::from_nonuniform_scale(1.0, 1.0 as f32)
[0.0,1.0,0.0], ),
[0.0,0.0,1.0 as f32], texture: assets.texture_atlas.texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
],*/
matrix: cgmath::conv::array3x3(cgmath::Matrix3::from_nonuniform_scale(1.0/crate::SCREEN_WIDTH*16.0, 1.0/crate::SCREEN_HEIGHT*16.0)),
texture: texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
}; };
target target