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 curvature = vec2(3.0, 3.0);
uniform vec2 scanline_opacity = vec2(1.0, 1.0);
uniform float brightness = 3.0;
uniform vec2 scanline_opacity = vec2(0.5, 0.5);
uniform float brightness = 2.0;
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 anymap::AnyMap;
use assets::{Assets, Shaders};
use cgmath::Matrix3;
use glium::{
glutin, index::PrimitiveType, texture::Texture2d, uniform, Display, Frame, IndexBuffer,
Surface, VertexBuffer,
};
use glium_glyph::{glyph_brush::Section, GlyphBrush};
use glium_glyph::{
glyph_brush::{rusttype::Font, Section},
GlyphBrush,
};
use glutin::{
event::{Event, WindowEvent},
event_loop::ControlFlow,
};
use resources::Shaders;
use simplelog::{TermLogger, TerminalMode};
use state::GameState;
pub mod resources;
pub mod assets;
pub mod state;
const TIMESTEP: f32 = 1.0 / 20.0;
@ -41,7 +44,7 @@ struct State {
current_state: Box<dyn GameState>,
next_state: Option<Box<dyn GameState>>,
resources: AnyMap,
resources: Assets,
}
impl State {
@ -83,12 +86,11 @@ impl 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;
// The resources map
let mut resources = AnyMap::new();
resources::load_resources(display, &mut resources);
let resources = Assets::new(display);
// Package it all together UwU
State {
@ -130,7 +132,7 @@ impl State {
let render_indices =
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);
if self.screen_scale.0 < self.screen_scale.1 {
@ -143,7 +145,7 @@ impl State {
let uniforms = uniform! {
matrix: cgmath::conv::array3x3(scale_matrix),
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],
scanline_opacity: [0.5, 0.5 as f32],
brightness: 2.0 as f32,*/
@ -180,6 +182,11 @@ fn main() {
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
let mut state = State::new(&display);
@ -220,7 +227,6 @@ fn main() {
state.render(&display, &mut target);
// Draw the FPS Indicator
let glyph_brush = state.resources.get_mut::<GlyphBrush>().unwrap();
glyph_brush.queue(Section {
text: &format!("FPS: {:?}", state.current_fps),
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;
pub use test_state::TestState;
use crate::assets::Assets;
pub trait GameState {
fn input(&mut self, resources: &mut AnyMap, event: &Event<()>);
fn update(&mut self, resources: &mut AnyMap, dt: f32) -> Option<Box<dyn GameState>>;
fn render(&mut self, resources: &mut AnyMap, display: &Display, target: &mut SimpleFrameBuffer);
fn input(&mut self, assets: &Assets, event: &Event<()>);
fn update(&mut self, assets: &Assets, dt: f32) -> Option<Box<dyn GameState>>;
fn render(&mut self, assets: &Assets, display: &Display, target: &mut SimpleFrameBuffer);
}
pub struct 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
}
fn input(&mut self, _resources: &mut AnyMap, _event: &Event<()>) {}
fn input(&mut self, _assets: &Assets, _event: &Event<()>) {}
fn render(
&mut self,
_resources: &mut AnyMap,
_display: &Display,
_target: &mut SimpleFrameBuffer,
) {
}
fn render(&mut self, _assets: &Assets, _display: &Display, _target: &mut SimpleFrameBuffer) {}
}

View file

@ -2,24 +2,26 @@ use glium::{
framebuffer::SimpleFrameBuffer, implement_vertex, index::PrimitiveType, uniform,
uniforms::Sampler, IndexBuffer, Surface, VertexBuffer,
};
use resources::Shaders;
use crate::resources::{self, Textures};
use crate::assets::Assets;
use super::GameState;
pub struct TestState;
pub struct TestState {
pub time: f32,
}
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
}
fn render(
&mut self,
resources: &mut anymap::AnyMap,
assets: &Assets,
display: &glium::Display,
target: &mut SimpleFrameBuffer,
) {
@ -33,24 +35,46 @@ impl GameState for TestState {
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(
display,
&[
Vertex {
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 {
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 {
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 {
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 =
IndexBuffer::new(display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();
let program = resources.get::<Shaders>().unwrap().get("basic").unwrap();
let texture = resources
.get::<Textures>()
.unwrap()
.get("tiles:dirt")
.unwrap();
let program = assets.shaders.get("basic").unwrap();
let uniforms = uniform! {
/*matrix: [
[1.0,0.0,0.0],
[0.0,1.0,0.0],
[0.0,0.0,1.0 as f32],
],*/
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),
matrix: cgmath::conv::array3x3(
cgmath::Matrix3::from_nonuniform_scale(1.0, 1.0 as f32)
),
texture: assets.texture_atlas.texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
};
target