feat: refine nightdrive world and authored car
Integrate the Blender grand tourer with a cohesive shader-driven road, terrain, atmosphere, lighting, and post-processing pass. Refine responsive drive dynamics and sign lifecycle behavior, and add durable visual, accessibility, and performance verification evidence.
This commit is contained in:
@@ -2,6 +2,7 @@ import * as THREE from "three";
|
||||
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
|
||||
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
|
||||
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
|
||||
import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
|
||||
import type {
|
||||
GpuRenderTargetAllocation,
|
||||
GpuRenderTargetReporter,
|
||||
@@ -10,6 +11,7 @@ import type {
|
||||
|
||||
export interface PostProcessor extends GpuRenderTargetReporter {
|
||||
resize(width: number, height: number, pixelRatio: number): void;
|
||||
setDynamics(acceleration: number): void;
|
||||
render(scene: unknown, camera: unknown): void;
|
||||
dispose(): void;
|
||||
}
|
||||
@@ -38,23 +40,32 @@ interface RenderPassLike {
|
||||
}
|
||||
|
||||
interface BloomPassLike {
|
||||
strength: number;
|
||||
radius: number;
|
||||
threshold: number;
|
||||
renderTargetBright?: RenderTargetLike;
|
||||
renderTargetsHorizontal?: readonly RenderTargetLike[];
|
||||
renderTargetsVertical?: readonly RenderTargetLike[];
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
interface OutputPassLike {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface PostProcessingFactories {
|
||||
createComposer(renderer: unknown): ComposerLike;
|
||||
createRenderPass(scene: unknown, camera: unknown): RenderPassLike;
|
||||
createBloomPass(): BloomPassLike;
|
||||
createOutputPass(): OutputPassLike;
|
||||
}
|
||||
|
||||
const productionFactories: PostProcessingFactories = {
|
||||
createComposer: (renderer) => new EffectComposer(renderer),
|
||||
createRenderPass: (scene, camera) => new RenderPass(scene, camera),
|
||||
createBloomPass: () =>
|
||||
new UnrealBloomPass(new THREE.Vector2(1, 1), 0.46, 0.32, 0.84),
|
||||
new UnrealBloomPass(new THREE.Vector2(1, 1), 0.54, 0.42, 0.88),
|
||||
createOutputPass: () => new OutputPass(),
|
||||
};
|
||||
|
||||
export function createPostProcessor(
|
||||
@@ -68,8 +79,10 @@ export function createPostProcessor(
|
||||
new THREE.Camera(),
|
||||
);
|
||||
const bloomPass = factories.createBloomPass();
|
||||
const outputPass = factories.createOutputPass();
|
||||
composer.addPass(renderPass);
|
||||
composer.addPass(bloomPass);
|
||||
composer.addPass(outputPass);
|
||||
let disposed = false;
|
||||
|
||||
const processor: PostProcessor = {
|
||||
@@ -84,6 +97,13 @@ export function createPostProcessor(
|
||||
Math.max(1, Math.floor(finiteOr(height, 1))),
|
||||
);
|
||||
},
|
||||
setDynamics(acceleration) {
|
||||
if (disposed) return;
|
||||
const energy = clamp(acceleration, 0, 1);
|
||||
bloomPass.strength = 0.54 + energy * 0.22;
|
||||
bloomPass.radius = 0.42 + energy * 0.08;
|
||||
bloomPass.threshold = 0.88 - energy * 0.03;
|
||||
},
|
||||
render(scene, camera) {
|
||||
if (disposed) return;
|
||||
renderPass.scene = scene;
|
||||
@@ -95,6 +115,7 @@ export function createPostProcessor(
|
||||
disposed = true;
|
||||
renderPass.dispose();
|
||||
bloomPass.dispose();
|
||||
outputPass.dispose();
|
||||
composer.dispose();
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user