From 18da547bc5d6c7ecc47dd8b0657378944dff9104 Mon Sep 17 00:00:00 2001 From: _ <> Date: Sat, 7 Mar 2020 03:36:05 +0000 Subject: [PATCH] Made some awful shadows --- Cargo.lock | 1 + Cargo.toml | 1 + shaders/pumpkin-frag.glsl | 16 +++-- shaders/pumpkin-vert.glsl | 7 +- shaders/shadow-frag.glsl | 20 ++++++ shaders/shadow-vert.glsl | 13 ++++ src/bin/pumpkin.rs | 144 +++++++++++++++++++++++++++++++------- src/glezz.rs | 18 +++++ src/shader.rs | 20 +++--- 9 files changed, 196 insertions(+), 44 deletions(-) create mode 100644 shaders/shadow-frag.glsl create mode 100644 shaders/shadow-vert.glsl diff --git a/Cargo.lock b/Cargo.lock index 5471053..9327f59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,6 +201,7 @@ dependencies = [ "iota 0.2.1 (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)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 01820fd..f6d7bb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,5 @@ iota = "0.2.1" nom = "5.1.0" png = "0.15.3" +rand = "0.6.5" sdl2 = "0.32.2" diff --git a/shaders/pumpkin-frag.glsl b/shaders/pumpkin-frag.glsl index 8fc60b3..78ab6e0 100644 --- a/shaders/pumpkin-frag.glsl +++ b/shaders/pumpkin-frag.glsl @@ -3,24 +3,26 @@ #define highp #line 0 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_color; varying lowp vec3 vary_normal; varying mediump vec2 vary_uv; void main (void) { lowp vec3 normal = normalize (vary_normal); - lowp vec3 albedo = uni_albedo * max (uni_min_albedo, texture2D (uni_texture, vary_uv).rgb); - //lowp vec3 albedo = vec3 (vary_uv, 0.0); + lowp vec3 albedo = vary_color * max (uni_min_albedo, texture2D (uni_texture, vary_uv).rgb); - 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 sky_color = pow (vec3 (42.0, 52.0, 109.0) / vec3 (255.0), vec3 (2.0)); + + lowp float sun_factor = dot (normal, uni_object_space_light); + lowp float sky_factor = normal.z; + + lowp vec3 sun = max (sun_factor, 0.0) * (vec3 (1.0) - sky_color); + lowp vec3 sky = (sky_factor * 0.5 + 0.5) * sky_color; lowp vec3 diffuse_color = albedo * max (uni_min_bright, (sun + sky)); gl_FragColor = vec4 (sqrt (diffuse_color), 1.0); diff --git a/shaders/pumpkin-vert.glsl b/shaders/pumpkin-vert.glsl index 191b090..aba9ed0 100644 --- a/shaders/pumpkin-vert.glsl +++ b/shaders/pumpkin-vert.glsl @@ -3,20 +3,21 @@ #define highp #line 0 uniform highp mat4 uni_mvp; +uniform lowp vec3 uni_albedo; attribute highp vec4 attr_pos; attribute mediump vec2 attr_uv; attribute lowp vec3 attr_normal; -varying mediump vec2 vary_uv; +varying lowp vec3 vary_color; varying lowp vec3 vary_normal; +varying mediump vec2 vary_uv; void main (void) { vary_uv = attr_uv; - lowp vec4 light_color = vec4 (1.0); - vary_normal = attr_normal; + vary_color = uni_albedo * uni_albedo; gl_Position = uni_mvp * attr_pos; } diff --git a/shaders/shadow-frag.glsl b/shaders/shadow-frag.glsl new file mode 100644 index 0000000..5e4c48f --- /dev/null +++ b/shaders/shadow-frag.glsl @@ -0,0 +1,20 @@ +#define lowp +#define mediump +#define highp +#line 0 + +uniform lowp float uni_dither_phase; + +void main (void) { + lowp float dither_phase = uni_dither_phase; + dither_phase += 4.0 * mod (gl_FragCoord.y + 0.5, 4.0); + dither_phase += mod (gl_FragCoord.x + 0.5, 4.0); + dither_phase = mod (dither_phase, 16.0); + + lowp float dither = 1.0; + if (dither_phase == 0.0) { + dither = 0.0; + } + + gl_FragColor = vec4 (vec3 (20.0, 12.0, 28.0) / vec3 (255.0), dither); +} diff --git a/shaders/shadow-vert.glsl b/shaders/shadow-vert.glsl new file mode 100644 index 0000000..57ca830 --- /dev/null +++ b/shaders/shadow-vert.glsl @@ -0,0 +1,13 @@ +#define lowp +#define mediump +#define highp +#line 0 +uniform highp mat4 uni_mvp; + +attribute highp vec4 attr_pos; + +void main (void) { + highp float depth_adjust = -1.0 / 512.0; + + gl_Position = uni_mvp * attr_pos + vec4 (0.0, 0.0, depth_adjust, 0.0); +} diff --git a/src/bin/pumpkin.rs b/src/bin/pumpkin.rs index a89f471..98ed2e6 100644 --- a/src/bin/pumpkin.rs +++ b/src/bin/pumpkin.rs @@ -1,4 +1,5 @@ use glam::{Mat4, Vec3, Vec4}; +use rand::Rng; use sdl2::event::Event; use sdl2::keyboard::{Keycode, Scancode}; @@ -107,6 +108,7 @@ iota! { , MIN_ALBEDO , MIN_BRIGHT , TEXTURE + , DITHER_PHASE } } @@ -138,10 +140,19 @@ fn main () { // And I'm still not actually checking errors - Just checkmarking // that I know where they are. - let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, "shaders/pumpkin-vert.glsl").unwrap (); - let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, "shaders/pumpkin-frag.glsl").unwrap (); + let shader_program = { + let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, "shaders/pumpkin-vert.glsl").unwrap (); + let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, "shaders/pumpkin-frag.glsl").unwrap (); + + ShaderProgram::new (&vert_shader, &frag_shader).unwrap () + }; - let shader_program = ShaderProgram::new (&vert_shader, &frag_shader).unwrap (); + let shadow_shader = { + let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, "shaders/shadow-vert.glsl").unwrap (); + let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, "shaders/shadow-frag.glsl").unwrap (); + + ShaderProgram::new (&vert_shader, &frag_shader).unwrap () + }; let uni_lookup: HashMap <_, &str> = HashMap::from_iter ({ use uniforms::*; @@ -152,15 +163,29 @@ fn main () { (MIN_ALBEDO, "min_albedo"), (MIN_BRIGHT, "min_bright"), (TEXTURE, "texture"), + (DITHER_PHASE, "dither_phase"), ].into_iter () }); - let unis = shader_program.get_uniform_locations (uni_lookup.values ().copied ()); + let unis = { + let unis = shader_program.get_uniform_locations (uni_lookup.values ().copied ()); + + let unis: HashMap = HashMap::from_iter ( + uni_lookup.iter () + .map (|(key, name)| (*key, *unis.get (*name).unwrap ())) + ); + unis + }; - let unis: HashMap = HashMap::from_iter ( - uni_lookup.iter () - .map (|(key, name)| (*key, *unis.get (*name).unwrap ())) - ); + let shadow_unis = { + let unis = shadow_shader.get_uniform_locations (uni_lookup.values ().copied ()); + + let unis: HashMap = HashMap::from_iter ( + uni_lookup.iter () + .map (|(key, name)| (*key, *unis.get (*name).unwrap ())) + ); + unis + }; let attrs = shader_program.get_attribute_locations (vec! [ "pos", @@ -168,6 +193,12 @@ fn main () { "normal", ].into_iter ()); + let shadow_attrs = shadow_shader.get_attribute_locations (vec! [ + "pos", + "uv", + "normal", + ].into_iter ()); + let texture = Texture::from_file ("sky.png"); texture.bind (); @@ -181,17 +212,42 @@ fn main () { let renderable_sky = RenderableModel::from_iqm (&sky_model); - let renderable_pitch = { + let (renderable_pitch, pitch_colors) = { let data = load_small_file ("pitch.iqm", 1024 * 1024); let model = Model::from_slice (&data); - for i in 0..model.meshes.len () { + let silver = (255.0, 255.0, 255.0); + let wood = (133.0, 76.0, 48.0); + + let color_lookup: HashMap <&str, _> = HashMap::from_iter (vec! [ + ("GoalN1", silver), + ("GoalN2", silver), + ("GoalN3", silver), + + ("GoalS1", silver), + ("GoalS2", silver), + ("GoalS3", silver), + + ("TowerNW", wood), + ("TowerNE", wood), + ("TowerSW", wood), + ("TowerSE", wood), + + ("Wall", wood), + + ("Grass", (52.0, 101.0, 36.0)), + ].into_iter ()); + + let colors: Vec <_> = (0..model.meshes.len ()).map (|i| { let name = str::from_utf8 (model.get_mesh_name (i)).unwrap (); - println! ("{} {}", i, name); - } + match color_lookup.get (name) { + Some (t) => color_from_255 (*t), + _ => (0.0, 0.0, 0.0).into (), + } + }).collect (); - RenderableModel::from_iqm (&model) + (RenderableModel::from_iqm (&model), colors) }; glezz::enable_vertex_attrib_array (attrs ["pos"]); @@ -227,45 +283,57 @@ fn main () { } window.gl_make_current (&gl_ctx).unwrap (); + let dither_phase = rand::thread_rng ().gen_range (0, 16); let longitude = state.azimuth.to_radians (); let latitude = (state.altitude - 90.0).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_translation (Vec3::from ((0.0, 0.0, -2.7 * 0.5))) + let model_mat = Mat4::identity (); + Mat4::from_translation ((0.0, 0.0, 0.0).into ()) ; + let shadow_model = { + let mut mat = Mat4::identity (); + mat.set_z_axis ((0.25, 0.125, 0.0, 0.0).into ()); + + mat * model_mat + }; + let view_mat = proj_mat * Mat4::from_translation (Vec3::from ((0.0, 0.0, -8.0))) * Mat4::from_rotation_x (latitude) * - Mat4::from_rotation_z (longitude) + Mat4::from_rotation_z (longitude) * + Mat4::from_translation ((0.0, 0.0, -2.7 * 0.5).into ()) ; let mvp_mat = view_mat * model_mat; + let shadow_mvp = view_mat * shadow_model; - let sky_mvp_mat = view_mat * Mat4::from_scale (Vec3::from ((16.0, 16.0, 16.0))); + let sky_mvp_mat = view_mat * Mat4::from_scale ((16.0, 16.0, 16.0).into ()); 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 object_space_light = Vec3::from ((object_space_light.x (), object_space_light.y (), object_space_light.z ())); - let orange = color_from_255 ((255.0, 154.0, 0.0)); - let green = color_from_255 ((14.0, 127.0, 24.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; + let orange = color_from_255 ((210.0, 125.0, 44.0)); + let green = color_from_255 ((52.0, 101.0, 36.0)); + let white = color_from_255 ((222.0, 238.0, 214.0)); + let black = color_from_255 ((0.0, 0.0, 0.0)); + let off_black = color_from_255 ((20.0, 12.0, 28.0)); glezz::clear_color (1.0f32, 1.0f32, 1.0f32, 1.0f32); glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); - glezz::disable (gl::CULL_FACE); + glezz::enable (gl::CULL_FACE); { use uniforms::*; + shader_program.use_program (); + glezz::front_face (gl::CW); + glezz::disable (gl::BLEND); + glezz::uniform_3fv (unis [&MIN_BRIGHT], &black); glezz::uniform_3fv (unis [&MIN_ALBEDO], &white); @@ -282,7 +350,7 @@ fn main () { { for i in 0..renderable_pitch.num_meshes () { - glezz::uniform_3fv (unis [&ALBEDO], &green); + glezz::uniform_3fv (unis [&ALBEDO], &pitch_colors [i]); renderable_pitch.draw (&attrs, i); } } @@ -297,6 +365,30 @@ fn main () { renderable_sky.draw (&attrs, 0); } + + shadow_shader.use_program (); + glezz::front_face (gl::CCW); + glezz::enable (gl::BLEND); + glezz::blend_func (gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + + glezz::uniform_1f (shadow_unis [&DITHER_PHASE], dither_phase as f32); + + glezz::uniform_3fv (shadow_unis [&MIN_BRIGHT], &black); + glezz::uniform_3fv (shadow_unis [&MIN_ALBEDO], &white); + + glezz::uniform_matrix_4fv (shadow_unis [&MVP], &shadow_mvp); + glezz::uniform_3fv (shadow_unis [&OBJECT_SPACE_LIGHT], &object_space_light); + + { + renderable_model.draw (&shadow_attrs, 0); + renderable_model.draw (&shadow_attrs, 1); + } + + { + for i in 0..renderable_pitch.num_meshes () { + renderable_pitch.draw (&shadow_attrs, i); + } + } } window.gl_swap_window (); diff --git a/src/glezz.rs b/src/glezz.rs index e7ce579..0c2d1e3 100644 --- a/src/glezz.rs +++ b/src/glezz.rs @@ -26,6 +26,18 @@ pub fn enable (constant: u32) { } } +pub fn front_face (constant: u32) { + unsafe { + gl::FrontFace (constant); + } +} + +pub fn blend_func (src: u32, dst: u32) { + unsafe { + gl::BlendFunc (src, dst); + } +} + pub fn enable_vertex_attrib_array (id: Option ) { if let Some (id) = id { // Are safety checks really needed here? @@ -41,6 +53,12 @@ pub fn uniform_1i (uni: i32, x: i32) { } } +pub fn uniform_1f (uni: i32, x: f32) { + unsafe { + gl::Uniform1f (uni, x); + } +} + pub fn uniform_3fv (uni: i32, v: &Vec3) { unsafe { gl::Uniform3fv (uni, 1, v as *const Vec3 as *const f32); diff --git a/src/shader.rs b/src/shader.rs index 9a9e9a4..2a3221f 100644 --- a/src/shader.rs +++ b/src/shader.rs @@ -119,9 +119,16 @@ impl ShaderProgram { } } - pub fn get_uniform_location (&self, name: &CStr) -> i32 { + pub fn use_program (&self) { unsafe { gl::UseProgram (self.id); + } + } + + pub fn get_uniform_location (&self, name: &CStr) -> i32 { + self.use_program (); + + unsafe { gl::GetUniformLocation (self.id, name.as_ptr ()) } } @@ -130,9 +137,7 @@ impl ShaderProgram { -> HashMap where I: Iterator { - unsafe { - gl::UseProgram (self.id); - } + self.use_program (); names .map (|name| { @@ -150,8 +155,9 @@ impl ShaderProgram { } pub fn get_attribute_location (&self, name: &CStr) -> i32 { + self.use_program (); + unsafe { - gl::UseProgram (self.id); gl::GetAttribLocation (self.id, name.as_ptr ()) } } @@ -160,9 +166,7 @@ impl ShaderProgram { -> HashMap > where I: Iterator { - unsafe { - gl::UseProgram (self.id); - } + self.use_program (); names .map (|name| {