From 97ffb9cd1b9bdf8f7691c1ed9751bf2b93a3d966 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Wed, 21 Jun 2023 08:57:30 -0700 Subject: Add ability to update texture contents. --- gfx/include/gfx/render_backend.h | 35 +++++++++++++------- gfx/src/render/texture.c | 69 +++++++++++++++++++++++++--------------- gfx/src/render/texture.h | 4 +++ gfx/src/util/texture.c | 4 +-- 4 files changed, 73 insertions(+), 39 deletions(-) diff --git a/gfx/include/gfx/render_backend.h b/gfx/include/gfx/render_backend.h index b07cf16..722ea5e 100644 --- a/gfx/include/gfx/render_backend.h +++ b/gfx/include/gfx/render_backend.h @@ -213,8 +213,10 @@ typedef struct ShaderUniform { } value; } ShaderUniform; +/// Texture dimension. typedef enum { Texture2D, TextureCubeMap } TextureDimension; +/// Texture data format. typedef enum { TextureDepth, TextureRG16, @@ -226,10 +228,13 @@ typedef enum { TextureSRGBA8 } TextureFormat; +/// Texture filtering. typedef enum { NearestFiltering, LinearFiltering } TextureFiltering; +/// Texture wrap mode. typedef enum { Repeat, ClampToEdge } TextureWrapping; +/// Cubemap faces. typedef enum { CubemapFacePosX, CubemapFaceNegX, @@ -239,16 +244,8 @@ typedef enum { CubemapFaceNegZ } CubemapFace; -/// Describes a texture. -typedef struct TextureDesc { - int width; - int height; - int depth; // Not used until 3D textures are exposed. - TextureDimension dimension; - TextureFormat format; - TextureFiltering filtering; - TextureWrapping wrap; - bool mipmaps; +/// Texture data descriptor. +typedef struct TextureDataDesc { union { const void* pixels; struct { @@ -260,6 +257,19 @@ typedef struct TextureDesc { const void* pixels_neg_z; } cubemap; }; +} TextureDataDesc; + +/// Describes a texture. +typedef struct TextureDesc { + int width; + int height; + int depth; // Not used until 3D textures are exposed. + TextureDimension dimension; + TextureFormat format; + TextureFiltering filtering; + TextureWrapping wrap; + bool mipmaps; + TextureDataDesc data; } TextureDesc; /// Describes a renderbuffer. @@ -339,7 +349,7 @@ Buffer* gfx_make_buffer(RenderBackend*, const BufferDesc*); void gfx_destroy_buffer(RenderBackend*, Buffer**); /// Update the buffer's data. -void gfx_update_buffer(RenderBackend*, Buffer*, const BufferDataDesc*); +void gfx_update_buffer(Buffer*, const BufferDataDesc*); // ----------------------------------------------------------------------------- // Geometry. @@ -385,6 +395,9 @@ Texture* gfx_make_texture(RenderBackend*, const TextureDesc*); /// Destroy the texture. void gfx_destroy_texture(RenderBackend*, Texture**); +/// Update the texture. +void gfx_update_texture(Texture*, const TextureDataDesc*); + // ----------------------------------------------------------------------------- // Renderbuffers. // ----------------------------------------------------------------------------- diff --git a/gfx/src/render/texture.c b/gfx/src/render/texture.c index 312aecc..489f7a2 100644 --- a/gfx/src/render/texture.c +++ b/gfx/src/render/texture.c @@ -37,32 +37,14 @@ bool gfx_init_texture(Texture* texture, const TextureDesc* desc) { return false; } - // glTexSubImageXD - const GLenum format = to_GL_format(desc->format); - const GLenum type = to_GL_type(desc->format); - switch (texture->target) { - case GL_TEXTURE_2D: - if (desc->pixels) { - glTexSubImage2D( - GL_TEXTURE_2D, /*level=*/0, /*xoffset=*/0, - /*yoffset=*/0, desc->width, desc->height, format, type, desc->pixels); - } - break; - case GL_TEXTURE_CUBE_MAP: - for (int i = 0; i < 6; ++i) { - const void* pixels = *(&desc->cubemap.pixels_pos_x + i); - if (pixels) { - glTexSubImage2D( - GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, /*level=*/0, /*xoffset=*/0, - /*yoffset=*/0, desc->width, desc->height, format, type, pixels); - } - } - break; - default: - assert(false && "Unhandled texture dimension"); - gfx_del_texture(texture); - return false; - } + texture->format = to_GL_format(desc->format); + texture->type = to_GL_type(desc->format); + texture->width = desc->width; + texture->height = desc->height; + gfx_update_texture(texture, &desc->data); + + // gfx_update_texture() unbinds the texture at the end, so re-bind it here. + glBindTexture(texture->target, texture->id); // Mipmaps. if (desc->mipmaps) { @@ -103,6 +85,41 @@ void gfx_del_texture(Texture* texture) { } } +void gfx_update_texture(Texture* texture, const TextureDataDesc* desc) { + assert(texture); + assert(desc); + + glBindTexture(texture->target, texture->id); + + // glTexSubImageXD + switch (texture->target) { + case GL_TEXTURE_2D: + if (desc->pixels) { + glTexSubImage2D( + GL_TEXTURE_2D, /*level=*/0, /*xoffset=*/0, + /*yoffset=*/0, texture->width, texture->height, texture->format, + texture->type, desc->pixels); + } + break; + case GL_TEXTURE_CUBE_MAP: + for (int i = 0; i < 6; ++i) { + const void* pixels = *(&desc->cubemap.pixels_pos_x + i); + if (pixels) { + glTexSubImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, /*level=*/0, /*xoffset=*/0, + /*yoffset=*/0, texture->width, texture->height, texture->format, + texture->type, pixels); + } + } + break; + default: + assert(false && "Unhandled texture dimension"); + break; + } + + glBindTexture(texture->target, 0); +} + GLenum to_GL_dimension(TextureDimension dim) { switch (dim) { case Texture2D: diff --git a/gfx/src/render/texture.h b/gfx/src/render/texture.h index b4e4bed..f667752 100644 --- a/gfx/src/render/texture.h +++ b/gfx/src/render/texture.h @@ -7,6 +7,10 @@ typedef struct Texture { GLuint id; GLenum target; + GLenum format; + GLenum type; + int width; + int height; } Texture; /// Create a new texture. diff --git a/gfx/src/util/texture.c b/gfx/src/util/texture.c index 7ec0e40..23f15f0 100644 --- a/gfx/src/util/texture.c +++ b/gfx/src/util/texture.c @@ -159,11 +159,11 @@ Texture* gfx_load_texture( switch (cmd->type) { case LoadTexture: - desc.pixels = pixels[0]; + desc.data.pixels = pixels[0]; break; case LoadCubemap: for (int i = 0; i < 6; ++i) { - *(&desc.cubemap.pixels_pos_x + i) = pixels[i]; + *(&desc.data.cubemap.pixels_pos_x + i) = pixels[i]; } break; } -- cgit v1.2.3