Skip to content

Terrain Experiment #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,518 changes: 1,018 additions & 500 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions lesson-24-x-text/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ fn run() -> Result<(), failure::Error> {
"core",
0,
resources::backend::FileSystem::from_rel_path(env!("CARGO_MANIFEST_DIR"), "core")
.with_write()
.with_watch(),
.with_write(),
);

let sdl = sdl2::init().map_err(err_msg)?;
Expand Down
7 changes: 7 additions & 0 deletions lesson-25-x-terrain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ authors = ["Nerijus Arlauskas <[email protected]>"]
edition = "2018"

[dependencies]
resources = { path = "../lib/resources", features = ["backend_filesystem_watch"] }
winput = { path = "../lib/winput" }
config = { path = "../lib/config" }
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 = "*"
log = "0.4.6"

toml_edit = "0.1.3"

[dependencies.sdl2]
version = "0.31.0"
features = ["bundled", "static-link"]
Expand Down
4 changes: 4 additions & 0 deletions lesson-25-x-terrain/core/Windows.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

[windows]
width = 800
height = 600
12 changes: 12 additions & 0 deletions lesson-25-x-terrain/core/shaders/quad.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#version 330 core

in VS_OUTPUT {
vec4 Color;
} IN;

out vec4 Color;

void main()
{
Color = IN.Color;
}
17 changes: 17 additions & 0 deletions lesson-25-x-terrain/core/shaders/quad.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#version 330 core

layout (location = 0) in vec3 Position;
layout (location = 1) in vec4 Color;

uniform mat4 ViewProjection;
uniform mat4 Model;

out VS_OUTPUT {
vec4 Color;
} OUT;

void main()
{
gl_Position = ViewProjection * Model * vec4(Position, 1.0);
OUT.Color = Color;
}
24 changes: 24 additions & 0 deletions lesson-25-x-terrain/render_gl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
3 changes: 3 additions & 0 deletions lesson-25-x-terrain/render_gl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#[macro_use] extern crate failure;

pub mod render_target;
90 changes: 90 additions & 0 deletions lesson-25-x-terrain/render_gl/src/render_target.rs
Original file line number Diff line number Diff line change
@@ -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<i32>,
gl: gl::Gl,
}

impl DefaultRenderTarget {
pub fn new(gl: &gl::Gl, size: na::Vector2<i32>) -> DefaultRenderTarget {
DefaultRenderTarget {
size,
gl: gl.clone(),
}
}

pub fn bind(&self) {
unsafe {
self.gl.BindFramebuffer(gl::FRAMEBUFFER, 0);
}
}
}

pub struct FramebufferTarget {
size: na::Vector2<i32>,
fb: GLuint,
tex: GLuint,
gl: gl::Gl,
}

impl FramebufferTarget {
pub fn new(gl: &gl::Gl, size: na::Vector2<i32>) -> Result<FramebufferTarget, Error> {
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);
}
}
}
11 changes: 11 additions & 0 deletions lesson-25-x-terrain/render_gl_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
121 changes: 121 additions & 0 deletions lesson-25-x-terrain/render_gl_derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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::<Self>();
let offset = 0;

#(#fields_vertex_attrib_pointer)*
}
}
}
}

fn generate_vertex_attrib_pointer_calls(body: &syn::Body) -> Vec<quote::Tokens> {
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>();
}
}
}
12 changes: 12 additions & 0 deletions lesson-25-x-terrain/src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
use failure;
use env_logger;

pub fn init_logging() {
let mut builder = env_logger::Builder::new();
builder.filter(None, log::LevelFilter::Trace);
builder.default_format_module_path(true);
builder.default_format_level(true);
if ::std::env::var("RUST_LOG").is_ok() {
builder.parse(&::std::env::var("RUST_LOG").unwrap());
}
builder.init();
}

pub fn failure_to_string(e: failure::Error) -> String {
use std::fmt::Write;
Expand Down
Loading