fix(ugc): each glitter brick gets its own fleck pattern

Every glitter brick had the same flecks in the same places: the UVs were
the vertex positions projected on an axis plane, so bricks a whole tile
apart (and every brick of the same shape at the same spot in its own
model) looked identical. Each brick now has a number of its own
(UgcGlitter::BrickSeed, from the model's id and the brick's index, kept
per vertex in Mesh::brickSeeds) that turns the projection by an angle
and moves it by an offset under a tile, differently for each axis
plane. A model made again gets the same patterns; every LOD of a brick
the same one. The icon now draws the flecks on the UVs the .nif has
(Mesh::uvs read back by FromNif). New setting glitter_random (1; 0 puts
the same pattern on every brick as before). Non-glitter models are
byte-identical (hash tests unchanged).

Check in game: reprocess a model with several glitter bricks of the
same shape; the fleck patterns differ from brick to brick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 00:17:43 -05:00
parent 0a1e33d3d2
commit 63bfaf545e
11 changed files with 148 additions and 11 deletions

View File

@@ -384,7 +384,10 @@ namespace UgcRender {
const auto look = mesh.looks.size() == mesh.positions.size() && (isOpaque || mesh.looks[i0] == UgcModel::eLook::GLITTER) ? mesh.looks[i0] : UgcModel::eLook::PLASTIC;
if (look == UgcModel::eLook::GLITTER) {
// LEGO-AnimUV: lerp(vertex color, the texture's white, its alpha), then lit as plastic
const float fleck = UgcGlitter::Sample(glitterAlpha, UgcGlitter::Uv(position, normal, options.glitter.tile));
// On the mesh's own UVs (read from the .nif: each brick's pattern placed as it was made), else projected
const auto uv = mesh.uvs.size() == mesh.positions.size() ? mesh.uvs[i0] * w0 + mesh.uvs[i1] * w1 + mesh.uvs[i2] * w2 :
UgcGlitter::Uv(position, normal, options.glitter.tile);
const float fleck = UgcGlitter::Sample(glitterAlpha, uv);
base = glm::vec4(glm::mix(glm::vec3(base), glm::vec3(1.0f), fleck), base.a);
}
if (look == UgcModel::eLook::PLASTIC || look == UgcModel::eLook::GLITTER) {