@needle-tools/materialx 1.0.1-next.b9467c8 → 1.0.1-next.b9638d9
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/README.md +0 -5
- package/codegen/register_types.ts +0 -4
- package/index.ts +1 -1
- package/package.json +3 -18
- package/src/{materialx.helper.ts → helper.js} +190 -162
- package/src/index.ts +2 -2
- package/src/loader/loader.needle.ts +40 -27
- package/src/loader/loader.three.ts +395 -152
- package/src/materialx.ts +128 -161
- package/src/textureHelper.ts +6 -6
- package/src/utils.ts +4 -39
- package/src/materialx.material.ts +0 -227
- package/src/materialx.types.d.ts +0 -50
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import { Camera, DoubleSide, FrontSide, GLSL3, Matrix3, Matrix4, Mesh, Object3D, ShaderMaterial, Texture, Vector3 } from "three";
|
|
2
|
-
import { debug } from "./utils.js";
|
|
3
|
-
import { MaterialXEnvironment, state } from "./materialx.js";
|
|
4
|
-
import { getUniformValues, Loaders } from "./materialx.helper.js";
|
|
5
|
-
import { Context } from "@needle-tools/engine";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// Add helper matrices for uniform updates (similar to MaterialX example)
|
|
9
|
-
const identityMatrix = new Matrix4();
|
|
10
|
-
const normalMat = new Matrix3();
|
|
11
|
-
const viewProjMat = new Matrix4();
|
|
12
|
-
const worldViewPos = new Vector3();
|
|
13
|
-
|
|
14
|
-
declare type MaterialXMaterialInitParameters = {
|
|
15
|
-
name: string,
|
|
16
|
-
shader: any,
|
|
17
|
-
loaders: Loaders,
|
|
18
|
-
transparent?: boolean,
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class MaterialXMaterial extends ShaderMaterial {
|
|
22
|
-
|
|
23
|
-
// copy(source: MaterialXMaterial): this {
|
|
24
|
-
// super.copy(source);
|
|
25
|
-
// this.name = source.name;
|
|
26
|
-
// this.uniforms = { ...source.uniforms }; // Shallow copy of uniforms
|
|
27
|
-
// this.envMapIntensity = source.envMapIntensity;
|
|
28
|
-
// this.envMap = source.envMap;
|
|
29
|
-
// this.updateUniforms = source.updateUniforms; // Copy the update function
|
|
30
|
-
// return this;
|
|
31
|
-
// }
|
|
32
|
-
|
|
33
|
-
constructor(init?: MaterialXMaterialInitParameters) {
|
|
34
|
-
|
|
35
|
-
// TODO: we need to properly copy the uniforms and other properties from the source material
|
|
36
|
-
if (!init) {
|
|
37
|
-
super();
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Get vertex and fragment shader source, and remove #version directive for newer js.
|
|
42
|
-
// It's added by three.js glslVersion.
|
|
43
|
-
let vertexShader = init.shader.getSourceCode("vertex");
|
|
44
|
-
let fragmentShader = init.shader.getSourceCode("pixel");
|
|
45
|
-
|
|
46
|
-
vertexShader = vertexShader.replace(/^#version.*$/gm, '').trim();
|
|
47
|
-
fragmentShader = fragmentShader.replace(/^#version.*$/gm, '').trim();
|
|
48
|
-
|
|
49
|
-
// MaterialX uses different attribute names than js defaults,
|
|
50
|
-
// so we patch the MaterialX shaders to match the js standard names.
|
|
51
|
-
// Otherwise, we'd have to modify the mesh attributes (see original MaterialX for reference).
|
|
52
|
-
|
|
53
|
-
// Patch vertexShader
|
|
54
|
-
vertexShader = vertexShader.replace(/\bi_position\b/g, 'position');
|
|
55
|
-
vertexShader = vertexShader.replace(/\bi_normal\b/g, 'normal');
|
|
56
|
-
vertexShader = vertexShader.replace(/\bi_texcoord_0\b/g, 'uv');
|
|
57
|
-
vertexShader = vertexShader.replace(/\bi_texcoord_1\b/g, 'uv1');
|
|
58
|
-
vertexShader = vertexShader.replace(/\bi_tangent\b/g, 'tangent');
|
|
59
|
-
vertexShader = vertexShader.replace(/\bi_color_0\b/g, 'color');
|
|
60
|
-
|
|
61
|
-
// Patch fragmentShader
|
|
62
|
-
fragmentShader = fragmentShader.replace(/\bi_position\b/g, 'position');
|
|
63
|
-
fragmentShader = fragmentShader.replace(/\bi_normal\b/g, 'normal');
|
|
64
|
-
fragmentShader = fragmentShader.replace(/\bi_texcoord_0\b/g, 'uv');
|
|
65
|
-
fragmentShader = fragmentShader.replace(/\bi_texcoord_1\b/g, 'uv1');
|
|
66
|
-
fragmentShader = fragmentShader.replace(/\bi_tangent\b/g, 'tangent');
|
|
67
|
-
fragmentShader = fragmentShader.replace(/\bi_color_0\b/g, 'color');
|
|
68
|
-
|
|
69
|
-
// Remove `in vec3 position;` and so on since they're already declared by ShaderMaterial
|
|
70
|
-
vertexShader = vertexShader.replace(/in\s+vec3\s+position;/g, '');
|
|
71
|
-
vertexShader = vertexShader.replace(/in\s+vec3\s+normal;/g, '');
|
|
72
|
-
vertexShader = vertexShader.replace(/in\s+vec3\s+uv;/g, '');
|
|
73
|
-
vertexShader = vertexShader.replace(/in\s+vec3\s+uv1;/g, '');
|
|
74
|
-
vertexShader = vertexShader.replace(/in\s+vec4\s+tangent;/g, '');
|
|
75
|
-
vertexShader = vertexShader.replace(/in\s+vec4\s+color;/g, '');
|
|
76
|
-
|
|
77
|
-
// Patch uv 2-component to 3-component (`texcoord_0 = uv;` needs to be replaced with `texcoord_0 = vec3(uv, 0.0);`)
|
|
78
|
-
// TODO what if we actually have a 3-component UV? Not sure what three.js does then
|
|
79
|
-
vertexShader = vertexShader.replace(/texcoord_0 = uv;/g, 'texcoord_0 = vec3(uv, 0.0);');
|
|
80
|
-
|
|
81
|
-
// Patch units – seems MaterialX uses different units and we end up with wrong light values?
|
|
82
|
-
// result.direction = light.position - position;
|
|
83
|
-
fragmentShader = fragmentShader.replace(
|
|
84
|
-
/result\.direction\s*=\s*light\.position\s*-\s*position;/g,
|
|
85
|
-
'result.direction = (light.position - position) * 10.0 / 1.0;');
|
|
86
|
-
|
|
87
|
-
// Add tonemapping and colorspace handling
|
|
88
|
-
// Replace `out vec4 out1;` with `out vec4 gl_FragColor;`
|
|
89
|
-
fragmentShader = fragmentShader.replace(
|
|
90
|
-
/out\s+vec4\s+out1;/,
|
|
91
|
-
'layout(location = 0) out vec4 pc_fragColor;\n#define gl_FragColor pc_fragColor');
|
|
92
|
-
|
|
93
|
-
// Replace `out1 = vec4(<CAPTURE>)` with `gl_FragColor = vec4(<CAPTURE>)` and tonemapping/colorspace handling
|
|
94
|
-
fragmentShader = fragmentShader.replace(/^\s*out1\s*=\s*vec4\((.*)\);/gm, `
|
|
95
|
-
gl_FragColor = vec4($1);
|
|
96
|
-
#include <tonemapping_fragment>
|
|
97
|
-
#include <colorspace_fragment>`);
|
|
98
|
-
|
|
99
|
-
const searchPath = ""; // Could be derived from the asset path if needed
|
|
100
|
-
const flipV = false; // Set based on your geometry requirements
|
|
101
|
-
const isTransparent = init.transparent ?? false;
|
|
102
|
-
super({
|
|
103
|
-
name: init.name,
|
|
104
|
-
uniforms: {
|
|
105
|
-
...getUniformValues(init.shader.getStage('vertex'), init.loaders, searchPath, flipV),
|
|
106
|
-
...getUniformValues(init.shader.getStage('pixel'), init.loaders, searchPath, flipV),
|
|
107
|
-
},
|
|
108
|
-
vertexShader: vertexShader,
|
|
109
|
-
fragmentShader: fragmentShader,
|
|
110
|
-
glslVersion: GLSL3,
|
|
111
|
-
transparent: isTransparent,
|
|
112
|
-
side: FrontSide,
|
|
113
|
-
depthTest: true,
|
|
114
|
-
depthWrite: !isTransparent,
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
Object.assign(this.uniforms, {
|
|
120
|
-
u_envMatrix: { value: new Matrix4() },
|
|
121
|
-
u_envRadiance: { value: null, type: 't' },
|
|
122
|
-
u_envRadianceMips: { value: 8, type: 'i' },
|
|
123
|
-
// TODO we need to figure out how we can set a PMREM here... doing many texture samples is prohibitively expensive
|
|
124
|
-
u_envRadianceSamples: { value: 8, type: 'i' },
|
|
125
|
-
u_envIrradiance: { value: null, type: 't' },
|
|
126
|
-
u_refractionEnv: { value: true },
|
|
127
|
-
u_numActiveLightSources: { value: 0 },
|
|
128
|
-
u_lightData: { value: [] }, // Array of light data
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
if (debug) {
|
|
132
|
-
// Get lighting and environment data from MaterialX environment
|
|
133
|
-
console.group("[MaterialX]: ", name);
|
|
134
|
-
console.log("Vertex shader length:", vertexShader.length, vertexShader);
|
|
135
|
-
console.log("Fragment shader length:", fragmentShader.length, fragmentShader);
|
|
136
|
-
console.groupEnd();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
envMapIntensity: number = 1.0; // Default intensity for environment map
|
|
143
|
-
envMap: Texture | null = null; // Environment map texture, can be set externally
|
|
144
|
-
updateUniforms = (context: Context, environment: MaterialXEnvironment, object: Object3D, camera: Camera) => {
|
|
145
|
-
|
|
146
|
-
const uniforms = this.uniforms;
|
|
147
|
-
|
|
148
|
-
if (!uniforms) return;
|
|
149
|
-
|
|
150
|
-
// TODO remove. Not sure why this is needed, but without it
|
|
151
|
-
// we currently get some "swimming" where matrices are not up to date.
|
|
152
|
-
camera.updateMatrixWorld(true);
|
|
153
|
-
|
|
154
|
-
// Update standard transformation matrices
|
|
155
|
-
if (uniforms.u_worldMatrix) {
|
|
156
|
-
if (!uniforms.u_worldMatrix.value?.isMatrix4) uniforms.u_worldMatrix.value = new Matrix4();
|
|
157
|
-
uniforms.u_worldMatrix.value = object.matrixWorld;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (uniforms.u_viewProjectionMatrix) {
|
|
161
|
-
if (!uniforms.u_viewProjectionMatrix.value?.isMatrix4) uniforms.u_viewProjectionMatrix.value = new Matrix4();
|
|
162
|
-
uniforms.u_viewProjectionMatrix.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (uniforms.u_viewPosition) {
|
|
166
|
-
if (!uniforms.u_viewPosition.value?.isVector3) uniforms.u_viewPosition.value = new Vector3();
|
|
167
|
-
uniforms.u_viewPosition.value.copy(camera.getWorldPosition(worldViewPos));
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (uniforms.u_worldInverseTransposeMatrix) {
|
|
171
|
-
if (!uniforms.u_worldInverseTransposeMatrix.value?.isMatrix4) uniforms.u_worldInverseTransposeMatrix.value = new Matrix4();
|
|
172
|
-
uniforms.u_worldInverseTransposeMatrix.value.setFromMatrix3(normalMat.getNormalMatrix(object.matrixWorld));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Update time uniforms
|
|
176
|
-
if (uniforms.u_time) {
|
|
177
|
-
uniforms.u_time.value = context.time.time;
|
|
178
|
-
}
|
|
179
|
-
if (uniforms.u_frame) {
|
|
180
|
-
uniforms.u_frame.value = context.time.frame;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Update light uniforms
|
|
184
|
-
this.updateEnvironmentUniforms(environment);
|
|
185
|
-
|
|
186
|
-
this.uniformsNeedUpdate = true;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
private updateEnvironmentUniforms = (environment: MaterialXEnvironment) => {
|
|
190
|
-
|
|
191
|
-
// Get lighting data from environment
|
|
192
|
-
const lightData = environment.lightData || null;
|
|
193
|
-
const lightCount = environment.lightCount || 0;
|
|
194
|
-
const textures = environment.getTextures(this) || null;
|
|
195
|
-
|
|
196
|
-
// Update each generated material's lighting uniforms
|
|
197
|
-
if (!this.uniforms) return;
|
|
198
|
-
|
|
199
|
-
// Update light count
|
|
200
|
-
if (this.uniforms.u_numActiveLightSources && lightCount >= 0) {
|
|
201
|
-
this.uniforms.u_numActiveLightSources.value = lightCount;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Update light data if we have lights
|
|
205
|
-
if (lightData) {
|
|
206
|
-
this.uniforms.u_lightData.value = lightData;
|
|
207
|
-
if (debug) console.log("[MaterialX] Updated light data for material", this.name, lightData, this.uniforms,);
|
|
208
|
-
}
|
|
209
|
-
else if (debug) console.warn("[MaterialX] No light data available to update uniforms for material", this.name);
|
|
210
|
-
|
|
211
|
-
// Update environment uniforms
|
|
212
|
-
if (this.uniforms.u_envMatrix) {
|
|
213
|
-
this.uniforms.u_envMatrix.value = identityMatrix;
|
|
214
|
-
}
|
|
215
|
-
if (this.uniforms.u_envRadiance) {
|
|
216
|
-
this.uniforms.u_envRadiance.value = textures.radianceTexture || null;
|
|
217
|
-
}
|
|
218
|
-
if (this.uniforms.u_envRadianceMips) {
|
|
219
|
-
this.uniforms.u_envRadianceMips.value = Math.trunc(Math.log2(Math.max(textures.radianceTexture?.source.data.width ?? 0, textures.radianceTexture?.source.data.height ?? 0))) + 1;
|
|
220
|
-
}
|
|
221
|
-
if (this.uniforms.u_envIrradiance) {
|
|
222
|
-
this.uniforms.u_envIrradiance.value = textures.irradianceTexture;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
this.uniformsNeedUpdate = true;
|
|
226
|
-
}
|
|
227
|
-
}
|
package/src/materialx.types.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export namespace MaterialX {
|
|
5
|
-
|
|
6
|
-
export type MODULE = {
|
|
7
|
-
ShaderInterfaceType: any;
|
|
8
|
-
HwSpecularEnvironmentMethod: any;
|
|
9
|
-
HwShaderGenerator: {
|
|
10
|
-
bindLightShader(def: any, id: number, genContext: GenContext): void;
|
|
11
|
-
unbindLightShaders(context: any): void;
|
|
12
|
-
};
|
|
13
|
-
createDocument(): Document;
|
|
14
|
-
readFromXmlString(doc: Document, xml: string, unknown: string): void;
|
|
15
|
-
loadStandardLibraries(genContext: GenContext): StandardLibrary;
|
|
16
|
-
isTransparentSurface(renderableElement: any, target: string): boolean;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export type GenContext = {
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type StandardLibrary = {
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// https://github.com/AcademySoftwareFoundation/MaterialX/blob/b74787db6544283dc32afc8085ebc93cabe937cb/source/MaterialXGenShader/ShaderStage.h#L56
|
|
28
|
-
export type ShaderStage = {
|
|
29
|
-
getUniformBlocks(): Record<string, any>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export type Document = {
|
|
33
|
-
setDataLibrary(lib: StandardLibrary): void;
|
|
34
|
-
importLibrary(lib: Document): void;
|
|
35
|
-
|
|
36
|
-
getNodes(): Node[];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type Node = {
|
|
40
|
-
getType(): string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export type Matrix = {
|
|
44
|
-
numRows(): number;
|
|
45
|
-
numColumns(): number;
|
|
46
|
-
get size(): number;
|
|
47
|
-
getItem(row: number, col: number): number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
}
|