summaryrefslogtreecommitdiff
path: root/engine/src/rendering
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-07-14 14:55:03 +0200
committerHampusM <hampus@hampusmat.com>2026-07-14 14:55:03 +0200
commitd3e678fa6112ac82b59e638c41cde8b9c4b0035e (patch)
tree551563fc84d1f7f203f238ea167b3de5e0624c85 /engine/src/rendering
parent908ae3fcaa119f8fcac1aacbf43bac649c75eac6 (diff)
feat(engine): add UpdateTexture rendering command
Diffstat (limited to 'engine/src/rendering')
-rw-r--r--engine/src/rendering/backend/opengl.rs144
-rw-r--r--engine/src/rendering/object.rs2
2 files changed, 110 insertions, 36 deletions
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
{