@needle-tools/materialx 1.0.0 → 1.0.1-next.19d0723
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/CHANGELOG.md +8 -0
- package/README.md +24 -0
- package/codegen/register_types.ts +4 -0
- package/index.ts +1 -1
- package/package.json +26 -4
- package/src/index.ts +2 -2
- package/src/loader/loader.needle.ts +27 -40
- package/src/loader/loader.three.ts +152 -395
- package/src/{helper.js → materialx.helper.ts} +162 -190
- package/src/materialx.material.ts +220 -0
- package/src/materialx.ts +189 -148
- package/src/materialx.types.d.ts +50 -0
- package/src/textureHelper.ts +6 -6
- package/src/utils.ts +39 -4
- package/bin/README.md +0 -5
- /package/bin/{JsMaterialXGenShader.data → JsMaterialXGenShader.data.txt} +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this package will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [1.0.1] - 2025-07-08
|
|
8
|
+
- Initial release
|
package/README.md
CHANGED
|
@@ -1 +1,25 @@
|
|
|
1
|
+
# Needle MaterialX
|
|
2
|
+
|
|
3
|
+
Load and display MaterialX materials in Needle Engine
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
`npm i @needle-tools/materialx`
|
|
7
|
+
|
|
8
|
+
## How to use
|
|
9
|
+
|
|
10
|
+
To use with Needle Engine simply import the module
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import "@needle-tools/materialx"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
<br />
|
|
17
|
+
|
|
18
|
+
# Contact ✒️
|
|
19
|
+
<b>[🌵 Needle](https://needle.tools)</b> •
|
|
20
|
+
[Github](https://github.com/needle-tools) •
|
|
21
|
+
[Twitter](https://twitter.com/NeedleTools) •
|
|
22
|
+
[Discord](https://discord.needle.tools) •
|
|
23
|
+
[Forum](https://forum.needle.tools) •
|
|
24
|
+
[Youtube](https://www.youtube.com/@needle-tools)
|
|
1
25
|
|
|
@@ -2,5 +2,9 @@
|
|
|
2
2
|
import { TypeStore } from "@needle-tools/engine"
|
|
3
3
|
|
|
4
4
|
// Import types
|
|
5
|
+
import { MaterialXMaterial } from "../src/materialx.material.js";
|
|
6
|
+
import { MaterialXUniformUpdate } from "../src/loader/loader.needle.js";
|
|
5
7
|
|
|
6
8
|
// Register types
|
|
9
|
+
TypeStore.add("MaterialXMaterial", MaterialXMaterial);
|
|
10
|
+
TypeStore.add("MaterialXUniformUpdate", MaterialXUniformUpdate);
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/materialx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1-next.19d0723",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.ts",
|
|
6
|
-
"
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./index.ts",
|
|
9
|
+
"require": "./index.js"
|
|
10
|
+
},
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
"./codegen/register_types.ts": {
|
|
13
|
+
"import": "./codegen/register_types.ts",
|
|
14
|
+
"require": "./codegen/register_types.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
7
17
|
"peerDependencies": {
|
|
8
18
|
"@needle-tools/engine": "4.x",
|
|
9
19
|
"three": "npm:@needle-tools/three@^0.169.5"
|
|
10
20
|
},
|
|
11
21
|
"devDependencies": {
|
|
12
22
|
"@needle-tools/engine": "4.x",
|
|
23
|
+
"@types/three": "0.169.0",
|
|
13
24
|
"three": "npm:@needle-tools/three@^0.169.5",
|
|
14
|
-
"
|
|
25
|
+
"vite": "^7.0.3"
|
|
15
26
|
},
|
|
16
27
|
"publishConfig": {
|
|
17
28
|
"access": "public",
|
|
18
29
|
"registry": "https://registry.npmjs.org/"
|
|
19
|
-
}
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"needle",
|
|
33
|
+
"materialx",
|
|
34
|
+
"material",
|
|
35
|
+
"shader",
|
|
36
|
+
"threejs",
|
|
37
|
+
"three.js",
|
|
38
|
+
"webgl",
|
|
39
|
+
"mtlx",
|
|
40
|
+
"rendering"
|
|
41
|
+
]
|
|
20
42
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ready, state } from "./materialx.js";
|
|
2
2
|
|
|
3
3
|
const getMaterialXEnvironment = () => state.materialXEnvironment;
|
|
4
4
|
|
|
5
|
-
export {
|
|
5
|
+
export { ready, getMaterialXEnvironment };
|
|
@@ -6,32 +6,21 @@ import type { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
|
6
6
|
import type { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
7
7
|
import { MaterialXLoader } from "./loader.three.js";
|
|
8
8
|
import { debug } from "../utils.js";
|
|
9
|
-
import { state } from "../materialx.js";
|
|
9
|
+
import { MaterialXEnvironment, state } from "../materialx.js";
|
|
10
|
+
import { MaterialXMaterial } from "../materialx.material.js";
|
|
10
11
|
|
|
11
12
|
//@dont-generate-component
|
|
12
13
|
export class MaterialXUniformUpdate extends Component {
|
|
13
14
|
|
|
14
|
-
static updateMaterial(mat: Material | Material[], object: Object3D, camera: Camera) {
|
|
15
|
-
if (Array.isArray(mat)) {
|
|
16
|
-
mat.forEach(m => {
|
|
17
|
-
if (m.userData?.updateUniforms) {
|
|
18
|
-
m.userData.updateUniforms(object, camera);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
} else if (mat.userData?.updateUniforms) {
|
|
22
|
-
mat.userData.updateUniforms(object, camera);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
15
|
onEnable(): void {
|
|
27
|
-
this.context.addBeforeRenderListener(this.gameObject, this.
|
|
16
|
+
this.context.addBeforeRenderListener(this.gameObject, this.onBeforeRenderThree);
|
|
28
17
|
}
|
|
29
18
|
|
|
30
19
|
onDisable(): void {
|
|
31
|
-
this.context.removeBeforeRenderListener(this.gameObject, this.
|
|
20
|
+
this.context.removeBeforeRenderListener(this.gameObject, this.onBeforeRenderThree);
|
|
32
21
|
}
|
|
33
22
|
|
|
34
|
-
|
|
23
|
+
onBeforeRenderThree = () => {
|
|
35
24
|
// Update uniforms or perform any pre-render logic here
|
|
36
25
|
const gameObject = this.gameObject as any as Mesh;
|
|
37
26
|
const material = gameObject?.material;
|
|
@@ -39,22 +28,24 @@ export class MaterialXUniformUpdate extends Component {
|
|
|
39
28
|
const camera = this.context.mainCamera;
|
|
40
29
|
if (!camera) return;
|
|
41
30
|
|
|
42
|
-
|
|
31
|
+
const env = state.materialXEnvironment;
|
|
43
32
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
33
|
+
if (Array.isArray(material)) {
|
|
34
|
+
for (const entry of material) {
|
|
35
|
+
if (entry && entry instanceof MaterialXMaterial) {
|
|
36
|
+
entry.updateUniforms(this.context, env, this.gameObject, camera);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} else if (material instanceof MaterialXMaterial) {
|
|
40
|
+
material.updateUniforms(this.context, env, this.gameObject, camera);
|
|
50
41
|
}
|
|
51
42
|
}
|
|
52
43
|
}
|
|
53
44
|
|
|
54
45
|
export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
55
|
-
name = "MaterialXLoaderPlugin";
|
|
46
|
+
readonly name = "MaterialXLoaderPlugin";
|
|
56
47
|
|
|
57
|
-
|
|
48
|
+
private loader: MaterialXLoader | null = null;
|
|
58
49
|
|
|
59
50
|
onImport = (loader: GLTFLoader, url: string, context: Context) => {
|
|
60
51
|
if (debug) console.log("MaterialXLoaderPlugin: Registering MaterialX extension for", url);
|
|
@@ -62,14 +53,18 @@ export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
|
62
53
|
// Register the MaterialX loader extension
|
|
63
54
|
// Environment initialization is now handled in the MaterialXLoader constructor
|
|
64
55
|
loader.register(p => {
|
|
65
|
-
this.
|
|
66
|
-
return this.
|
|
56
|
+
this.loader = new MaterialXLoader(p, context);
|
|
57
|
+
return this.loader;
|
|
67
58
|
});
|
|
68
59
|
};
|
|
69
60
|
|
|
70
61
|
onLoaded = (url: string, gltf: GLTF, _context: Context) => {
|
|
71
|
-
if (debug) console.log("MaterialXLoaderPlugin: glTF loaded", url, gltf.scene);
|
|
62
|
+
if (debug) console.log("[MaterialX] MaterialXLoaderPlugin: glTF loaded", { url, scene: gltf.scene, materialX_root_data: this.loader?.materialX_root_data });
|
|
72
63
|
|
|
64
|
+
// If we don't have MaterialX data in the loaded glTF we don't need to do anything else here
|
|
65
|
+
if (!this.loader?.materialX_root_data) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
73
68
|
// Set up onBeforeRender callbacks for objects with MaterialX materials
|
|
74
69
|
// This ensures uniforms are updated properly during rendering
|
|
75
70
|
gltf.scene.traverse((child) => {
|
|
@@ -77,26 +72,18 @@ export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
|
77
72
|
const mesh = child as Mesh;
|
|
78
73
|
const material = mesh.material as Material;
|
|
79
74
|
|
|
80
|
-
if (material
|
|
81
|
-
if (debug) console.log("Adding MaterialX uniform update component to:", child.name);
|
|
75
|
+
if (material instanceof MaterialXMaterial) {
|
|
76
|
+
if (debug) console.log("[MaterialX] Adding MaterialX uniform update component to:", child.name);
|
|
82
77
|
child.addComponent(MaterialXUniformUpdate);
|
|
83
78
|
}
|
|
84
79
|
}
|
|
85
80
|
});
|
|
86
81
|
|
|
87
|
-
if (debug) console.log("Loaded: ", this.
|
|
88
|
-
|
|
89
|
-
// Initialize MaterialX lighting system with scene data
|
|
90
|
-
const environment = state.materialXEnvironment;
|
|
91
|
-
environment.initializeFromContext().then(() => {
|
|
92
|
-
if (this.mtlxLoader) {
|
|
93
|
-
this.mtlxLoader.updateLightingFromEnvironment(environment);
|
|
94
|
-
}
|
|
95
|
-
});
|
|
82
|
+
if (debug) console.log("[MaterialX] Loaded: ", this.loader);
|
|
96
83
|
};
|
|
97
84
|
|
|
98
85
|
onExport = (_exporter: GLTFExporter, _context: Context) => {
|
|
99
|
-
console.log("TODO: MaterialXLoaderPlugin: Setting up export extensions");
|
|
86
|
+
console.log("[MaterialX] TODO: MaterialXLoaderPlugin: Setting up export extensions");
|
|
100
87
|
// TODO: Add MaterialX export functionality if needed
|
|
101
88
|
};
|
|
102
89
|
}
|