From 703fc95134ca15984f27c49e37c44f52685377ed Mon Sep 17 00:00:00 2001 From: Nerijus Arlauskas Date: Sun, 2 Dec 2018 22:04:34 +0200 Subject: [PATCH] Render target --- Cargo.lock | 38 ++++++ lesson-25-x-terrain/Cargo.toml | 3 + lesson-25-x-terrain/render_gl/Cargo.toml | 24 ++++ lesson-25-x-terrain/render_gl/src/lib.rs | 3 + .../render_gl/src/render_target.rs | 90 +++++++++++++ .../render_gl_derive/Cargo.toml | 11 ++ .../render_gl_derive/src/lib.rs | 121 ++++++++++++++++++ lesson-25-x-terrain/src/main.rs | 1 + lib/resources/src/lib.rs | 3 +- lib/winput/Cargo.toml | 7 + lib/winput/src/lib.rs | 12 ++ 11 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 lesson-25-x-terrain/render_gl/Cargo.toml create mode 100644 lesson-25-x-terrain/render_gl/src/lib.rs create mode 100644 lesson-25-x-terrain/render_gl/src/render_target.rs create mode 100644 lesson-25-x-terrain/render_gl_derive/Cargo.toml create mode 100644 lesson-25-x-terrain/render_gl_derive/src/lib.rs create mode 100644 lib/winput/Cargo.toml create mode 100644 lib/winput/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 10ecfd4..12be30d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1217,9 +1217,12 @@ dependencies = [ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.1.0", + "lesson_25_x_render_gl 0.1.0", + "lesson_25_x_render_gl_derive 0.1.0", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "resources 0.1.0", "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winput 0.1.0", ] [[package]] @@ -1372,6 +1375,37 @@ dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lesson_25_x_render_gl" +version = "0.1.0" +dependencies = [ + "euclid 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "floating-duration 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.1.0 (git+https://github.com/Nercury/font-kit?branch=patch-lyon-deps)", + "gl 0.1.0", + "half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)", + "int_hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lesson_25_x_render_gl_derive 0.1.0", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lyon_path 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lyon_tessellation 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nalgebra 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ncollide3d 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "resources 0.1.0", + "slotmap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vec-2-10-10-10 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lesson_25_x_render_gl_derive" +version = "0.1.0" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.44" @@ -3027,6 +3061,10 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winput" +version = "0.1.0" + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/lesson-25-x-terrain/Cargo.toml b/lesson-25-x-terrain/Cargo.toml index 81ff14b..5549718 100644 --- a/lesson-25-x-terrain/Cargo.toml +++ b/lesson-25-x-terrain/Cargo.toml @@ -6,6 +6,9 @@ edition = "2018" [dependencies] resources = { path = "../lib/resources", features = ["backend_filesystem_watch"] } +winput = { path = "../lib/winput" } +lesson_25_x_render_gl = { path = "render_gl" } +lesson_25_x_render_gl_derive = { path = "render_gl_derive" } gl = { path = "../lib/gl" } failure = "0.1.3" env_logger = "*" diff --git a/lesson-25-x-terrain/render_gl/Cargo.toml b/lesson-25-x-terrain/render_gl/Cargo.toml new file mode 100644 index 0000000..4d9b882 --- /dev/null +++ b/lesson-25-x-terrain/render_gl/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "lesson_25_x_render_gl" +version = "0.1.0" +authors = [] +edition = "2018" + +[dependencies] +gl = { path = "../../lib/gl" } +resources = { path = "../../lib/resources" } +lesson_25_x_render_gl_derive = { path = "../render_gl_derive" } +half = "1.1.1" +vec-2-10-10-10 = "0.1.2" +nalgebra = "0.16" +ncollide3d = "0.17" +failure = "0.1.3" +font-kit = { version = "0.1.0" } +euclid = "0.18.2" +image = "0.20.1" +lyon_tessellation = "0.11.0" +lyon_path = "0.11.0" +int_hash = "0.1.1" +slotmap = "0.3" +log = "0.4.6" +floating-duration = "0.1.2" \ No newline at end of file diff --git a/lesson-25-x-terrain/render_gl/src/lib.rs b/lesson-25-x-terrain/render_gl/src/lib.rs new file mode 100644 index 0000000..9f27b8e --- /dev/null +++ b/lesson-25-x-terrain/render_gl/src/lib.rs @@ -0,0 +1,3 @@ +#[macro_use] extern crate failure; + +pub mod render_target; diff --git a/lesson-25-x-terrain/render_gl/src/render_target.rs b/lesson-25-x-terrain/render_gl/src/render_target.rs new file mode 100644 index 0000000..5c3e91b --- /dev/null +++ b/lesson-25-x-terrain/render_gl/src/render_target.rs @@ -0,0 +1,90 @@ +use nalgebra as na; +use failure; +use gl; +use gl::types::*; + +#[derive(Debug, Fail)] +pub enum Error { + #[fail(display = "Render target creation failed. The framebuffer was not complete.")] + TheFramebufferWasNotComplete, +} + +pub struct DefaultRenderTarget { + size: na::Vector2, + gl: gl::Gl, +} + +impl DefaultRenderTarget { + pub fn new(gl: &gl::Gl, size: na::Vector2) -> DefaultRenderTarget { + DefaultRenderTarget { + size, + gl: gl.clone(), + } + } + + pub fn bind(&self) { + unsafe { + self.gl.BindFramebuffer(gl::FRAMEBUFFER, 0); + } + } +} + +pub struct FramebufferTarget { + size: na::Vector2, + fb: GLuint, + tex: GLuint, + gl: gl::Gl, +} + +impl FramebufferTarget { + pub fn new(gl: &gl::Gl, size: na::Vector2) -> Result { + let mut tex = 0; + let mut fb = 0; + + unsafe { + gl.GenFramebuffers(1, &mut fb); + gl.BindFramebuffer(gl::FRAMEBUFFER, fb); + + gl.GenTextures(1, &mut tex); + gl.BindTexture(gl::TEXTURE_2D, tex); + gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32); + gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32); + + gl.FramebufferTexture(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, tex, 0); + + gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, size.x, size.y, 0, gl::RGBA, gl::UNSIGNED_BYTE, std::ptr::null()); + + let complete = gl.CheckFramebufferStatus(gl::FRAMEBUFFER); + + gl.BindFramebuffer(gl::FRAMEBUFFER, 0); + gl.BindTexture(gl::TEXTURE_2D, 0); + + if complete != gl::FRAMEBUFFER_COMPLETE { + return Err(Error::TheFramebufferWasNotComplete); + } + } + + Ok(FramebufferTarget { + size, + fb, + tex, + gl: gl.clone(), + }) + } + + pub fn bind(&self) { + unsafe { + self.gl.BindFramebuffer(gl::FRAMEBUFFER, self.fb); + } + } +} + +impl Drop for FramebufferTarget +{ + fn drop(&mut self){ + unsafe{ + self.gl.DeleteFramebuffers(1, &self.fb); + self.gl.DeleteTextures(1, &self.tex); + } + } +} \ No newline at end of file diff --git a/lesson-25-x-terrain/render_gl_derive/Cargo.toml b/lesson-25-x-terrain/render_gl_derive/Cargo.toml new file mode 100644 index 0000000..93d4109 --- /dev/null +++ b/lesson-25-x-terrain/render_gl_derive/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "lesson_25_x_render_gl_derive" +version = "0.1.0" +authors = [] + +[dependencies] +quote = "0.3.15" +syn = "0.11.11" + +[lib] +proc-macro = true \ No newline at end of file diff --git a/lesson-25-x-terrain/render_gl_derive/src/lib.rs b/lesson-25-x-terrain/render_gl_derive/src/lib.rs new file mode 100644 index 0000000..3996548 --- /dev/null +++ b/lesson-25-x-terrain/render_gl_derive/src/lib.rs @@ -0,0 +1,121 @@ +#![recursion_limit = "128"] + +extern crate proc_macro; +extern crate syn; +#[macro_use] +extern crate quote; + +#[proc_macro_derive(VertexAttribPointers, attributes(location, divisor))] +pub fn vertex_attrib_pointers_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let s = input.to_string(); + let ast = syn::parse_derive_input(&s).unwrap(); + let gen = generate_impl(&ast); + gen.parse().unwrap() +} + +fn generate_impl(ast: &syn::DeriveInput) -> quote::Tokens { + let ident = &ast.ident; + let generics = &ast.generics; + let where_clause = &ast.generics.where_clause; + let fields_vertex_attrib_pointer = generate_vertex_attrib_pointer_calls(&ast.body); + + quote!{ + impl #ident #generics #where_clause { + #[allow(unused_variables)] + pub fn vertex_attrib_pointers(gl: &::gl::Gl) { + let stride = ::std::mem::size_of::(); + let offset = 0; + + #(#fields_vertex_attrib_pointer)* + } + } + } +} + +fn generate_vertex_attrib_pointer_calls(body: &syn::Body) -> Vec { + match body { + &syn::Body::Enum(_) => panic!("VertexAttribPointers can not be implemented for enums"), + &syn::Body::Struct(syn::VariantData::Unit) => { + panic!("VertexAttribPointers can not be implemented for Unit structs") + } + &syn::Body::Struct(syn::VariantData::Tuple(_)) => { + panic!("VertexAttribPointers can not be implemented for Tuple structs") + } + &syn::Body::Struct(syn::VariantData::Struct(ref s)) => s + .iter() + .map(generate_struct_field_vertex_attrib_pointer_call) + .collect(), + } +} + +fn generate_struct_field_vertex_attrib_pointer_call(field: &syn::Field) -> quote::Tokens { + let field_name = match field.ident { + Some(ref i) => format!("{}", i), + None => String::from(""), + }; + let field_ty = &field.ty; + + if let Some(location_attr) = field + .attrs + .iter() + .filter(|a| a.value.name() == "location") + .next() + { + let location_value: usize = match location_attr.value { + syn::MetaItem::NameValue(_, syn::Lit::Str(ref s, _)) => { + s.parse().unwrap_or_else(|_| { + panic!( + "Field {} location attribute value must contain an integer", + field_name + ) + }) + } + _ => panic!( + "Field {} location attribute value must be a string literal", + field_name + ), + }; + + let divisor_call = match field + .attrs + .iter() + .filter(|a| a.value.name() == "divisor") + .next() + { + Some(attr) => { + let divisor_value: u32 = match attr.value { + syn::MetaItem::NameValue(_, syn::Lit::Str(ref s, _)) => { + s.parse().unwrap_or_else(|_| { + panic!( + "Field {} divisor attribute value must contain an integer", + field_name + ) + }) + } + _ => panic!( + "Field {} divisor attribute value must be a string literal", + field_name + ), + }; + + quote! { + gl.VertexAttribDivisor(#location_value as u32, #divisor_value); + } + } + None => quote!{}, + }; + + quote! { + let location = #location_value; + unsafe { + #field_ty::vertex_attrib_pointer(gl, stride, location, offset); + #divisor_call + } + let offset = offset + ::std::mem::size_of::<#field_ty>(); + } + } else { + quote! { + let offset = offset + ::std::mem::size_of::<#field_ty>(); + } + } +} diff --git a/lesson-25-x-terrain/src/main.rs b/lesson-25-x-terrain/src/main.rs index b34b2b3..9d27b06 100644 --- a/lesson-25-x-terrain/src/main.rs +++ b/lesson-25-x-terrain/src/main.rs @@ -3,6 +3,7 @@ use resources::{ Resources, backend::FileSystem }; +use winput; mod debug; mod onion; diff --git a/lib/resources/src/lib.rs b/lib/resources/src/lib.rs index bdb95f9..aff1434 100644 --- a/lib/resources/src/lib.rs +++ b/lib/resources/src/lib.rs @@ -246,8 +246,7 @@ mod test { } #[test] - fn writing_resource_should_produce_change_sync_point_and_other_resource_proxies_should_see_it_as_modified( -) { + fn writing_resource_should_produce_change_sync_point_and_other_resource_proxies_should_see_it_as_modified() { let res = Resources::new().loaded_from("a", 0, backend::InMemory::new().with("name", b"hello")); diff --git a/lib/winput/Cargo.toml b/lib/winput/Cargo.toml new file mode 100644 index 0000000..6075f3b --- /dev/null +++ b/lib/winput/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "winput" +version = "0.1.0" +authors = [] +edition = "2018" + +[dependencies] diff --git a/lib/winput/src/lib.rs b/lib/winput/src/lib.rs new file mode 100644 index 0000000..217a4c4 --- /dev/null +++ b/lib/winput/src/lib.rs @@ -0,0 +1,12 @@ +#[derive(Debug, Copy, Clone)] +pub struct WindowDimensions { + pub size: WindowSize, + pub hdpi_size: WindowSize, + pub high_dpi: bool, +} + +#[derive(Debug, Copy, Clone)] +pub struct WindowSize { + pub width: i32, + pub height: i32, +} \ No newline at end of file