feat: retire the gantry and billboard districts and light the rest as steel
This commit is contained in:
Binary file not shown.
@@ -18,8 +18,6 @@ import { WORLD_DEPTH, WORLD_FAR_Z } from './metrics';
|
||||
* like the expressway furniture. Districts at rest are hidden, so only the
|
||||
* current chapter's pieces cost draw calls. */
|
||||
export type DistrictPiece =
|
||||
| 'gantry'
|
||||
| 'billboard'
|
||||
| 'rack-row'
|
||||
| 'mast'
|
||||
| 'workshop'
|
||||
@@ -34,7 +32,7 @@ interface Placement {
|
||||
/** Yaw in radians, applied before mirroring. */
|
||||
ry?: number;
|
||||
s?: number;
|
||||
/** Extra vertical stretch (gantries clear the chase camera). */
|
||||
/** Extra vertical stretch (the arch clears the chase camera). */
|
||||
sy?: number;
|
||||
}
|
||||
|
||||
@@ -42,18 +40,10 @@ interface Placement {
|
||||
export const DISTRICT_PRESENCE: Readonly<
|
||||
Record<DistrictPiece, Partial<Record<SectionId, number>>>
|
||||
> = {
|
||||
gantry: {
|
||||
profile: 1,
|
||||
experience: 1,
|
||||
infrastructure: 1,
|
||||
'selected-builds': 1,
|
||||
'additional-work': 1,
|
||||
toolkit: 1,
|
||||
},
|
||||
billboard: { profile: 1, experience: 1 },
|
||||
// Pieces rise fully or not at all: a part-raised piece is squashed flat.
|
||||
'rack-row': { infrastructure: 1 },
|
||||
mast: { infrastructure: 0.75, toolkit: 1 },
|
||||
workshop: { 'selected-builds': 1, 'additional-work': 0.5 },
|
||||
mast: { infrastructure: 1, toolkit: 1 },
|
||||
workshop: { 'selected-builds': 1 },
|
||||
crane: { 'selected-builds': 1, 'additional-work': 1 },
|
||||
container: { 'additional-work': 1 },
|
||||
arch: { contact: 1 },
|
||||
@@ -67,14 +57,6 @@ const span = (count: number, from: number, to: number) =>
|
||||
function placementsFor(piece: DistrictPiece, dense: boolean): Placement[] {
|
||||
const n = (full: number) => (dense ? full : Math.ceil(full / 2));
|
||||
switch (piece) {
|
||||
case 'gantry':
|
||||
return span(n(3), -70, -70 - WORLD_DEPTH).map((z) => ({ x: 0, z, sy: 1.42 }));
|
||||
case 'billboard':
|
||||
return span(n(10), -40, -40 - WORLD_DEPTH).map((z, i) => ({
|
||||
x: (i % 2 ? 1 : -1) * 16,
|
||||
z,
|
||||
ry: (i % 2 ? 1 : -1) * 0.28,
|
||||
}));
|
||||
case 'rack-row':
|
||||
return span(n(18), -26, -26 - WORLD_DEPTH).flatMap((z, i) => {
|
||||
const side = i % 2 ? 1 : -1;
|
||||
@@ -194,17 +176,28 @@ export function createDistricts(
|
||||
varying float vHeight;
|
||||
void main() {
|
||||
${FADES}
|
||||
// Opaque dark steel, like the sign truss: fades dissolve through a
|
||||
// fixed screen-door pattern instead of alpha, so pieces never read
|
||||
// as translucent sheets over the sky and the sun.
|
||||
float cover = fade * smoothstep(0.0, 0.25, vRise);
|
||||
vec2 cell = mod(floor(gl_FragCoord.xy), 4.0);
|
||||
float threshold = (mod(cell.x + cell.y * 2.0, 4.0) * 4.0 + mod(cell.y, 2.0) * 2.0 + mod(cell.x, 2.0) + 0.5) / 16.0;
|
||||
if (cover < threshold) discard;
|
||||
vec3 n = normalize(cross(dFdx(vWorld), dFdy(vWorld)));
|
||||
float key = max(0.0, dot(n, normalize(vec3(-0.45, 0.85, 0.35))));
|
||||
float rim = pow(1.0 - abs(n.y), 3.0) * 0.5;
|
||||
vec3 color = vec3(0.03, 0.016, 0.05) + vec3(0.085, 0.06, 0.14) * key;
|
||||
color += uAccent * rim * 0.06 * (0.4 + 0.6 * smoothstep(0.0, 12.0, vHeight));
|
||||
gl_FragColor = vec4(color, fade * smoothstep(0.0, 0.25, vRise));
|
||||
float fill = max(0.0, dot(n, normalize(vec3(0.6, 0.2, -0.4))));
|
||||
vec3 color = vec3(0.022, 0.018, 0.034) + vec3(0.07, 0.06, 0.1) * key + vec3(0.02, 0.015, 0.035) * fill;
|
||||
// Emissive edge: the silhouette catches the chapter colour, and
|
||||
// the tops of the pieces carry a thin lit band.
|
||||
float rim = pow(1.0 - abs(dot(n, normalize(cameraPosition - vWorld))), 4.0);
|
||||
float crown = smoothstep(0.92, 1.0, n.y) * smoothstep(1.0, 6.0, vHeight);
|
||||
color += uAccent * (rim * 0.22 + crown * 0.05);
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
#include <tonemapping_fragment>
|
||||
#include <colorspace_fragment>
|
||||
}
|
||||
`,
|
||||
transparent: true,
|
||||
transparent: false,
|
||||
depthWrite: true,
|
||||
side: THREE.DoubleSide,
|
||||
}),
|
||||
@@ -253,7 +246,7 @@ export function createDistricts(
|
||||
const entry = state.get(piece);
|
||||
if (!entry) return;
|
||||
const placements = placementsFor(piece, quality.postEffects);
|
||||
const accentMix = piece === 'gantry' || piece === 'arch' || piece === 'billboard' ? 1 : 0.35;
|
||||
const accentMix = piece === 'arch' ? 1 : 0.35;
|
||||
for (const [geometry, material] of [
|
||||
[body, bodyMaterial(entry.rise)],
|
||||
[light, lightMaterial(entry.rise, accentMix)],
|
||||
|
||||
Reference in New Issue
Block a user