chore(render): delete dead ParticleBatcher chain (2026-07-24 audit review)

ParticleBatcher/ParticleEmitterRenderer/ActiveParticleEmitter (src/AcDream.App/Rendering/Wb/)
are an earlier WorldBuilder-derived particle-preview design with zero live call
sites: ParticleBatcher.Begin/AddParticle/Flush/End are only called from
ParticleEmitterRenderer.Render, which is only called from
ActiveParticleEmitter.Render, and `new ActiveParticleEmitter` has zero call
sites anywhere in the repo (verified by grep across src/tests/tools). The only
wiring was OpenGLGraphicsDevice.ParticleBatcher (property + null-init + Dispose)
and a single assignment in WbMeshAdapter.cs.

ParticleBatcher's constructor unconditionally allocated a ParticleInstance[65536]
managed array (~3.5 MiB) plus a matching GPU instance buffer, a shader, a VAO,
and 3 more GL buffers, none tracked by GpuMemoryTracker or ever drawn from.

ParticleEmitterRenderer's per-particle-type physics (Particle::Init vector-space
resolution, CalculatePosition integration) duplicates, without retail address
citations, what src/AcDream.Core/Vfx/ParticleSystem.cs already implements with
Particle::Init (0x0051c930) / Particle::Update (0x0051c290) citations and the
same ParticleType switch — the production path (ParticleSystem.cs +
AcDream.App/Rendering/ParticleRenderer.cs) supersedes it. No unique retail
knowledge is lost.

EmbeddedResourceReader.cs and the wb_particle.vert/frag shader sources are
deleted alongside it: EmbeddedResourceReader's own doc comment says it exists
solely so ParticleBatcher/ParticleEmitterRenderer can load WB-style shader
resource names, and GetEmbeddedResource had no other caller in the repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 4afedafd085a5fadd1867418d3ec71610d9d15a7)
This commit is contained in:
Erik 2026-07-24 11:35:16 +02:00
parent cf25330458
commit a4b1214e0f
8 changed files with 0 additions and 906 deletions

View file

@ -1,22 +0,0 @@
#version 330 core
in vec2 TexCoord;
in float Opacity;
in float TextureIndex;
uniform sampler2DArray uTextureArray;
out vec4 FragColor;
void main() {
// Reverting to standard non-premultiplied sampling.
vec4 color = texture(uTextureArray, vec3(TexCoord, TextureIndex));
// Standard alpha blending: SrcAlpha, OneMinusSrcAlpha.
color.a *= Opacity;
// Alpha test to discard fully transparent pixels (standard AC behavior)
if (color.a < 0.005) discard;
FragColor = color;
}

View file

@ -1,52 +0,0 @@
#version 330 core
layout (location = 0) in vec3 aPosition; // Basic quad vertex (-0.5 to 0.5)
layout (location = 1) in vec2 aTexCoord;
// Instance attributes
layout (location = 2) in vec3 iPosition;
layout (location = 3) in vec3 iScaleOpacityActive; // x=Scale, y=Opacity, z=Active
layout (location = 4) in float iTextureIndex;
layout (location = 5) in vec4 iRotation; // Quaternion
layout (location = 6) in vec2 iSize;
layout (location = 7) in float iIsBillboard;
uniform mat4 uViewProjection;
uniform vec3 uCameraUp;
uniform vec3 uCameraRight;
out vec2 TexCoord;
out float Opacity;
out float TextureIndex;
vec3 rotate_vector(vec3 v, vec4 q) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
}
void main() {
TexCoord = aTexCoord;
Opacity = iScaleOpacityActive.y;
TextureIndex = iTextureIndex;
float scale = iScaleOpacityActive.x;
vec3 worldPos;
if (iIsBillboard > 0.5) {
// Spherical billboarding - always face camera
vec3 billboardRight = uCameraRight;
vec3 billboardUp = uCameraUp;
worldPos = iPosition
+ billboardRight * aPosition.x * iSize.x * scale
+ billboardUp * aPosition.z * iSize.y * scale;
} else {
// Standard 3D rotation using quaternion
vec3 localPos = vec3(aPosition.x * iSize.x * scale,
0.0,
aPosition.z * iSize.y * scale);
worldPos = iPosition + rotate_vector(localPos, iRotation);
}
gl_Position = uViewProjection * vec4(worldPos, 1.0);
}