three-stuff 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fpscontrols.js +148 -0
- package/package.json +13 -0
- package/physics.js +57 -0
- package/shadowinit.js +262 -0
package/fpscontrols.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
|
|
3
|
+
|
|
4
|
+
export class FpsControls {
|
|
5
|
+
constructor(camera, domElement, weaponModel = null) {
|
|
6
|
+
this.camera = camera;
|
|
7
|
+
this.controls = new PointerLockControls(camera, domElement);
|
|
8
|
+
this.domElement = domElement;
|
|
9
|
+
|
|
10
|
+
// --- Physics Config ---
|
|
11
|
+
this.acceleration = 100.0;
|
|
12
|
+
this.friction = 10.0;
|
|
13
|
+
this.gravity = 30.0;
|
|
14
|
+
this.jumpForce = 12.0;
|
|
15
|
+
this.playerHeight = 1.6;
|
|
16
|
+
this.playerRadius = 0.6; // Width of the player (keep this larger than your move speed)
|
|
17
|
+
|
|
18
|
+
this.jump = false;
|
|
19
|
+
this.allobj = false;
|
|
20
|
+
this.collidableObjects = [];
|
|
21
|
+
|
|
22
|
+
// --- Internal State ---
|
|
23
|
+
this.velocity = new THREE.Vector3();
|
|
24
|
+
this.move = { forward: false, backward: false, left: false, right: false, sprint: false };
|
|
25
|
+
this.canJump = false;
|
|
26
|
+
this.prevTime = performance.now();
|
|
27
|
+
|
|
28
|
+
// --- Raycasters ---
|
|
29
|
+
this.raycaster = new THREE.Raycaster();
|
|
30
|
+
|
|
31
|
+
this.initUI();
|
|
32
|
+
this.initListeners();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set sensitivity(val) { this.controls.pointerSpeed = val / 50; }
|
|
36
|
+
|
|
37
|
+
initUI() {
|
|
38
|
+
const dot = document.createElement('div');
|
|
39
|
+
dot.style.cssText = `position:fixed;top:50%;left:50%;width:4px;height:4px;background:white;border-radius:50%;transform:translate(-50%,-50%);pointer-events:none;z-index:1000;mix-blend-mode:difference;`;
|
|
40
|
+
document.body.appendChild(dot);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
initListeners() {
|
|
44
|
+
this.domElement.addEventListener('click', () => this.controls.lock());
|
|
45
|
+
window.addEventListener('keydown', (e) => this.updateKey(e.code, true));
|
|
46
|
+
window.addEventListener('keyup', (e) => this.updateKey(e.code, false));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
addobj(...objs) { this.collidableObjects.push(...objs); }
|
|
50
|
+
|
|
51
|
+
updateKey(code, isPressed) {
|
|
52
|
+
switch (code) {
|
|
53
|
+
case 'KeyW': this.move.forward = isPressed; break;
|
|
54
|
+
case 'KeyS': this.move.backward = isPressed; break;
|
|
55
|
+
case 'KeyA': this.move.left = isPressed; break;
|
|
56
|
+
case 'KeyD': this.move.right = isPressed; break;
|
|
57
|
+
case 'ShiftLeft': this.move.sprint = isPressed; break;
|
|
58
|
+
case 'Space':
|
|
59
|
+
if (isPressed && this.jump && this.canJump) {
|
|
60
|
+
this.velocity.y = this.jumpForce;
|
|
61
|
+
this.canJump = false;
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
update() {
|
|
68
|
+
if (!this.controls.isLocked) return;
|
|
69
|
+
|
|
70
|
+
const time = performance.now();
|
|
71
|
+
const delta = Math.min((time - this.prevTime) / 1000, 0.05);
|
|
72
|
+
this.prevTime = time;
|
|
73
|
+
|
|
74
|
+
const targets = this.allobj && this.camera.parent ? this.camera.parent.children : this.collidableObjects;
|
|
75
|
+
|
|
76
|
+
// 1. Physics Calculations
|
|
77
|
+
this.velocity.x -= this.velocity.x * this.friction * delta;
|
|
78
|
+
this.velocity.z -= this.velocity.z * this.friction * delta;
|
|
79
|
+
this.velocity.y -= this.gravity * delta;
|
|
80
|
+
|
|
81
|
+
const multiplier = this.move.sprint ? 2.0 : 1.0;
|
|
82
|
+
const accel = this.acceleration * multiplier * delta;
|
|
83
|
+
|
|
84
|
+
if (this.move.forward) this.velocity.z += accel;
|
|
85
|
+
if (this.move.backward) this.velocity.z -= accel;
|
|
86
|
+
if (this.move.left) this.velocity.x -= accel;
|
|
87
|
+
if (this.move.right) this.velocity.x += accel;
|
|
88
|
+
|
|
89
|
+
// 2. HORIZONTAL COLLISION (Wall Checking)
|
|
90
|
+
// We create a vector of where we WANT to go
|
|
91
|
+
const moveVector = new THREE.Vector3();
|
|
92
|
+
moveVector.x = this.velocity.x * delta;
|
|
93
|
+
moveVector.z = this.velocity.z * delta;
|
|
94
|
+
|
|
95
|
+
if (moveVector.length() > 0) {
|
|
96
|
+
// Get movement direction in world space
|
|
97
|
+
const worldDir = new THREE.Vector3(moveVector.x, 0, -moveVector.z).applyQuaternion(this.camera.quaternion);
|
|
98
|
+
worldDir.y = 0; // Keep check horizontal
|
|
99
|
+
worldDir.normalize();
|
|
100
|
+
|
|
101
|
+
// Cast a ray from "hip height" so we don't trip over the floor we are standing on
|
|
102
|
+
const rayOrigin = this.camera.position.clone();
|
|
103
|
+
rayOrigin.y -= 0.5;
|
|
104
|
+
|
|
105
|
+
this.raycaster.set(rayOrigin, worldDir);
|
|
106
|
+
this.raycaster.far = this.playerRadius;
|
|
107
|
+
|
|
108
|
+
const wallHits = this.raycaster.intersectObjects(targets, true);
|
|
109
|
+
|
|
110
|
+
if (wallHits.length > 0) {
|
|
111
|
+
// We hit a wall! Stop horizontal velocity
|
|
112
|
+
this.velocity.x = 0;
|
|
113
|
+
this.velocity.z = 0;
|
|
114
|
+
} else {
|
|
115
|
+
// Path clear, apply horizontal movement
|
|
116
|
+
this.controls.moveRight(moveVector.x);
|
|
117
|
+
this.controls.moveForward(moveVector.z);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 3. VERTICAL COLLISION (Floor/Gravity)
|
|
122
|
+
this.camera.position.y += this.velocity.y * delta;
|
|
123
|
+
|
|
124
|
+
this.raycaster.set(this.camera.position, new THREE.Vector3(0, -1, 0));
|
|
125
|
+
this.raycaster.far = this.playerHeight;
|
|
126
|
+
|
|
127
|
+
const floorHits = this.raycaster.intersectObjects(targets, true);
|
|
128
|
+
|
|
129
|
+
if (floorHits.length > 0) {
|
|
130
|
+
const hit = floorHits[0];
|
|
131
|
+
// Only snap to floor if we are actually falling ONTO it,
|
|
132
|
+
// not if the floor is magically above our heads.
|
|
133
|
+
if (this.velocity.y <= 0) {
|
|
134
|
+
this.camera.position.y = hit.point.y + this.playerHeight;
|
|
135
|
+
this.velocity.y = 0;
|
|
136
|
+
this.canJump = true;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
this.canJump = false;
|
|
140
|
+
// Basic ground plane at 0
|
|
141
|
+
if (this.camera.position.y < this.playerHeight) {
|
|
142
|
+
this.camera.position.y = this.playerHeight;
|
|
143
|
+
this.velocity.y = 0;
|
|
144
|
+
this.canJump = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "three-stuff",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "this is ibaads files of modules that he made with easy acces to things like fps controls, physics, and shadows without having to write complicated stuff",
|
|
5
|
+
"main": "fpscontrols.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"type": "commonjs"
|
|
13
|
+
}
|
package/physics.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as CANNON from 'cannon-es';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
|
|
4
|
+
export class PhysicsEngine {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.world = new CANNON.World();
|
|
7
|
+
this.world.gravity.set(0, -9.82, 0);
|
|
8
|
+
this.meshMap = new Map();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
update(scene) {
|
|
12
|
+
this.world.step(1 / 60);
|
|
13
|
+
|
|
14
|
+
scene.traverse((obj) => {
|
|
15
|
+
if (obj.isMesh && (obj.dynamic === true || obj.static === true)) {
|
|
16
|
+
if (!this.meshMap.has(obj)) {
|
|
17
|
+
this._addBody(obj);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (obj.dynamic) {
|
|
21
|
+
const body = this.meshMap.get(obj);
|
|
22
|
+
obj.position.copy(body.position);
|
|
23
|
+
obj.quaternion.copy(body.quaternion);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_addBody(mesh) {
|
|
30
|
+
// Measure the geometry
|
|
31
|
+
mesh.geometry.computeBoundingBox();
|
|
32
|
+
const size = new THREE.Vector3();
|
|
33
|
+
mesh.geometry.boundingBox.getSize(size);
|
|
34
|
+
|
|
35
|
+
// --- THE FIX IS HERE ---
|
|
36
|
+
// We ensure no dimension is 0. If it's a plane, we give it 0.1 thickness.
|
|
37
|
+
const hitBoxSize = new CANNON.Vec3(
|
|
38
|
+
Math.max(size.x * mesh.scale.x, 0.1) / 2,
|
|
39
|
+
Math.max(size.y * mesh.scale.y, 0.1) / 2,
|
|
40
|
+
Math.max(size.z * mesh.scale.z, 0.1) / 2
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const shape = new CANNON.Box(hitBoxSize);
|
|
44
|
+
|
|
45
|
+
const body = new CANNON.Body({
|
|
46
|
+
mass: mesh.dynamic ? (mesh.mass || 1) : 0,
|
|
47
|
+
shape: shape
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Sync initial state
|
|
51
|
+
body.position.copy(mesh.position);
|
|
52
|
+
body.quaternion.copy(mesh.quaternion);
|
|
53
|
+
|
|
54
|
+
this.world.addBody(body);
|
|
55
|
+
this.meshMap.set(mesh, body);
|
|
56
|
+
}
|
|
57
|
+
}
|
package/shadowinit.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// ShadowInit.js
|
|
2
|
+
import * as THREE from 'https://esm.sh/three@0.160.0';
|
|
3
|
+
import { EffectComposer } from 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/postprocessing/EffectComposer.js/+esm';
|
|
4
|
+
import { RenderPass } from 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/postprocessing/RenderPass.js/+esm';
|
|
5
|
+
import { SSAOPass } from 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/postprocessing/SSAOPass.js/+esm';
|
|
6
|
+
import { UnrealBloomPass } from 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/postprocessing/UnrealBloomPass.js/+esm';
|
|
7
|
+
import { SSRPass } from 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/postprocessing/SSRPass.js/+esm';
|
|
8
|
+
|
|
9
|
+
export class ShadowInit {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.scene = null;
|
|
12
|
+
this.renderer = null;
|
|
13
|
+
this.camera = null;
|
|
14
|
+
|
|
15
|
+
this.emissiveLights = new Map();
|
|
16
|
+
this.reflectionCameras = new Map();
|
|
17
|
+
|
|
18
|
+
this._patched = false;
|
|
19
|
+
this._raytracing = false;
|
|
20
|
+
|
|
21
|
+
// Composer and passes for hybrid RTX-like mode
|
|
22
|
+
this.composer = null;
|
|
23
|
+
this.renderPass = null;
|
|
24
|
+
this.ssaoPass = null;
|
|
25
|
+
this.ssrPass = null;
|
|
26
|
+
this.bloomPass = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* ------------------------ ATTACH ------------------------ */
|
|
30
|
+
attach(scene, renderer, camera) {
|
|
31
|
+
this.scene = scene;
|
|
32
|
+
this.renderer = renderer;
|
|
33
|
+
this.camera = camera;
|
|
34
|
+
|
|
35
|
+
this._enableRasterMode(); // <-- set default shadows
|
|
36
|
+
this._addSunLight(); // default directional light
|
|
37
|
+
|
|
38
|
+
if (!this._patched) {
|
|
39
|
+
this._patchSceneAdd(); // auto-detect new meshes
|
|
40
|
+
this._patched = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Process all existing meshes in the scene
|
|
44
|
+
scene.traverse(obj => this._processObject(obj));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* ------------------------ RASTER MODE ------------------------ */
|
|
48
|
+
_enableRasterMode() {
|
|
49
|
+
if (!this.renderer) return;
|
|
50
|
+
|
|
51
|
+
this.renderer.shadowMap.enabled = true;
|
|
52
|
+
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
53
|
+
this.renderer.physicallyCorrectLights = true;
|
|
54
|
+
this.renderer.outputColorSpace = THREE.SRGBColorSpace;
|
|
55
|
+
this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
|
56
|
+
this.renderer.toneMappingExposure = 1.25;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ------------------------ PATCH SCENE.ADD ------------------------ */
|
|
60
|
+
_patchSceneAdd() {
|
|
61
|
+
const originalAdd = this.scene.add.bind(this.scene);
|
|
62
|
+
this.scene.add = (...objects) => {
|
|
63
|
+
objects.forEach(obj => this._processObject(obj));
|
|
64
|
+
originalAdd(...objects);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ------------------------ PROCESS OBJECT ------------------------ */
|
|
69
|
+
_processObject(obj) {
|
|
70
|
+
if (!obj || obj.__shadowEngineProcessed) return;
|
|
71
|
+
|
|
72
|
+
if (obj.isMesh) {
|
|
73
|
+
obj.castShadow = true;
|
|
74
|
+
obj.receiveShadow = true;
|
|
75
|
+
|
|
76
|
+
if (!obj.shadows) obj.shadows = {};
|
|
77
|
+
|
|
78
|
+
// eLight property
|
|
79
|
+
Object.defineProperty(obj.shadows, "eLight", {
|
|
80
|
+
set: v => this._applyEmissiveLight(obj, v)
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// reflective property
|
|
84
|
+
Object.defineProperty(obj.shadows, "reflective", {
|
|
85
|
+
set: v => this._applyReflection(obj, v)
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// helper to update reflection
|
|
89
|
+
obj.shadows.updateReflection = () => this._updateReflection(obj);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
obj.__shadowEngineProcessed = true;
|
|
93
|
+
|
|
94
|
+
if (obj.children) obj.children.forEach(c => this._processObject(c));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* ------------------------ DEFAULT SUN ------------------------ */
|
|
98
|
+
_addSunLight() {
|
|
99
|
+
const sun = new THREE.DirectionalLight(0xffffff, 1.2);
|
|
100
|
+
sun.position.set(15, 25, 15);
|
|
101
|
+
sun.castShadow = true;
|
|
102
|
+
sun.shadow.mapSize.set(2048, 2048);
|
|
103
|
+
sun.shadow.camera.near = 1;
|
|
104
|
+
sun.shadow.camera.far = 150;
|
|
105
|
+
sun.shadow.camera.left = -40;
|
|
106
|
+
sun.shadow.camera.right = 40;
|
|
107
|
+
sun.shadow.camera.top = 40;
|
|
108
|
+
sun.shadow.camera.bottom = -40;
|
|
109
|
+
sun.shadow.bias = -0.0002;
|
|
110
|
+
|
|
111
|
+
this.scene.add(sun);
|
|
112
|
+
this.scene.add(sun.target);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* ------------------------ EMISSIVE LIGHT ------------------------ */
|
|
116
|
+
_applyEmissiveLight(mesh, value) {
|
|
117
|
+
if (!Array.isArray(value)) return;
|
|
118
|
+
|
|
119
|
+
const baseIntensity = value[0] ?? 1;
|
|
120
|
+
const color = new THREE.Color(value[1] ?? 0xffffff).convertSRGBToLinear();
|
|
121
|
+
|
|
122
|
+
// remove old lights
|
|
123
|
+
if (this.emissiveLights.has(mesh)) {
|
|
124
|
+
this.emissiveLights.get(mesh).forEach(l => mesh.remove(l));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// compute mesh size
|
|
128
|
+
const box = new THREE.Box3().setFromObject(mesh);
|
|
129
|
+
const size = box.getSize(new THREE.Vector3());
|
|
130
|
+
const area = size.x * size.y + size.y * size.z + size.x * size.z;
|
|
131
|
+
const intensity = baseIntensity * area * 0.15;
|
|
132
|
+
|
|
133
|
+
const lights = [];
|
|
134
|
+
|
|
135
|
+
// area-light approximation
|
|
136
|
+
const offsets = [
|
|
137
|
+
[0.5, 0, 0], [-0.5, 0, 0],
|
|
138
|
+
[0, 0.5, 0], [0, -0.5, 0],
|
|
139
|
+
[0, 0, 0.5], [0, 0, -0.5]
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
for (const o of offsets) {
|
|
143
|
+
const light = new THREE.PointLight(color, intensity / offsets.length);
|
|
144
|
+
light.castShadow = true;
|
|
145
|
+
light.shadow.mapSize.set(1024, 1024);
|
|
146
|
+
light.shadow.bias = -0.00025;
|
|
147
|
+
light.distance = Math.max(size.x, size.y, size.z) * 8;
|
|
148
|
+
light.position.set(o[0]*size.x, o[1]*size.y, o[2]*size.z);
|
|
149
|
+
mesh.add(light);
|
|
150
|
+
lights.push(light);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// fake bounce light
|
|
154
|
+
const bounce = new THREE.PointLight(color, intensity * 0.25);
|
|
155
|
+
bounce.castShadow = false;
|
|
156
|
+
bounce.distance = Math.max(size.x, size.y, size.z) * 12;
|
|
157
|
+
bounce.position.set(0, -size.y*0.6, 0);
|
|
158
|
+
mesh.add(bounce);
|
|
159
|
+
lights.push(bounce);
|
|
160
|
+
|
|
161
|
+
if (mesh.material?.isMeshStandardMaterial) {
|
|
162
|
+
mesh.material.emissive = color.clone();
|
|
163
|
+
mesh.material.emissiveIntensity = baseIntensity;
|
|
164
|
+
mesh.material.needsUpdate = true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.emissiveLights.set(mesh, lights);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* ------------------------ REFLECTION ------------------------ */
|
|
171
|
+
_applyReflection(mesh, strength = 0.5) {
|
|
172
|
+
strength = THREE.MathUtils.clamp(strength, 0, 1);
|
|
173
|
+
if (!mesh.material?.isMeshStandardMaterial) return;
|
|
174
|
+
|
|
175
|
+
let cam = this.reflectionCameras.get(mesh);
|
|
176
|
+
if (!cam) {
|
|
177
|
+
cam = new THREE.CubeCamera(0.1, 1500, 256);
|
|
178
|
+
this.scene.add(cam);
|
|
179
|
+
this.reflectionCameras.set(mesh, cam);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
mesh.material.envMap = cam.renderTarget.texture;
|
|
183
|
+
mesh.material.metalness = strength;
|
|
184
|
+
mesh.material.roughness = 1 - strength*0.9;
|
|
185
|
+
mesh.material.needsUpdate = true;
|
|
186
|
+
|
|
187
|
+
this._updateReflection(mesh);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
_updateReflection(mesh) {
|
|
191
|
+
const cam = this.reflectionCameras.get(mesh);
|
|
192
|
+
if (!cam) return;
|
|
193
|
+
mesh.visible = false;
|
|
194
|
+
cam.position.copy(mesh.getWorldPosition(new THREE.Vector3()));
|
|
195
|
+
cam.update(this.renderer, this.scene);
|
|
196
|
+
mesh.visible = true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* ------------------------ HYBRID RTX-LIKE PIPELINE ------------------------ */
|
|
200
|
+
set raytracing(val) {
|
|
201
|
+
this._raytracing = val;
|
|
202
|
+
|
|
203
|
+
if (!this.renderer || !this.camera) return;
|
|
204
|
+
|
|
205
|
+
if (val) this._enableHybridPipeline();
|
|
206
|
+
else this._disableHybridPipeline();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
get raytracing() { return this._raytracing; }
|
|
210
|
+
|
|
211
|
+
_enableHybridPipeline() {
|
|
212
|
+
if (!this.renderer || !this.camera) return;
|
|
213
|
+
|
|
214
|
+
if (!this.composer) {
|
|
215
|
+
this.composer = new EffectComposer(this.renderer);
|
|
216
|
+
this.renderPass = new RenderPass(this.scene, this.camera);
|
|
217
|
+
this.composer.addPass(this.renderPass);
|
|
218
|
+
|
|
219
|
+
this.ssaoPass = new SSAOPass(this.scene, this.camera, window.innerWidth, window.innerHeight);
|
|
220
|
+
this.ssaoPass.kernelRadius = 8;
|
|
221
|
+
this.composer.addPass(this.ssaoPass);
|
|
222
|
+
|
|
223
|
+
this.ssrPass = new SSRPass({
|
|
224
|
+
renderer: this.renderer,
|
|
225
|
+
scene: this.scene,
|
|
226
|
+
camera: this.camera,
|
|
227
|
+
width: window.innerWidth,
|
|
228
|
+
height: window.innerHeight,
|
|
229
|
+
groundReflector: null,
|
|
230
|
+
selects: []
|
|
231
|
+
});
|
|
232
|
+
this.composer.addPass(this.ssrPass);
|
|
233
|
+
|
|
234
|
+
this.bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.6, 0.4, 0.85);
|
|
235
|
+
this.composer.addPass(this.bloomPass);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
this.renderer.shadowMap.enabled = false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
_disableHybridPipeline() {
|
|
242
|
+
if (this.composer) {
|
|
243
|
+
this.composer.passes = [];
|
|
244
|
+
this.composer = null;
|
|
245
|
+
}
|
|
246
|
+
this._enableRasterMode();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ------------------------ RENDER ------------------------ */
|
|
250
|
+
render() {
|
|
251
|
+
if (this._raytracing && this.composer) {
|
|
252
|
+
if (this.renderer.domElement.parentElement) this.composer.render();
|
|
253
|
+
} else {
|
|
254
|
+
if (this.renderer && this.scene && this.camera) this.renderer.render(this.scene, this.camera);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* ------------------------ OPTIONAL: VOLMETRICS ------------------------ */
|
|
259
|
+
enableVolumetrics(color = 0x0a0a0a, density = 0.02) {
|
|
260
|
+
this.scene.fog = new THREE.FogExp2(color, density);
|
|
261
|
+
}
|
|
262
|
+
}
|