summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-03-01 19:34:09 +0100
committerHampusM <hampus@hampusmat.com>2024-03-01 19:34:09 +0100
commit697e29e5ad4a09110180736294b8a1330a13eb6e (patch)
tree520fac535b0f63bf6efea88a5264c1aca29c90c9 /engine
parent2db4158d0eaa05b9a7cc7b2e18567cdb38e45a20 (diff)
refactor(engine): create texture OpenGL objects when needed
Diffstat (limited to 'engine')
-rw-r--r--engine/src/opengl/texture.rs79
-rw-r--r--engine/src/renderer/mod.rs36
-rw-r--r--engine/src/texture.rs119
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