diff options
-rw-r--r-- | engine/src/opengl/texture.rs | 79 | ||||
-rw-r--r-- | engine/src/renderer/mod.rs | 36 | ||||
-rw-r--r-- | engine/src/texture.rs | 119 |
3 files changed, 101 insertions, 133 deletions
diff --git a/engine/src/opengl/texture.rs b/engine/src/opengl/texture.rs index 56eb118..5d12729 100644 --- a/engine/src/opengl/texture.rs +++ b/engine/src/opengl/texture.rs @@ -1,7 +1,7 @@ use std::ptr::null; use crate::opengl::currently_bound::CurrentlyBound; -use crate::texture::Id; +use crate::texture::{Id, Properties}; use crate::vector::Vec2; #[derive(Debug)] @@ -49,7 +49,24 @@ impl Texture } } - pub fn set_wrap(_: CurrentlyBound<Self>, wrapping: Wrapping) + pub fn apply_properties(&self, properties: &Properties) + { + self.bind(|texture_curr_bound| { + Texture::set_wrap(&texture_curr_bound, properties.wrap); + + Texture::set_magnifying_filter( + &texture_curr_bound, + properties.magnifying_filter, + ); + + Texture::set_minifying_filter( + &texture_curr_bound, + properties.minifying_filter, + ); + }); + } + + pub fn set_wrap(_: &CurrentlyBound<Self>, wrapping: Wrapping) { let wrapping_gl = wrapping.to_gl(); @@ -60,7 +77,7 @@ impl Texture } } - pub fn set_magnifying_filter(_: CurrentlyBound<Self>, filtering: Filtering) + pub fn set_magnifying_filter(_: &CurrentlyBound<Self>, filtering: Filtering) { let filtering_gl = filtering.to_gl(); @@ -74,7 +91,7 @@ impl Texture } } - pub fn set_minifying_filter(_: CurrentlyBound<Self>, filtering: Filtering) + pub fn set_minifying_filter(_: &CurrentlyBound<Self>, filtering: Filtering) { let filtering_gl = filtering.to_gl(); @@ -88,60 +105,6 @@ impl Texture } } - /// Creates a copy of the texture & the texture images. - /// - /// `src_offset` and `dst_offset` are source & destination offsets from the - /// bottom-left of the images. - /// - /// New mipmaps are generated using the largest mipmap. - pub fn copy( - &self, - dimensions: &Vec2<u32>, - pixel_data_format: PixelDataFormat, - src_offset: &Vec2<u32>, - dst_offset: &Vec2<u32>, - ) -> Self - { - let new_texture = Self::new(); - - new_texture.bind(|curr_bound| { - Self::alloc_image(&curr_bound, pixel_data_format, dimensions, None); - - // Mipmap have to be generated since CopyImageSubData demands that the - // destination texture is completed - unsafe { - gl::GenerateMipmap(gl::TEXTURE_2D); - } - }); - - #[allow(clippy::cast_possible_wrap)] - unsafe { - gl::CopyImageSubData( - self.texture, - gl::TEXTURE_2D, - 0, - src_offset.x as i32, - src_offset.y as i32, - 0, - new_texture.texture, - gl::TEXTURE_2D, - 0, - dst_offset.x as i32, - dst_offset.y as i32, - 0, - dimensions.x as i32, - dimensions.y as i32, - 1, - ); - } - - unsafe { - gl::GenerateMipmap(gl::TEXTURE_2D); - } - - new_texture - } - fn alloc_image( _: &CurrentlyBound<Self>, pixel_data_format: PixelDataFormat, diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs index 8977ac9..6c04323 100644 --- a/engine/src/renderer/mod.rs +++ b/engine/src/renderer/mod.rs @@ -24,11 +24,16 @@ use crate::opengl::shader::{ Program as GlShaderProgram, Shader as GlShader, }; -use crate::opengl::texture::{set_active_texture_unit, TextureUnit}; +use crate::opengl::texture::{ + set_active_texture_unit, + Texture as GlTexture, + TextureUnit, +}; use crate::opengl::vertex_array::{PrimitiveKind, VertexArray}; use crate::opengl::{clear_buffers, enable, BufferClearMask, Capability}; use crate::projection::new_perspective; use crate::shader::Program as ShaderProgram; +use crate::texture::{Id as TextureId, Texture}; use crate::vector::{Vec2, Vec3}; use crate::vertex::Vertex; @@ -37,6 +42,7 @@ pub struct Renderer<CameraT> { camera: CameraT, shader_programs: HashMap<u64, GlShaderProgram>, + textures: HashMap<TextureId, GlTexture>, } impl<CameraT> Renderer<CameraT> @@ -73,6 +79,7 @@ where Ok(Self { camera, shader_programs: HashMap::new(), + textures: HashMap::new(), }) } @@ -111,7 +118,7 @@ where } pub fn render<'obj>( - &self, + &mut self, objects: impl IntoIterator<Item = &'obj Object>, light_source: Option<&LightSource>, window_size: &WindowSize, @@ -143,12 +150,17 @@ where ); for (texture_id, texture) in obj.textures() { + let gl_texture = self + .textures + .entry(*texture_id) + .or_insert_with(|| create_gl_texture(texture)); + let texture_unit = TextureUnit::from_texture_id(*texture_id) .ok_or(Error::TextureIdIsInvalidTextureUnit)?; set_active_texture_unit(texture_unit); - texture.inner().bind(|_| {}); + gl_texture.bind(|_| {}); } Self::draw_object(obj); @@ -219,6 +231,24 @@ where } } +fn create_gl_texture(texture: &Texture) -> GlTexture +{ + let gl_texture = GlTexture::new(); + + gl_texture.bind(|texture_curr_bound| { + GlTexture::generate( + &texture_curr_bound, + &texture.dimensions(), + texture.image().as_bytes(), + texture.pixel_data_format(), + ); + }); + + gl_texture.apply_properties(texture.properties()); + + gl_texture +} + #[derive(Debug)] pub struct Renderable { diff --git a/engine/src/texture.rs b/engine/src/texture.rs index f644b58..2d7ba51 100644 --- a/engine/src/texture.rs +++ b/engine/src/texture.rs @@ -1,10 +1,10 @@ use std::path::Path; use image::io::Reader as ImageReader; -use image::{DynamicImage, EncodableLayout, ImageError, Rgb, RgbImage}; +use image::{DynamicImage, ImageError, Rgb, RgbImage}; use crate::color::Color; -use crate::opengl::texture::{PixelDataFormat, Texture as InnerTexture}; +use crate::opengl::texture::PixelDataFormat; use crate::vector::Vec2; mod reexports @@ -14,12 +14,13 @@ mod reexports pub use reexports::*; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Texture { - inner: InnerTexture, + image: DynamicImage, pixel_data_format: PixelDataFormat, dimensions: Vec2<u32>, + properties: Properties, } impl Texture @@ -46,26 +47,14 @@ impl Texture } }; - let inner = InnerTexture::new(); - let dimensions = Vec2 { x: image.width(), y: image.height() }; - inner.bind(|texture_curr_bound| { - InnerTexture::generate( - &texture_curr_bound, - &dimensions, - image.as_bytes(), - pixel_data_format, - ); - }); - - let me = Self { inner, pixel_data_format, dimensions }; - - me.set_wrap(Wrapping::Repeat); - me.set_magnifying_filter(Filtering::Linear); - me.set_minifying_filter(Filtering::Nearest); - - Ok(me) + Ok(Self { + image, + pixel_data_format, + dimensions, + properties: Properties::default(), + }) } #[must_use] @@ -77,73 +66,37 @@ impl Texture Rgb([color.red, color.green, color.blue]), ); - let inner = InnerTexture::new(); - - inner.bind(|texture_curr_bound| { - InnerTexture::generate( - &texture_curr_bound, - dimensions, - image.as_bytes(), - PixelDataFormat::Rgb, - ); - }); - - let me = Self { - inner, + Self { + image: image.into(), pixel_data_format: PixelDataFormat::Rgb, dimensions: dimensions.clone(), - }; - - me.set_wrap(Wrapping::Repeat); - me.set_magnifying_filter(Filtering::Linear); - me.set_minifying_filter(Filtering::Nearest); - - me + properties: Properties::default(), + } } - pub fn set_wrap(&self, wrapping: Wrapping) + pub fn properties(&self) -> &Properties { - self.inner.bind(|texture_curr_bound| { - InnerTexture::set_wrap(texture_curr_bound, wrapping); - }); + &self.properties } - pub fn set_magnifying_filter(&self, filtering: Filtering) + pub fn properties_mut(&mut self) -> &mut Properties { - self.inner.bind(|texture_curr_bound| { - InnerTexture::set_magnifying_filter(texture_curr_bound, filtering); - }); + &mut self.properties } - pub fn set_minifying_filter(&self, filtering: Filtering) + pub fn dimensions(&self) -> &Vec2<u32> { - self.inner.bind(|texture_curr_bound| { - InnerTexture::set_minifying_filter(texture_curr_bound, filtering); - }); + &self.dimensions } - pub(crate) fn inner(&self) -> &InnerTexture + pub fn pixel_data_format(&self) -> PixelDataFormat { - &self.inner + self.pixel_data_format } -} -impl Clone for Texture -{ - fn clone(&self) -> Self + pub fn image(&self) -> &DynamicImage { - let inner = self.inner.copy( - &self.dimensions, - self.pixel_data_format, - &Vec2::ZERO, - &Vec2::ZERO, - ); - - Self { - inner, - pixel_data_format: self.pixel_data_format, - dimensions: self.dimensions.clone(), - } + &self.image } } @@ -161,6 +114,28 @@ pub enum Error UnsupportedImageDataKind, } +/// Texture properties +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct Properties +{ + pub wrap: Wrapping, + pub magnifying_filter: Filtering, + pub minifying_filter: Filtering, +} + +impl Default for Properties +{ + fn default() -> Self + { + Self { + wrap: Wrapping::Repeat, + magnifying_filter: Filtering::Linear, + minifying_filter: Filtering::Nearest, + } + } +} + /// Texture ID. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id |