fix(dashboard): light the UGC model view like the game

Metal was drawn with metalness 1 in the room environment at half strength with one
sun, so metal groups came out nearly black. The game's metal keeps the vertex
color (lit, plus a reflection tinted by it), so metal is now part metal with a
stronger reflection, the environment is brighter and a sky over ground fill
lights the sides away from the sun.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-30 03:50:02 -05:00
parent 19b6443fb4
commit c6831ac80e
2 changed files with 20 additions and 5 deletions

View File

@@ -11,6 +11,18 @@ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
import { parseModel, mergeMeshes, linearColors, metalOf, addGlitter, glitterSettings, SHADER_LOOK } from '/js/scenery-core.js';
/**
* The game's metal (Metallic.fx) is not a mirror: it is the vertex color lit (0.3 ambient plus 0.7 N.L^4), plus the
* metal cube's reflection tinted by the vertex color (up to twice it, facing the sun), plus a sun highlight. So the
* brick's color stays visible and metal is about as bright as its plastic; a metalness of 1 in a dim room is nearly
* black. Part metal, a little glossier than plastic, with the room's reflection a little stronger.
*/
const METAL = {
none: { roughness: 0.6, metalness: 0 },
polished: { roughness: 0.25, metalness: 0.5, envMapIntensity: 1.6 },
brushed: { roughness: 0.45, metalness: 0.4, envMapIntensity: 1.4 },
};
export function createNifViewer(container) {
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
@@ -22,9 +34,11 @@ export function createNifViewer(container) {
scene.background = new THREE.Color(0x1e2126);
const pmrem = new THREE.PMREMGenerator(renderer);
scene.environment = pmrem.fromScene(new RoomEnvironment(), 0.04).texture;
scene.environmentIntensity = 0.5;
scene.environmentIntensity = 0.8;
const sun = new THREE.DirectionalLight(0xffffff, 1.4);
scene.add(sun, sun.target);
// A sky over ground fill, so no side of a model (a baseplate's underside, the side away from the sun) is black
const sky = new THREE.HemisphereLight(0xffffff, 0x8a8f99, 0.6);
scene.add(sun, sun.target, sky);
const camera = new THREE.PerspectiveCamera(40, 1, 0.05, 20000);
const controls = new OrbitControls(camera, renderer.domElement);
@@ -130,8 +144,7 @@ export function createNifViewer(container) {
const material = sparkles ? new THREE.MeshLambertMaterial({ color: baseColor.clone(), vertexColors: hasColors })
: look & SHADER_LOOK.EMISSIVE
? new THREE.MeshBasicMaterial({ color: baseColor.clone(), vertexColors: hasColors })
: new THREE.MeshStandardMaterial({ color: baseColor.clone(), vertexColors: hasColors, transparent: seeThrough,
roughness: metal === 'polished' ? 0.18 : metal === 'brushed' ? 0.45 : 0.6, metalness: metal ? 1 : 0 });
: new THREE.MeshStandardMaterial({ color: baseColor.clone(), vertexColors: hasColors, transparent: seeThrough, ...METAL[metal || 'none'] });
// Glitter: the fleck texture's UVs, one tile of it each; the sparkle shapes' UVs, one sparkle tile each
let glitter = null;
const settings = glitterSettings();

View File

@@ -479,7 +479,9 @@ client's 88, 89 and 46) and draws glow at its plain color (by `glow_emissive`, u
light, a sky over dark ground reflection tinted by its color and a sun highlight (sharp for polished, broad for
brushed). This is an approximation of the game's environment maps. `NifFile::ShaderLookFor` gives 98 `REFLECTIVE`,
99 `REFLECTIVE | BRUSHED` and 53 `EMISSIVE`; the UGC page's 3D view gets each mesh's look (`/api/ugc/mesh`, "look")
and draws metal as reflective (metalness 1, the view's environment) and glow unlit, and the zone views draw
and draws metal as the game does, its color kept (part metal: metalness 0.5 polished, 0.4 brushed, with a stronger
reflection of the view's environment; a metalness of 1 in the view's dim room was nearly black) and glow unlit, under
a sun and a sky over ground fill so no side of a model is black, and the zone views draw
LEGO-Emissive objects going to their vertex color by its alpha (metal there stays lit like the rest).
#### Glitter