diff options
| author | HampusM <hampus@hampusmat.com> | 2023-11-20 22:00:34 +0100 | 
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2023-11-20 22:00:34 +0100 | 
| commit | b0315b7ebc16fcbae6c3098db6c824f9057d2a71 (patch) | |
| tree | c7473fbdbcc59aff933790892ee015a6f05d8565 | |
| parent | a65c8abcae46b382b2e1bb7cc5d13768325083b4 (diff) | |
feat(engine): add materials
| -rw-r--r-- | engine/fragment-color.glsl | 4 | ||||
| -rw-r--r-- | engine/fragment-texture.glsl | 4 | ||||
| -rw-r--r-- | engine/light.glsl | 35 | ||||
| -rw-r--r-- | engine/src/color.rs | 12 | ||||
| -rw-r--r-- | engine/src/lib.rs | 21 | ||||
| -rw-r--r-- | engine/src/lighting.rs | 72 | ||||
| -rw-r--r-- | engine/src/material.rs | 113 | ||||
| -rw-r--r-- | engine/src/object.rs | 35 | ||||
| -rw-r--r-- | engine/src/opengl/shader.rs | 10 | ||||
| -rw-r--r-- | engine/src/renderer/mod.rs | 61 | ||||
| -rw-r--r-- | engine/src/vector.rs | 14 | 
11 files changed, 289 insertions, 92 deletions
diff --git a/engine/fragment-color.glsl b/engine/fragment-color.glsl index fcf8d28..4213860 100644 --- a/engine/fragment-color.glsl +++ b/engine/fragment-color.glsl @@ -12,9 +12,9 @@ uniform vec3 view_pos;  void main()  { -	vec3 ambient_light = ambient_light_strength * light_color; +	vec3 ambient_light = calc_ambient_light(); -	vec3 light_direction = normalize(light_pos - in_frag_pos); +	vec3 light_direction = normalize(light.position - in_frag_pos);  	vec3 norm = normalize(in_normal);  	vec3 diffuse_light = calc_diffuse_light(light_direction, norm); diff --git a/engine/fragment-texture.glsl b/engine/fragment-texture.glsl index 2948a2e..69718a6 100644 --- a/engine/fragment-texture.glsl +++ b/engine/fragment-texture.glsl @@ -15,9 +15,9 @@ uniform sampler2D input_texture;  void main()  { -	vec3 ambient_light = ambient_light_strength * light_color; +	vec3 ambient_light = calc_ambient_light(); -	vec3 light_direction = normalize(light_pos - in_frag_pos); +	vec3 light_direction = normalize(light.position - in_frag_pos);  	vec3 norm = normalize(in_normal);  	vec3 diffuse_light = calc_diffuse_light(light_direction, norm); diff --git a/engine/light.glsl b/engine/light.glsl index 3f1c601..0ceac16 100644 --- a/engine/light.glsl +++ b/engine/light.glsl @@ -1,18 +1,33 @@  #version 330 core -uniform vec3 light_color; -uniform vec3 light_pos; - -uniform float ambient_light_strength; -uniform float specular_light_strength; - -uniform uint specular_shininess; +struct Material { +    vec3 ambient; +    vec3 diffuse; +    vec3 specular; +    float shininess; +};  + +struct Light { +	vec3 position; + +    vec3 ambient; +    vec3 diffuse; +    vec3 specular; +};  +   +uniform Material material; +uniform Light light; + +vec3 calc_ambient_light() +{ +	return light.ambient * material.ambient; +}  vec3 calc_diffuse_light(in vec3 light_dir, in vec3 norm)  {  	float diff = max(dot(norm, light_dir), 0.0); -	return diff * light_color; +	return light.diffuse * (diff * material.diffuse);  }  vec3 calc_specular_light( @@ -27,8 +42,8 @@ vec3 calc_specular_light(  	vec3 reflect_direction = reflect(-light_dir, norm);  	float spec = -		pow(max(dot(view_direction, reflect_direction), 0.0), specular_shininess); +		pow(max(dot(view_direction, reflect_direction), 0.0), material.shininess); -	return specular_light_strength * spec * light_color; +	return light.specular * (spec * material.specular);  } diff --git a/engine/src/color.rs b/engine/src/color.rs index 2fd2cd3..697ea8b 100644 --- a/engine/src/color.rs +++ b/engine/src/color.rs @@ -11,3 +11,15 @@ impl Color<f32>  {      pub const WHITE_F32: Self = Self { red: 1.0, green: 1.0, blue: 1.0 };  } + +impl<Value: Clone> From<Value> for Color<Value> +{ +    fn from(value: Value) -> Self +    { +        Self { +            red: value.clone(), +            green: value.clone(), +            blue: value, +        } +    } +} diff --git a/engine/src/lib.rs b/engine/src/lib.rs index e6568a1..30346ed 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -7,7 +7,7 @@ use glfw::window::KeyState;  use glfw::{Window, WindowBuilder};  use crate::camera::Camera; -use crate::lighting::{LightSettings, LightSource}; +use crate::lighting::LightSource;  use crate::object::{Id as ObjectId, Object};  use crate::renderer::Renderer;  use crate::vector::Vec2; @@ -22,6 +22,7 @@ mod transform;  pub mod camera;  pub mod color;  pub mod lighting; +pub mod material;  pub mod math;  pub mod object;  pub mod texture; @@ -37,7 +38,6 @@ pub struct Engine      /// Objects have to be dropped before window. Otherwise, UB.      objects: BTreeMap<ObjectId, Object>,      light_source: Option<LightSource>, -    light_settings: Option<LightSettings>,      window: Window,      renderer: Renderer,      delta_time: Duration, @@ -76,7 +76,6 @@ impl Engine              renderer,              objects: BTreeMap::new(),              light_source: None, -            light_settings: None,              delta_time: Duration::ZERO,          })      } @@ -129,8 +128,6 @@ impl Engine      {          let mut prev_frame_start: Option<Instant> = None; -        let default_light_settings = LightSettings::default(); -          while !self.window.should_close() {              self.update_delta_time(&mut prev_frame_start); @@ -141,9 +138,6 @@ impl Engine              self.renderer.render(                  self.objects.values(),                  self.light_source.as_ref(), -                self.light_settings -                    .as_ref() -                    .unwrap_or(&default_light_settings),                  &window_size,              ); @@ -204,17 +198,6 @@ impl Engine          Ok(Vec2 { x: pos.x, y: pos.y })      } -    pub fn set_light_settings(&mut self, light_settings: LightSettings) -    { -        self.light_settings = Some(light_settings); -    } - -    #[must_use] -    pub fn light_settings(&self) -> Option<&LightSettings> -    { -        self.light_settings.as_ref() -    } -      fn update_delta_time(&mut self, prev_frame_start: &mut Option<Instant>)      {          let frame_start_time = Instant::now(); diff --git a/engine/src/lighting.rs b/engine/src/lighting.rs index e7fb901..f14c0b3 100644 --- a/engine/src/lighting.rs +++ b/engine/src/lighting.rs @@ -2,30 +2,12 @@ use crate::color::Color;  use crate::vector::Vec3;  #[derive(Debug, Clone)] -pub struct LightSettings -{ -    pub ambient_light_strength: f32, -    pub specular_light_strength: f32, -    pub specular_shininess: u32, -} - -impl Default for LightSettings -{ -    fn default() -> Self -    { -        Self { -            ambient_light_strength: 1.0, -            specular_light_strength: 0.0, -            specular_shininess: 32, -        } -    } -} - -#[derive(Debug, Clone)]  pub struct LightSource  {      position: Vec3<f32>, -    color: Color<f32>, +    ambient: Color<f32>, +    diffuse: Color<f32>, +    specular: Color<f32>,  }  impl LightSource @@ -37,9 +19,21 @@ impl LightSource      }      #[must_use] -    pub fn color(&self) -> &Color<f32> +    pub fn ambient(&self) -> &Color<f32> +    { +        &self.ambient +    } + +    #[must_use] +    pub fn diffuse(&self) -> &Color<f32>      { -        &self.color +        &self.diffuse +    } + +    #[must_use] +    pub fn specular(&self) -> &Color<f32> +    { +        &self.specular      }      pub fn translate(&mut self, translation: Vec3<f32>) @@ -52,7 +46,9 @@ impl LightSource  pub struct LightSourceBuilder  {      position: Vec3<f32>, -    color: Color<f32>, +    ambient: Color<f32>, +    diffuse: Color<f32>, +    specular: Color<f32>,  }  impl LightSourceBuilder @@ -62,7 +58,9 @@ impl LightSourceBuilder      {          Self {              position: Vec3::default(), -            color: Color::WHITE_F32, +            ambient: Color::WHITE_F32, +            diffuse: Color::WHITE_F32, +            specular: Color::WHITE_F32,          }      } @@ -75,9 +73,25 @@ impl LightSourceBuilder      }      #[must_use] -    pub fn color(mut self, color: Color<f32>) -> Self +    pub fn ambient(mut self, ambient: Color<f32>) -> Self +    { +        self.ambient = ambient; + +        self +    } + +    #[must_use] +    pub fn diffuse(mut self, diffuse: Color<f32>) -> Self +    { +        self.diffuse = diffuse; + +        self +    } + +    #[must_use] +    pub fn specular(mut self, specular: Color<f32>) -> Self      { -        self.color = color; +        self.specular = specular;          self      } @@ -87,7 +101,9 @@ impl LightSourceBuilder      {          LightSource {              position: self.position.clone(), -            color: self.color.clone(), +            ambient: self.ambient.clone(), +            diffuse: self.diffuse.clone(), +            specular: self.specular.clone(),          }      }  } diff --git a/engine/src/material.rs b/engine/src/material.rs new file mode 100644 index 0000000..240d7e2 --- /dev/null +++ b/engine/src/material.rs @@ -0,0 +1,113 @@ +use crate::color::Color; + +#[derive(Debug, Clone)] +pub struct Material +{ +    ambient: Color<f32>, +    diffuse: Color<f32>, +    specular: Color<f32>, +    shininess: f32, +} + +impl Material +{ +    #[must_use] +    pub fn ambient(&self) -> &Color<f32> +    { +        &self.ambient +    } + +    #[must_use] +    pub fn diffuse(&self) -> &Color<f32> +    { +        &self.diffuse +    } + +    #[must_use] +    pub fn specular(&self) -> &Color<f32> +    { +        &self.specular +    } + +    #[must_use] +    pub fn shininess(&self) -> f32 +    { +        self.shininess +    } +} + +/// [`Material`] builder. +#[derive(Debug, Clone)] +pub struct Builder +{ +    ambient: Color<f32>, +    diffuse: Color<f32>, +    specular: Color<f32>, +    shininess: f32, +} + +impl Builder +{ +    #[must_use] +    pub fn new() -> Self +    { +        Self { +            ambient: 0.2.into(), +            diffuse: 0.5.into(), +            specular: 1.0.into(), +            shininess: 32.0, +        } +    } + +    #[must_use] +    pub fn ambient(mut self, ambient: Color<f32>) -> Self +    { +        self.ambient = ambient; + +        self +    } + +    #[must_use] +    pub fn diffuse(mut self, diffuse: Color<f32>) -> Self +    { +        self.diffuse = diffuse; + +        self +    } + +    #[must_use] +    pub fn specular(mut self, specular: Color<f32>) -> Self +    { +        self.specular = specular; + +        self +    } + +    #[must_use] +    pub fn shininess(mut self, shininess: f32) -> Self +    { +        self.shininess = shininess; + +        self +    } + +    /// Builds a new [`Material`]. +    #[must_use] +    pub fn build(&self) -> Material +    { +        Material { +            ambient: self.ambient.clone(), +            diffuse: self.diffuse.clone(), +            specular: self.specular.clone(), +            shininess: self.shininess, +        } +    } +} + +impl Default for Builder +{ +    fn default() -> Self +    { +        Self::new() +    } +} diff --git a/engine/src/object.rs b/engine/src/object.rs index 3827763..6749124 100644 --- a/engine/src/object.rs +++ b/engine/src/object.rs @@ -2,6 +2,7 @@ use std::fs::read_to_string;  use std::io::Error as IoError;  use std::path::{Path, PathBuf}; +use crate::material::{Builder as MaterialBuilder, Material};  use crate::opengl::shader::{      Error as ShaderError,      Kind as ShaderKind, @@ -28,6 +29,7 @@ pub struct Object      renderable: Renderable,      transform: Transform,      texture: Option<Texture>, +    material: Material,  }  impl Object @@ -62,6 +64,12 @@ impl Object          self.texture.as_ref()      } +    #[must_use] +    pub fn material(&self) -> &Material +    { +        &self.material +    } +      pub(crate) fn renderable(&self) -> &Renderable      {          &self.renderable @@ -74,12 +82,13 @@ impl Object  }  /// Object builder. -#[derive(Debug, Default)] +#[derive(Debug)]  pub struct Builder  {      vertices: Vec<Vertex>,      indices: Option<Vec<u32>>,      texture: Option<Texture>, +    material: Material,  }  impl Builder @@ -88,7 +97,12 @@ impl Builder      #[must_use]      pub fn new() -> Self      { -        Self::default() +        Self { +            vertices: Vec::new(), +            indices: None, +            texture: None, +            material: MaterialBuilder::new().build(), +        }      }      #[must_use] @@ -115,6 +129,14 @@ impl Builder          self      } +    #[must_use] +    pub fn material(mut self, material: Material) -> Self +    { +        self.material = material; + +        self +    } +      /// Builds a new [`Object`].      ///      /// # Errors @@ -212,6 +234,7 @@ impl Builder              renderable,              transform,              texture: self.texture, +            material: self.material,          })      } @@ -226,6 +249,14 @@ impl Builder      }  } +impl Default for Builder +{ +    fn default() -> Self +    { +        Self::new() +    } +} +  /// Object error  #[derive(Debug, thiserror::Error)]  pub enum Error diff --git a/engine/src/opengl/shader.rs b/engine/src/opengl/shader.rs index 4bf56aa..9bed09b 100644 --- a/engine/src/opengl/shader.rs +++ b/engine/src/opengl/shader.rs @@ -205,16 +205,6 @@ impl Program          }      } -    pub fn set_uniform_1uiv(&self, _: &CurrentlyBound<Self>, name: &CStr, num: u32) -    { -        let uniform_location = -            unsafe { gl::GetUniformLocation(self.program, name.as_ptr().cast()) }; - -        unsafe { -            gl::Uniform1uiv(uniform_location, 1, &num); -        } -    } -      fn get_info_log(&self) -> String      {          let mut buf = vec![gl::types::GLchar::default(); 512]; diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs index d46612f..6fa692c 100644 --- a/engine/src/renderer/mod.rs +++ b/engine/src/renderer/mod.rs @@ -6,7 +6,7 @@ use glfw::WindowSize;  use crate::camera::Camera;  use crate::color::Color; -use crate::lighting::{LightSettings, LightSource}; +use crate::lighting::LightSource;  use crate::object::Object;  use crate::opengl::buffer::{      ArrayKind as ArrayBufferKind, @@ -68,7 +68,6 @@ impl Renderer          &self,          objects: impl IntoIterator<Item = &'obj Object>,          light_source: Option<&LightSource>, -        light_settings: &LightSettings,          window_size: &WindowSize,      )      { @@ -90,7 +89,6 @@ impl Renderer                          light_source,                          &self.camera,                          &shader_program_curr_bound, -                        light_settings,                      );                      if let Some(texture) = obj.texture() { @@ -262,43 +260,68 @@ fn apply_light(      light_source: Option<&LightSource>,      camera: &Camera,      shader_program_curr_bound: &CurrentlyBound<ShaderProgram>, -    light_settings: &LightSettings,  )  {      obj.renderable().shader_program.set_uniform_vec_3fv(          shader_program_curr_bound, -        cstr!("light_color"), +        cstr!("light.position"), +        &light_source.map_or_else(Vec3::default, |light_source| { +            light_source.position().clone() +        }), +    ); + +    obj.renderable().shader_program.set_uniform_vec_3fv( +        shader_program_curr_bound, +        cstr!("light.ambient"),          &light_source              .map_or(Color::WHITE_F32, |light_source| { -                light_source.color().clone() +                light_source.ambient().clone()              })              .into(),      );      obj.renderable().shader_program.set_uniform_vec_3fv(          shader_program_curr_bound, -        cstr!("light_pos"), -        &light_source.map_or_else(Vec3::default, |light_source| { -            light_source.position().clone() -        }), +        cstr!("light.diffuse"), +        &light_source +            .map_or(Color::WHITE_F32, |light_source| { +                light_source.diffuse().clone() +            }) +            .into(),      ); -    obj.renderable().shader_program.set_uniform_1fv( +    obj.renderable().shader_program.set_uniform_vec_3fv(          shader_program_curr_bound, -        cstr!("ambient_light_strength"), -        light_settings.ambient_light_strength, +        cstr!("light.specular"), +        &light_source +            .map_or(Color::WHITE_F32, |light_source| { +                light_source.specular().clone() +            }) +            .into(),      ); -    obj.renderable().shader_program.set_uniform_1fv( +    obj.renderable().shader_program.set_uniform_vec_3fv(          shader_program_curr_bound, -        cstr!("specular_light_strength"), -        light_settings.specular_light_strength, +        cstr!("material.ambient"), +        &obj.material().ambient().clone().into(),      ); -    obj.renderable().shader_program.set_uniform_1uiv( +    obj.renderable().shader_program.set_uniform_vec_3fv( +        shader_program_curr_bound, +        cstr!("material.diffuse"), +        &obj.material().diffuse().clone().into(), +    ); + +    obj.renderable().shader_program.set_uniform_vec_3fv( +        shader_program_curr_bound, +        cstr!("material.specular"), +        &obj.material().specular().clone().into(), +    ); + +    obj.renderable().shader_program.set_uniform_1fv(          shader_program_curr_bound, -        cstr!("specular_shininess"), -        light_settings.specular_shininess, +        cstr!("material.shininess"), +        obj.material().shininess(),      );      obj.renderable().shader_program.set_uniform_vec_3fv( diff --git a/engine/src/vector.rs b/engine/src/vector.rs index a5ef911..e0aa262 100644 --- a/engine/src/vector.rs +++ b/engine/src/vector.rs @@ -226,6 +226,20 @@ where      }  } +impl<Value> From<Value> for Vec3<Value> +where +    Value: Clone, +{ +    fn from(value: Value) -> Self +    { +        Self { +            x: value.clone(), +            y: value.clone(), +            z: value, +        } +    } +} +  impl<Value> From<Color<Value>> for Vec3<Value>  {      fn from(color: Color<Value>) -> Self  | 
