@needle-tools/engine 2.40.0-pre → 2.42.0-pre

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/needle-engine.d.ts +332 -126
  3. package/dist/needle-engine.js +401 -401
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +53 -53
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/engine_element.js +1 -1
  8. package/lib/engine/engine_element.js.map +1 -1
  9. package/lib/engine/engine_element_loading.js +6 -1
  10. package/lib/engine/engine_element_loading.js.map +1 -1
  11. package/lib/engine/engine_gizmos.d.ts +8 -21
  12. package/lib/engine/engine_gizmos.js +51 -5
  13. package/lib/engine/engine_gizmos.js.map +1 -1
  14. package/lib/engine/engine_math.d.ts +9 -6
  15. package/lib/engine/engine_math.js +9 -0
  16. package/lib/engine/engine_math.js.map +1 -1
  17. package/lib/engine/engine_physics.js +14 -6
  18. package/lib/engine/engine_physics.js.map +1 -1
  19. package/lib/engine/engine_serialization_core.js +2 -0
  20. package/lib/engine/engine_serialization_core.js.map +1 -1
  21. package/lib/engine/engine_setup.d.ts +3 -0
  22. package/lib/engine/engine_setup.js +15 -0
  23. package/lib/engine/engine_setup.js.map +1 -1
  24. package/lib/engine/engine_three_utils.d.ts +16 -1
  25. package/lib/engine/engine_three_utils.js +94 -54
  26. package/lib/engine/engine_three_utils.js.map +1 -1
  27. package/lib/engine/engine_types.d.ts +6 -0
  28. package/lib/engine/engine_types.js.map +1 -1
  29. package/lib/engine/engine_utils.d.ts +1 -0
  30. package/lib/engine/engine_utils.js +3 -0
  31. package/lib/engine/engine_utils.js.map +1 -1
  32. package/lib/engine-components/AnimationCurve.js +20 -5
  33. package/lib/engine-components/AnimationCurve.js.map +1 -1
  34. package/lib/engine-components/BoxHelperComponent.js +9 -10
  35. package/lib/engine-components/BoxHelperComponent.js.map +1 -1
  36. package/lib/engine-components/Light.d.ts +2 -0
  37. package/lib/engine-components/Light.js +33 -9
  38. package/lib/engine-components/Light.js.map +1 -1
  39. package/lib/engine-components/ParticleSystem.d.ts +29 -26
  40. package/lib/engine-components/ParticleSystem.js +349 -187
  41. package/lib/engine-components/ParticleSystem.js.map +1 -1
  42. package/lib/engine-components/ParticleSystemModules.d.ts +243 -64
  43. package/lib/engine-components/ParticleSystemModules.js +722 -153
  44. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  45. package/lib/engine-components/ReflectionProbe.js +29 -11
  46. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  47. package/lib/engine-components/Renderer.d.ts +1 -0
  48. package/lib/engine-components/Renderer.js +4 -2
  49. package/lib/engine-components/Renderer.js.map +1 -1
  50. package/lib/engine-components/WebXR.js +8 -3
  51. package/lib/engine-components/WebXR.js.map +1 -1
  52. package/lib/engine-components/codegen/components.d.ts +7 -0
  53. package/lib/engine-components/codegen/components.js +7 -0
  54. package/lib/engine-components/codegen/components.js.map +1 -1
  55. package/package.json +4 -2
  56. package/src/engine/codegen/register_types.js +28 -0
  57. package/src/engine/dist/engine_three_utils.js +279 -0
  58. package/src/engine/engine_element.ts +1 -1
  59. package/src/engine/engine_element_loading.ts +5 -1
  60. package/src/engine/engine_gizmos.ts +58 -6
  61. package/src/engine/engine_math.ts +19 -6
  62. package/src/engine/engine_physics.ts +17 -7
  63. package/src/engine/engine_serialization_core.ts +1 -0
  64. package/src/engine/engine_setup.ts +25 -2
  65. package/src/engine/engine_three_utils.ts +103 -62
  66. package/src/engine/engine_types.ts +8 -1
  67. package/src/engine/engine_utils.ts +5 -0
  68. package/src/engine-components/AnimationCurve.ts +25 -11
  69. package/src/engine-components/BoxHelperComponent.ts +12 -15
  70. package/src/engine-components/Light.ts +39 -8
  71. package/src/engine-components/ParticleSystem.ts +395 -199
  72. package/src/engine-components/ParticleSystemModules.ts +638 -152
  73. package/src/engine-components/ReflectionProbe.ts +37 -13
  74. package/src/engine-components/Renderer.ts +4 -2
  75. package/src/engine-components/WebXR.ts +11 -8
  76. package/src/engine-components/codegen/components.ts +7 -0
  77. package/src/engine/dist/engine_physics.js +0 -739
  78. package/src/engine/dist/engine_setup.js +0 -777
  79. package/src/engine-components/dist/CharacterController.js +0 -123
  80. package/src/engine-components/dist/RigidBody.js +0 -458
@@ -1,6 +1,6 @@
1
1
  import * as THREE from "three";
2
2
  import { Mathf } from "./engine_math"
3
- import { Vector3, Quaternion, Uniform } from "three";
3
+ import { WebGLRenderTarget, WebGLRenderer, Vector3, Quaternion, Uniform, Texture, Material, ShaderMaterial, CanvasTexture } from "three";
4
4
  import { CircularBuffer } from "./engine_utils";
5
5
 
6
6
 
@@ -78,7 +78,7 @@ const _worldScale2: THREE.Vector3 = new THREE.Vector3();
78
78
 
79
79
  export function getWorldScale(obj: THREE.Object3D, vec: THREE.Vector3 | null = null): THREE.Vector3 {
80
80
  if (!obj) return _worldScale.set(0, 0, 0);
81
- if (!obj.parent) return _worldScale.copy(obj.position);
81
+ if (!obj.parent) return _worldScale.copy(obj.scale);
82
82
  obj.getWorldScale(vec ?? _worldScale);
83
83
  return vec ?? _worldScale;
84
84
  }
@@ -180,39 +180,109 @@ export function logHierarchy(root: THREE.Object3D | null | undefined, collapsibl
180
180
 
181
181
 
182
182
 
183
- const planeGeometry = new THREE.PlaneGeometry(2, 2, 1, 1);
184
- const renderer = new THREE.WebGLRenderer({ antialias: false });
185
- const perspectiveCam = new THREE.PerspectiveCamera();
186
- const scene = new THREE.Scene();
187
- const shaderMaterial = new THREE.ShaderMaterial({
188
- uniforms: { blitTexture: new Uniform(null) },
189
- vertexShader: `
190
- varying vec2 vUv;
191
- void main(){
192
- vUv = uv;
193
- gl_Position = vec4(position.xy * 1.0,0.,.999999);
194
- }`,
195
- fragmentShader: `
196
- uniform sampler2D blitTexture;
197
- varying vec2 vUv;
198
- void main(){
199
- vec2 uv = vUv;
200
- uv.y = 1.0 - uv.y;
201
- gl_FragColor = vec4(uv.xy, 0, 1);
202
- gl_FragColor = texture2D( blitTexture, uv);
203
- }`
204
- });
205
183
 
184
+ export class Graphics {
185
+ private static planeGeometry = new THREE.PlaneGeometry(2, 2, 1, 1);
186
+ private static renderer = new WebGLRenderer({ antialias: false });
187
+ private static perspectiveCam = new THREE.PerspectiveCamera();
188
+ private static scene = new THREE.Scene();
189
+ private static readonly vertex = `
190
+ varying vec2 vUv;
191
+ void main(){
192
+ vUv = uv;
193
+ gl_Position = vec4(position.xy * 1.0,0.,.999999);
194
+ }`;
195
+ private static readonly fragment = `
196
+ uniform sampler2D map;
197
+ varying vec2 vUv;
198
+ void main(){
199
+ vec2 uv = vUv;
200
+ uv.y = 1.0 - uv.y;
201
+ gl_FragColor = texture2D( map, uv);
202
+ // gl_FragColor = vec4(uv.xy, 0, 1);
203
+ }`;
204
+ private static readonly blipMaterial = new ShaderMaterial({
205
+ uniforms: { map: new Uniform(null) },
206
+ vertexShader: this.vertex,
207
+ fragmentShader: this.fragment
208
+ });
209
+
210
+ static createBlitMaterial(fragment: string): ShaderMaterial {
211
+ return new ShaderMaterial({
212
+ uniforms: { map: new Uniform(null) },
213
+ vertexShader: this.vertex,
214
+ fragmentShader: fragment
215
+ });
216
+ }
217
+ private static readonly mesh = new THREE.Mesh(this.planeGeometry, this.blipMaterial);
218
+
219
+ static copyTexture(texture: Texture, blitMaterial?: ShaderMaterial) {
220
+ const material = blitMaterial ?? this.blipMaterial;
221
+ material.uniforms.map.value = texture;
222
+ material.needsUpdate = true;
223
+ material.uniformsNeedUpdate = true;
224
+ const mesh = this.mesh;
225
+ mesh.material = material;
226
+ mesh.frustumCulled = false;
227
+ this.scene.children.length = 0;
228
+ this.scene.add(mesh);
229
+ this.renderer.setSize(texture.image.width, texture.image.height);
230
+ this.renderer.clear();
231
+ this.renderer.render(this.scene, this.perspectiveCam);
232
+ const tex = new Texture(this.renderer.domElement);
233
+ tex.name = "Copy";
234
+ tex.needsUpdate = true; // < important!
235
+ return tex;
236
+ }
237
+
238
+ // static blit(src: Texture, target: Texture, blitMaterial?: ShaderMaterial) {
239
+ // let material = blitMaterial ?? this.blipMaterial;
240
+ // material.uniforms.map.value = src;
241
+ // this.mesh.material = material;
242
+ // this.mesh.frustumCulled = false;
243
+ // this.mesh.matrix.identity();
244
+ // this.scene.children.length = 0;
245
+ // this.scene.add(this.mesh);
246
+ // this.renderer.setSize(src.image.width, src.image.height);
247
+ // this.renderer.clear();
248
+ // this.renderer.render(this.scene, this.perspectiveCam);
249
+ // return new Texture(this.renderer.domElement);
250
+ // }
251
+
252
+ static textureToCanvas(texture: Texture, force: boolean) {
253
+ if (!texture) return null;
254
+
255
+ if (force === true || texture["isCompressedTexture"] === true) {
256
+ texture = copyTexture(texture);
257
+ }
258
+ const image = texture.image;
259
+ if (isImageBitmap(image)) {
260
+
261
+ const canvas = document.createElement('canvas');
262
+ canvas.width = image.width;
263
+ canvas.height = image.height;
264
+
265
+ const context = canvas.getContext('2d');
266
+ if (!context) {
267
+ console.error("Failed getting canvas 2d context");
268
+ return null;
269
+ }
270
+ context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
271
+ return canvas;
272
+
273
+ }
274
+ return null;
275
+ }
276
+ }
277
+
278
+ /**@obsolete use Graphics.copyTexture */
206
279
  export function copyTexture(texture: THREE.Texture): THREE.Texture {
207
- shaderMaterial.uniforms.blitTexture.value = texture;
208
- const mesh = new THREE.Mesh(planeGeometry, shaderMaterial);
209
- mesh.frustumCulled = false;
210
- scene.children.length = 0;
211
- scene.add(mesh);
212
- renderer.setSize(texture.image.width, texture.image.height);
213
- renderer.clear();
214
- renderer.render(scene, perspectiveCam);
215
- return new THREE.Texture(renderer.domElement);
280
+ return Graphics.copyTexture(texture);
281
+ }
282
+
283
+ /**@obsolete use Graphics.textureToCanvas */
284
+ export function textureToCanvas(texture: THREE.Texture, force: boolean = false): HTMLCanvasElement | null {
285
+ return Graphics.textureToCanvas(texture, force);
216
286
  }
217
287
 
218
288
  declare class OffscreenCanvas { };
@@ -222,33 +292,4 @@ function isImageBitmap(image) {
222
292
  (typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
223
293
  (typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas) ||
224
294
  (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap);
225
- }
226
-
227
-
228
- export function textureToCanvas(texture: THREE.Texture, force : boolean = false): HTMLCanvasElement | null {
229
-
230
- if(!texture) return null;
231
-
232
- if (force === true || texture["isCompressedTexture"] === true) {
233
- texture = copyTexture(texture);
234
- }
235
-
236
- const image = texture.image;
237
-
238
- if (isImageBitmap(image)) {
239
-
240
- const canvas = document.createElement('canvas');
241
- canvas.width = image.width;
242
- canvas.height = image.height;
243
-
244
- const context = canvas.getContext('2d');
245
- if (!context) {
246
- console.error("Failed getting canvas 2d context");
247
- return null;
248
- }
249
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
250
- return canvas;
251
-
252
- }
253
- return null;
254
295
  }
@@ -157,7 +157,14 @@ export type Vec2 = {
157
157
  export type Vec3 = {
158
158
  x: number,
159
159
  y: number,
160
- z: number
160
+ z: number,
161
+ }
162
+
163
+ export type Vec4 = {
164
+ x: number,
165
+ y: number,
166
+ z: number,
167
+ w: number,
161
168
  }
162
169
 
163
170
  const contactsVectorBuffer = new CircularBuffer(() => new Vector3(), 20);
@@ -363,4 +363,9 @@ export class Watch implements IWatch {
363
363
  }
364
364
  this._watches.length = 0;
365
365
  }
366
+ }
367
+
368
+
369
+ export function isMobileDevice() {
370
+ return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1);
366
371
  }
@@ -22,21 +22,35 @@ export class AnimationCurve {
22
22
 
23
23
  @serializeable(Keyframe)
24
24
  keys!: Array<Keyframe>;
25
-
26
- get duration() : number {
27
- if(!this.keys || this.keys.length == 0) return 0;
25
+
26
+ get duration(): number {
27
+ if (!this.keys || this.keys.length == 0) return 0;
28
28
  return this.keys[this.keys.length - 1].time;
29
- }
29
+ }
30
30
 
31
31
  evaluate(time: number): number {
32
- if(!this.keys || this.keys.length == 0) return 0;
33
- let lastKeyframe : Keyframe | null = null;
34
- for (const kf of this.keys) {
35
- if (lastKeyframe && kf.time > time && time > lastKeyframe!.time) {
36
- return Mathf.lerp(lastKeyframe!.value, kf.value, (time - lastKeyframe!.time) / (kf.time - lastKeyframe!.time));
32
+ if (!this.keys || this.keys.length == 0) return 0;
33
+ // if the first keyframe time is already greater than the time we want to evaluate
34
+ // then we dont need to iterate
35
+ if (this.keys[0].time >= time) {
36
+ return this.keys[0].value;
37
+ }
38
+ for (let i = 0; i < this.keys.length; i++) {
39
+ const kf = this.keys[i];
40
+ if (kf.time <= time) {
41
+ const hasNextKeyframe = i+1 < this.keys.length;
42
+ if (hasNextKeyframe) {
43
+ const nextKf = this.keys[i+1];
44
+ // if the next
45
+ if(nextKf.time < time) continue;
46
+ const t = Mathf.remap(time, kf.time, nextKf.time, 0, 1);
47
+ return Mathf.lerp(kf.value, nextKf.value, t);
48
+ }
49
+ else {
50
+ return kf.value;
51
+ }
37
52
  }
38
- lastKeyframe = kf;
39
53
  }
40
- return this.keys[this.keys.length-1].value;
54
+ return this.keys[this.keys.length - 1].value;
41
55
  }
42
56
  }
@@ -1,10 +1,11 @@
1
1
  import { Behaviour } from "./Component";
2
2
  import * as THREE from "three";
3
3
  import { getParam } from "../engine/engine_utils";
4
- import { CreateWireCube } from "../engine/engine_gizmos";
4
+ import { CreateWireCube, Gizmos } from "../engine/engine_gizmos";
5
5
  import { getWorldPosition, getWorldScale } from "../engine/engine_three_utils";
6
6
 
7
7
  const gizmos = getParam("gizmos");
8
+ const debug = getParam("debugboxhelper");
8
9
 
9
10
  export class BoxHelperComponent extends Behaviour {
10
11
 
@@ -14,7 +15,7 @@ export class BoxHelperComponent extends Behaviour {
14
15
  private static _position: THREE.Vector3 = new THREE.Vector3();
15
16
  private static _size: THREE.Vector3 = new THREE.Vector3(.01, .01, .01);
16
17
 
17
- public isInBox(obj: THREE.Object3D, scaleFactor? : number): boolean | undefined {
18
+ public isInBox(obj: THREE.Object3D, scaleFactor?: number): boolean | undefined {
18
19
  if (!obj) return undefined;
19
20
 
20
21
  // if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
@@ -24,15 +25,13 @@ export class BoxHelperComponent extends Behaviour {
24
25
  this.box = new THREE.Box3();
25
26
  }
26
27
 
28
+
27
29
  if (obj.type === "Mesh") {
28
30
  BoxHelperComponent.testBox.setFromObject(obj);
29
31
  }
30
32
  else if (obj.type === "Group") {
33
+ BoxHelperComponent.testBox.makeEmpty();
31
34
  if (obj.children.length > 0) {
32
- BoxHelperComponent.testBox.setFromCenterAndSize(
33
- BoxHelperComponent._position.set(0, 0, 0),
34
- BoxHelperComponent._size.set(0, 0, 0)
35
- );
36
35
  for (let i = 0; i < obj.children.length; i++) {
37
36
  const ch = obj.children[i];
38
37
  if (ch.type === "Mesh") {
@@ -44,19 +43,17 @@ export class BoxHelperComponent extends Behaviour {
44
43
  else {
45
44
  const wp = getWorldPosition(obj, BoxHelperComponent._position);
46
45
  const size = getWorldScale(obj, BoxHelperComponent._size);
47
- if(scaleFactor !== undefined) size.multiplyScalar(scaleFactor);
46
+ if (scaleFactor !== undefined) size.multiplyScalar(scaleFactor);
48
47
  BoxHelperComponent.testBox.setFromCenterAndSize(wp, size);
49
48
  }
50
49
 
51
- // console.log("Obj box:", obj.name, obj.uuid, BoxHelperComponent.testBox.getCenter(new THREE.Vector3()), BoxHelperComponent.testBox.getSize(new THREE.Vector3()),
52
- // "\nTest box:", this.box.getCenter(new THREE.Vector3()), this.box.getSize(new THREE.Vector3()), this.context.time.frameCount);
53
- // this.tp.copy(obj.geometry.boundingBox);
54
- // // this.tp.setFromCenterAndSize(obj.position, obj.scale);
55
- // this.tp.applyMatrix4(obj.matrixWorld);
56
- // console.log(this.tp);
57
- // console.log(this.box?.min, this.box?.max, this.tp.min, this.tp.max);
58
50
  this.updateBox();
59
- return this.box?.intersectsBox(BoxHelperComponent.testBox);
51
+ const intersects = this.box?.intersectsBox(BoxHelperComponent.testBox);
52
+ if (intersects) {
53
+ if (debug)
54
+ Gizmos.DrawBox3(BoxHelperComponent.testBox, 0xff0000, 5);
55
+ }
56
+ return intersects;
60
57
  }
61
58
 
62
59
  public intersects(box: THREE.Box3): boolean {
@@ -1,6 +1,6 @@
1
1
  import { Behaviour, GameObject } from "./Component";
2
2
  import * as THREE from "three";
3
- import { getParam } from "../engine/engine_utils";
3
+ import { getParam, isMobileDevice } from "../engine/engine_utils";
4
4
  import { setWorldPositionXYZ } from "../engine/engine_three_utils";
5
5
  import { FrameEvent } from "../engine/engine_setup";
6
6
  import { serializeable } from "../engine/engine_serialization_decorator";
@@ -8,6 +8,7 @@ import { Color, DirectionalLight, OrthographicCamera } from "three";
8
8
  import { WebXR, WebXREvent } from "./WebXR";
9
9
  import { WebARSessionRoot } from "./WebARSessionRoot";
10
10
  import { ILight } from "../engine/engine_types";
11
+ import { Mathf } from "../engine/engine_math";
11
12
 
12
13
  // https://threejs.org/examples/webgl_shadowmap_csm.html
13
14
 
@@ -87,6 +88,7 @@ export class Light extends Behaviour implements ILight {
87
88
 
88
89
  @serializeable()
89
90
  private type: LightType = 0;
91
+
90
92
  public range: number = 1;
91
93
  public spotAngle: number = 1;
92
94
  public innerSpotAngle: number = 1;
@@ -137,7 +139,8 @@ export class Light extends Behaviour implements ILight {
137
139
  set shadows(val: LightShadows) {
138
140
  this._shadows = val;
139
141
  if (this.light) {
140
- this.light.castShadow = val === LightShadows.Hard || val === LightShadows.Soft;
142
+ this.light.castShadow = val !== LightShadows.None;
143
+ this.updateShadowSoftHard();
141
144
  }
142
145
  }
143
146
  get shadows(): LightShadows { return this._shadows; }
@@ -284,9 +287,9 @@ export class Light extends Behaviour implements ILight {
284
287
  }
285
288
 
286
289
  createLight() {
287
- if (this.light) return;
288
- let lightAlreadyCreated = this.selfIsLight;
289
- if (lightAlreadyCreated) {
290
+ const lightAlreadyCreated = this.selfIsLight;
291
+
292
+ if (lightAlreadyCreated && !this.light) {
290
293
  this.light = this.gameObject as unknown as THREE.Light;
291
294
 
292
295
  switch (this.type) {
@@ -295,7 +298,7 @@ export class Light extends Behaviour implements ILight {
295
298
  break;
296
299
  }
297
300
  }
298
- else {
301
+ else if(!this.light) {
299
302
  switch (this.type) {
300
303
  case LightType.Directional:
301
304
  // console.log(this);
@@ -339,7 +342,7 @@ export class Light extends Behaviour implements ILight {
339
342
  }
340
343
 
341
344
 
342
- if (this.light !== undefined) {
345
+ if (this.light) {
343
346
  this._intensity = this.light.intensity;
344
347
 
345
348
  if (this.shadows !== LightShadows.None) {
@@ -356,6 +359,9 @@ export class Light extends Behaviour implements ILight {
356
359
  this.light.shadow.mapSize.width = 2048;
357
360
  this.light.shadow.mapSize.height = 2048;
358
361
  }
362
+ // this.light.shadow.needsUpdate = true;
363
+ // console.log(this.light.shadow.mapSize);
364
+ // return;
359
365
 
360
366
  if (debug)
361
367
  console.log("Override shadow bias?", this._overrideShadowBiasSettings, this.shadowBias, this.shadowNormalBias);
@@ -370,7 +376,8 @@ export class Light extends Behaviour implements ILight {
370
376
  this.light.shadow.normalBias = this.shadowNormalBias * .0001;
371
377
  }
372
378
 
373
- // console.log(this.light.shadow, this);
379
+ this.updateShadowSoftHard();
380
+
374
381
  const cam = this.light.shadow.camera as THREE.OrthographicCamera;
375
382
  cam.near = this.shadowNearPlane;
376
383
  // use shadow distance that was set explictly (if any)
@@ -399,6 +406,8 @@ export class Light extends Behaviour implements ILight {
399
406
  cam.top *= sy;
400
407
  cam.bottom *= sy;
401
408
  }
409
+
410
+
402
411
  this.light.shadow.needsUpdate = true;
403
412
  if (debug)
404
413
  this.context.scene.add(new THREE.CameraHelper(cam));
@@ -425,6 +434,28 @@ export class Light extends Behaviour implements ILight {
425
434
  }
426
435
  }
427
436
 
437
+ static allowChangingRendererShadowMapType: boolean = true;
438
+
439
+ private updateShadowSoftHard() {
440
+ if (!this.light) return;
441
+ if (this.shadows === LightShadows.Soft) {
442
+ const radius = this.light.shadow.mapSize.width / 1024 * 5;
443
+ const samples = Mathf.clamp(Math.round(radius), 2, 10);
444
+ this.light.shadow.radius = radius;
445
+ this.light.shadow.blurSamples = samples;
446
+ if (isMobileDevice()) {
447
+ this.light.shadow.radius *= .5;
448
+ this.light.shadow.blurSamples = Math.floor(this.light.shadow.blurSamples * .5);
449
+ }
450
+ if (Light.allowChangingRendererShadowMapType)
451
+ this.context.renderer.shadowMap.type = THREE.VSMShadowMap;
452
+ }
453
+ else {
454
+ this.light.shadow.radius = 1;
455
+ this.light.shadow.blurSamples = 1;
456
+ }
457
+ }
458
+
428
459
  private setDirectionalLight(dirLight: DirectionalLight) {
429
460
  dirLight.add(dirLight.target);
430
461
  dirLight.target.position.set(0, 0, -1);