@needle-tools/materialx 1.6.0-next.2af5fc1 → 1.7.0-next.0d06218
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 +15 -1
- package/README.md +33 -1
- package/bin/JsMaterialXCore.js +5 -13
- package/bin/JsMaterialXCore.wasm +0 -0
- package/bin/JsMaterialXGenShader.data.txt +2127 -2453
- package/bin/JsMaterialXGenShader.js +5 -13
- package/bin/JsMaterialXGenShader.wasm +0 -0
- package/bin/revision.json +3 -3
- package/package.json +10 -6
- package/src/index.d.ts +1 -2
- package/src/loader/loader.three.d.ts +10 -1
- package/src/loader/loader.three.js +26 -19
- package/src/materialx.d.ts +9 -5
- package/src/materialx.helper.d.ts +1 -1
- package/src/materialx.helper.js +97 -42
- package/src/materialx.js +83 -24
- package/src/materialx.material.d.ts +11 -2
- package/src/materialx.material.js +512 -10
- package/src/materialx.types.d.ts +65 -10
- package/src/utils.texture.d.ts +11 -0
- package/src/utils.texture.js +194 -37
- /package/bin/{SHA_0e7685f37737511f2816949b9486d511a5fa71bd → SHA_ab218c56f016a9a2d398e8d306f3aeb439ae9e9e} +0 -0
package/src/materialx.types.d.ts
CHANGED
|
@@ -2,21 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
export namespace MaterialX {
|
|
5
|
+
export type Collection<T> = T[] | {
|
|
6
|
+
size(): number;
|
|
7
|
+
get(index: number): T | null | undefined;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type AttributeElement = {
|
|
11
|
+
getName?(): string;
|
|
12
|
+
getType?(): string;
|
|
13
|
+
getCategory?(): string;
|
|
14
|
+
getNodeString?(): string;
|
|
15
|
+
getNodeGroup?(): string;
|
|
16
|
+
getValueString?(): string;
|
|
17
|
+
getNodeName?(): string;
|
|
18
|
+
getInterfaceName?(): string;
|
|
19
|
+
getAttribute?(name: string): string | null | undefined;
|
|
20
|
+
hasAttribute?(name: string): boolean;
|
|
21
|
+
getAttributeNames?(): Iterable<string>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type VariableBlock = Collection<{
|
|
25
|
+
getPath?(): string;
|
|
26
|
+
getVariable?(): string;
|
|
27
|
+
}>;
|
|
5
28
|
|
|
6
29
|
export type MODULE = {
|
|
7
|
-
ShaderInterfaceType:
|
|
8
|
-
HwSpecularEnvironmentMethod:
|
|
30
|
+
ShaderInterfaceType: Record<string, number>;
|
|
31
|
+
HwSpecularEnvironmentMethod: Record<string, number>;
|
|
9
32
|
HwShaderGenerator: {
|
|
10
|
-
bindLightShader(def:
|
|
11
|
-
unbindLightShaders(context:
|
|
33
|
+
bindLightShader(def: NodeDef, id: number, genContext: GenContext): void;
|
|
34
|
+
unbindLightShaders(context: GenContext): void;
|
|
12
35
|
};
|
|
13
36
|
createDocument(): Document;
|
|
14
37
|
readFromXmlString(doc: Document, xml: string, searchPath?: string): void;
|
|
15
38
|
loadStandardLibraries(genContext: GenContext): StandardLibrary;
|
|
16
|
-
isTransparentSurface(renderableElement:
|
|
39
|
+
isTransparentSurface(renderableElement: Node, target: string): boolean;
|
|
17
40
|
/** Returns the alpha mode for a renderable element: "opaque", "mask", or "blend".
|
|
18
41
|
* Inspects the shader node (and its nodegraph implementation) for alpha_mode inputs. */
|
|
19
|
-
getAlphaMode?(renderableElement:
|
|
42
|
+
getAlphaMode?(renderableElement: Node, target: string): string;
|
|
20
43
|
/** Extracts a detailed error message from a WASM exception pointer, including error logs. */
|
|
21
44
|
getExceptionDetailedMessage?(exceptionPtr: number): string;
|
|
22
45
|
/** Extracts a basic error message from a WASM exception pointer. */
|
|
@@ -28,12 +51,13 @@ export namespace MaterialX {
|
|
|
28
51
|
}
|
|
29
52
|
|
|
30
53
|
export type StandardLibrary = {
|
|
31
|
-
|
|
54
|
+
getNodeDefs?(): Collection<NodeDef>;
|
|
55
|
+
getNodeGraphs?(): Collection<NodeGraph>;
|
|
32
56
|
}
|
|
33
57
|
|
|
34
58
|
// https://github.com/AcademySoftwareFoundation/MaterialX/blob/b74787db6544283dc32afc8085ebc93cabe937cb/source/MaterialXGenShader/ShaderStage.h#L56
|
|
35
59
|
export type ShaderStage = {
|
|
36
|
-
getUniformBlocks(): Record<string,
|
|
60
|
+
getUniformBlocks(): Record<string, VariableBlock>;
|
|
37
61
|
}
|
|
38
62
|
|
|
39
63
|
export type Document = {
|
|
@@ -43,10 +67,35 @@ export namespace MaterialX {
|
|
|
43
67
|
validate?(): { valid: boolean; message: string };
|
|
44
68
|
|
|
45
69
|
getNodes(): Node[];
|
|
70
|
+
getMaterialNodes(): MaterialXNode[];
|
|
71
|
+
getNodeGraphs(): NodeGraph[];
|
|
46
72
|
}
|
|
47
73
|
|
|
48
|
-
export type
|
|
74
|
+
export type Input = AttributeElement;
|
|
75
|
+
|
|
76
|
+
export type Output = AttributeElement;
|
|
77
|
+
|
|
78
|
+
export type Node = AttributeElement & {
|
|
79
|
+
getName(): string;
|
|
49
80
|
getType(): string;
|
|
81
|
+
getNodeDef?(): NodeDef | null;
|
|
82
|
+
getNodeDefString?(): string;
|
|
83
|
+
getInputs?(): Collection<Input>;
|
|
84
|
+
getOutputs?(): Collection<Output>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type NodeDef = AttributeElement & {
|
|
88
|
+
getName(): string;
|
|
89
|
+
getNodeString?(): string;
|
|
90
|
+
getActiveInputs?(): Collection<Input>;
|
|
91
|
+
getActiveOutputs?(): Collection<Output>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type NodeGraph = AttributeElement & {
|
|
95
|
+
getName(): string;
|
|
96
|
+
getNodes(): Node[];
|
|
97
|
+
getOutputs?(): Collection<Output>;
|
|
98
|
+
getNodeDefString?(): string;
|
|
50
99
|
}
|
|
51
100
|
|
|
52
101
|
export type Matrix = {
|
|
@@ -56,4 +105,10 @@ export namespace MaterialX {
|
|
|
56
105
|
getItem(row: number, col: number): number;
|
|
57
106
|
}
|
|
58
107
|
|
|
59
|
-
|
|
108
|
+
export type MaterialXNode = Node & {
|
|
109
|
+
getNamePath?: () => string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type MaterilaXNode = MaterialXNode;
|
|
113
|
+
|
|
114
|
+
}
|
package/src/utils.texture.d.ts
CHANGED
|
@@ -13,3 +13,14 @@ export function renderPMREMToEquirect(
|
|
|
13
13
|
height?: number,
|
|
14
14
|
renderTargetHeight?: number
|
|
15
15
|
): WebGLRenderTarget;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Renders a PMREM environment map to an equirectangular texture with roughness encoded in mip levels.
|
|
19
|
+
*/
|
|
20
|
+
export function renderPMREMToPrefilteredEquirect(
|
|
21
|
+
renderer: WebGLRenderer,
|
|
22
|
+
pmremTexture: Texture,
|
|
23
|
+
width?: number,
|
|
24
|
+
height?: number,
|
|
25
|
+
renderTargetHeight?: number
|
|
26
|
+
): WebGLRenderTarget;
|
package/src/utils.texture.js
CHANGED
|
@@ -1,12 +1,96 @@
|
|
|
1
|
-
import { WebGLRenderer, Scene, WebGLRenderTarget, PlaneGeometry, OrthographicCamera, ShaderMaterial, RGBAFormat, FloatType, LinearFilter, Mesh, EquirectangularReflectionMapping, RepeatWrapping, LinearMipMapLinearFilter,
|
|
1
|
+
import { WebGLRenderer, Scene, WebGLRenderTarget, PlaneGeometry, OrthographicCamera, ShaderMaterial, RGBAFormat, FloatType, LinearFilter, Mesh, EquirectangularReflectionMapping, RepeatWrapping, LinearMipMapLinearFilter, DataTexture, UnsignedByteType, Vector4 } from 'three';
|
|
2
2
|
import { getParam } from './utils.js';
|
|
3
3
|
|
|
4
4
|
const debug = getParam("debugmaterialx");
|
|
5
|
+
const _viewport = new Vector4();
|
|
5
6
|
|
|
6
|
-
export const whiteTexture = new
|
|
7
|
+
export const whiteTexture = new DataTexture(new Uint8Array([255, 255, 255, 255]), 1, 1, RGBAFormat, UnsignedByteType);
|
|
7
8
|
whiteTexture.needsUpdate = true;
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
function toGlslFloat(value) {
|
|
11
|
+
if (!Number.isFinite(value)) return "0.0";
|
|
12
|
+
const result = Number(value).toPrecision(12).replace(/\.?0+($|e)/, "$1");
|
|
13
|
+
return result.includes(".") || result.includes("e") ? result : result + ".0";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getPMREMCubeUVSize(pmremTexture, renderTargetHeight) {
|
|
17
|
+
renderTargetHeight ??= pmremTexture?.userData?.pmremRenderTargetHeight;
|
|
18
|
+
if (Number.isFinite(renderTargetHeight) && renderTargetHeight > 0) {
|
|
19
|
+
const imageHeight = renderTargetHeight;
|
|
20
|
+
const maxMip = Math.max(0, Math.log2(imageHeight) - 2);
|
|
21
|
+
return {
|
|
22
|
+
imageHeight,
|
|
23
|
+
maxMip,
|
|
24
|
+
texelWidth: 1.0 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16)),
|
|
25
|
+
texelHeight: 1.0 / imageHeight,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const imageHeight = pmremTexture.image?.height;
|
|
29
|
+
const resolvedImageHeight = Number.isFinite(imageHeight) && imageHeight > 0 ? imageHeight : 256;
|
|
30
|
+
const maxMip = Math.max(0, Math.log2(resolvedImageHeight) - 2);
|
|
31
|
+
return {
|
|
32
|
+
imageHeight: resolvedImageHeight,
|
|
33
|
+
maxMip,
|
|
34
|
+
texelWidth: 1.0 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16)),
|
|
35
|
+
texelHeight: 1.0 / resolvedImageHeight,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function createPrefilteredEquirectMaterial(pmremTexture, cubeUVSize) {
|
|
40
|
+
return new ShaderMaterial({
|
|
41
|
+
defines: {
|
|
42
|
+
USE_ENVMAP: '',
|
|
43
|
+
ENVMAP_TYPE_CUBE_UV: '',
|
|
44
|
+
CUBEUV_TEXEL_WIDTH: toGlslFloat(cubeUVSize.texelWidth),
|
|
45
|
+
CUBEUV_TEXEL_HEIGHT: toGlslFloat(cubeUVSize.texelHeight),
|
|
46
|
+
CUBEUV_MAX_MIP: toGlslFloat(cubeUVSize.maxMip),
|
|
47
|
+
},
|
|
48
|
+
uniforms: {
|
|
49
|
+
envMap: { value: pmremTexture },
|
|
50
|
+
roughness: { value: 0.0 },
|
|
51
|
+
},
|
|
52
|
+
vertexShader: `
|
|
53
|
+
varying vec2 vUv;
|
|
54
|
+
|
|
55
|
+
void main() {
|
|
56
|
+
vUv = uv;
|
|
57
|
+
gl_Position = vec4(position.xy, 0.0, 1.0);
|
|
58
|
+
}
|
|
59
|
+
`,
|
|
60
|
+
fragmentShader: `
|
|
61
|
+
uniform sampler2D envMap;
|
|
62
|
+
uniform float roughness;
|
|
63
|
+
varying vec2 vUv;
|
|
64
|
+
|
|
65
|
+
#include <common>
|
|
66
|
+
#include <cube_uv_reflection_fragment>
|
|
67
|
+
|
|
68
|
+
vec3 materialXLatlongDirection(vec2 uv) {
|
|
69
|
+
float longitude = (uv.x - 0.5) * (2.0 * PI);
|
|
70
|
+
float latitude = (uv.y - 0.5) * PI;
|
|
71
|
+
float cosLatitude = cos(latitude);
|
|
72
|
+
|
|
73
|
+
return vec3(
|
|
74
|
+
cosLatitude * sin(longitude),
|
|
75
|
+
-sin(latitude),
|
|
76
|
+
-cosLatitude * cos(longitude)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void main() {
|
|
81
|
+
vec3 direction = materialXLatlongDirection(vUv);
|
|
82
|
+
|
|
83
|
+
#ifdef ENVMAP_TYPE_CUBE_UV
|
|
84
|
+
vec4 envColor = textureCubeUV(envMap, direction, roughness);
|
|
85
|
+
#else
|
|
86
|
+
vec4 envColor = vec4(1.0, 0.0, 1.0, 1.0);
|
|
87
|
+
#endif
|
|
88
|
+
|
|
89
|
+
gl_FragColor = vec4(envColor.rgb, 1.0);
|
|
90
|
+
}
|
|
91
|
+
`
|
|
92
|
+
});
|
|
93
|
+
}
|
|
10
94
|
|
|
11
95
|
|
|
12
96
|
|
|
@@ -37,21 +121,7 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
37
121
|
// TODO Validate inputs
|
|
38
122
|
// console.log(renderer, pmremTexture);
|
|
39
123
|
|
|
40
|
-
|
|
41
|
-
// For PMREM CubeUV layout, we need the cube face size to calculate proper parameters
|
|
42
|
-
// Use renderTargetHeight if provided, otherwise try to derive from texture
|
|
43
|
-
let imageHeight;
|
|
44
|
-
if (renderTargetHeight) {
|
|
45
|
-
imageHeight = renderTargetHeight;
|
|
46
|
-
} else if (pmremTexture.image) {
|
|
47
|
-
imageHeight = pmremTexture.image.height / 4; // Fallback: assume CubeUV layout height / 4
|
|
48
|
-
} else {
|
|
49
|
-
imageHeight = 256; // Final fallback
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const maxMip = Math.log2(imageHeight) - 2;
|
|
53
|
-
const cubeUVHeight = imageHeight;
|
|
54
|
-
const cubeUVWidth = 3 * Math.max(Math.pow(2, maxMip), 7 * 16);
|
|
124
|
+
const cubeUVSize = getPMREMCubeUVSize(pmremTexture, renderTargetHeight);
|
|
55
125
|
|
|
56
126
|
// Create render target for equirectangular output
|
|
57
127
|
const renderTarget = new WebGLRenderTarget(width, height, {
|
|
@@ -63,7 +133,6 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
63
133
|
wrapS: RepeatWrapping,
|
|
64
134
|
anisotropy: renderer.capabilities.getMaxAnisotropy(),
|
|
65
135
|
});
|
|
66
|
-
|
|
67
136
|
// Create fullscreen quad geometry and camera
|
|
68
137
|
const geometry = new PlaneGeometry(2, 2);
|
|
69
138
|
const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
@@ -73,9 +142,9 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
73
142
|
defines: {
|
|
74
143
|
USE_ENVMAP: '',
|
|
75
144
|
ENVMAP_TYPE_CUBE_UV: '',
|
|
76
|
-
CUBEUV_TEXEL_WIDTH:
|
|
77
|
-
CUBEUV_TEXEL_HEIGHT:
|
|
78
|
-
CUBEUV_MAX_MIP: (maxMip
|
|
145
|
+
CUBEUV_TEXEL_WIDTH: toGlslFloat(cubeUVSize.texelWidth),
|
|
146
|
+
CUBEUV_TEXEL_HEIGHT: toGlslFloat(cubeUVSize.texelHeight),
|
|
147
|
+
CUBEUV_MAX_MIP: toGlslFloat(cubeUVSize.maxMip),
|
|
79
148
|
},
|
|
80
149
|
uniforms: {
|
|
81
150
|
envMap: { value: pmremTexture },
|
|
@@ -98,21 +167,17 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
98
167
|
#include <cube_uv_reflection_fragment>
|
|
99
168
|
|
|
100
169
|
void main() {
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
float
|
|
107
|
-
|
|
108
|
-
// Rotate 90° around Y
|
|
109
|
-
phi -= PI / 2.0; // Adjust to match Three.js convention
|
|
110
|
-
|
|
111
|
-
// Convert spherical to cartesian coordinates
|
|
170
|
+
// Use the inverse of MaterialX's mx_latlong_projection().
|
|
171
|
+
// MaterialX samples u_envRadiance through mx_latlong_map_lookup,
|
|
172
|
+
// so this conversion must write the same latlong convention.
|
|
173
|
+
float longitude = (vUv.x - 0.5) * (2.0 * PI);
|
|
174
|
+
float latitude = (vUv.y - 0.5) * PI;
|
|
175
|
+
float cosLatitude = cos(latitude);
|
|
176
|
+
|
|
112
177
|
vec3 direction = vec3(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
178
|
+
cosLatitude * sin(longitude),
|
|
179
|
+
-sin(latitude),
|
|
180
|
+
-cosLatitude * cos(longitude)
|
|
116
181
|
);
|
|
117
182
|
|
|
118
183
|
// Sample the PMREM cube texture using the direction and roughness
|
|
@@ -137,6 +202,7 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
137
202
|
const currentAutoClear = renderer.autoClear;
|
|
138
203
|
const currentXrEnabled = renderer.xr.enabled;
|
|
139
204
|
const currentShadowMapEnabled = renderer.shadowMap.enabled;
|
|
205
|
+
const currentViewport = renderer.getViewport(_viewport);
|
|
140
206
|
|
|
141
207
|
renderTarget.texture.generateMipmaps = true;
|
|
142
208
|
|
|
@@ -147,12 +213,15 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
147
213
|
|
|
148
214
|
// Render to our target
|
|
149
215
|
renderer.autoClear = true;
|
|
216
|
+
renderTarget.viewport.set(0, 0, width, height);
|
|
217
|
+
renderTarget.scissor.set(0, 0, width, height);
|
|
150
218
|
renderer.setRenderTarget(renderTarget);
|
|
151
219
|
renderer.clear(); // Explicitly clear the render target
|
|
152
220
|
renderer.render(tempScene, camera);
|
|
153
221
|
} finally {
|
|
154
222
|
// Restore renderer state completely
|
|
155
223
|
renderer.setRenderTarget(currentRenderTarget);
|
|
224
|
+
renderer.setViewport(currentViewport);
|
|
156
225
|
renderer.autoClear = currentAutoClear;
|
|
157
226
|
renderer.xr.enabled = currentXrEnabled;
|
|
158
227
|
renderer.shadowMap.enabled = currentShadowMapEnabled;
|
|
@@ -176,3 +245,91 @@ export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, w
|
|
|
176
245
|
|
|
177
246
|
return renderTarget;
|
|
178
247
|
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Renders a Three.js PMREM CubeUV texture to an equirectangular texture whose mip
|
|
251
|
+
* levels encode increasing roughness for MaterialX SPECULAR_ENVIRONMENT_PREFILTER.
|
|
252
|
+
* @param {WebGLRenderer} renderer
|
|
253
|
+
* @param {Texture} pmremTexture
|
|
254
|
+
* @param {number} [width=2048]
|
|
255
|
+
* @param {number} [height=1024]
|
|
256
|
+
* @param {number} [renderTargetHeight]
|
|
257
|
+
* @returns {WebGLRenderTarget}
|
|
258
|
+
*/
|
|
259
|
+
export function renderPMREMToPrefilteredEquirect(renderer, pmremTexture, width = 2048, height = 1024, renderTargetHeight) {
|
|
260
|
+
const cubeUVSize = getPMREMCubeUVSize(pmremTexture, renderTargetHeight);
|
|
261
|
+
const mipCount = Math.floor(Math.log2(Math.max(width, height))) + 1;
|
|
262
|
+
const materialXRadianceMipCount = Math.min(8, mipCount);
|
|
263
|
+
|
|
264
|
+
const renderTarget = new WebGLRenderTarget(width, height, {
|
|
265
|
+
format: RGBAFormat,
|
|
266
|
+
type: FloatType,
|
|
267
|
+
minFilter: LinearMipMapLinearFilter,
|
|
268
|
+
magFilter: LinearFilter,
|
|
269
|
+
generateMipmaps: false,
|
|
270
|
+
wrapS: RepeatWrapping,
|
|
271
|
+
anisotropy: renderer.capabilities.getMaxAnisotropy(),
|
|
272
|
+
});
|
|
273
|
+
renderTarget.texture.mipmaps = Array.from({ length: mipCount }, (_, mip) => ({
|
|
274
|
+
width: Math.max(1, width >> mip),
|
|
275
|
+
height: Math.max(1, height >> mip),
|
|
276
|
+
}));
|
|
277
|
+
|
|
278
|
+
const geometry = new PlaneGeometry(2, 2);
|
|
279
|
+
const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
280
|
+
const material = createPrefilteredEquirectMaterial(pmremTexture, cubeUVSize);
|
|
281
|
+
|
|
282
|
+
const tempScene = new Scene();
|
|
283
|
+
const mesh = new Mesh(geometry, material);
|
|
284
|
+
tempScene.add(mesh);
|
|
285
|
+
|
|
286
|
+
const currentRenderTarget = renderer.getRenderTarget();
|
|
287
|
+
const currentAutoClear = renderer.autoClear;
|
|
288
|
+
const currentXrEnabled = renderer.xr.enabled;
|
|
289
|
+
const currentShadowMapEnabled = renderer.shadowMap.enabled;
|
|
290
|
+
const currentViewport = renderer.getViewport(_viewport);
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
renderer.xr.enabled = false;
|
|
294
|
+
renderer.shadowMap.enabled = false;
|
|
295
|
+
renderer.autoClear = true;
|
|
296
|
+
|
|
297
|
+
for (let mip = 0; mip < mipCount; mip++) {
|
|
298
|
+
const materialXMip = Math.min(mip, materialXRadianceMipCount - 1);
|
|
299
|
+
const lodBias = materialXMip / Math.max(1, materialXRadianceMipCount - 1);
|
|
300
|
+
const alpha = lodBias < 0.5 ? lodBias * lodBias : 2.0 * (lodBias - 0.375);
|
|
301
|
+
const roughness = Math.sqrt(Math.min(1, Math.max(0, alpha)));
|
|
302
|
+
const mipWidth = Math.max(1, width >> mip);
|
|
303
|
+
const mipHeight = Math.max(1, height >> mip);
|
|
304
|
+
material.uniforms.roughness.value = Math.min(1, Math.max(0, roughness));
|
|
305
|
+
renderTarget.viewport.set(0, 0, mipWidth, mipHeight);
|
|
306
|
+
renderTarget.scissor.set(0, 0, mipWidth, mipHeight);
|
|
307
|
+
renderer.setRenderTarget(renderTarget, 0, mip);
|
|
308
|
+
renderer.clear();
|
|
309
|
+
renderer.render(tempScene, camera);
|
|
310
|
+
}
|
|
311
|
+
} finally {
|
|
312
|
+
renderer.setRenderTarget(currentRenderTarget);
|
|
313
|
+
renderer.setViewport(currentViewport);
|
|
314
|
+
renderer.autoClear = currentAutoClear;
|
|
315
|
+
renderer.xr.enabled = currentXrEnabled;
|
|
316
|
+
renderer.shadowMap.enabled = currentShadowMapEnabled;
|
|
317
|
+
|
|
318
|
+
geometry.dispose();
|
|
319
|
+
material.dispose();
|
|
320
|
+
tempScene.remove(mesh);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
renderTarget.texture.name = 'PMREM_Prefiltered_Equirectangular_Texture';
|
|
324
|
+
renderTarget.texture.mapping = EquirectangularReflectionMapping;
|
|
325
|
+
renderTarget.texture.generateMipmaps = false;
|
|
326
|
+
renderTarget.texture.userData.materialXRadianceMips = materialXRadianceMipCount;
|
|
327
|
+
|
|
328
|
+
if (debug) console.log('[MaterialX] PMREM to prefiltered equirect render target:', {
|
|
329
|
+
width: renderTarget.width,
|
|
330
|
+
height: renderTarget.height,
|
|
331
|
+
mipCount,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
return renderTarget;
|
|
335
|
+
}
|
|
File without changes
|