mumain/ClientLibrary
janblade 0702144c84 feat(render): GPU bone skinning (15-20x CPU win), retire fixed-function GL
Two changes bundled together: moving skeletal skinning off the CPU onto the
GPU, and retiring the fixed-function pipeline (FFP) in favor of a real
backend-agnostic render hardware interface (RHI) with a GL implementation.

GPU bone skinning
- Per-vertex skeletal skinning (BMD::Transform()'s CPU loop, previously run
  for every vertex of every visible body, every frame) moves to the GPU:
  the CPU now only computes and uploads the (much smaller) per-bone matrix
  palette; the vertex shader does the per-vertex transform in parallel.
- Measured result: `Transform()` self-time at a standard crowded spot
  dropped from ~0.25ms to 0.01-0.02ms -- a 15-20x reduction. This is exactly
  the cost that scales worst in an MMO client (town crowds, mass PK/boss
  events), so the win is disproportionately larger in the scenarios that
  used to hurt most.
- Cloth cape meshes are the one remaining CPU-skinned case (pinned-vertex
  physics read/write-back), deliberately deferred rather than forced into
  this pass.

Eliminating the fixed-function pipeline
- Render/Core/ImmediateRenderer.{h,cpp} ("IR"): a streaming-VBO bridge that
  mirrors the legacy glBegin/glEnd/glVertex/glColor/glTexCoord immediate-mode
  API 1:1 (decomposing GL_QUADS to GL_TRIANGLES), so the ~hundreds of legacy
  immediate-mode call sites across UI/effects code didn't need a per-site
  rewrite -- they draw through IR, which streams into a VBO and issues a real
  shader-backed glDrawArrays instead of relying on FFP's glBegin/glEnd.
- Render/Core/GlobalUBO.{h,cpp} / SceneUBO.{h,cpp} / BoneUBO.{h,cpp}: replace
  the FFP matrix stack (glMatrixMode/glLoadMatrix/glMultMatrix) and per-bone
  transform state with explicit uniform buffers the shaders read instead.
- Render/Core/GLColorIntercept.h: glColor*() under Core Profile is a no-op
  and glGetFloatv(GL_CURRENT_COLOR, ...) is illegal, so ~340 RenderColor()/
  RenderBitmap()-family call sites that used to read back "current color"
  via that query now read a shadow g_CurrentColor mirrored by macro-
  intercepted glColor* wrappers instead.
- Render/Core/BindState.{h,cpp}: single-source-of-truth glUseProgram/
  glBindTexture/glBindVertexArray wrapper with last-bound-id caching, so
  shader/texture/VAO state is tracked explicitly instead of relying on GL's
  implicit FFP-era binding state.
- tools/check_gl_wrapper_monopoly.py, wired into CMake as an always-rerun
  build target (CheckGLWrapperMonopoly): fails the build if a raw gl*() call
  appears outside Render/ that isn't on its allowlist, so no new FFP call
  site can sneak back in. The current allowlist is a deliberately documented
  set of deferrals (screenshot readback, one-time startup queries, event fog
  params), not oversights.
- ~60 supporting files (Models/Effects/UI/GameMaps/Terrain/etc.) updated to
  route through the new wrapper family instead of calling gl* directly.

RHI abstraction
- Render/RHI/{RHI,RHI_GL}.{h,cpp}: buffer/texture/uniform-block/draw
  abstraction so rendering code targets a stable interface rather than raw
  GL calls -- a GL implementation today, sized to add other backends later
  without touching call sites.
- Render/Shaders/{BMDMeshShader,TerrainShader,PassthroughShader,
  PlanarShadowShader,ItemSpecularShader}.{h,cpp} (+ glsl/*.vert/.frag):
  GLSL shader pairs replacing the fixed-function mesh/terrain/UI-sprite/
  planar-shadow/item-specular rendering paths -- this is also what the GPU
  skinning above actually runs inside of.
2026-08-05 16:47:50 +08:00
..
Properties/PublishProfiles Changes in submodules and files required after rename 2026-01-18 17:57:44 +01:00
.gitignore Replaced .NET 8 Hosting by Native AOT of .NET 9 2024-11-19 07:28:51 +01:00
Common.xslt Added enum code generation from packet definitions 2026-04-20 17:16:21 +02:00
ConnectionManager.ChatServer.Custom.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
ConnectionManager.ChatServerFunctions.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
ConnectionManager.ClientToServer.Custom.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
ConnectionManager.ClientToServerFunctions.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
ConnectionManager.ConnectServerFunctions.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
ConnectionManager.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
ConnectionWrapper.cs Replaced .NET 8 Hosting by Native AOT of .NET 9 2024-11-19 07:28:51 +01:00
GenerateBindingsHeader.xslt Added enum code generation from packet definitions 2026-04-20 17:16:21 +02:00
GenerateEnums.xslt Added enum code generation from packet definitions 2026-04-20 17:16:21 +02:00
GenerateExtensionsDotNet.xslt Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00
GenerateFunctions.xslt Added enum code generation from packet definitions 2026-04-20 17:16:21 +02:00
GenerateFunctionsHeader.xslt Added enum code generation from packet definitions 2026-04-20 17:16:21 +02:00
MUnique.Client.Library.csproj feat(render): GPU bone skinning (15-20x CPU win), retire fixed-function GL 2026-08-05 16:47:50 +08:00
NativeInterop.cs Run and connect the client natively on Linux (issue #462 Phase 4) 2026-06-13 18:22:03 +02:00