From 31ab38f5e8162807e6285b51cb43abfa9e51a152 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sun, 6 Apr 2025 23:09:52 +0200 Subject: [PATCH] tr1/output: store all uvws in a common buffer --- src/tr1/game/output/meshes/objects.c | 2 +- src/tr1/game/output/meshes/rooms.c | 2 +- src/tr1/game/output/sprites.c | 8 +- src/tr1/game/output/textures.c | 201 +++++++++++++++------------ src/tr1/game/output/textures.h | 4 +- 5 files changed, 120 insertions(+), 97 deletions(-) diff --git a/src/tr1/game/output/meshes/objects.c b/src/tr1/game/output/meshes/objects.c index 44fd13209..21d346519 100644 --- a/src/tr1/game/output/meshes/objects.c +++ b/src/tr1/game/output/meshes/objects.c @@ -421,7 +421,7 @@ void Output_Meshes_RenderObjectMesh( glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetObjectUVWsTexture()); + glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetUVWsTexture()); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture()); glActiveTexture(GL_TEXTURE3); diff --git a/src/tr1/game/output/meshes/rooms.c b/src/tr1/game/output/meshes/rooms.c index 21ddac690..ca36330dc 100644 --- a/src/tr1/game/output/meshes/rooms.c +++ b/src/tr1/game/output/meshes/rooms.c @@ -311,7 +311,7 @@ void Output_Meshes_RenderRoomMesh( glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetObjectUVWsTexture()); + glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetUVWsTexture()); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture()); glActiveTexture(GL_TEXTURE3); diff --git a/src/tr1/game/output/sprites.c b/src/tr1/game/output/sprites.c index 722fa44e2..dfd4924ea 100644 --- a/src/tr1/game/output/sprites.c +++ b/src/tr1/game/output/sprites.c @@ -71,10 +71,8 @@ static void M_MakeQuad( for (int32_t k = 0; k < 4; k++) { out_quad[k].pos = (XYZ_F) { .x = pos.x, .y = pos.y, .z = pos.z }; - } - - for (int32_t k = 0; k < 4; k++) { - out_quad[k].uvw_idx = sprite_idx * 4 + k; + out_quad[k].uvw_idx = + Output_Textures_GetSpritesUVWsBase() + sprite_idx * 4 + k; } out_quad[0].displacement.x = sprite->x0; @@ -194,7 +192,7 @@ static void M_DrawBuffer( glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetSpriteUVWsTexture()); + glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetUVWsTexture()); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture()); GFX_GL_CheckError(); diff --git a/src/tr1/game/output/textures.c b/src/tr1/game/output/textures.c index 5a00e4a7d..4bfc97e3f 100644 --- a/src/tr1/game/output/textures.c +++ b/src/tr1/game/output/textures.c @@ -34,13 +34,6 @@ typedef struct { M_UVW corners[4]; } M_UVW_PACK; -typedef struct { - GLuint tbo; // buffer to hold UV data - GLuint tex; // texture to hold UV buffer - int32_t count; - M_UVW_PACK *uvw; -} M_TEXTURE_DATA; - static struct { M_ANIMATION_RANGES objects; M_ANIMATION_RANGES sprites; @@ -49,12 +42,24 @@ static struct { static struct { GLuint tex_atlas; GLuint tex_env_map; - M_TEXTURE_DATA objects; - M_TEXTURE_DATA sprites; + + struct { + GLuint tbo; // buffer to hold UV data + GLuint tex; // texture to hold UV buffer + int32_t count; + int32_t count_objects; + int32_t count_sprites; + M_UVW_PACK *data; + M_UVW_PACK *data_objects; + M_UVW_PACK *data_sprites; + } uvws; + struct { GLuint tex; GLuint tbo; M_ATLAS_SIZE *data; + M_ATLAS_SIZE *data_objects; + M_ATLAS_SIZE *data_sprites; } atlas_sizes; } m_Priv = {}; @@ -169,21 +174,9 @@ static void M_PrepareAnimationRanges(void) M_PrepareSpriteAnimationRanges(); } -static void M_FreeTextureData(M_TEXTURE_DATA *const data) +static void M_FillAtlasObjectSize(const int32_t i) { - if (data->tbo != 0) { - glDeleteBuffers(1, &data->tbo); - data->tbo = 0; - } - if (data->tex != 0) { - glDeleteTextures(1, &data->tex); - data->tex = 0; - } -} - -static void M_FillAtlasSize(const int32_t i) -{ - M_ATLAS_SIZE *size = &m_Priv.atlas_sizes.data[i]; + M_ATLAS_SIZE *const size = &m_Priv.atlas_sizes.data_objects[i]; const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(i); size->x0 = texture->uv[0].u; size->y0 = texture->uv[0].v; @@ -201,10 +194,25 @@ static void M_FillAtlasSize(const int32_t i) size->y1 /= 65535.0; } +static void M_FillAtlasSpriteSize(const int32_t i) +{ + M_ATLAS_SIZE *const size = &m_Priv.atlas_sizes.data_sprites[i]; + const SPRITE_TEXTURE *const sprite = Output_GetSpriteTexture(i); + const float adj = 0.1 / 256.0f; + const float u0 = (sprite->offset & 0xFF) / 256.0f + adj; + const float v0 = (sprite->offset >> 8) / 256.0f + adj; + const float u1 = u0 + (sprite->width >> 8) / 256.0f - 2 * adj; + const float v1 = v0 + (sprite->height >> 8) / 256.0f - 2 * adj; + size->x0 = u0; + size->y0 = v0; + size->x1 = u1; + size->y1 = v1; +} + static void M_FillObjectUVW(const int32_t i) { const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(i); - M_UVW *const corners = m_Priv.objects.uvw[i].corners; + M_UVW *const corners = m_Priv.uvws.data_objects[i].corners; for (int32_t j = 0; j < 4; j++) { corners[j].u = texture->uv[j].u / 65535.0f; corners[j].v = texture->uv[j].v / 65535.0f; @@ -220,7 +228,7 @@ static void M_FillSpriteUVW(const int32_t i) const float v0 = (sprite->offset >> 8) / 256.0f + adj; const float u1 = u0 + (sprite->width >> 8) / 256.0f - 2 * adj; const float v1 = v0 + (sprite->height >> 8) / 256.0f - 2 * adj; - M_UVW *const corners = m_Priv.sprites.uvw[i].corners; + M_UVW *const corners = m_Priv.uvws.data_sprites[i].corners; // clang-format off corners[0].u = u0; corners[0].v = v0; corners[0].w = sprite->tex_page; corners[1].u = u1; corners[1].v = v0; corners[1].w = sprite->tex_page; @@ -243,97 +251,103 @@ static void M_FillSpriteUVWs(void) } } -static void M_UploadTextureData(const M_TEXTURE_DATA *const data) +static void M_UploadUVWs(void) { - glBindBuffer(GL_TEXTURE_BUFFER, data->tbo); + glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.uvws.tbo); GFX_TRACK_DATA( - glBufferData, GL_TEXTURE_BUFFER, data->count * sizeof(M_UVW_PACK), - data->uvw, GL_DYNAMIC_DRAW); + glBufferData, GL_TEXTURE_BUFFER, m_Priv.uvws.count * sizeof(M_UVW_PACK), + m_Priv.uvws.data, GL_DYNAMIC_DRAW); GFX_GL_CheckError(); } -static void M_UploadObjectUVWs(void) -{ - M_UploadTextureData(&m_Priv.objects); -} - -static void M_UploadSpriteUVWs(void) -{ - M_UploadTextureData(&m_Priv.sprites); -} - static void M_UploadObjectAnimatedUVWs(const M_ANIMATION_RANGES *const source) { - glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.objects.tbo); + glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.uvws.tbo); for (int32_t i = 0; i < source->range_count; i++) { const M_ANIMATION_RANGE *const range = &source->ranges[i]; for (int32_t j = 0; j < range->count; j++) { M_FillObjectUVW(range->index + j); } + const M_UVW_PACK *const source = + m_Priv.uvws.data_objects + range->index; GFX_TRACK_DATA( glBufferSubData, GL_TEXTURE_BUFFER, - range->index * sizeof(M_UVW_PACK), - range->count * sizeof(M_UVW_PACK), - m_Priv.objects.uvw + range->index); + (source - m_Priv.uvws.data) * sizeof(M_UVW_PACK), + range->count * sizeof(M_UVW_PACK), source); } glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tbo); for (int32_t i = 0; i < source->range_count; i++) { const M_ANIMATION_RANGE *const range = &source->ranges[i]; for (int32_t j = 0; j < range->count; j++) { - M_FillAtlasSize(range->index + j); + M_FillAtlasObjectSize(range->index + j); } + const M_ATLAS_SIZE *const source = + m_Priv.atlas_sizes.data_objects + range->index; GFX_TRACK_DATA( glBufferSubData, GL_TEXTURE_BUFFER, - range->index * sizeof(M_ATLAS_SIZE), - range->count * sizeof(M_ATLAS_SIZE), - m_Priv.atlas_sizes.data + range->index); + (source - m_Priv.atlas_sizes.data) * sizeof(M_ATLAS_SIZE), + range->count * sizeof(M_ATLAS_SIZE), source); } } static void M_UploadSpriteAnimatedUVWs(const M_ANIMATION_RANGES *const source) { - glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.sprites.tbo); + glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.uvws.tbo); for (int32_t i = 0; i < source->range_count; i++) { const M_ANIMATION_RANGE *const range = &source->ranges[i]; for (int32_t j = 0; j < range->count; j++) { M_FillSpriteUVW(range->index + j); } + const M_UVW_PACK *const source = + m_Priv.uvws.data_sprites + range->index; GFX_TRACK_DATA( glBufferSubData, GL_TEXTURE_BUFFER, - range->index * sizeof(M_UVW_PACK), - range->count * sizeof(M_UVW_PACK), - m_Priv.sprites.uvw + range->index); + (source - m_Priv.uvws.data) * sizeof(M_UVW_PACK), + range->count * sizeof(M_UVW_PACK), source); + } + + glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tbo); + for (int32_t i = 0; i < source->range_count; i++) { + const M_ANIMATION_RANGE *const range = &source->ranges[i]; + for (int32_t j = 0; j < range->count; j++) { + M_FillAtlasSpriteSize(range->index + j); + } + const M_ATLAS_SIZE *const source = + m_Priv.atlas_sizes.data_sprites + range->index; + GFX_TRACK_DATA( + glBufferSubData, GL_TEXTURE_BUFFER, + (source - m_Priv.atlas_sizes.data) * sizeof(M_ATLAS_SIZE), + range->count * sizeof(M_ATLAS_SIZE), source); } } -static void M_PrepareTextureData(M_TEXTURE_DATA *const data, const size_t count) +static void M_PrepareUVWBuffers(void) { - data->count = count; - data->uvw = Memory_Alloc(data->count * sizeof(M_UVW_PACK)); + m_Priv.uvws.count_objects = Output_GetObjectTextureCount(); + m_Priv.uvws.count_sprites = Output_GetSpriteTextureCount(); + m_Priv.uvws.count = m_Priv.uvws.count_objects + m_Priv.uvws.count_sprites; + m_Priv.uvws.data = Memory_Alloc(m_Priv.uvws.count * sizeof(M_UVW_PACK)); + m_Priv.uvws.data_objects = m_Priv.uvws.data; + m_Priv.uvws.data_sprites = m_Priv.uvws.data + m_Priv.uvws.count_objects; - glGenBuffers(1, &data->tbo); - glBindBuffer(GL_TEXTURE_BUFFER, data->tbo); + glGenBuffers(1, &m_Priv.uvws.tbo); + glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.uvws.tbo); GLint limit; glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &limit); - ASSERT(data->count * sizeof(M_UVW_PACK) <= (size_t)limit); + ASSERT(m_Priv.uvws.count * sizeof(M_UVW_PACK) <= (size_t)limit); - glGenTextures(1, &data->tex); - glBindTexture(GL_TEXTURE_BUFFER, data->tex); - glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, data->tbo); + glGenTextures(1, &m_Priv.uvws.tex); + glBindTexture(GL_TEXTURE_BUFFER, m_Priv.uvws.tex); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, m_Priv.uvws.tbo); GFX_GL_CheckError(); } -static void M_PrepareObjectUVWs(void) +static void M_PrepareUVWs(void) { - M_PrepareTextureData(&m_Priv.objects, Output_GetObjectTextureCount()); + M_PrepareUVWBuffers(); M_FillObjectUVWs(); -} - -static void M_PrepareSpriteUVWs(void) -{ - M_PrepareTextureData(&m_Priv.sprites, Output_GetSpriteTextureCount()); M_FillSpriteUVWs(); } @@ -355,11 +369,18 @@ static void M_PrepareAtlasSizes(void) glGenTextures(1, &m_Priv.atlas_sizes.tex); glBindTexture(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tex); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_Priv.atlas_sizes.tbo); - const int32_t count = Output_GetObjectTextureCount(); + const int32_t count_objects = Output_GetObjectTextureCount(); + const int32_t count_sprites = Output_GetSpriteTextureCount(); + const int32_t count = count_objects + count_sprites; m_Priv.atlas_sizes.data = Memory_Realloc(m_Priv.atlas_sizes.data, count * sizeof(M_ATLAS_SIZE)); - for (int32_t i = 0; i < count; i++) { - M_FillAtlasSize(i); + m_Priv.atlas_sizes.data_objects = m_Priv.atlas_sizes.data; + m_Priv.atlas_sizes.data_sprites = m_Priv.atlas_sizes.data + count_objects; + for (int32_t i = 0; i < count_objects; i++) { + M_FillAtlasObjectSize(i); + } + for (int32_t i = 0; i < count_sprites; i++) { + M_FillAtlasSpriteSize(i); } GFX_TRACK_DATA( glBufferData, GL_TEXTURE_BUFFER, count * sizeof(M_ATLAS_SIZE), @@ -407,8 +428,14 @@ static void M_FreeLevelData(void) { glBindTexture(GL_TEXTURE_BUFFER, 0); glBindBuffer(GL_TEXTURE_BUFFER, 0); - M_FreeTextureData(&m_Priv.objects); - M_FreeTextureData(&m_Priv.sprites); + if (m_Priv.uvws.tbo != 0) { + glDeleteBuffers(1, &m_Priv.uvws.tbo); + m_Priv.uvws.tbo = 0; + } + if (m_Priv.uvws.tex != 0) { + glDeleteTextures(1, &m_Priv.uvws.tex); + m_Priv.uvws.tex = 0; + } if (m_Priv.tex_atlas != 0) { glDeleteTextures(1, &m_Priv.tex_atlas); m_Priv.tex_atlas = 0; @@ -444,10 +471,8 @@ void Output_Textures_ObserveLevelLoad(void) { M_FreeLevelData(); M_PrepareAnimationRanges(); - M_PrepareObjectUVWs(); - M_PrepareSpriteUVWs(); - M_UploadObjectUVWs(); - M_UploadSpriteUVWs(); + M_PrepareUVWs(); + M_UploadUVWs(); M_UploadAtlas(); } @@ -475,22 +500,15 @@ void Output_Textures_UpdateEnvironmentMap(void) void Output_Textures_CycleAnimations(void) { - if (m_Priv.sprites.tex != 0) { + if (m_Priv.uvws.tex != 0) { M_UploadSpriteAnimatedUVWs(&m_AnimationRanges.sprites); - } - if (m_Priv.objects.tex != 0) { M_UploadObjectAnimatedUVWs(&m_AnimationRanges.objects); } } -GLuint Output_Textures_GetObjectUVWsTexture(void) +GLuint Output_Textures_GetUVWsTexture(void) { - return m_Priv.objects.tex; -} - -GLuint Output_Textures_GetSpriteUVWsTexture(void) -{ - return m_Priv.sprites.tex; + return m_Priv.uvws.tex; } GLuint Output_Textures_GetAtlasTexture(void) @@ -508,11 +526,18 @@ GLuint Output_Textures_GetEnvMapTexture(void) return m_Priv.tex_env_map; } +int32_t Output_Textures_GetSpritesUVWsBase(void) +{ + const size_t num = sizeof(M_UVW_PACK) / sizeof(M_UVW); + ASSERT(num == 4); + return m_Priv.uvws.count_objects * num; +} + void Output_Textures_ApplyRenderSettings(void) { // re-adjust UVs when the bilinear filter is toggled. - if (m_Priv.objects.tex != 0) { + if (m_Priv.uvws.tex != 0) { M_FillObjectUVWs(); - M_UploadObjectUVWs(); + M_UploadUVWs(); } } diff --git a/src/tr1/game/output/textures.h b/src/tr1/game/output/textures.h index c4cfa128e..8a11c5745 100644 --- a/src/tr1/game/output/textures.h +++ b/src/tr1/game/output/textures.h @@ -8,8 +8,8 @@ void Output_Textures_ObserveLevelLoad(void); void Output_Textures_UpdateEnvironmentMap(void); void Output_Textures_CycleAnimations(void); void Output_Textures_ApplyRenderSettings(void); -GLuint Output_Textures_GetObjectUVWsTexture(void); -GLuint Output_Textures_GetSpriteUVWsTexture(void); +GLuint Output_Textures_GetUVWsTexture(void); GLuint Output_Textures_GetAtlasTexture(void); GLuint Output_Textures_GetAtlasSizesTexture(void); GLuint Output_Textures_GetEnvMapTexture(void); +int32_t Output_Textures_GetSpritesUVWsBase(void);