From a1911141e12e5987c10f7fd4cbcae3b637f47a1e Mon Sep 17 00:00:00 2001 From: _ <> Date: Sun, 12 Jan 2020 18:46:16 +0000 Subject: [PATCH] Pumpkin is lit af but stem isn't drawing yet --- Cargo.lock | 7 +++ Cargo.toml | 4 ++ src/main.rs | 157 +++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 142 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9907cb..0aa30d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,11 @@ dependencies = [ "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "glam" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "khronos_api" version = "3.1.0" @@ -151,6 +156,7 @@ name = "opengl-rust" version = "0.1.0" dependencies = [ "gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glam 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -350,6 +356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" "checksum gl_generator 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +"checksum glam 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bb24d4e1b92ceed0450bbf803ac894b597c5b8d0e16f175f7ef28c42024d8cbd" "checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14" diff --git a/Cargo.toml b/Cargo.toml index 2018926..5ea19f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,10 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + gl = "0.14.0" +glam = "0.8.5" + +# TODO: Drop nom depend. It's way overkill for iqm. nom = "5.1.0" sdl2 = "0.32.2" diff --git a/src/main.rs b/src/main.rs index 38ccbeb..02546b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use glam::{Mat4, Vec3, Vec4, Quat}; use nom::{ IResult, bytes::complete::{tag}, @@ -13,7 +14,7 @@ use std::ffi::{c_void, CStr, CString}; use std::fs::File; use std::io::Read; use std::path::Path; -use std::time::Duration; +use std::time::{Duration, Instant}; mod iqm_consts { pub const VERSION: usize = 0; @@ -217,7 +218,11 @@ impl <'a> IqmModel <'a> { let offset = vertexarrays_offset + i * vertexarray_size; let vertexarray_slice = &data [offset..offset + vertexarray_size]; - vertexarrays.push (IqmVertexArray::from_slice (vertexarray_slice).unwrap ().1); + let vertexarray = IqmVertexArray::from_slice (vertexarray_slice).unwrap ().1; + + //println! ("{:?}", vertexarray); + + vertexarrays.push (vertexarray); } vertexarrays @@ -292,15 +297,17 @@ attribute highp vec4 attr_pos; attribute mediump vec2 attr_uv; attribute lowp vec3 attr_normal; -varying lowp vec4 vary_color; varying mediump vec2 vary_uv; +varying lowp vec3 vary_normal; void main (void) { vary_uv = attr_uv; lowp vec4 light_color = vec4 (1.0); - vary_color = light_color; + //vary_color = dot (attr_normal, object_space_light.xyz) * light_color; + //vary_color.xyz = attr_normal; + vary_normal = attr_normal; vec4 world_pos = uni_model * attr_pos; @@ -313,14 +320,25 @@ const FRAG_SHADER_SRC: &str = #define mediump #define highp #line 0 -uniform lowp sampler2D uni_texture; +//uniform lowp sampler2D uni_texture; +uniform lowp vec3 uni_albedo; +uniform lowp vec4 uni_object_space_light; -varying lowp vec4 vary_color; +//varying lowp vec4 vary_color; +varying lowp vec3 vary_normal; varying mediump vec2 vary_uv; void main (void) { - gl_FragColor = texture2D (uni_texture, vary_uv) * vary_color; - //gl_FragColor = vec4 (1.0, 0.0, 1.0, 1.0); + //lowp vec4 albedo = texture2D (uni_texture, vary_uv); + lowp vec3 normal = normalize (vary_normal); + //lowp vec3 albedo = pow (vec3 (255.0 / 255.0, 154.0 / 255.0, 0.0 / 255.0), vec3 (2.0)); + + lowp float diffuse_factor = dot (normal, uni_object_space_light.xyz); + lowp vec3 sun = max (diffuse_factor, 0.0) * vec3 (0.95, 0.9, 0.85); + lowp vec3 sky = (diffuse_factor * 0.45 + 0.55) * vec3 (0.05, 0.1, 0.15); + lowp vec3 diffuse_color = uni_albedo * (sun + sky); + + gl_FragColor = vec4 (sqrt (diffuse_color), 1.0); } "; @@ -455,6 +473,26 @@ impl Drop for ShaderProgram { } } +fn enable_vertex_attrib_array (id: Option ) { + match id { + Some (id) => unsafe { + gl::EnableVertexAttribArray (id); + }, + _ => (), + } +} + +unsafe fn vertex_attrib_pointer (id: Option , num_coords: i32, slice: &[u8]) { + const FALSE_U8: u8 = 0; + const FLOAT_SIZE: i32 = 4; + match id { + Some (id) => { + gl::VertexAttribPointer (id, num_coords, gl::FLOAT, FALSE_U8, FLOAT_SIZE * num_coords, &slice [0] as *const u8 as *const c_void); + }, + _ => (), + } +} + fn main () { let sdl_context = sdl2::init ().unwrap (); let video_subsystem = sdl_context.video ().unwrap (); @@ -494,24 +532,29 @@ fn main () { let unis: HashMap <_, _> = vec! [ "model", "viewproj", + "object_space_light", + "albedo", ].iter () .map (|name| { let mut s = String::from ("uni_"); s.push_str (name); let c_str = CString::new (s.as_bytes ()).unwrap (); + let loc = shader_program.get_uniform_location (&c_str); - (String::from (*name), shader_program.get_uniform_location (&c_str)) + println! ("Uni {} --> {}", name, loc); + + (String::from (*name), loc) }) .collect (); - println! ("uni_model: {}", unis ["model"]); - println! ("uni_viewproj: {}", unis ["viewproj"]); + //println! ("uni_model: {}", unis ["model"]); + //println! ("uni_viewproj: {}", unis ["viewproj"]); - let attrs: HashMap <_, u32> = vec! [ + let attrs: HashMap <_, Option > = vec! [ "pos", "uv", - //"normal", + "normal", ].iter () .map (|name| { let mut s = String::from ("attr_"); @@ -519,12 +562,19 @@ fn main () { let c_str = CString::new (s.as_bytes ()).unwrap (); let loc = shader_program.get_attribute_location (&c_str); + let loc = match loc.try_into () { + Ok (i) => Some (i), + _ => { + println! ("Attribute {} not found - Optimized out?", name); + None + }, + }; - (String::from (*name), loc.try_into ().unwrap ()) + (String::from (*name), loc) }) .collect (); - println! ("attr_pos: {}", attrs ["pos"]); + //println! ("attr_pos: {}", attrs ["pos"]); let tri_mesh: Vec = vec! [ 0.0, 0.0, @@ -535,18 +585,14 @@ fn main () { let model_data = load_small_file ("pumpking.iqm"); let model = IqmModel::from_slice (&model_data [..]); let vertex_slice = model.get_vertex_slice (0, 0); + let normal_slice = model.get_vertex_slice (0, 2); let index_slice = model.get_index_slice (0); - let id_mat: Vec = vec! [ - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0, - ]; + let id_mat = Mat4::identity (); let view_mat: Vec = vec! [ 0.3125, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.3125, 0.0, 0.0, 0.0, 0.0, 1.0, ]; let indexes: Vec = vec! [0, 1, 2]; @@ -554,19 +600,44 @@ fn main () { const FALSE_U8: u8 = 0; unsafe { - gl::EnableVertexAttribArray (attrs ["pos"]); + enable_vertex_attrib_array (attrs ["pos"]); + enable_vertex_attrib_array (attrs ["normal"]); + gl::Enable (gl::DEPTH_TEST); let num_coords = 3; let stride = 4 * num_coords; - gl::VertexAttribPointer (attrs ["pos"], num_coords, gl::FLOAT, FALSE_U8, stride, &vertex_slice [0] as *const u8 as *const c_void); - gl::UniformMatrix4fv (unis ["viewproj"], 1, FALSE_U8, &view_mat [0]); - gl::UniformMatrix4fv (unis ["model"], 1, FALSE_U8, &id_mat [0]); } + let mut last_frame_time = Instant::now (); + let mut frame = 0; + let mut timestep_accum = Duration::from_millis (0); + let mut event_pump = sdl_context.event_pump ().unwrap (); 'running: loop { + let frame_time = Instant::now (); + + // Take 60 steps every 1,000 milliseconds. + // I know this is a float, but since we're multiplying it will + // be deterministic, since it's a whole number. + let fps_num = 60.0; + let fps_den = 1000; + + timestep_accum += (frame_time - last_frame_time).mul_f32 (fps_num); + + for _ in 0..4 { + if timestep_accum > Duration::from_millis (fps_den) { + frame += 1; + timestep_accum -= Duration::from_millis (fps_den); + } + else { + break; + } + } + + last_frame_time = frame_time; + let _mouse = event_pump.mouse_state (); for event in event_pump.poll_iter() { @@ -581,12 +652,46 @@ fn main () { window.gl_make_current (&gl_ctx).unwrap (); + let longitude = (frame as f32).to_radians (); + let latitude = (frame as f32 / 5.0).to_radians ().sin () * 45.0f32.to_radians () - 120.0f32.to_radians (); + let model_mat = + Mat4::from_rotation_x (latitude) * + Mat4::from_rotation_z (longitude) * + Mat4::from_translation (Vec3::from ((0.0, 0.0, -1.0))) + ; + + let light = Vec4::from ((0.0, 0.0, 0.0, 1.0)); + let object_space_light = model_mat.inverse () * light; + + let orange = Vec3::from ((255.0 / 255.0, 154.0 / 255.0, 0.0 / 255.0)); + let green = Vec3::from ((14.0 / 255.0, 127.0 / 255.0, 24.0 / 255.0)); + + let orange = orange * orange; + let green = green * green; + unsafe { gl::ClearColor (1.0f32, 0.0f32, 1.0f32, 1.0f32); gl::Clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); gl::Disable (gl::CULL_FACE); + gl::UniformMatrix4fv (unis ["model"], 1, FALSE_U8, &model_mat as *const Mat4 as *const f32); + gl::Uniform4fv (unis ["object_space_light"], 1, &object_space_light as *const Vec4 as *const f32); + + gl::Uniform3fv (unis ["albedo"], 1, &orange as *const Vec3 as *const f32); + + vertex_attrib_pointer (attrs ["pos"], 3, model.get_vertex_slice (0, 0)); + vertex_attrib_pointer (attrs ["normal"], 3, model.get_vertex_slice (0, 2)); + gl::DrawElements (gl::TRIANGLES, (model.meshes [0].num_triangles * 3) as i32, gl::UNSIGNED_INT, &index_slice [0] as *const u8 as *const c_void); + + if false { + gl::Uniform3fv (unis ["albedo"], 1, &green as *const Vec3 as *const f32); + + vertex_attrib_pointer (attrs ["pos"], 3, model.get_vertex_slice (1, 0)); + vertex_attrib_pointer (attrs ["normal"], 3, model.get_vertex_slice (1, 2)); + + gl::DrawElements (gl::TRIANGLES, (model.meshes [1].num_triangles * 3) as i32, gl::UNSIGNED_INT, &index_slice [1] as *const u8 as *const c_void); + } } window.gl_swap_window ();