From 9a1e43700d7286adaa4b199956af5fae3a5a17b8 Mon Sep 17 00:00:00 2001 From: _ <> Date: Wed, 15 Jan 2020 03:45:47 +0000 Subject: [PATCH] Add textured sky sphere --- Cargo.lock | 53 ++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ src/main.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 133 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0aa30d6..c280a86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.12" @@ -18,6 +23,11 @@ name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.10" @@ -31,6 +41,23 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "deflate" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -59,6 +86,14 @@ name = "glam" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -158,9 +193,21 @@ 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)", + "png 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "png" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)", + "inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.6.5" @@ -348,15 +395,20 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)" = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" "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 inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" "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" @@ -369,6 +421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +"checksum png 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef859a23054bbfee7811284275ae522f0434a3c8e7f4b74bd4a35ae7e1c4a283" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" diff --git a/Cargo.toml b/Cargo.toml index 5ea19f8..0bd440e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,6 @@ glam = "0.8.5" # TODO: Drop nom depend. It's way overkill for iqm. nom = "5.1.0" + +png = "0.15.3" sdl2 = "0.32.2" diff --git a/src/main.rs b/src/main.rs index 4007e2c..9fa88d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -247,7 +247,7 @@ impl <'a> IqmModel <'a> { let vertexarray = &self.vertexarrays [vertexarray_index]; let bytes_per_float = 4; let stride = bytes_per_float * vertexarray.va_size; - assert_eq! (stride, 12); + //assert_eq! (stride, 12); let offset: usize = (vertexarray.va_offset).try_into ().unwrap (); let num_bytes: usize = (stride * self.header.fields [iqm_consts::NUM_VERTEXES]).try_into ().unwrap (); @@ -286,6 +286,30 @@ where P: AsRef data } +pub fn ugly_load_texture

(name: P) -> u32 +where P: AsRef +{ + let decoder = png::Decoder::new (File::open (name).unwrap ()); + let (info, mut reader) = decoder.read_info ().unwrap (); + // Allocate the output buffer. + let mut buf = vec! [0; info.buffer_size ()]; + // Read the next frame. Currently this function should only called once. + // The default options + reader.next_frame (&mut buf).unwrap (); + + unsafe { + gl::BindTexture (gl::TEXTURE_2D, 1); + gl::TexImage2D (gl::TEXTURE_2D, 0, gl::RGBA.try_into ().unwrap (), 1024, 1024, 0, gl::RGBA, gl::UNSIGNED_BYTE, &buf [0] as *const u8 as *const c_void); + + gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32); + gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32); + gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32); + gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32); + } + + 1 +} + const VERT_SHADER_SRC: &str = " #define lowp @@ -306,8 +330,6 @@ void main (void) { lowp vec4 light_color = vec4 (1.0); - //vary_color = dot (attr_normal, object_space_light.xyz) * light_color; - //vary_color.xyz = attr_normal; vary_normal = attr_normal; gl_Position = uni_mvp * attr_pos; @@ -319,23 +341,26 @@ 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 vec3 uni_object_space_light; +uniform lowp vec3 uni_min_bright; +uniform lowp vec3 uni_min_albedo; //varying lowp vec4 vary_color; varying lowp vec3 vary_normal; varying mediump vec2 vary_uv; void main (void) { - //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 vec3 albedo = uni_albedo * max (uni_min_albedo, texture2D (uni_texture, vary_uv).rgb); + //lowp vec3 albedo = vec3 (vary_uv, 0.0); lowp float diffuse_factor = dot (normal, uni_object_space_light); 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); + lowp vec3 diffuse_color = albedo * max (uni_min_bright, (sun + sky)); gl_FragColor = vec4 (sqrt (diffuse_color), 1.0); } @@ -532,6 +557,9 @@ fn main () { "mvp", "object_space_light", "albedo", + "min_albedo", + "min_bright", + "texture", ].iter () .map (|name| { let mut s = String::from ("uni_"); @@ -569,15 +597,23 @@ fn main () { }) .collect (); + let texture = ugly_load_texture ("sky.png"); + let model_data = load_small_file ("pumpking.iqm"); let model = IqmModel::from_slice (&model_data [..]); + let sky_data = load_small_file ("sky-sphere.iqm"); + let sky_model = IqmModel::from_slice (&sky_data [..]); + const FALSE_U8: u8 = 0; unsafe { enable_vertex_attrib_array (attrs ["pos"]); + enable_vertex_attrib_array (attrs ["uv"]); enable_vertex_attrib_array (attrs ["normal"]); + gl::Enable (gl::DEPTH_TEST); + gl::Enable (gl::TEXTURE); let num_coords = 3; let stride = 4 * num_coords; @@ -587,6 +623,8 @@ fn main () { let mut frame = 0; let mut timestep_accum = Duration::from_millis (0); + //println! ("Entering main loop"); + let mut event_pump = sdl_context.event_pump ().unwrap (); 'running: loop { let frame_time = Instant::now (); @@ -628,23 +666,29 @@ fn main () { let longitude = (frame as f32).to_radians (); let latitude = (frame as f32 / 5.0).to_radians ().sin () * -40.0f32.to_radians () - 75.0f32.to_radians (); + let proj_mat = Mat4::perspective_rh_gl (30.0f32.to_radians (), 1280.0 / 720.0, 0.5, 500.0); + let model_mat = - Mat4::from_rotation_z (longitude) * Mat4::from_translation (Vec3::from ((0.0, 0.0, -2.7 * 0.5))) ; - let mvp_mat = - Mat4::perspective_rh_gl (30.0f32.to_radians (), 1280.0 / 720.0, 0.5, 500.0) * + let view_mat = proj_mat * Mat4::from_translation (Vec3::from ((0.0, 0.0, -8.0))) * - Mat4::from_rotation_x (latitude) * - model_mat + Mat4::from_rotation_x (latitude) * + Mat4::from_rotation_z (longitude) ; + let mvp_mat = view_mat * model_mat; + + let sky_mvp_mat = view_mat * Mat4::from_scale (Vec3::from ((16.0, 16.0, 16.0))); + let light = Vec3::from ((2.0, 0.0, 5.0)).normalize (); let object_space_light = model_mat.inverse () * Vec4::from ((light.x (), light.y (), light.z (), 0.0)); 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 white = Vec3::from ((1.0, 1.0, 1.0)); + let black = Vec3::from ((0.0, 0.0, 0.0)); let orange = orange * orange; let green = green * green; @@ -654,12 +698,16 @@ fn main () { gl::Clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); gl::Disable (gl::CULL_FACE); + gl::Uniform3fv (unis ["min_bright"], 1, &black as *const Vec3 as *const f32); + gl::Uniform3fv (unis ["min_albedo"], 1, &white as *const Vec3 as *const f32); + gl::UniformMatrix4fv (unis ["mvp"], 1, FALSE_U8, &mvp_mat as *const Mat4 as *const f32); gl::Uniform3fv (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)); + vertex_attrib_pointer (attrs ["uv"], 2, model.get_vertex_slice (1)); vertex_attrib_pointer (attrs ["normal"], 3, model.get_vertex_slice (2)); gl::DrawElements (gl::TRIANGLES, (model.meshes [0].num_triangles * 3) as i32, gl::UNSIGNED_INT, &model.get_index_slice (0) [0] as *const u8 as *const c_void); @@ -667,11 +715,26 @@ fn main () { if true { gl::Uniform3fv (unis ["albedo"], 1, &green as *const Vec3 as *const f32); - vertex_attrib_pointer (attrs ["pos"], 3, model.get_vertex_slice (0)); - vertex_attrib_pointer (attrs ["normal"], 3, model.get_vertex_slice (2)); - gl::DrawElements (gl::TRIANGLES, (model.meshes [1].num_triangles * 3) as i32, gl::UNSIGNED_INT, &model.get_index_slice (1) [0] as *const u8 as *const c_void); } + + let draw_sky = true; + if draw_sky { + //println! ("Drawing sky"); + + gl::UniformMatrix4fv (unis ["mvp"], 1, FALSE_U8, &sky_mvp_mat as *const Mat4 as *const f32); + + gl::Uniform3fv (unis ["albedo"], 1, &white as *const Vec3 as *const f32); + gl::Uniform3fv (unis ["min_bright"], 1, &white as *const Vec3 as *const f32); + gl::Uniform3fv (unis ["min_albedo"], 1, &black as *const Vec3 as *const f32); + gl::Uniform1i (unis ["texture"], 0); + + vertex_attrib_pointer (attrs ["pos"], 3, sky_model.get_vertex_slice (0)); + vertex_attrib_pointer (attrs ["uv"], 2, sky_model.get_vertex_slice (1)); + vertex_attrib_pointer (attrs ["normal"], 3, sky_model.get_vertex_slice (2)); + + gl::DrawElements (gl::TRIANGLES, (sky_model.meshes [0].num_triangles * 3) as i32, gl::UNSIGNED_INT, &sky_model.get_index_slice (0) [0] as *const u8 as *const c_void); + } } window.gl_swap_window ();