@volter/blender-engine 0.1.84 → 0.1.86
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.
|
@@ -28,6 +28,16 @@ const uniforms = new WeakMap<THREE.MeshPhysicalMaterial, {
|
|
|
28
28
|
blenderMapClip: {value: boolean}; blenderRoughnessClip: {value: boolean}; blenderNormalClip: {value: boolean};
|
|
29
29
|
blenderWorldExtinction: {value: THREE.Vector3};
|
|
30
30
|
}>();
|
|
31
|
+
const drawHooks = new WeakMap<THREE.Material, Pick<THREE.Material, 'onBeforeRender' | 'onBeforeCompile' | 'customProgramCacheKey'>>();
|
|
32
|
+
|
|
33
|
+
/** Internal draws can preserve the engine's known hooks or Three's defaults.
|
|
34
|
+
* A later custom hook may depend on the original object/material identity. */
|
|
35
|
+
export function materialDrawHooksSupported(material: THREE.Material): boolean {
|
|
36
|
+
const hooks = drawHooks.get(material) ?? THREE.Material.prototype;
|
|
37
|
+
return material.onBeforeRender === hooks.onBeforeRender &&
|
|
38
|
+
material.onBeforeCompile === hooks.onBeforeCompile &&
|
|
39
|
+
material.customProgramCacheKey === hooks.customProgramCacheKey;
|
|
40
|
+
}
|
|
31
41
|
|
|
32
42
|
export function applyWorldExtinction(material: THREE.MeshPhysicalMaterial, extinction: THREE.Vector3): void {
|
|
33
43
|
if (!uniforms.has(material)) applyPhysicalMaterial(material);
|
|
@@ -59,7 +69,7 @@ function graphShadow(material: THREE.MeshPhysicalMaterial): THREE.MeshPhysicalMa
|
|
|
59
69
|
/** Copy physical values into an independently cached draw form. Textures and
|
|
60
70
|
* graph uniform values remain borrowed from the authoritative source material. */
|
|
61
71
|
export function syncPhysicalDrawMaterial(source: THREE.Material, target?: THREE.MeshPhysicalMaterial): THREE.MeshPhysicalMaterial | null {
|
|
62
|
-
if (!(source instanceof THREE.MeshPhysicalMaterial) || !uniforms.has(source)) return null;
|
|
72
|
+
if (!(source instanceof THREE.MeshPhysicalMaterial) || !uniforms.has(source) || !materialDrawHooksSupported(source)) return null;
|
|
63
73
|
const copy = target ?? graphShadow(source);
|
|
64
74
|
if (!borrowGraphDrawBinding(source, copy)) {
|
|
65
75
|
if (!target) copy.dispose();
|
|
@@ -180,6 +190,8 @@ export function applyPhysicalMaterial(material: THREE.MeshPhysicalMaterial, inpu
|
|
|
180
190
|
// surface inputs it carries (`blender-graph-material.ts`).
|
|
181
191
|
applyGraphShader(material, shader);
|
|
182
192
|
};
|
|
193
|
+
drawHooks.set(material, {onBeforeRender: material.onBeforeRender,
|
|
194
|
+
onBeforeCompile: material.onBeforeCompile, customProgramCacheKey: material.customProgramCacheKey});
|
|
183
195
|
material.needsUpdate = true;
|
|
184
196
|
}
|
|
185
197
|
values.blenderCoatIor.value = Math.max(1, data.coat_ior);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { graphDrawAttributes } from './blender-graph-material';
|
|
3
|
+
import { materialDrawHooksSupported } from './blender-physical-material';
|
|
3
4
|
|
|
4
5
|
// Small spatial batches retain frustum rejection without duplicating geometry.
|
|
5
6
|
const BATCH_SIZE = 64;
|
|
@@ -12,6 +13,11 @@ function sameMaterials(a: THREE.Material | THREE.Material[], b: THREE.Material |
|
|
|
12
13
|
: a === b;
|
|
13
14
|
}
|
|
14
15
|
|
|
16
|
+
export function instanceObjectHooksSupported(object: THREE.Object3D): boolean {
|
|
17
|
+
return object.onBeforeRender === THREE.Object3D.prototype.onBeforeRender &&
|
|
18
|
+
object.onAfterRender === THREE.Object3D.prototype.onAfterRender;
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
export function instanceObjectShown(object: THREE.Object3D): boolean {
|
|
16
22
|
for (let node: THREE.Object3D | null = object; node; node = node.parent)
|
|
17
23
|
if (!node.visible) return false;
|
|
@@ -60,12 +66,13 @@ export class BlenderRuntimeInstances {
|
|
|
60
66
|
for (const object of objects) {
|
|
61
67
|
const mesh = object as THREE.Mesh;
|
|
62
68
|
if (!mesh.isMesh) continue;
|
|
69
|
+
if (!instanceObjectHooksSupported(mesh)) { exclude('customHooks'); continue; }
|
|
63
70
|
if ((mesh as THREE.SkinnedMesh).isSkinnedMesh ||
|
|
64
71
|
(mesh as THREE.InstancedMesh).isInstancedMesh || mesh.morphTargetInfluences ||
|
|
65
72
|
mesh.layers.mask !== 1) { exclude('deformationOrLayers'); continue; }
|
|
66
73
|
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
67
74
|
if (materials.some(m => m.transparent || (m as THREE.MeshPhysicalMaterial).transmission > 0 ||
|
|
68
|
-
(m as THREE.ShaderMaterial).isShaderMaterial)) { exclude('material'); continue; }
|
|
75
|
+
(m as THREE.ShaderMaterial).isShaderMaterial || !materialDrawHooksSupported(m))) { exclude('material'); continue; }
|
|
69
76
|
// Four slots for instanceMatrix, at most twelve for each actual program.
|
|
70
77
|
// Count active inputs, NOT every stored authored layer: retaining unused
|
|
71
78
|
// UVs/colours must not disable batching. No channel is deleted to fit.
|
|
@@ -125,6 +132,8 @@ export class BlenderRuntimeInstances {
|
|
|
125
132
|
if (!this.batches.length) return;
|
|
126
133
|
this.inverse.copy(this.root.matrixWorld).invert();
|
|
127
134
|
for (const {draw, members} of this.batches) {
|
|
135
|
+
const materials = Array.isArray(draw.material) ? draw.material : [draw.material];
|
|
136
|
+
const supportedHooks = materials.every(materialDrawHooksSupported);
|
|
128
137
|
let count = 0;
|
|
129
138
|
let changed = false;
|
|
130
139
|
for (const member of members) {
|
|
@@ -133,6 +142,7 @@ export class BlenderRuntimeInstances {
|
|
|
133
142
|
// A drag can introduce negative scale/shear, or a skin can replace a
|
|
134
143
|
// mesh between frames. Fall back immediately without touching its data.
|
|
135
144
|
const compatible = mesh.parent !== null && mesh.geometry === draw.geometry &&
|
|
145
|
+
supportedHooks && instanceObjectHooksSupported(mesh) &&
|
|
136
146
|
sameMaterials(mesh.material, draw.material) && instanceMatrixSupported(this.matrix);
|
|
137
147
|
if (!compatible) {
|
|
138
148
|
mesh.layers.mask |= member.layers;
|
|
@@ -3,7 +3,8 @@ import {BlenderOrderedBatches, ORDERED_BATCH_CAPACITY} from './blender-ordered-b
|
|
|
3
3
|
import {BlenderDrawMaterials} from './blender-draw-materials';
|
|
4
4
|
import {presenterChanged} from './blender-presenter-change';
|
|
5
5
|
import {graphDrawAttributes} from './blender-graph-material';
|
|
6
|
-
import {
|
|
6
|
+
import {materialDrawHooksSupported} from './blender-physical-material';
|
|
7
|
+
import {instanceMatrixSupported, instanceObjectShown, instanceObjectHooksSupported} from './blender-runtime-instances';
|
|
7
8
|
|
|
8
9
|
const CAPACITY = ORDERED_BATCH_CAPACITY;
|
|
9
10
|
type Entry = {mesh: THREE.Mesh; material: THREE.Material | null; key: string | null; batchKey: string | null; groupOrder: number; z: number; centre: THREE.Vector3};
|
|
@@ -112,6 +113,7 @@ export class BlenderTransparentInstances {
|
|
|
112
113
|
const candidate = materials.length === 1 ? materials[0]! : null;
|
|
113
114
|
const order = groupOrder(mesh);
|
|
114
115
|
if (candidate && candidate.visible && candidate.transparent &&
|
|
116
|
+
materialDrawHooksSupported(candidate) && instanceObjectHooksSupported(mesh) &&
|
|
115
117
|
!(candidate as THREE.ShaderMaterial).isShaderMaterial &&
|
|
116
118
|
!((candidate as THREE.MeshPhysicalMaterial).transmission > 0) &&
|
|
117
119
|
(candidate.side !== THREE.DoubleSide || candidate.forceSinglePass) &&
|
|
@@ -291,6 +293,7 @@ export class BlenderTransparentInstances {
|
|
|
291
293
|
this.observe(mesh.renderOrder);
|
|
292
294
|
this.observe(groupOrder(mesh));
|
|
293
295
|
this.observe(mesh.frustumCulled ? 1 : 0);
|
|
296
|
+
this.observe(instanceObjectHooksSupported(mesh) ? 1 : 0);
|
|
294
297
|
this.observe(mesh.morphTargetInfluences ? 1 : 0);
|
|
295
298
|
for (const n of mesh.matrixWorld.elements) this.observe(n);
|
|
296
299
|
const geometry = mesh.geometry;
|
|
@@ -329,6 +332,7 @@ export class BlenderTransparentInstances {
|
|
|
329
332
|
}
|
|
330
333
|
|
|
331
334
|
private observeMaterial(material: THREE.Material): void {
|
|
335
|
+
this.observe(materialDrawHooksSupported(material) ? 1 : 0);
|
|
332
336
|
this.observe(material.uuid); this.observe(material.version);
|
|
333
337
|
this.observe(material.visible ? 1 : 0); this.observe(material.transparent ? 1 : 0);
|
|
334
338
|
this.observe(material.side); this.observe(material.forceSinglePass ? 1 : 0);
|