Needle Engine

Changes between version 3.37.10-alpha.2 and 3.37.10-alpha.3
Files changed (2) hide show
  1. src/engine-components/Renderer.ts +4 -1
  2. src/engine-components/RendererLightmap.ts +48 -19
src/engine-components/Renderer.ts CHANGED
@@ -622,8 +622,9 @@
622
622
  else {
623
623
  this.context.removeBeforeRenderListener(this.gameObject, this.onBeforeRenderThree);
624
624
  }
625
+ }
625
626
 
626
- }
627
+
627
628
  onBeforeRender() {
628
629
  if (!this.gameObject) {
629
630
  return;
@@ -695,6 +696,7 @@
695
696
  const environmentIntensity = this.context.mainCameraComponent?.environmentIntensity ?? 1;
696
697
  material.envMapIntensity = Math.max(0, environmentIntensity * this.context.sceneLighting.environmentIntensity / factor);
697
698
  }
699
+
698
700
  // if (this._reflectionProbe?.texture) {
699
701
  // material.envMap = this._reflectionProbe.texture;
700
702
  // // this.context.renderer.prop
@@ -733,6 +735,7 @@
733
735
  if (this._lightmaps) {
734
736
  for (const lm of this._lightmaps) {
735
737
  lm.updateLightmapUniforms(material);
738
+ lm.applyLightmap();
736
739
  }
737
740
  }
738
741
  }
src/engine-components/RendererLightmap.ts CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  const debug = getParam("debuglightmaps");
7
7
 
8
+ declare type MaterialWithLightmap = Material & { lightMap?: Texture | null };
9
+
8
10
  // this component is automatically added by the Renderer if the object has lightmap uvs AND we have a lightmap
9
11
  // for multimaterial objects GLTF exports a "Group" with the renderer component
10
12
  // and every child mesh is a material from unity
@@ -36,16 +38,15 @@
36
38
 
37
39
  init(lightmapIndex: number, lightmapScaleOffset: Vector4, lightmapTexture: Texture) {
38
40
  console.assert(this.gameObject !== undefined && this.gameObject !== null, "Missing gameobject", this);
39
-
40
41
  this.lightmapIndex = lightmapIndex;
41
42
  if (this.lightmapIndex < 0) return;
42
43
  this.lightmapScaleOffset = lightmapScaleOffset;
43
44
  this.lightmapTexture = lightmapTexture;
44
-
45
- if (debug) {
45
+ if (debug == "show") {
46
46
  console.log("Lightmap:", this.gameObject.name, lightmapIndex, "\nScaleOffset:", lightmapScaleOffset, "\nTexture:", lightmapTexture)
47
47
  this.setLightmapDebugMaterial();
48
48
  }
49
+ else if(debug) console.log("Use debuglightmaps=show to render lightmaps only in the scene.")
49
50
  this.applyLightmap();
50
51
  }
51
52
 
@@ -57,8 +58,10 @@
57
58
  }
58
59
  }
59
60
 
60
-
61
- private applyLightmap() {
61
+ /**
62
+ * Apply the lightmap to the object. This will clone the material and set the lightmap texture and scale/offset
63
+ */
64
+ applyLightmap() {
62
65
  if (this.gameObject.type === "Object3D") {
63
66
  if (debug)
64
67
  console.warn("Can not add lightmap. Is this object missing a renderer?", this.gameObject.name);
@@ -79,31 +82,57 @@
79
82
  if (Array.isArray(this.gameObject.material)) {
80
83
  const mats: Material[] = this.gameObject.material;
81
84
  for (let i = 0; i < mats.length; i++) {
82
- const mat = mats[i];
83
- const cloned = mat.clone();
84
- mats[i] = cloned;
85
- cloned.onBeforeCompile = this.onBeforeCompile;
85
+ mats[i] = this.ensureLightmapMaterial(mats[i]);
86
86
  }
87
87
  }
88
88
  else {
89
- const mat: Material = this.gameObject.material.clone();
90
- this.gameObject.material = mat;
91
- this.gameObject.material.onBeforeCompile = this.onBeforeCompile;
89
+ this.gameObject.material = this.ensureLightmapMaterial(this.gameObject.material);
92
90
  }
93
91
 
94
92
  if (this.lightmapIndex >= 0 && this.lightmapTexture) {
95
- const mat = this.gameObject.material as any;
96
- if (mat) {
97
- mat.lightMap = this.lightmapTexture;
98
- // always on channel 1 for now. We could optimize this by passing the correct lightmap index along
99
- this.lightmapTexture.channel = 1;
100
- mat.needsUpdate = true;
93
+ // always on channel 1 for now. We could optimize this by passing the correct lightmap index along
94
+ this.lightmapTexture.channel = 1;
95
+ const mat = this.gameObject.material;
96
+ if (Array.isArray(mat)) {
97
+ for (const entry of mat) {
98
+ this.assignLightmapTexture(entry as any);
99
+
100
+ }
101
101
  }
102
+ else if (mat) {
103
+ this.assignLightmapTexture(mat);
104
+ }
102
105
  }
103
106
  }
104
107
 
108
+ private ensureLightmapMaterial(material: Material) {
109
+ if (!material.userData) material.userData = {};
110
+ // check if the material version has changed and only then clone the material
111
+ if (material["NEEDLE:lightmap-material-version"] != material.version) {
112
+ if (material["NEEDLE:lightmap-material-version"] == undefined) {
113
+ if (debug) console.warn("Cloning material for lightmap " + material.name);
114
+ const mat: Material = material.clone();
115
+ material = mat;
116
+ material.onBeforeCompile = this.onBeforeCompile;
117
+ }
118
+ else {
119
+ // we need to clone the material
120
+ }
121
+ }
122
+ return material;
123
+ }
124
+
125
+ private assignLightmapTexture(material: MaterialWithLightmap) {
126
+ if (!material) return;
127
+ // assign the lightmap
128
+ material.lightMap = this.lightmapTexture;
129
+ // store the version of the material
130
+ material["NEEDLE:lightmap-material-version"] = material.version;
131
+ // mat.needsUpdate = true;
132
+ }
133
+
105
134
  private onBeforeCompile = (shader: WebGLProgramParametersWithUniforms, _) => {
106
- if (debug) console.log("Lightmaps, before compile", shader)
135
+ if (debug) console.log("Lightmaps, before compile\n", shader)
107
136
  this.lightmapScaleOffsetUniform.value = this.lightmapScaleOffset;
108
137
  this.lightmapUniform.value = this.lightmapTexture;
109
138
  shader.uniforms.lightmapScaleOffset = this.lightmapScaleOffsetUniform;