@volter/threejs-runtime 0.5.82 → 0.5.84
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/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@volter/threejs-runtime",
|
|
3
3
|
"author": "Volter AI, Inc.",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.84",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@dimforge/rapier3d-compat": "^0.14.0",
|
|
44
44
|
"@recast-navigation/three": "^0.43.0",
|
|
45
45
|
"@sparkjsdev/spark": "^2.1.0",
|
|
46
|
-
"@volter/editor-project": "0.5.
|
|
46
|
+
"@volter/editor-project": "0.5.84",
|
|
47
47
|
"n8ao": "^1.10.1",
|
|
48
48
|
"postprocessing": "^6.38.0",
|
|
49
49
|
"quarks.core": "0.16.0",
|
|
@@ -103,9 +103,11 @@ export interface IblOverrideOptions {
|
|
|
103
103
|
/**
|
|
104
104
|
* The GLSL that replaces `#include <envmap_physical_pars_fragment>`. Read at
|
|
105
105
|
* COMPILE time, not at install time, so a caller whose probe count is still
|
|
106
|
-
* settling does not have to reinstall to change it.
|
|
106
|
+
* settling does not have to reinstall to change it. `null` leaves this
|
|
107
|
+
* program as three's own: nothing is spliced and `onCompile` is not called
|
|
108
|
+
* (a caller with no probes to light, say).
|
|
107
109
|
*/
|
|
108
|
-
readonly fragment: () => string;
|
|
110
|
+
readonly fragment: () => string | null;
|
|
109
111
|
/**
|
|
110
112
|
* Appended to the material's own `customProgramCacheKey`, after a `|`. Must
|
|
111
113
|
* distinguish every shape of {@link IblOverrideOptions.fragment} the caller
|
|
@@ -129,8 +131,14 @@ export interface IblOverride {
|
|
|
129
131
|
* `shader.uniforms`.
|
|
130
132
|
*/
|
|
131
133
|
readonly shader: IblOverrideShader | null;
|
|
132
|
-
/**
|
|
133
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Put the material's own `onBeforeCompile`/`customProgramCacheKey` back, if
|
|
136
|
+
* they are still this override's, and return `true`. Once something else has
|
|
137
|
+
* installed its hooks over it, restoring would remove theirs too, so the
|
|
138
|
+
* override stays and this returns `false`: the caller then still owns an
|
|
139
|
+
* override that is live.
|
|
140
|
+
*/
|
|
141
|
+
restore(): boolean;
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
/**
|
|
@@ -139,7 +147,10 @@ export interface IblOverride {
|
|
|
139
147
|
* (in particular this never assigns `envMap`, which stays the caller's).
|
|
140
148
|
*
|
|
141
149
|
* The caller's own `onBeforeCompile` runs FIRST and its result is what gets
|
|
142
|
-
* spliced, so an override composes over a material that already had one.
|
|
150
|
+
* spliced, so an override composes over a material that already had one. If
|
|
151
|
+
* that hook has already consumed a chunk the splice needs, the program keeps
|
|
152
|
+
* three's own lighting and the material warns once, rather than failing the
|
|
153
|
+
* draw.
|
|
143
154
|
*/
|
|
144
155
|
export function overrideMaterialIbl(
|
|
145
156
|
material: MeshStandardMaterial,
|
|
@@ -148,11 +159,23 @@ export function overrideMaterialIbl(
|
|
|
148
159
|
const previousCompile = material.onBeforeCompile;
|
|
149
160
|
const previousCacheKey = material.customProgramCacheKey;
|
|
150
161
|
let compiled: IblOverrideShader | null = null;
|
|
162
|
+
let warned = false;
|
|
151
163
|
|
|
152
|
-
|
|
164
|
+
const compile: MeshStandardMaterial['onBeforeCompile'] = (shader, renderer) => {
|
|
153
165
|
previousCompile.call(material, shader, renderer);
|
|
154
|
-
|
|
155
|
-
|
|
166
|
+
const fragment = options.fragment();
|
|
167
|
+
if (fragment === null) return;
|
|
168
|
+
const missing = missingChunk(shader);
|
|
169
|
+
if (missing !== null) {
|
|
170
|
+
if (!warned) {
|
|
171
|
+
warned = true;
|
|
172
|
+
// biome-ignore lint/suspicious/noConsole: a hook before this one took a chunk the splice needs; say why the override is not drawn.
|
|
173
|
+
console.warn(
|
|
174
|
+
`[overrideMaterialIbl] material "${material.name}" keeps three's own lighting: its program no longer contains ${missing}, which an earlier onBeforeCompile replaced.`,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
156
179
|
shader.vertexShader = `varying vec3 ${IBL_WORLD_POSITION};\n${shader.vertexShader.replace(
|
|
157
180
|
'#include <worldpos_vertex>',
|
|
158
181
|
`#include <worldpos_vertex>
|
|
@@ -162,12 +185,14 @@ export function overrideMaterialIbl(
|
|
|
162
185
|
)}`;
|
|
163
186
|
shader.fragmentShader = `varying vec3 ${IBL_WORLD_POSITION};\n${shader.fragmentShader.replace(
|
|
164
187
|
'#include <envmap_physical_pars_fragment>',
|
|
165
|
-
|
|
188
|
+
fragment,
|
|
166
189
|
)}`;
|
|
167
190
|
compiled = shader;
|
|
168
191
|
options.onCompile?.(shader);
|
|
169
192
|
};
|
|
170
|
-
|
|
193
|
+
const cacheKey = () => `${previousCacheKey.call(material)}|${options.cacheKey()}`;
|
|
194
|
+
material.onBeforeCompile = compile;
|
|
195
|
+
material.customProgramCacheKey = cacheKey;
|
|
171
196
|
material.needsUpdate = true;
|
|
172
197
|
|
|
173
198
|
return {
|
|
@@ -176,27 +201,31 @@ export function overrideMaterialIbl(
|
|
|
176
201
|
return compiled;
|
|
177
202
|
},
|
|
178
203
|
restore() {
|
|
204
|
+
// A hook installed after this one wraps it: putting the earlier hooks back
|
|
205
|
+
// would remove that one too, so the override then stays.
|
|
206
|
+
if (material.onBeforeCompile !== compile || material.customProgramCacheKey !== cacheKey) return false;
|
|
179
207
|
material.onBeforeCompile = previousCompile;
|
|
180
208
|
material.customProgramCacheKey = previousCacheKey;
|
|
181
209
|
material.needsUpdate = true;
|
|
182
210
|
compiled = null;
|
|
211
|
+
return true;
|
|
183
212
|
},
|
|
184
213
|
};
|
|
185
214
|
}
|
|
186
215
|
|
|
187
216
|
/**
|
|
188
|
-
*
|
|
217
|
+
* The chunk the splice needs that `shader` no longer contains, or null.
|
|
189
218
|
*
|
|
190
219
|
* `String.replace` with no match returns the string unchanged, which would
|
|
191
220
|
* leave the varying declared and never assigned — a shader that links and
|
|
192
|
-
* renders the wrong thing. The
|
|
221
|
+
* renders the wrong thing. The way to reach this is a preceding
|
|
193
222
|
* `onBeforeCompile` in the same chain having already replaced the chunk (two
|
|
194
|
-
* IBL overrides stacked on one material)
|
|
195
|
-
* the chunk instead of a black frame.
|
|
223
|
+
* IBL overrides stacked on one material).
|
|
196
224
|
*/
|
|
197
|
-
function
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
225
|
+
function missingChunk(shader: IblOverrideShader): string | null {
|
|
226
|
+
if (!shader.vertexShader.includes('#include <worldpos_vertex>')) return '#include <worldpos_vertex>';
|
|
227
|
+
if (!shader.fragmentShader.includes('#include <envmap_physical_pars_fragment>')) {
|
|
228
|
+
return '#include <envmap_physical_pars_fragment>';
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
202
231
|
}
|