@@ -6,8 +6,11 @@
|
|
6
6
|
import { AxesHelper, Object3D } from 'three';
|
7
7
|
import { ICanvas, IGraphic } from './Interfaces';
|
8
8
|
import { ShadowCastingMode } from '../Renderer';
|
9
|
+
import { getParam } from '../../engine/engine_utils';
|
9
10
|
export const includesDir = "./include";
|
10
11
|
|
12
|
+
const debug = getParam("debugshadowcomponents");
|
13
|
+
|
11
14
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
|
12
15
|
|
13
16
|
|
@@ -128,6 +131,8 @@
|
|
128
131
|
// otherwise it will fail when object are enabled at runtime
|
129
132
|
if (needsUpdate)
|
130
133
|
ThreeMeshUI.update();
|
134
|
+
|
135
|
+
if(debug) console.log(this.shadowComponent)
|
131
136
|
}
|
132
137
|
|
133
138
|
|
@@ -8,7 +8,7 @@
|
|
8
8
|
import { getWorldPosition, Graphics } from "../engine/engine_three_utils";
|
9
9
|
import { Gizmos } from "../engine/engine_gizmos";
|
10
10
|
|
11
|
-
import { EquirectangularReflectionMapping, OrthographicCamera, PerspectiveCamera, Ray, sRGBEncoding, Vector3 } from "three";
|
11
|
+
import { EquirectangularReflectionMapping, OrthographicCamera, PerspectiveCamera, Ray, SRGBColorSpace, sRGBEncoding, Vector3 } from "three";
|
12
12
|
import { OrbitControls } from "./OrbitControls";
|
13
13
|
import { RenderTexture } from "../engine/engine_texture";
|
14
14
|
|
@@ -261,7 +261,7 @@
|
|
261
261
|
else
|
262
262
|
cam = this.gameObject.children[0] as THREE.PerspectiveCamera | THREE.OrthographicCamera | null;
|
263
263
|
if (cam && cam.isCamera) {
|
264
|
-
if (cam
|
264
|
+
if (cam instanceof PerspectiveCamera) {
|
265
265
|
if (this._fov)
|
266
266
|
cam.fov = this._fov;
|
267
267
|
cam.near = this._nearClipPlane;
|
@@ -391,7 +391,7 @@
|
|
391
391
|
else if (this.context.scene.background !== this._skybox) {
|
392
392
|
if (debug)
|
393
393
|
console.log("Set skybox", this._camera, this._skybox);
|
394
|
-
this._skybox.
|
394
|
+
this._skybox.colorSpace = SRGBColorSpace;
|
395
395
|
this._skybox.mapping = EquirectangularReflectionMapping;
|
396
396
|
this.context.scene.background = this._skybox;
|
397
397
|
}
|
@@ -190,6 +190,7 @@
|
|
190
190
|
}
|
191
191
|
|
192
192
|
onBeforeRenderRoutine = () => {
|
193
|
+
if(this.context.isInVR) return;
|
193
194
|
this.previousParent = this.gameObject.parent;
|
194
195
|
// console.log(this.previousParent?.name + "/" + this.gameObject.name);
|
195
196
|
|
@@ -208,6 +209,7 @@
|
|
208
209
|
}
|
209
210
|
|
210
211
|
onAfterRenderRoutine = () => {
|
212
|
+
if(this.context.isInVR) return;
|
211
213
|
if ((this.screenspace || this.renderOnTop) && this.previousParent && this.context.mainCamera) {
|
212
214
|
if (this.screenspace) {
|
213
215
|
const camObj = this.context.mainCamera;
|
@@ -215,7 +217,10 @@
|
|
215
217
|
} else {
|
216
218
|
this.previousParent.add(this.gameObject);
|
217
219
|
}
|
220
|
+
const prevAutoClearDepth = this.context.renderer.autoClear;
|
221
|
+
const prevAutoClearColor = this.context.renderer.autoClearColor;
|
218
222
|
this.context.renderer.autoClear = false;
|
223
|
+
this.context.renderer.autoClearColor = false;
|
219
224
|
this.context.renderer.clearDepth();
|
220
225
|
this.onUpdateRenderMode(true);
|
221
226
|
this.handleLayoutUpdates();
|
@@ -223,7 +228,8 @@
|
|
223
228
|
// this.handleLayoutUpdates();
|
224
229
|
EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context);
|
225
230
|
this.context.renderer.render(this.gameObject, this.context.mainCamera);
|
226
|
-
this.context.renderer.autoClear =
|
231
|
+
this.context.renderer.autoClear = prevAutoClearDepth;
|
232
|
+
this.context.renderer.autoClearColor = prevAutoClearColor;
|
227
233
|
this.previousParent.add(this.gameObject);
|
228
234
|
}
|
229
235
|
this._lastMatrixWorld?.copy(this.gameObject.matrixWorld);
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import {
|
2
2
|
BufferGeometry, Cache, Camera, Clock, Color, DepthTexture, Group,
|
3
3
|
Material, NearestFilter, NoToneMapping, Object3D, PCFSoftShadowMap,
|
4
|
-
PerspectiveCamera, RGBAFormat, Scene,
|
5
|
-
Texture, WebGLRenderer, WebGLRendererParameters, WebGLRenderTarget
|
4
|
+
PerspectiveCamera, RGBAFormat, Scene, SRGBColorSpace,
|
5
|
+
Texture, WebGLRenderer, WebGLRendererParameters, WebGLRenderTarget, WebXRArrayCamera
|
6
6
|
} from 'three'
|
7
7
|
import { Input } from './engine_input';
|
8
8
|
import { Physics } from './engine_physics';
|
@@ -28,7 +28,7 @@
|
|
28
28
|
import { CoroutineData, GLTF, ICamera, IComponent, IContext, ILight } from "./engine_types"
|
29
29
|
import { destroy, foreachComponent } from './engine_gameobject';
|
30
30
|
import { ContextEvent, ContextRegistry } from './engine_context_registry';
|
31
|
-
import { delay } from './engine_utils';
|
31
|
+
import { delay, getParam } from './engine_utils';
|
32
32
|
import { VERSION } from './engine_constants';
|
33
33
|
import { isDevEnvironment, LogType, showBalloonMessage } from './debug';
|
34
34
|
|
@@ -202,6 +202,7 @@
|
|
202
202
|
get isInAR() { return this.xrSessionMode === XRSessionMode.ImmersiveAR; }
|
203
203
|
get xrSession() { return this.renderer.xr?.getSession(); }
|
204
204
|
get xrFrame() { return this._xrFrame }
|
205
|
+
get xrCamera() : WebXRArrayCamera | undefined { return this.renderer.xr?.getCamera(); }
|
205
206
|
private _xrFrame: XRFrame | null = null;
|
206
207
|
get arOverlayElement(): HTMLElement {
|
207
208
|
const el = this.domElement as any;
|
@@ -276,7 +277,7 @@
|
|
276
277
|
private _isCreating: boolean = false;
|
277
278
|
private _isVisible: boolean = false;
|
278
279
|
|
279
|
-
private _stats
|
280
|
+
private _stats = stats ? new Stats.default() : null;
|
280
281
|
|
281
282
|
constructor(args?: ContextArgs) {
|
282
283
|
this.name = args?.name || "";
|
@@ -323,9 +324,7 @@
|
|
323
324
|
private createRenderer() {
|
324
325
|
this.renderer?.dispose();
|
325
326
|
|
326
|
-
const params
|
327
|
-
antialias: true,
|
328
|
-
};
|
327
|
+
const params = this.getWebGLRendererParameters();
|
329
328
|
|
330
329
|
// get canvas already configured in the Needle Engine Web Component
|
331
330
|
const canvas = this.domElement?.shadowRoot?.querySelector("canvas");
|
@@ -333,23 +332,31 @@
|
|
333
332
|
|
334
333
|
this.renderer = new WebGLRenderer(params);
|
335
334
|
|
335
|
+
this.renderer.debug.checkShaderErrors = isDevEnvironment() || getParam("checkshadererrors") === true;
|
336
|
+
|
336
337
|
// some tonemapping other than "NONE" is required for adjusting exposure with EXR environments
|
337
338
|
this.renderer.toneMappingExposure = 1; // range [0...inf] instead of the usual -15..15
|
338
339
|
this.renderer.toneMapping = NoToneMapping; // could also set to LinearToneMapping, ACESFilmicToneMapping
|
339
340
|
|
340
341
|
this.renderer.setClearColor(new Color('lightgrey'), 0);
|
341
|
-
// @ts-ignore
|
342
|
-
this.renderer.
|
343
|
-
// @ts-ignore
|
344
|
-
this.renderer.alpha = false;
|
342
|
+
// // @ts-ignore
|
343
|
+
// this.renderer.alpha = false;
|
345
344
|
this.renderer.shadowMap.enabled = true;
|
346
345
|
this.renderer.shadowMap.type = PCFSoftShadowMap;
|
347
346
|
this.renderer.setSize(this.domWidth, this.domHeight);
|
348
|
-
this.renderer.
|
349
|
-
|
347
|
+
this.renderer.outputColorSpace = SRGBColorSpace;
|
348
|
+
// https://github.com/mrdoob/three.js/pull/25556
|
349
|
+
this.renderer.useLegacyLights = false;
|
350
350
|
}
|
351
351
|
|
352
|
+
private getWebGLRendererParameters(): WebGLRendererParameters {
|
353
|
+
return {
|
354
|
+
antialias: true,
|
355
|
+
alpha: false,
|
356
|
+
};
|
357
|
+
}
|
352
358
|
|
359
|
+
|
353
360
|
private _intersectionObserver: IntersectionObserver | null = null;
|
354
361
|
private internalOnUpdateVisible() {
|
355
362
|
this._intersectionObserver?.disconnect();
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { LightmapType } from "./extensions/NEEDLE_lightmaps";
|
2
|
-
import { Texture } from "three";
|
2
|
+
import { Texture, ShaderChunk, UniformsLib, Vector4 } from "three";
|
3
3
|
import { Context } from "./engine_setup";
|
4
|
-
import * as THREE from "three";
|
5
4
|
import { getParam } from "./engine_utils";
|
6
5
|
import { SourceIdentifier } from "./engine_types";
|
7
6
|
|
@@ -78,9 +77,8 @@
|
|
78
77
|
// all the chunks we can patch
|
79
78
|
// console.log(THREE.ShaderChunk);
|
80
79
|
// Unity: ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; ambientOrLightmapUV.zw = 0;
|
81
|
-
|
82
|
-
|
83
|
-
vec2 lUv = vUv2.xy * lightmapScaleOffset.xy + vec2(lightmapScaleOffset.z, (1. - (lightmapScaleOffset.y + lightmapScaleOffset.w)));
|
80
|
+
ShaderChunk.lights_fragment_maps = ShaderChunk.lights_fragment_maps.replace("vec4 lightMapTexel = texture2D( lightMap, vLightMapUv );", `
|
81
|
+
vec2 lUv = vLightMapUv.xy * lightmapScaleOffset.xy + vec2(lightmapScaleOffset.z, (1. - (lightmapScaleOffset.y + lightmapScaleOffset.w)));
|
84
82
|
vec4 lightMapTexel = texture2D( lightMap, lUv);
|
85
83
|
// The range of RGBM lightmaps goes from 0 to 34.49 (5^2.2) in linear space, and from 0 to 5 in gamma space.
|
86
84
|
lightMapTexel.rgb *= lightMapTexel.a * 8.; // no idea where that "8" comes from... heuristically derived
|
@@ -88,7 +86,7 @@
|
|
88
86
|
lightMapTexel = conv_sRGBToLinear(lightMapTexel);
|
89
87
|
`);
|
90
88
|
|
91
|
-
|
89
|
+
ShaderChunk.lightmap_pars_fragment = `
|
92
90
|
#ifdef USE_LIGHTMAP
|
93
91
|
uniform sampler2D lightMap;
|
94
92
|
uniform float lightMapIntensity;
|
@@ -105,7 +103,7 @@
|
|
105
103
|
// so they shouldn't receive light probe lighting.
|
106
104
|
// TODO: this gets difficult if there are additional real-time lightprobes added; we would need to exclude
|
107
105
|
// exactly those that were active when lighting was baked... that's complicated!
|
108
|
-
|
106
|
+
ShaderChunk.lights_fragment_begin = ShaderChunk.lights_fragment_begin.replace(
|
109
107
|
"irradiance += getLightProbeIrradiance( lightProbe, geometry.normal );", `
|
110
108
|
#if defined(USE_LIGHTMAP)
|
111
109
|
irradiance += 0.;
|
@@ -113,4 +111,4 @@
|
|
113
111
|
irradiance += getLightProbeIrradiance( lightProbe, geometry.normal );
|
114
112
|
#endif`);
|
115
113
|
|
116
|
-
|
114
|
+
UniformsLib.lightmap["lightmapScaleOffset"] = { value: new Vector4(1, 1, 0, 0) };
|
@@ -7,7 +7,7 @@
|
|
7
7
|
const localNetworkResults = new Map<string, boolean>();
|
8
8
|
|
9
9
|
export function isLocalNetwork(hostname = window.location.hostname) {
|
10
|
-
if(localNetworkResults.has(hostname)) return localNetworkResults.get(hostname)
|
10
|
+
if(localNetworkResults.has(hostname)) return localNetworkResults.get(hostname)!;
|
11
11
|
const isLocalNetwork = new RegExp("[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|localhost", "gm").test(hostname);
|
12
12
|
localNetworkResults.set(hostname, isLocalNetwork);
|
13
13
|
if (isLocalNetwork === true) return true;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Vector4, EquirectangularReflectionMapping, sRGBEncoding, WebGLCubeRenderTarget, Texture, LightProbe, Color, SphericalHarmonics3 } from "three";
|
1
|
+
import { Vector4, EquirectangularReflectionMapping, sRGBEncoding, WebGLCubeRenderTarget, Texture, LightProbe, Color, SphericalHarmonics3, SRGBColorSpace } from "three";
|
2
2
|
import { LightProbeGenerator } from "three/examples/jsm/lights/LightProbeGenerator.js"
|
3
3
|
import { Context } from "./engine_setup";
|
4
4
|
import { SceneLightSettings } from "./extensions/NEEDLE_lighting_settings";
|
@@ -164,7 +164,7 @@
|
|
164
164
|
if (debug) console.log("Setting environment reflection", existing);
|
165
165
|
const scene = this.context.scene;
|
166
166
|
const tex = existing.Source;
|
167
|
-
tex.
|
167
|
+
tex.colorSpace = SRGBColorSpace;
|
168
168
|
tex.mapping = EquirectangularReflectionMapping;
|
169
169
|
scene.environment = tex;
|
170
170
|
return;
|
@@ -179,7 +179,7 @@
|
|
179
179
|
if (settings.ambientTrilight) {
|
180
180
|
const colors = settings.ambientTrilight;
|
181
181
|
const tex = createTrilightTexture(colors[0], colors[1], colors[2], 64, 64);
|
182
|
-
tex.
|
182
|
+
tex.colorSpace = SRGBColorSpace;
|
183
183
|
tex.mapping = EquirectangularReflectionMapping;
|
184
184
|
this.context.scene.environment = tex;
|
185
185
|
}
|
@@ -188,7 +188,7 @@
|
|
188
188
|
case AmbientMode.Flat:
|
189
189
|
if (settings.ambientLight) {
|
190
190
|
const tex = createFlatTexture(settings.ambientLight, 64);
|
191
|
-
tex.
|
191
|
+
tex.colorSpace = SRGBColorSpace;
|
192
192
|
tex.mapping = EquirectangularReflectionMapping;
|
193
193
|
this.context.scene.environment = tex;
|
194
194
|
}
|
@@ -259,7 +259,7 @@
|
|
259
259
|
this._source = tex;
|
260
260
|
this._ambientScale = ambientScale;
|
261
261
|
tex.mapping = EquirectangularReflectionMapping;
|
262
|
-
tex.
|
262
|
+
tex.colorSpace = SRGBColorSpace;
|
263
263
|
}
|
264
264
|
|
265
265
|
getSphericalHarmonicsArray(intensityFactor: number = 1): SphericalHarmonicsData | null {
|
@@ -16,7 +16,17 @@
|
|
16
16
|
import { InternalUsageTrackerPlugin } from "./usage_tracker";
|
17
17
|
import { isUsageTrackingEnabled } from "../engine_assetdatabase";
|
18
18
|
import { GLTFLoaderPlugin } from "three/examples/jsm/loaders/GLTFLoader";
|
19
|
+
// import { GLTFAnimationPointerExtension } from "three/examples/jsm/loaders/GLTFLoaderAnimationPointer";
|
19
20
|
|
21
|
+
// lazily import the GLTFAnimationPointerExtension in case it doesnt exist (e.g. using vanilla three)
|
22
|
+
let GLTFAnimationPointerExtension : any;
|
23
|
+
import("three/examples/jsm/loaders/GLTFLoaderAnimationPointer").then(mod => {
|
24
|
+
GLTFAnimationPointerExtension = mod.GLTFAnimationPointerExtension;
|
25
|
+
return GLTFAnimationPointerExtension;
|
26
|
+
}).catch(e => {
|
27
|
+
console.warn("Failed to import GLTFLoaderAnimationPointer. Please use @needle-tools/three for full KHR_animation support", e);
|
28
|
+
});
|
29
|
+
|
20
30
|
const _addedCustomExtension = new Array<ConstructorConcrete<GLTFLoaderPlugin>>();
|
21
31
|
|
22
32
|
export function addCustomExtension(ext: ConstructorConcrete<GLTFLoaderPlugin>) {
|
@@ -70,8 +80,13 @@
|
|
70
80
|
for (const ext of _addedCustomExtension)
|
71
81
|
loader.register(p => new ext(p));
|
72
82
|
|
73
|
-
|
74
|
-
|
75
|
-
|
83
|
+
loader.register(p => {
|
84
|
+
if (GLTFAnimationPointerExtension) {
|
85
|
+
const ext = new GLTFAnimationPointerExtension(p);
|
86
|
+
const setPointerResolverFunction = ext.setAnimationPointerResolver;
|
87
|
+
setPointerResolverFunction.bind(ext)(new PointerResolver());
|
88
|
+
return ext;
|
89
|
+
}
|
90
|
+
});
|
76
91
|
|
77
92
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
2
|
-
import {
|
2
|
+
import { GroundProjectedSkybox as GroundProjection } from 'three/examples/jsm/objects/GroundProjectedSkybox.js';
|
3
3
|
import { serializable } from "../engine/engine_serialization_decorator";
|
4
4
|
import { Watch as Watch } from "../engine/engine_utils";
|
5
5
|
import { Texture } from "three";
|
@@ -173,6 +173,7 @@
|
|
173
173
|
}
|
174
174
|
this.light.intensity = val * factor;
|
175
175
|
}
|
176
|
+
if (debug) console.log("Set light intensity to " + this._intensity, val, this)
|
176
177
|
}
|
177
178
|
get intensity(): number { return this._intensity; }
|
178
179
|
private _intensity: number = -1;
|
@@ -180,7 +181,7 @@
|
|
180
181
|
@serializable()
|
181
182
|
get shadowDistance(): number {
|
182
183
|
const light = this.light;
|
183
|
-
if (light) {
|
184
|
+
if (light?.shadow) {
|
184
185
|
const cam = light.shadow.camera as OrthographicCamera;
|
185
186
|
return cam.far;
|
186
187
|
}
|
@@ -189,7 +190,7 @@
|
|
189
190
|
set shadowDistance(val: number) {
|
190
191
|
this._shadowDistance = val;
|
191
192
|
const light = this.light;
|
192
|
-
if (light) {
|
193
|
+
if (light?.shadow) {
|
193
194
|
const cam = light.shadow.camera as OrthographicCamera;
|
194
195
|
cam.far = val;
|
195
196
|
cam.updateProjectionMatrix();
|
@@ -203,7 +204,7 @@
|
|
203
204
|
@serializable()
|
204
205
|
get shadowResolution(): number {
|
205
206
|
const light = this.light;
|
206
|
-
if (light) {
|
207
|
+
if (light?.shadow) {
|
207
208
|
return light.shadow.mapSize.x;
|
208
209
|
}
|
209
210
|
return -1;
|
@@ -212,7 +213,7 @@
|
|
212
213
|
if (val === this._shadowResolution) return;
|
213
214
|
this._shadowResolution = val;
|
214
215
|
const light = this.light;
|
215
|
-
if (light) {
|
216
|
+
if (light?.shadow) {
|
216
217
|
light.shadow.mapSize.set(val, val);
|
217
218
|
light.shadow.needsUpdate = true;
|
218
219
|
}
|
@@ -256,12 +257,13 @@
|
|
256
257
|
}
|
257
258
|
|
258
259
|
onEnable(): void {
|
259
|
-
if(debug) console.log("ENABLE LIGHT", this.name);
|
260
|
+
if (debug) console.log("ENABLE LIGHT", this.name);
|
260
261
|
this.createLight();
|
261
262
|
if (this.isBaked) return;
|
262
263
|
else if (this.light) {
|
263
264
|
this.light.visible = true;
|
264
265
|
this.light.intensity = this._intensity;
|
266
|
+
if (debug) console.log("Set light intensity to " + this.light.intensity, this.name)
|
265
267
|
if (this.selfIsLight) {
|
266
268
|
// nothing to do
|
267
269
|
}
|
@@ -275,7 +277,7 @@
|
|
275
277
|
}
|
276
278
|
|
277
279
|
onDisable() {
|
278
|
-
if(debug) console.log("DISABLE LIGHT", this.name);
|
280
|
+
if (debug) console.log("DISABLE LIGHT", this.name);
|
279
281
|
if (this.light) {
|
280
282
|
if (this.selfIsLight)
|
281
283
|
this.light.intensity = 0;
|
@@ -376,62 +378,64 @@
|
|
376
378
|
}
|
377
379
|
else this.light.castShadow = false;
|
378
380
|
|
379
|
-
|
380
|
-
|
381
|
-
this.
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
381
|
+
if (this.light.shadow) {
|
382
|
+
// shadow intensity is currently not a thing: https://github.com/mrdoob/three.js/pull/14087
|
383
|
+
if (this._shadowResolution !== undefined && this._shadowResolution > 4) {
|
384
|
+
this.light.shadow.mapSize.width = this._shadowResolution;
|
385
|
+
this.light.shadow.mapSize.height = this._shadowResolution;
|
386
|
+
}
|
387
|
+
else {
|
388
|
+
this.light.shadow.mapSize.width = 2048;
|
389
|
+
this.light.shadow.mapSize.height = 2048;
|
390
|
+
}
|
391
|
+
// this.light.shadow.needsUpdate = true;
|
392
|
+
// console.log(this.light.shadow.mapSize);
|
393
|
+
// return;
|
391
394
|
|
392
|
-
|
393
|
-
|
395
|
+
if (debug)
|
396
|
+
console.log("Override shadow bias?", this._overrideShadowBiasSettings, this.shadowBias, this.shadowNormalBias);
|
394
397
|
|
395
|
-
|
396
|
-
|
398
|
+
this.light.shadow.bias = this.shadowBias;
|
399
|
+
this.light.shadow.normalBias = this.shadowNormalBias;
|
397
400
|
|
398
|
-
|
401
|
+
this.updateShadowSoftHard();
|
399
402
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
403
|
+
const cam = this.light.shadow.camera as THREE.OrthographicCamera;
|
404
|
+
cam.near = this.shadowNearPlane;
|
405
|
+
// use shadow distance that was set explictly (if any)
|
406
|
+
if (this._shadowDistance !== undefined && typeof this._shadowDistance === "number")
|
407
|
+
cam.far = this._shadowDistance;
|
408
|
+
else // otherwise fallback to object scale and max distance
|
409
|
+
cam.far = shadowMaxDistance * Math.abs(this.gameObject.scale.z);
|
407
410
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
411
|
+
// width and height
|
412
|
+
this.gameObject.scale.set(1, 1, 1);
|
413
|
+
if (this.shadowWidth !== undefined) {
|
414
|
+
cam.left = -this.shadowWidth / 2;
|
415
|
+
cam.right = this.shadowWidth / 2;
|
416
|
+
}
|
417
|
+
else {
|
418
|
+
const sx = this.gameObject.scale.x;
|
419
|
+
cam.left *= sx;
|
420
|
+
cam.right *= sx;
|
421
|
+
}
|
422
|
+
if (this.shadowHeight !== undefined) {
|
423
|
+
cam.top = this.shadowHeight / 2;
|
424
|
+
cam.bottom = -this.shadowHeight / 2;
|
425
|
+
}
|
426
|
+
else {
|
427
|
+
const sy = this.gameObject.scale.y;
|
428
|
+
cam.top *= sy;
|
429
|
+
cam.bottom *= sy;
|
430
|
+
}
|
431
|
+
this.light.shadow.needsUpdate = true;
|
432
|
+
|
433
|
+
if (debug)
|
434
|
+
this.context.scene.add(new THREE.CameraHelper(cam));
|
413
435
|
}
|
414
|
-
else {
|
415
|
-
const sx = this.gameObject.scale.x;
|
416
|
-
cam.left *= sx;
|
417
|
-
cam.right *= sx;
|
418
|
-
}
|
419
|
-
if (this.shadowHeight !== undefined) {
|
420
|
-
cam.top = this.shadowHeight / 2;
|
421
|
-
cam.bottom = -this.shadowHeight / 2;
|
422
|
-
}
|
423
|
-
else {
|
424
|
-
const sy = this.gameObject.scale.y;
|
425
|
-
cam.top *= sy;
|
426
|
-
cam.bottom *= sy;
|
427
|
-
}
|
428
436
|
|
429
437
|
|
430
|
-
this.light.shadow.needsUpdate = true;
|
431
|
-
if (debug)
|
432
|
-
this.context.scene.add(new THREE.CameraHelper(cam));
|
433
438
|
|
434
|
-
|
435
439
|
if (this.isBaked) {
|
436
440
|
this.light.removeFromParent();
|
437
441
|
}
|
@@ -457,6 +461,7 @@
|
|
457
461
|
|
458
462
|
private updateShadowSoftHard() {
|
459
463
|
if (!this.light) return;
|
464
|
+
if (!this.light.shadow) return;
|
460
465
|
if (this.shadows === LightShadows.Soft) {
|
461
466
|
// const radius = this.light.shadow.mapSize.width / 1024 * 5;
|
462
467
|
// const samples = Mathf.clamp(Math.round(radius), 2, 10);
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ILightDataRegistry } from "../engine_lightdata";
|
2
|
-
import { FloatType, HalfFloatType, LinearEncoding, sRGBEncoding, Texture } from "three";
|
2
|
+
import { FloatType, HalfFloatType, LinearEncoding, LinearSRGBColorSpace, SRGBColorSpace, sRGBEncoding, Texture } from "three";
|
3
3
|
import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
|
4
4
|
import { SourceIdentifier } from "../engine_types";
|
5
5
|
import { resolveReferences } from "./extension_utils";
|
@@ -70,9 +70,9 @@
|
|
70
70
|
else {
|
71
71
|
// TODO this is most likely wrong for floating point textures
|
72
72
|
if (entry.type !== LightmapType.Lightmap)
|
73
|
-
tex.
|
73
|
+
tex.colorSpace = SRGBColorSpace;
|
74
74
|
else
|
75
|
-
tex.
|
75
|
+
tex.colorSpace = LinearSRGBColorSpace;
|
76
76
|
|
77
77
|
|
78
78
|
// Dont flip skybox textures anymore - previously we exported them flipped when baking in Unity but now we allow to pass through export without re-baking exisitng skybox textures if they use default values. So we expect textures to be NOT flipped anymore
|
@@ -22,6 +22,8 @@
|
|
22
22
|
IncrementWrapStencilOp,
|
23
23
|
DecrementWrapStencilOp,
|
24
24
|
InvertStencilOp,
|
25
|
+
StencilFunc,
|
26
|
+
StencilOp as ThreeStencilOp,
|
25
27
|
} from "three";
|
26
28
|
import { getParam, isDebugMode } from "../engine_utils";
|
27
29
|
import { showBalloonWarning } from "../debug";
|
@@ -81,10 +83,10 @@
|
|
81
83
|
mat.stencilWriteMask = 255;
|
82
84
|
mat.stencilFuncMask = 255;
|
83
85
|
mat.stencilRef = stencil.value;
|
84
|
-
mat.stencilFunc = stencil.compareFunc;
|
85
|
-
mat.stencilZPass = stencil.passOp;
|
86
|
-
mat.stencilFail = stencil.failOp;
|
87
|
-
mat.stencilZFail = stencil.zFailOp;
|
86
|
+
mat.stencilFunc = stencil.compareFunc as StencilFunc;
|
87
|
+
mat.stencilZPass = stencil.passOp as ThreeStencilOp;
|
88
|
+
mat.stencilFail = stencil.failOp as ThreeStencilOp;
|
89
|
+
mat.stencilZFail = stencil.zFailOp as ThreeStencilOp;
|
88
90
|
obj.sharedMaterials[i] = mat;
|
89
91
|
}
|
90
92
|
}
|
@@ -116,7 +118,7 @@
|
|
116
118
|
if (stencils && Array.isArray(stencils)) {
|
117
119
|
for (const stencil of stencils) {
|
118
120
|
const obj: StencilSettingsModel = { ...stencil };
|
119
|
-
obj.compareFunc = ToThreeCompareFunction(obj.compareFunc);
|
121
|
+
obj.compareFunc = ToThreeCompareFunction(obj.compareFunc as number);
|
120
122
|
obj.passOp = ToThreeStencilOp(obj.passOp);
|
121
123
|
obj.failOp = ToThreeStencilOp(obj.failOp);
|
122
124
|
obj.zFailOp = ToThreeStencilOp(obj.zFailOp);
|
@@ -161,7 +163,7 @@
|
|
161
163
|
Always,
|
162
164
|
}
|
163
165
|
|
164
|
-
function ToThreeStencilOp(op: StencilOp):
|
166
|
+
function ToThreeStencilOp(op: StencilOp): ThreeStencilOp {
|
165
167
|
switch (op) {
|
166
168
|
case StencilOp.Keep:
|
167
169
|
return KeepStencilOp;
|
@@ -183,7 +185,7 @@
|
|
183
185
|
return 0;
|
184
186
|
}
|
185
187
|
|
186
|
-
function ToThreeCompareFunction(func: CompareFunction):
|
188
|
+
function ToThreeCompareFunction(func: CompareFunction): StencilFunc {
|
187
189
|
switch (func) {
|
188
190
|
case CompareFunction.Never:
|
189
191
|
return NeverStencilFunc;
|
@@ -202,7 +204,7 @@
|
|
202
204
|
case CompareFunction.Always:
|
203
205
|
return AlwaysStencilFunc;
|
204
206
|
}
|
205
|
-
return
|
207
|
+
return NeverStencilFunc;
|
206
208
|
}
|
207
209
|
|
208
210
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
|
2
2
|
import { FindShaderTechniques, whiteDefaultTexture, ToUnityMatrixArray, SetUnitySphericalHarmonics } from '../engine_shaders';
|
3
|
-
import { AlwaysDepth, BackSide, Camera, DoubleSide, EqualDepth, FrontSide, GreaterDepth, GreaterEqualDepth, IUniform, LessDepth, LessEqualDepth, LinearEncoding, Material, Matrix4, NotEqualDepth, Object3D, RawShaderMaterial, Vector3, Vector4 } from 'three';
|
3
|
+
import { AlwaysDepth, BackSide, Camera, DoubleSide, EqualDepth, FrontSide, GLSL3, GreaterDepth, GreaterEqualDepth, IUniform, LessDepth, LessEqualDepth, LinearEncoding, Material, Matrix4, NotEqualDepth, Object3D, RawShaderMaterial, Vector3, Vector4 } from 'three';
|
4
4
|
import { Context } from '../engine_setup';
|
5
5
|
import { getParam } from "../engine_utils";
|
6
6
|
import * as SHADERDATA from "../shaders/shaderData"
|
@@ -455,7 +455,11 @@
|
|
455
455
|
// "USE_SHADOWMAP" : true
|
456
456
|
// },
|
457
457
|
});
|
458
|
+
material.glslVersion = GLSL3;
|
459
|
+
material.vertexShader = material.vertexShader.replace("#version 300 es", "");
|
460
|
+
material.fragmentShader = material.fragmentShader.replace("#version 300 es", "");
|
458
461
|
|
462
|
+
|
459
463
|
const culling = uniforms["_Cull"]?.value;
|
460
464
|
switch (culling) {
|
461
465
|
case CullMode.Off:
|
@@ -272,10 +272,10 @@
|
|
272
272
|
if (!freeCam && this.lookAtConstraint?.locked) this.setFromTargetPosition(0, this.lookAtConstraint01);
|
273
273
|
|
274
274
|
|
275
|
-
if (this._controls
|
275
|
+
if (this._controls) {
|
276
276
|
if (this.debugLog)
|
277
277
|
this._controls.domElement = this.context.renderer.domElement;
|
278
|
-
this._controls.enabled = !this._shouldDisable && this._camera === this.context.mainCameraComponent;
|
278
|
+
this._controls.enabled = !this._shouldDisable && this._camera === this.context.mainCameraComponent && !this.context.isInXR;
|
279
279
|
this._controls.enableDamping = this.enableDamping;
|
280
280
|
this._controls.keys = this.enableKeys ? defaultKeys : disabledKeys;
|
281
281
|
this._controls.autoRotate = this.autoRotate;
|
@@ -283,7 +283,8 @@
|
|
283
283
|
this._controls.enableZoom = this.enableZoom;
|
284
284
|
this._controls.dampingFactor = this.dampingFactor;
|
285
285
|
this._controls.enablePan = this.enablePan;
|
286
|
-
this.
|
286
|
+
if (!this.context.isInXR)
|
287
|
+
this._controls.update();
|
287
288
|
}
|
288
289
|
}
|
289
290
|
|
@@ -69,7 +69,21 @@
|
|
69
69
|
return res;
|
70
70
|
}
|
71
71
|
|
72
|
+
private static _havePatchedQuarkShaders = false;
|
73
|
+
|
72
74
|
getMaterial(trailEnabled: boolean = false) {
|
75
|
+
|
76
|
+
if (!ParticleSystemRenderer._havePatchedQuarkShaders) {
|
77
|
+
ParticleSystemRenderer._havePatchedQuarkShaders = true;
|
78
|
+
|
79
|
+
// HACK patch three.quarks fo three152+, see https://github.com/Alchemist0823/three.quarks/issues/56#issuecomment-1560825038
|
80
|
+
const _rebuild = TrailBatch.prototype.rebuildMaterial;
|
81
|
+
TrailBatch.prototype.rebuildMaterial = function () {
|
82
|
+
_rebuild.call(this);
|
83
|
+
this.material.defines.MAP_UV = "uv";
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
73
87
|
const material = (trailEnabled === true && this.trailMaterial) ? this.trailMaterial : this.particleMaterial;
|
74
88
|
|
75
89
|
// progressive load on start
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Behaviour } from "./Component";
|
2
|
-
import { Box3, Color, EquirectangularReflectionMapping, LinearEncoding, LineBasicMaterial, Material, MeshStandardMaterial, Object3D, SrcAlphaFactor, sRGBEncoding, Texture, Vector3, WebGLCubeRenderTarget, WebGLRenderTarget } from "three";
|
2
|
+
import { Box3, Color, EquirectangularReflectionMapping, LinearEncoding, LineBasicMaterial, Material, MeshStandardMaterial, Object3D, SrcAlphaFactor, SRGBColorSpace, sRGBEncoding, Texture, Vector3, WebGLCubeRenderTarget, WebGLRenderTarget } from "three";
|
3
3
|
import { serializable } from "../engine/engine_serialization";
|
4
4
|
import { Context } from "../engine/engine_setup";
|
5
5
|
import { getWorldPosition, getWorldScale } from "../engine/engine_three_utils";
|
@@ -54,7 +54,7 @@
|
|
54
54
|
this._texture = tex;
|
55
55
|
if (tex) {
|
56
56
|
tex.mapping = EquirectangularReflectionMapping;
|
57
|
-
tex.
|
57
|
+
tex.colorSpace = SRGBColorSpace;
|
58
58
|
tex.needsUpdate = true;
|
59
59
|
}
|
60
60
|
}
|
@@ -89,7 +89,7 @@
|
|
89
89
|
|
90
90
|
if (this.texture) {
|
91
91
|
this.texture.mapping = EquirectangularReflectionMapping;
|
92
|
-
this.texture.
|
92
|
+
this.texture.colorSpace = SRGBColorSpace;
|
93
93
|
this.texture.needsUpdate = true;
|
94
94
|
}
|
95
95
|
}
|
@@ -20,7 +20,6 @@
|
|
20
20
|
|
21
21
|
const debugRenderer = getParam("debugrenderer");
|
22
22
|
const suppressInstancing = getParam("noInstancing");
|
23
|
-
const debugLightmap = getParam("debuglightmaps") ? true : false;
|
24
23
|
const debugInstancing = getParam("debuginstancing");
|
25
24
|
const debugProgressiveLoading = getParam("debugprogressive");
|
26
25
|
const suppressProgressiveLoading = getParam("noprogressive");
|
@@ -420,7 +419,7 @@
|
|
420
419
|
this._lightmaps.push(rm);
|
421
420
|
}
|
422
421
|
const rm = this._lightmaps[0];
|
423
|
-
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex
|
422
|
+
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex);
|
424
423
|
}
|
425
424
|
else {
|
426
425
|
if (mat)
|
@@ -440,7 +439,7 @@
|
|
440
439
|
}
|
441
440
|
else
|
442
441
|
rm = this._lightmaps[i];
|
443
|
-
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex
|
442
|
+
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex);
|
444
443
|
// onBeforeRender is not called when the renderer is on a group
|
445
444
|
// this is an issue we probably also need to handle for custom shaders
|
446
445
|
// and need a better solution, but for now this fixes lightmaps for multimaterial objects
|
@@ -1,8 +1,10 @@
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
2
|
-
import
|
3
|
-
import { Texture } from "three";
|
2
|
+
import { Material, Mesh, ShaderMaterial, Texture, Vector4 } from "three";
|
4
3
|
import { Context, OnRenderCallback } from "../engine/engine_setup";
|
4
|
+
import { getParam } from "../engine/engine_utils";
|
5
5
|
|
6
|
+
const debug = getParam("debuglightmaps");
|
7
|
+
|
6
8
|
// this component is automatically added by the Renderer if the object has lightmap uvs AND we have a lightmap
|
7
9
|
// for multimaterial objects GLTF exports a "Group" with the renderer component
|
8
10
|
// and every child mesh is a material from unity
|
@@ -19,20 +21,20 @@
|
|
19
21
|
}
|
20
22
|
|
21
23
|
lightmapIndex: number = -1;
|
22
|
-
lightmapScaleOffset: THREE.Vector4 = new
|
24
|
+
lightmapScaleOffset: THREE.Vector4 = new Vector4(1, 1, 0, 0);
|
23
25
|
|
24
26
|
private context: Context;
|
25
27
|
private gameObject: GameObject;
|
26
|
-
private lightmapTexture:
|
27
|
-
private lightmapScaleOffsetUniform = { value: new
|
28
|
-
private lightmapUniform: { value:
|
28
|
+
private lightmapTexture: Texture | null = null;
|
29
|
+
private lightmapScaleOffsetUniform = { value: new Vector4(1, 1, 0, 0) };
|
30
|
+
private lightmapUniform: { value: Texture | null } = { value: null };
|
29
31
|
|
30
32
|
constructor(gameObject: GameObject, context: Context) {
|
31
33
|
this.gameObject = gameObject;
|
32
34
|
this.context = context;
|
33
35
|
}
|
34
36
|
|
35
|
-
init(lightmapIndex: number, lightmapScaleOffset:
|
37
|
+
init(lightmapIndex: number, lightmapScaleOffset: Vector4, lightmapTexture: Texture) {
|
36
38
|
console.assert(this.gameObject !== undefined && this.gameObject !== null, "Missing gameobject", this);
|
37
39
|
|
38
40
|
this.lightmapIndex = lightmapIndex;
|
@@ -40,8 +42,7 @@
|
|
40
42
|
this.lightmapScaleOffset = lightmapScaleOffset;
|
41
43
|
this.lightmapTexture = lightmapTexture;
|
42
44
|
|
43
|
-
|
44
|
-
if (debugLightmaps) this.setLightmapDebugMaterial();
|
45
|
+
if (debug) this.setLightmapDebugMaterial();
|
45
46
|
this.applyLightmap();
|
46
47
|
}
|
47
48
|
|
@@ -68,15 +69,16 @@
|
|
68
69
|
|
69
70
|
console.assert(this.gameObject.type === "Mesh", "Lightmap only works on meshes", this);
|
70
71
|
|
71
|
-
const mesh = this.gameObject as unknown as
|
72
|
+
const mesh = this.gameObject as unknown as Mesh;
|
72
73
|
// TODO: ensure uv2 exists
|
73
|
-
if (!mesh.geometry.getAttribute("
|
74
|
-
mesh.geometry.setAttribute("
|
74
|
+
if (!mesh.geometry.getAttribute("uv1"))
|
75
|
+
mesh.geometry.setAttribute("uv1", mesh.geometry.getAttribute("uv"));
|
75
76
|
|
76
|
-
const mat = this.gameObject["material"].clone();
|
77
|
+
const mat: Material = this.gameObject["material"].clone();
|
77
78
|
this.gameObject["material"] = mat;
|
78
79
|
|
79
80
|
this.gameObject["material"].onBeforeCompile = (shader, _) => {
|
81
|
+
shader.lightMapUv = "uv1";
|
80
82
|
shader.uniforms.lightmap = this.lightmapUniform;
|
81
83
|
shader.uniforms.lightmapScaleOffset = this.lightmapScaleOffsetUniform;
|
82
84
|
};
|
@@ -107,13 +109,12 @@
|
|
107
109
|
private setLightmapDebugMaterial() {
|
108
110
|
|
109
111
|
// debug lightmaps
|
110
|
-
this.gameObject["material"] = new
|
112
|
+
this.gameObject["material"] = new ShaderMaterial({
|
111
113
|
vertexShader: `
|
112
|
-
|
113
|
-
varying vec2 vUv2;
|
114
|
+
varying vec2 vUv1;
|
114
115
|
void main()
|
115
116
|
{
|
116
|
-
|
117
|
+
vUv1 = uv1;
|
117
118
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
118
119
|
}
|
119
120
|
`,
|
@@ -121,7 +122,7 @@
|
|
121
122
|
uniform sampler2D lightmap;
|
122
123
|
uniform float lightMapIntensity;
|
123
124
|
uniform vec4 lightmapScaleOffset;
|
124
|
-
varying vec2
|
125
|
+
varying vec2 vUv1;
|
125
126
|
|
126
127
|
// took from threejs 05fc79cd52b79e8c3e8dec1e7dca72c5c39983a4
|
127
128
|
vec4 conv_sRGBToLinear( in vec4 value ) {
|
@@ -129,7 +130,7 @@
|
|
129
130
|
}
|
130
131
|
|
131
132
|
void main() {
|
132
|
-
vec2 lUv =
|
133
|
+
vec2 lUv = vUv1.xy * lightmapScaleOffset.xy + vec2(lightmapScaleOffset.z, (1. - (lightmapScaleOffset.y + lightmapScaleOffset.w)));
|
133
134
|
|
134
135
|
vec4 lightMapTexel = texture2D( lightmap, lUv);
|
135
136
|
// The range of RGBM lightmaps goes from 0 to 34.49 (5^2.2) in linear space, and from 0 to 5 in gamma space.
|
@@ -138,7 +139,7 @@
|
|
138
139
|
//lightMapTexel = conv_sRGBToLinear(lightMapTexel);
|
139
140
|
// lightMapTexel.rgb = vec3(1.);
|
140
141
|
|
141
|
-
// gl_FragColor = vec4(
|
142
|
+
// gl_FragColor = vec4(vUv1.xy, 0, 1);
|
142
143
|
gl_FragColor = lightMapTexel;
|
143
144
|
}
|
144
145
|
`,
|
@@ -3,7 +3,6 @@
|
|
3
3
|
import { RGBAColor } from "../js-extensions/RGBAColor"
|
4
4
|
import { WebXR } from "./WebXR";
|
5
5
|
import {
|
6
|
-
Camera as ThreeCamera,
|
7
6
|
Scene,
|
8
7
|
Texture,
|
9
8
|
Mesh, MeshBasicMaterial,
|
@@ -11,7 +10,8 @@
|
|
11
10
|
PlaneGeometry,
|
12
11
|
ShaderLib,
|
13
12
|
ShaderMaterial,
|
14
|
-
DoubleSide
|
13
|
+
DoubleSide,
|
14
|
+
PerspectiveCamera
|
15
15
|
} from "three";
|
16
16
|
|
17
17
|
export class WebARCameraBackground extends Behaviour {
|
@@ -53,7 +53,7 @@
|
|
53
53
|
const geometry = new PlaneGeometry();
|
54
54
|
const scene = new Scene();
|
55
55
|
scene.add(new Mesh(geometry, material));
|
56
|
-
const camera = new
|
56
|
+
const camera = new PerspectiveCamera();
|
57
57
|
|
58
58
|
return function forceTextureInitialization(renderer, texture) {
|
59
59
|
material.map = texture;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ArrayCamera, Color, Euler, EventDispatcher, Group, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, RingGeometry, Texture, Vector3 } from 'three';
|
1
|
+
import { ArrayCamera, Color, Euler, EventDispatcher, Group, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, RingGeometry, Texture, Vector3, WebXRArrayCamera } from 'three';
|
2
2
|
import { ARButton } from '../../include/three/ARButton.js';
|
3
3
|
import { VRButton } from '../../include/three/VRButton.js';
|
4
4
|
|
@@ -393,7 +393,7 @@
|
|
393
393
|
private _originalXRRigRotation: Quaternion = new Quaternion();
|
394
394
|
|
395
395
|
private onEnterXR(session: XRSession, frame: XRFrame) {
|
396
|
-
console.log("[XR] session begin", session);
|
396
|
+
console.log("[XR] session begin", session, frame);
|
397
397
|
WebXR._isInXr = true;
|
398
398
|
|
399
399
|
this.ensureRig();
|
@@ -414,16 +414,16 @@
|
|
414
414
|
// we set layers to sync raycasting and have a similar behaviour to unity
|
415
415
|
const xr = this.context.renderer.xr;
|
416
416
|
if (this.context.mainCamera) {
|
417
|
-
|
418
|
-
|
417
|
+
const cam = xr.getCamera() as WebXRArrayCamera;
|
418
|
+
if(debugWebXR) console.log("WebXRCamera", cam);
|
419
419
|
const cull = this.context.mainCameraComponent?.cullingMask;
|
420
|
-
if(cull !== undefined){
|
420
|
+
if(cam && cull !== undefined){
|
421
421
|
for (const c of cam.cameras) {
|
422
422
|
c.layers.mask = cull;
|
423
423
|
}
|
424
424
|
cam.layers.mask = cull;
|
425
425
|
}
|
426
|
-
else {
|
426
|
+
else if (cam) {
|
427
427
|
for (const c of cam.cameras) {
|
428
428
|
c.layers.enableAll();
|
429
429
|
}
|