diff options
Diffstat (limited to 'engine/src')
| -rw-r--r-- | engine/src/rendering.rs | 6 | ||||
| -rw-r--r-- | engine/src/rendering/backend/opengl.rs | 144 | ||||
| -rw-r--r-- | engine/src/rendering/object.rs | 2 |
3 files changed, 116 insertions, 36 deletions
diff --git a/engine/src/rendering.rs b/engine/src/rendering.rs index 8ce48fc..9a6350e 100644 --- a/engine/src/rendering.rs +++ b/engine/src/rendering.rs @@ -238,6 +238,12 @@ pub enum Command ActivateShader(ObjectId), SetShaderBinding(ShaderBindingLocation, ShaderBindingValue), CreateTexture(ObjectId, AssetOrValue<Texture>), + UpdateTexture + { + obj_id: ObjectId, + texture: AssetOrValue<Texture>, + offset: Vec2<u32>, + }, RemoveTexture(ObjectId), CreateMesh { diff --git a/engine/src/rendering/backend/opengl.rs b/engine/src/rendering/backend/opengl.rs index 821d039..0fbfb37 100644 --- a/engine/src/rendering/backend/opengl.rs +++ b/engine/src/rendering/backend/opengl.rs @@ -5,6 +5,7 @@ use std::collections::HashMap; use std::num::NonZero; use ecs::query::term::With; +use ecs::util::BorrowedOrOwned; use glutin::config::Config as GlutinConfig; use glutin::display::GetGlDisplay; use glutin::error::Error as GlutinError; @@ -48,7 +49,7 @@ use opengl_bindings::shader::{ }; use opengl_bindings::texture::{ ColorSpace as GlTextureColorSpace, - Error as GlTextureGenerateError, + Error as GlTextureError, Filtering as GlTextureFiltering, PixelDataFormat as GlTexturePixelDataFormat, Texture as GlTexture, @@ -708,6 +709,18 @@ fn handle_commands( tracing::error!("Failed to create texture object: {err}"); } } + Command::UpdateTexture { obj_id, texture, offset } => { + if let Err(err) = update_texture_object( + gl_context, + object_store, + assets, + obj_id, + texture, + offset, + ) { + tracing::error!("Failed to update texture object: {err}"); + } + } Command::RemoveTexture(texture_object_id) => { let Some(texture_object) = object_store.remove(&texture_object_id).flatten() @@ -1077,31 +1090,19 @@ enum CreateGlContextError MakeContextCurrent(#[source] GlMakeContextCurrentError), } -#[tracing::instrument(skip_all)] -fn create_texture_object( - curr_gl_ctx: &MaybeCurrentContextWithFns, - object_store: &mut ObjectStore, - assets: &Assets, - texture_object_id: ObjectId, - texture: AssetOrValue<Texture>, -) -> Result<(), GlTextureGenerateError> +fn retrieve_texture<'a>( + assets: &'a Assets, + texture: &'a AssetOrValue<Texture>, +) -> Option<(BorrowedOrOwned<'a, Image>, &'a TextureProperties)> { - if object_store.contains_non_pending_with_id(&texture_object_id) { - tracing::error!( - texture_object_id=?texture_object_id, - "Object store already contains object with this ID" - ); - return Ok(()); - } - - let texture = match &texture { + let Texture { image, properties } = match &texture { AssetOrValue::Asset(texture_asset) => { let Some(texture) = assets.get(&texture_asset) else { tracing::error!( texture_asset_id=?texture_asset.id(), "Texture asset does not exist" ); - return Ok(()); + return None; }; texture @@ -1109,8 +1110,8 @@ fn create_texture_object( AssetOrValue::Value(texture) => texture, }; - let texture_image = match texture.image.color_type() { - ImageColorType::Rgb8 if (texture.image.dimensions().width * 3) % 4 != 0 => { + let texture_image = match image.color_type() { + ImageColorType::Rgb8 if (image.dimensions().width * 3) % 4 != 0 => { // The texture will be corrupted if the alignment of each horizontal line of // the texture pixel array is not multiple of 4. // @@ -1127,15 +1128,40 @@ fn create_texture_object( "texture image's pixel format to RGBA8" )); - &texture.image.to_rgba8() + BorrowedOrOwned::Owned(image.to_rgba8()) } - _ => &texture.image, + _ => BorrowedOrOwned::Borrowned(image), + }; + + Some((texture_image, properties)) +} + +#[tracing::instrument(skip_all)] +fn create_texture_object( + curr_gl_ctx: &MaybeCurrentContextWithFns, + object_store: &mut ObjectStore, + assets: &Assets, + texture_object_id: ObjectId, + texture: AssetOrValue<Texture>, +) -> Result<(), GlTextureError> +{ + if object_store.contains_non_pending_with_id(&texture_object_id) { + tracing::error!( + texture_object_id=?texture_object_id, + "Object store already contains object with this ID" + ); + return Ok(()); + } + + let Some((texture_image, texture_properties)) = retrieve_texture(assets, &texture) + else { + return Ok(()); }; object_store.insert( texture_object_id, Object::from_raw( - create_gl_texture(curr_gl_ctx, texture_image, &texture.properties)? + create_gl_texture(curr_gl_ctx, &*texture_image, texture_properties)? .into_raw(), ObjectKind::Texture, ), @@ -1144,6 +1170,52 @@ fn create_texture_object( Ok(()) } +#[tracing::instrument(skip_all)] +fn update_texture_object( + curr_gl_ctx: &MaybeCurrentContextWithFns, + object_store: &mut ObjectStore, + assets: &Assets, + texture_object_id: ObjectId, + texture: AssetOrValue<Texture>, + offset: Vec2<u32>, +) -> Result<(), GlTextureError> +{ + let Some((texture_image, _)) = retrieve_texture(assets, &texture) else { + return Ok(()); + }; + + let Some(texture_obj) = object_store.get_obj(&texture_object_id) else { + tracing::error!( + texture_object_id=?texture_object_id, + "Object store does not contain a object with this ID" + ); + return Ok(()); + }; + + if texture_obj.kind() != ObjectKind::Texture { + tracing::error!( + texture_object_id=?texture_object_id, + "Object with this ID is not a texture" + ); + return Ok(()); + } + + let gl_texture = GlTexture::from_raw(texture_obj.as_raw()); + + gl_texture.store_image( + curr_gl_ctx, + 0, + offset.into(), + texture_image.dimensions().into(), + get_image_pixel_data_format(&*texture_image), + texture_image.as_bytes(), + )?; + + gl_texture.generate_mipmap(curr_gl_ctx); + + Ok(()) +} + fn draw_mesh( current_context: &MaybeCurrentContextWithFns, graphics_mesh: &GraphicsMesh, @@ -1174,23 +1246,25 @@ fn draw_mesh( Ok(()) } +fn get_image_pixel_data_format(image: &Image) -> GlTexturePixelDataFormat +{ + match image.color_type() { + ImageColorType::Rgb8 => GlTexturePixelDataFormat::Rgb8, + ImageColorType::Rgba8 => GlTexturePixelDataFormat::Rgba8, + _ => { + unimplemented!(); + } + } +} + fn create_gl_texture( curr_gl_context: &MaybeCurrentContextWithFns, image: &Image, texture_properties: &TextureProperties, -) -> Result<GlTexture, GlTextureGenerateError> +) -> Result<GlTexture, GlTextureError> { let gl_texture = GlTexture::builder() - .image( - image.as_bytes(), - match image.color_type() { - ImageColorType::Rgb8 => GlTexturePixelDataFormat::Rgb8, - ImageColorType::Rgba8 => GlTexturePixelDataFormat::Rgba8, - _ => { - unimplemented!(); - } - }, - ) + .image(image.as_bytes(), get_image_pixel_data_format(image)) .size(image.dimensions().into()) .color_space(if image.color_space_is_srgb() { GlTextureColorSpace::Srgb diff --git a/engine/src/rendering/object.rs b/engine/src/rendering/object.rs index 3fcb461..8d8e634 100644 --- a/engine/src/rendering/object.rs +++ b/engine/src/rendering/object.rs @@ -134,7 +134,7 @@ impl Object } /// Rendering object kind. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] pub enum Kind { |
