tr1/output: store all uvws in a common buffer
Some checks are pending
Run code linters / Run code linters (push) Waiting to run

This commit is contained in:
Marcin Kurczewski 2025-04-06 23:09:52 +02:00
parent 414ada1e3b
commit 31ab38f5e8
No known key found for this signature in database
GPG key ID: CC65E6FD28CAE42A
5 changed files with 120 additions and 97 deletions

View file

@ -421,7 +421,7 @@ void Output_Meshes_RenderObjectMesh(
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture()); glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture());
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetObjectUVWsTexture()); glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetUVWsTexture());
glActiveTexture(GL_TEXTURE2); glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture()); glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture());
glActiveTexture(GL_TEXTURE3); glActiveTexture(GL_TEXTURE3);

View file

@ -311,7 +311,7 @@ void Output_Meshes_RenderRoomMesh(
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture()); glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture());
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetObjectUVWsTexture()); glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetUVWsTexture());
glActiveTexture(GL_TEXTURE2); glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture()); glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture());
glActiveTexture(GL_TEXTURE3); glActiveTexture(GL_TEXTURE3);

View file

@ -71,10 +71,8 @@ static void M_MakeQuad(
for (int32_t k = 0; k < 4; k++) { for (int32_t k = 0; k < 4; k++) {
out_quad[k].pos = (XYZ_F) { .x = pos.x, .y = pos.y, .z = pos.z }; out_quad[k].pos = (XYZ_F) { .x = pos.x, .y = pos.y, .z = pos.z };
} out_quad[k].uvw_idx =
Output_Textures_GetSpritesUVWsBase() + sprite_idx * 4 + k;
for (int32_t k = 0; k < 4; k++) {
out_quad[k].uvw_idx = sprite_idx * 4 + k;
} }
out_quad[0].displacement.x = sprite->x0; out_quad[0].displacement.x = sprite->x0;
@ -194,7 +192,7 @@ static void M_DrawBuffer(
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture()); glBindTexture(GL_TEXTURE_2D_ARRAY, Output_Textures_GetAtlasTexture());
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetSpriteUVWsTexture()); glBindTexture(GL_TEXTURE_BUFFER, Output_Textures_GetUVWsTexture());
glActiveTexture(GL_TEXTURE2); glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture()); glBindTexture(GL_TEXTURE_2D, Output_Textures_GetEnvMapTexture());
GFX_GL_CheckError(); GFX_GL_CheckError();

View file

@ -34,13 +34,6 @@ typedef struct {
M_UVW corners[4]; M_UVW corners[4];
} M_UVW_PACK; } 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 { static struct {
M_ANIMATION_RANGES objects; M_ANIMATION_RANGES objects;
M_ANIMATION_RANGES sprites; M_ANIMATION_RANGES sprites;
@ -49,12 +42,24 @@ static struct {
static struct { static struct {
GLuint tex_atlas; GLuint tex_atlas;
GLuint tex_env_map; 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 { struct {
GLuint tex; GLuint tex;
GLuint tbo; GLuint tbo;
M_ATLAS_SIZE *data; M_ATLAS_SIZE *data;
M_ATLAS_SIZE *data_objects;
M_ATLAS_SIZE *data_sprites;
} atlas_sizes; } atlas_sizes;
} m_Priv = {}; } m_Priv = {};
@ -169,21 +174,9 @@ static void M_PrepareAnimationRanges(void)
M_PrepareSpriteAnimationRanges(); M_PrepareSpriteAnimationRanges();
} }
static void M_FreeTextureData(M_TEXTURE_DATA *const data) static void M_FillAtlasObjectSize(const int32_t i)
{ {
if (data->tbo != 0) { M_ATLAS_SIZE *const size = &m_Priv.atlas_sizes.data_objects[i];
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];
const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(i); const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(i);
size->x0 = texture->uv[0].u; size->x0 = texture->uv[0].u;
size->y0 = texture->uv[0].v; size->y0 = texture->uv[0].v;
@ -201,10 +194,25 @@ static void M_FillAtlasSize(const int32_t i)
size->y1 /= 65535.0; 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) static void M_FillObjectUVW(const int32_t i)
{ {
const OBJECT_TEXTURE *const texture = Output_GetObjectTexture(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++) { for (int32_t j = 0; j < 4; j++) {
corners[j].u = texture->uv[j].u / 65535.0f; corners[j].u = texture->uv[j].u / 65535.0f;
corners[j].v = texture->uv[j].v / 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 v0 = (sprite->offset >> 8) / 256.0f + adj;
const float u1 = u0 + (sprite->width >> 8) / 256.0f - 2 * adj; const float u1 = u0 + (sprite->width >> 8) / 256.0f - 2 * adj;
const float v1 = v0 + (sprite->height >> 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 // clang-format off
corners[0].u = u0; corners[0].v = v0; corners[0].w = sprite->tex_page; 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; 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( GFX_TRACK_DATA(
glBufferData, GL_TEXTURE_BUFFER, data->count * sizeof(M_UVW_PACK), glBufferData, GL_TEXTURE_BUFFER, m_Priv.uvws.count * sizeof(M_UVW_PACK),
data->uvw, GL_DYNAMIC_DRAW); m_Priv.uvws.data, GL_DYNAMIC_DRAW);
GFX_GL_CheckError(); 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) 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++) { for (int32_t i = 0; i < source->range_count; i++) {
const M_ANIMATION_RANGE *const range = &source->ranges[i]; const M_ANIMATION_RANGE *const range = &source->ranges[i];
for (int32_t j = 0; j < range->count; j++) { for (int32_t j = 0; j < range->count; j++) {
M_FillObjectUVW(range->index + j); M_FillObjectUVW(range->index + j);
} }
const M_UVW_PACK *const source =
m_Priv.uvws.data_objects + range->index;
GFX_TRACK_DATA( GFX_TRACK_DATA(
glBufferSubData, GL_TEXTURE_BUFFER, glBufferSubData, GL_TEXTURE_BUFFER,
range->index * sizeof(M_UVW_PACK), (source - m_Priv.uvws.data) * sizeof(M_UVW_PACK),
range->count * sizeof(M_UVW_PACK), range->count * sizeof(M_UVW_PACK), source);
m_Priv.objects.uvw + range->index);
} }
glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tbo); glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.atlas_sizes.tbo);
for (int32_t i = 0; i < source->range_count; i++) { for (int32_t i = 0; i < source->range_count; i++) {
const M_ANIMATION_RANGE *const range = &source->ranges[i]; const M_ANIMATION_RANGE *const range = &source->ranges[i];
for (int32_t j = 0; j < range->count; j++) { 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( GFX_TRACK_DATA(
glBufferSubData, GL_TEXTURE_BUFFER, glBufferSubData, GL_TEXTURE_BUFFER,
range->index * sizeof(M_ATLAS_SIZE), (source - m_Priv.atlas_sizes.data) * sizeof(M_ATLAS_SIZE),
range->count * sizeof(M_ATLAS_SIZE), range->count * sizeof(M_ATLAS_SIZE), source);
m_Priv.atlas_sizes.data + range->index);
} }
} }
static void M_UploadSpriteAnimatedUVWs(const M_ANIMATION_RANGES *const 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++) { for (int32_t i = 0; i < source->range_count; i++) {
const M_ANIMATION_RANGE *const range = &source->ranges[i]; const M_ANIMATION_RANGE *const range = &source->ranges[i];
for (int32_t j = 0; j < range->count; j++) { for (int32_t j = 0; j < range->count; j++) {
M_FillSpriteUVW(range->index + j); M_FillSpriteUVW(range->index + j);
} }
const M_UVW_PACK *const source =
m_Priv.uvws.data_sprites + range->index;
GFX_TRACK_DATA( GFX_TRACK_DATA(
glBufferSubData, GL_TEXTURE_BUFFER, glBufferSubData, GL_TEXTURE_BUFFER,
range->index * sizeof(M_UVW_PACK), (source - m_Priv.uvws.data) * sizeof(M_UVW_PACK),
range->count * sizeof(M_UVW_PACK), range->count * sizeof(M_UVW_PACK), source);
m_Priv.sprites.uvw + range->index); }
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; m_Priv.uvws.count_objects = Output_GetObjectTextureCount();
data->uvw = Memory_Alloc(data->count * sizeof(M_UVW_PACK)); 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); glGenBuffers(1, &m_Priv.uvws.tbo);
glBindBuffer(GL_TEXTURE_BUFFER, data->tbo); glBindBuffer(GL_TEXTURE_BUFFER, m_Priv.uvws.tbo);
GLint limit; GLint limit;
glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &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); glGenTextures(1, &m_Priv.uvws.tex);
glBindTexture(GL_TEXTURE_BUFFER, data->tex); glBindTexture(GL_TEXTURE_BUFFER, m_Priv.uvws.tex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, data->tbo); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, m_Priv.uvws.tbo);
GFX_GL_CheckError(); GFX_GL_CheckError();
} }
static void M_PrepareObjectUVWs(void) static void M_PrepareUVWs(void)
{ {
M_PrepareTextureData(&m_Priv.objects, Output_GetObjectTextureCount()); M_PrepareUVWBuffers();
M_FillObjectUVWs(); M_FillObjectUVWs();
}
static void M_PrepareSpriteUVWs(void)
{
M_PrepareTextureData(&m_Priv.sprites, Output_GetSpriteTextureCount());
M_FillSpriteUVWs(); M_FillSpriteUVWs();
} }
@ -355,11 +369,18 @@ static void M_PrepareAtlasSizes(void)
glGenTextures(1, &m_Priv.atlas_sizes.tex); glGenTextures(1, &m_Priv.atlas_sizes.tex);
glBindTexture(GL_TEXTURE_BUFFER, 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); 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 = m_Priv.atlas_sizes.data =
Memory_Realloc(m_Priv.atlas_sizes.data, count * sizeof(M_ATLAS_SIZE)); Memory_Realloc(m_Priv.atlas_sizes.data, count * sizeof(M_ATLAS_SIZE));
for (int32_t i = 0; i < count; i++) { m_Priv.atlas_sizes.data_objects = m_Priv.atlas_sizes.data;
M_FillAtlasSize(i); 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( GFX_TRACK_DATA(
glBufferData, GL_TEXTURE_BUFFER, count * sizeof(M_ATLAS_SIZE), glBufferData, GL_TEXTURE_BUFFER, count * sizeof(M_ATLAS_SIZE),
@ -407,8 +428,14 @@ static void M_FreeLevelData(void)
{ {
glBindTexture(GL_TEXTURE_BUFFER, 0); glBindTexture(GL_TEXTURE_BUFFER, 0);
glBindBuffer(GL_TEXTURE_BUFFER, 0); glBindBuffer(GL_TEXTURE_BUFFER, 0);
M_FreeTextureData(&m_Priv.objects); if (m_Priv.uvws.tbo != 0) {
M_FreeTextureData(&m_Priv.sprites); 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) { if (m_Priv.tex_atlas != 0) {
glDeleteTextures(1, &m_Priv.tex_atlas); glDeleteTextures(1, &m_Priv.tex_atlas);
m_Priv.tex_atlas = 0; m_Priv.tex_atlas = 0;
@ -444,10 +471,8 @@ void Output_Textures_ObserveLevelLoad(void)
{ {
M_FreeLevelData(); M_FreeLevelData();
M_PrepareAnimationRanges(); M_PrepareAnimationRanges();
M_PrepareObjectUVWs(); M_PrepareUVWs();
M_PrepareSpriteUVWs(); M_UploadUVWs();
M_UploadObjectUVWs();
M_UploadSpriteUVWs();
M_UploadAtlas(); M_UploadAtlas();
} }
@ -475,22 +500,15 @@ void Output_Textures_UpdateEnvironmentMap(void)
void Output_Textures_CycleAnimations(void) void Output_Textures_CycleAnimations(void)
{ {
if (m_Priv.sprites.tex != 0) { if (m_Priv.uvws.tex != 0) {
M_UploadSpriteAnimatedUVWs(&m_AnimationRanges.sprites); M_UploadSpriteAnimatedUVWs(&m_AnimationRanges.sprites);
}
if (m_Priv.objects.tex != 0) {
M_UploadObjectAnimatedUVWs(&m_AnimationRanges.objects); M_UploadObjectAnimatedUVWs(&m_AnimationRanges.objects);
} }
} }
GLuint Output_Textures_GetObjectUVWsTexture(void) GLuint Output_Textures_GetUVWsTexture(void)
{ {
return m_Priv.objects.tex; return m_Priv.uvws.tex;
}
GLuint Output_Textures_GetSpriteUVWsTexture(void)
{
return m_Priv.sprites.tex;
} }
GLuint Output_Textures_GetAtlasTexture(void) GLuint Output_Textures_GetAtlasTexture(void)
@ -508,11 +526,18 @@ GLuint Output_Textures_GetEnvMapTexture(void)
return m_Priv.tex_env_map; 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) void Output_Textures_ApplyRenderSettings(void)
{ {
// re-adjust UVs when the bilinear filter is toggled. // re-adjust UVs when the bilinear filter is toggled.
if (m_Priv.objects.tex != 0) { if (m_Priv.uvws.tex != 0) {
M_FillObjectUVWs(); M_FillObjectUVWs();
M_UploadObjectUVWs(); M_UploadUVWs();
} }
} }

View file

@ -8,8 +8,8 @@ void Output_Textures_ObserveLevelLoad(void);
void Output_Textures_UpdateEnvironmentMap(void); void Output_Textures_UpdateEnvironmentMap(void);
void Output_Textures_CycleAnimations(void); void Output_Textures_CycleAnimations(void);
void Output_Textures_ApplyRenderSettings(void); void Output_Textures_ApplyRenderSettings(void);
GLuint Output_Textures_GetObjectUVWsTexture(void); GLuint Output_Textures_GetUVWsTexture(void);
GLuint Output_Textures_GetSpriteUVWsTexture(void);
GLuint Output_Textures_GetAtlasTexture(void); GLuint Output_Textures_GetAtlasTexture(void);
GLuint Output_Textures_GetAtlasSizesTexture(void); GLuint Output_Textures_GetAtlasSizesTexture(void);
GLuint Output_Textures_GetEnvMapTexture(void); GLuint Output_Textures_GetEnvMapTexture(void);
int32_t Output_Textures_GetSpritesUVWsBase(void);