From 40b2e93be7ec24a597017e04b117a58162840016 Mon Sep 17 00:00:00 2001 From: ManDude <7569514+ManDude@users.noreply.github.com> Date: Sat, 6 May 2023 02:08:33 +0100 Subject: [PATCH] pack tfrag normals into 10 bits (#2625) Saves 16 bits and lets us align the `color_index` field properly. This shouldn't improve or decrease performance by any noticeable amount except maybe in really low end systems. --- common/custom_data/TFrag3Data.cpp | 30 ++++++++++--------- common/custom_data/Tfrag3Data.h | 11 +++---- .../opengl_renderer/background/Tfrag3.cpp | 2 +- .../opengl_renderer/background/Tie3.cpp | 8 ++--- game/overlord/jak2/stream.cpp | 4 +-- game/overlord/jak2/vag.cpp | 2 +- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/common/custom_data/TFrag3Data.cpp b/common/custom_data/TFrag3Data.cpp index 14699f5a1c..b827125637 100644 --- a/common/custom_data/TFrag3Data.cpp +++ b/common/custom_data/TFrag3Data.cpp @@ -173,23 +173,30 @@ std::array tie_normal_transform_v2(const std::array= -512 && nx <= 511); + ASSERT(ny >= -512 && ny <= 511); + ASSERT(nz >= -512 && nz <= 511); + return (nx & 0x3ff) | ((ny & 0x3ff) << 10) | ((nz & 0x3ff) << 20); +} + /*! * Unpack tie normal by transforming and converting to s16 for OpenGL. */ -math::Vector unpack_tie_normal(const std::array& mat, - s8 nx, - s8 ny, - s8 nz) { +u32 unpack_tie_normal(const std::array& mat, s8 nx, s8 ny, s8 nz) { // rotate the normal math::Vector3f nrm = math::Vector3f::zero(); nrm += mat[0] * nx; nrm += mat[1] * ny; nrm += mat[2] * nz; // convert to s16 for OpenGL renderer - nrm *= 0.0078125; // number from EE asm - nrm *= 256.f * 128.f; // for normalize s16 -> float conversion by OpenGL. + // nrm /= 0x100; // number from EE asm + // nrm *= 0x200; // for normalized s10 -> float conversion by OpenGL. + nrm *= 2; // for normalized s10 -> float conversion by OpenGL. - return nrm.cast(); + auto as_int = nrm.cast(); + + return pack_to_gl_normal(as_int.x(), as_int.y(), as_int.z()); } void TieTree::unpack() { @@ -206,9 +213,7 @@ void TieTree::unpack() { vtx.z = proto_vtx.z; vtx.s = proto_vtx.s; vtx.t = proto_vtx.t; - vtx.nx = proto_vtx.nx << 8; - vtx.ny = proto_vtx.ny << 8; - vtx.nz = proto_vtx.nz << 8; + vtx.nor = pack_to_gl_normal(proto_vtx.nx << 1, proto_vtx.ny << 1, proto_vtx.nz << 1); vtx.r = proto_vtx.r; vtx.g = proto_vtx.g; vtx.b = proto_vtx.b; @@ -229,10 +234,7 @@ void TieTree::unpack() { vtx.z = temp.z(); vtx.s = proto_vtx.s; vtx.t = proto_vtx.t; - auto nrm = unpack_tie_normal(nmat, proto_vtx.nx, proto_vtx.ny, proto_vtx.nz); - vtx.nx = nrm.x(); - vtx.ny = nrm.y(); - vtx.nz = nrm.z(); + vtx.nor = unpack_tie_normal(nmat, proto_vtx.nx, proto_vtx.ny, proto_vtx.nz); vtx.r = proto_vtx.r; vtx.g = proto_vtx.g; vtx.b = proto_vtx.b; diff --git a/common/custom_data/Tfrag3Data.h b/common/custom_data/Tfrag3Data.h index dca141ad36..5e45a59856 100644 --- a/common/custom_data/Tfrag3Data.h +++ b/common/custom_data/Tfrag3Data.h @@ -73,23 +73,24 @@ struct MemoryUsageTracker { void add(MemoryUsageCategory category, u32 size_bytes) { data[category] += size_bytes; } }; -constexpr int TFRAG3_VERSION = 34; +constexpr int TFRAG3_VERSION = 35; // These vertices should be uploaded to the GPU at load time and don't change struct PreloadedVertex { // the vertex position float x = 0, y = 0, z = 0; + // envmap tint color, not used in == or hash. + u8 r = 0, g = 0, b = 0, a = 0; // texture coordinates float s = 0, t = 0; - u8 r = 0, g = 0, b = 0, a = 0; // envmap tint color, not used in == or hash. + // not used in == or hash!! + // note that this is a 10-bit 3-element field packed into 32-bits. + u32 nor = 0; // color table index u16 color_index = 0; - // not used in == or hash!! - s16 nx = 0, ny = 0, nz = 0; - struct hash { std::size_t operator()(const PreloadedVertex& x) const; }; diff --git a/game/graphics/opengl_renderer/background/Tfrag3.cpp b/game/graphics/opengl_renderer/background/Tfrag3.cpp index dd46cd0594..fcafd3cb9c 100644 --- a/game/graphics/opengl_renderer/background/Tfrag3.cpp +++ b/game/graphics/opengl_renderer/background/Tfrag3.cpp @@ -111,7 +111,7 @@ void Tfrag3::update_load(const std::vector& tree_kind ); glVertexAttribIPointer(2, // location 2 in the shader - 1, // 1 values per vert + 2, // 1 values per vert GL_UNSIGNED_SHORT, // u16 sizeof(tfrag3::PreloadedVertex), // stride (void*)offsetof(tfrag3::PreloadedVertex, color_index) // offset (0) diff --git a/game/graphics/opengl_renderer/background/Tie3.cpp b/game/graphics/opengl_renderer/background/Tie3.cpp index aa3ece5f36..98a8b13cca 100644 --- a/game/graphics/opengl_renderer/background/Tie3.cpp +++ b/game/graphics/opengl_renderer/background/Tie3.cpp @@ -136,18 +136,18 @@ void Tie3::load_from_fr3_data(const LevelData* loader_data) { ); glVertexAttribIPointer(2, // location 2 in the shader - 1, // 1 values per vert + 2, // 1 values per vert GL_UNSIGNED_SHORT, // u16 sizeof(tfrag3::PreloadedVertex), // stride (void*)offsetof(tfrag3::PreloadedVertex, color_index) // offset (0) ); glVertexAttribPointer(3, // location 1 in the shader - 3, // 3 values per vert - GL_SHORT, // floats + 4, // 3 values per vert + GL_INT_2_10_10_10_REV, // floats GL_TRUE, // normalized sizeof(tfrag3::PreloadedVertex), // stride - (void*)offsetof(tfrag3::PreloadedVertex, nx) // offset (0) + (void*)offsetof(tfrag3::PreloadedVertex, nor) // offset (0) ); glVertexAttribPointer(4, // location 1 in the shader diff --git a/game/overlord/jak2/stream.cpp b/game/overlord/jak2/stream.cpp index 63ad1b91a6..e36a22068f 100644 --- a/game/overlord/jak2/stream.cpp +++ b/game/overlord/jak2/stream.cpp @@ -251,11 +251,11 @@ void* RPC_PLAY([[maybe_unused]] unsigned int fno, void* _cmd, int size) { list_node.prio = iVar5; pRVar2 = FindThisVagStream(cmd_iter->names[s].chars, cmd_iter->id[s]); if ((pRVar2 == 0x0) || (pRVar2->byte4 == '\0')) { - printf(" didn't exist, looks like it needs to be added!\n"); + // printf(" didn't exist, looks like it needs to be added!\n"); WaitSema(EEPlayList.sema); iVar3 = (VagStrListNode*)FindVagStreamInList(&list_node, &EEPlayList); if (iVar3 == (VagStrListNode*)0x0) { - printf("node also doesn't exist, adding it!\n"); + // printf("node also doesn't exist, adding it!\n"); iVar4 = (VagStrListNode*)InsertVagStreamInList(&list_node, &EEPlayList); iVar4->id = list_node.id; diff --git a/game/overlord/jak2/vag.cpp b/game/overlord/jak2/vag.cpp index d0b3cc739a..9532e55073 100644 --- a/game/overlord/jak2/vag.cpp +++ b/game/overlord/jak2/vag.cpp @@ -377,7 +377,7 @@ void TerminateVAG(VagCmd* cmd, int param_2) { lfo_node.plugin_id = cmd->plugin_id; RemoveLfoStreamFromList(&lfo_node, &LfoList); } - printf("termina removing %s (2)\n", vag_node.name); + // printf("termina removing %s (2)\n", vag_node.name); RemoveVagStreamFromList(&vag_node, &EEPlayList); if (param_2 == 1) {