downtown demo scene: paid Downtown City MegaKit block (texture-crushed to 512), kerbside quaternius vehicles, dusk fog lighting
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
2a5449cc24
commit
f32747d2ce
BIN
assets/city/Building_Large_2.glb
Normal file
BIN
assets/city/Building_Large_2.glb
Normal file
Binary file not shown.
BIN
assets/city/Building_Medium_2_001.glb
Normal file
BIN
assets/city/Building_Medium_2_001.glb
Normal file
Binary file not shown.
BIN
assets/city/Building_Small_1.glb
Normal file
BIN
assets/city/Building_Small_1.glb
Normal file
Binary file not shown.
BIN
assets/city/Cop.glb
Normal file
BIN
assets/city/Cop.glb
Normal file
Binary file not shown.
BIN
assets/city/NormalCar1.glb
Normal file
BIN
assets/city/NormalCar1.glb
Normal file
Binary file not shown.
BIN
assets/city/Prop_Bollard.glb
Normal file
BIN
assets/city/Prop_Bollard.glb
Normal file
Binary file not shown.
BIN
assets/city/Prop_Planter_Single.glb
Normal file
BIN
assets/city/Prop_Planter_Single.glb
Normal file
Binary file not shown.
BIN
assets/city/Sidewalk_Straight_3m.glb
Normal file
BIN
assets/city/Sidewalk_Straight_3m.glb
Normal file
Binary file not shown.
BIN
assets/city/Street_2Lane.glb
Normal file
BIN
assets/city/Street_2Lane.glb
Normal file
Binary file not shown.
BIN
assets/city/Street_4WayIntersection.glb
Normal file
BIN
assets/city/Street_4WayIntersection.glb
Normal file
Binary file not shown.
BIN
assets/city/Street_Asphalt_9x9.glb
Normal file
BIN
assets/city/Street_Asphalt_9x9.glb
Normal file
Binary file not shown.
BIN
assets/city/Taxi.glb
Normal file
BIN
assets/city/Taxi.glb
Normal file
Binary file not shown.
124
src/main.js
124
src/main.js
@ -4,7 +4,7 @@ import { GLTFLoader } from '../vendor/GLTFLoader.js';
|
||||
import { OrbitControls } from '../vendor/OrbitControls.js';
|
||||
import { RetroScreen, retroState, retrofyObject, patchRetroMaterial } from './retro.js';
|
||||
|
||||
const FOG_COLOR = 0x2a2036;
|
||||
const FOG_COLOR = 0x8d84a8;
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: false });
|
||||
renderer.setPixelRatio(1);
|
||||
@ -12,70 +12,98 @@ document.getElementById('view').appendChild(renderer.domElement);
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(FOG_COLOR);
|
||||
scene.fog = new THREE.Fog(FOG_COLOR, 6, 26);
|
||||
scene.fog = new THREE.Fog(FOG_COLOR, 14, 55);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(60, 4 / 3, 0.1, 100);
|
||||
camera.position.set(3.2, 2.2, 4.2);
|
||||
camera.position.set(6.5, 3.2, 9.5);
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.target.set(0, 1, 0);
|
||||
controls.enableDamping = true;
|
||||
|
||||
scene.add(new THREE.HemisphereLight(0xcabfe8, 0x4a3c5e, 1.6));
|
||||
const sun = new THREE.DirectionalLight(0xffeedd, 2.2);
|
||||
scene.add(new THREE.HemisphereLight(0xe8e2f5, 0x8a7a95, 2.4));
|
||||
const sun = new THREE.DirectionalLight(0xfff2dd, 3.2);
|
||||
sun.position.set(4, 6, 3);
|
||||
scene.add(sun);
|
||||
|
||||
const screen = new RetroScreen(renderer);
|
||||
|
||||
// --- procedural retro textures (canvas, nearest) ------------------------------
|
||||
function canvasTexture(draw, size = 64) {
|
||||
const c = document.createElement('canvas');
|
||||
c.width = c.height = size;
|
||||
draw(c.getContext('2d'), size);
|
||||
const t = new THREE.CanvasTexture(c);
|
||||
t.magFilter = THREE.NearestFilter;
|
||||
t.minFilter = THREE.NearestFilter;
|
||||
t.generateMipmaps = false;
|
||||
t.wrapS = t.wrapT = THREE.RepeatWrapping;
|
||||
return t;
|
||||
// --- downtown block (paid Downtown City MegaKit, texture-crushed) --------------
|
||||
const cityLoader = new GLTFLoader();
|
||||
function loadPiece(name) {
|
||||
return new Promise((res, rej) =>
|
||||
cityLoader.load('assets/city/' + name + '.glb', (g) => {
|
||||
retrofyObject(g.scene);
|
||||
res(g.scene);
|
||||
}, undefined, rej));
|
||||
}
|
||||
const checkerTex = canvasTexture((g, s) => {
|
||||
for (let y = 0; y < 8; y++) for (let x = 0; x < 8; x++) {
|
||||
g.fillStyle = (x + y) % 2 ? '#4a3f66' : '#5d5080';
|
||||
g.fillRect(x * s / 8, y * s / 8, s / 8, s / 8);
|
||||
function sizeOf(obj) {
|
||||
const b = new THREE.Box3().setFromObject(obj);
|
||||
return { size: b.getSize(new THREE.Vector3()), min: b.min, max: b.max };
|
||||
}
|
||||
function put(proto, x, z, ry = 0) {
|
||||
const c = proto.clone(true);
|
||||
c.position.set(x, 0, z);
|
||||
c.rotation.y = ry;
|
||||
scene.add(c);
|
||||
return c;
|
||||
}
|
||||
});
|
||||
checkerTex.repeat.set(12, 12);
|
||||
const brickTex = canvasTexture((g, s) => {
|
||||
g.fillStyle = '#6e5a4e'; g.fillRect(0, 0, s, s);
|
||||
g.fillStyle = '#8a7263';
|
||||
for (let y = 0; y < 4; y++) for (let x = 0; x < 4; x++)
|
||||
g.fillRect(x * 16 + (y % 2 ? 8 : 0) + 1, y * 16 + 1, 14, 14);
|
||||
});
|
||||
|
||||
const ground = new THREE.Mesh(
|
||||
new THREE.PlaneGeometry(40, 40),
|
||||
patchRetroMaterial(new THREE.MeshLambertMaterial({ map: checkerTex }))
|
||||
// dark asphalt base plane so there are no holes at the fog line
|
||||
const base = new THREE.Mesh(
|
||||
new THREE.PlaneGeometry(120, 120),
|
||||
patchRetroMaterial(new THREE.MeshLambertMaterial({ color: 0x2b2b30 }))
|
||||
);
|
||||
ground.rotation.x = -Math.PI / 2;
|
||||
scene.add(ground);
|
||||
base.rotation.x = -Math.PI / 2;
|
||||
base.position.y = -0.03;
|
||||
scene.add(base);
|
||||
|
||||
// scatter some chunky geometry so the wobble has something to chew on
|
||||
const brickMat = patchRetroMaterial(new THREE.MeshLambertMaterial({ map: brickTex }));
|
||||
const shapes = [];
|
||||
for (let i = 0; i < 14; i++) {
|
||||
const kind = i % 3;
|
||||
const geo = kind === 0 ? new THREE.BoxGeometry(1.4, 1 + (i % 4), 1.4)
|
||||
: kind === 1 ? new THREE.ConeGeometry(0.9, 1.8, 6)
|
||||
: new THREE.CylinderGeometry(0.6, 0.6, 1.4, 8);
|
||||
const m = new THREE.Mesh(geo, brickMat);
|
||||
const a = (i / 14) * Math.PI * 2;
|
||||
const r = 6 + (i % 3) * 3;
|
||||
m.position.set(Math.cos(a) * r, geo.parameters.height ? geo.parameters.height / 2 : 0.7, Math.sin(a) * r);
|
||||
m.rotation.y = a;
|
||||
scene.add(m);
|
||||
shapes.push(m);
|
||||
(async () => {
|
||||
try {
|
||||
const [street, walk, bSmall, bMed, bLarge, bollard, planter, taxi, car, cop] =
|
||||
await Promise.all([
|
||||
loadPiece('Street_2Lane'), loadPiece('Sidewalk_Straight_3m'),
|
||||
loadPiece('Building_Small_1'), loadPiece('Building_Medium_2_001'),
|
||||
loadPiece('Building_Large_2'), loadPiece('Prop_Bollard'),
|
||||
loadPiece('Prop_Planter_Single'), loadPiece('Taxi'),
|
||||
loadPiece('NormalCar1'), loadPiece('Cop'),
|
||||
]);
|
||||
const st = sizeOf(street);
|
||||
const stepX = st.size.x || 3; // tile the road along X
|
||||
const roadHalf = (st.size.z || 9) / 2;
|
||||
for (let i = -5; i <= 5; i++) put(street, i * stepX, 0);
|
||||
const wk = sizeOf(walk);
|
||||
const wkStep = wk.size.x || 3;
|
||||
for (let i = -10; i <= 10; i++) {
|
||||
put(walk, i * wkStep, roadHalf + wk.size.z / 2);
|
||||
put(walk, i * wkStep, -(roadHalf + wk.size.z / 2), Math.PI);
|
||||
}
|
||||
// buildings lining both sides, fronts to the road
|
||||
const row = roadHalf + wk.size.z + 0.2;
|
||||
const north = [bSmall, bMed, bLarge, bSmall];
|
||||
let x = -22;
|
||||
for (const b of north) {
|
||||
const bs = sizeOf(b);
|
||||
put(b, x + bs.size.x / 2, row + bs.size.z / 2, Math.PI);
|
||||
x += bs.size.x + 1.2;
|
||||
}
|
||||
const south = [bLarge, bSmall, bMed];
|
||||
x = -18;
|
||||
for (const b of south) {
|
||||
const bs = sizeOf(b);
|
||||
put(b, x + bs.size.x / 2, -(row + bs.size.z / 2));
|
||||
x += bs.size.x + 1.5;
|
||||
}
|
||||
// kerbside cars + props
|
||||
put(taxi, -4, roadHalf - 1.2, Math.PI);
|
||||
put(car, 5, roadHalf - 1.2, Math.PI);
|
||||
put(cop, 10, -(roadHalf - 1.2));
|
||||
for (let i = -3; i <= 3; i++) put(bollard, i * 6 + 1.5, roadHalf + 0.6);
|
||||
put(planter, -8, roadHalf + 1.4);
|
||||
put(planter, 8, roadHalf + 1.4);
|
||||
} catch (e) {
|
||||
console.error('city load failed', e);
|
||||
}
|
||||
})();
|
||||
|
||||
// --- character ----------------------------------------------------------------
|
||||
let mixer = null;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user