@luma.gl/gltf 9.3.0-alpha.4 → 9.3.0-alpha.8
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/dist/dist.dev.js +1305 -327
- package/dist/dist.min.js +98 -46
- package/dist/gltf/animations/animations.d.ts +16 -4
- package/dist/gltf/animations/animations.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.d.ts +4 -3
- package/dist/gltf/animations/interpolate.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.js +27 -36
- package/dist/gltf/animations/interpolate.js.map +1 -1
- package/dist/gltf/create-gltf-model.d.ts +15 -1
- package/dist/gltf/create-gltf-model.d.ts.map +1 -1
- package/dist/gltf/create-gltf-model.js +154 -48
- package/dist/gltf/create-gltf-model.js.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.d.ts +37 -2
- package/dist/gltf/create-scenegraph-from-gltf.d.ts.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.js +74 -6
- package/dist/gltf/create-scenegraph-from-gltf.js.map +1 -1
- package/dist/gltf/gltf-animator.d.ts +26 -0
- package/dist/gltf/gltf-animator.d.ts.map +1 -1
- package/dist/gltf/gltf-animator.js +22 -19
- package/dist/gltf/gltf-animator.js.map +1 -1
- package/dist/gltf/gltf-extension-support.d.ts +10 -0
- package/dist/gltf/gltf-extension-support.d.ts.map +1 -0
- package/dist/gltf/gltf-extension-support.js +173 -0
- package/dist/gltf/gltf-extension-support.js.map +1 -0
- package/dist/index.cjs +1247 -294
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/parsers/parse-gltf-animations.d.ts +1 -0
- package/dist/parsers/parse-gltf-animations.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-animations.js +73 -28
- package/dist/parsers/parse-gltf-animations.js.map +1 -1
- package/dist/parsers/parse-gltf-lights.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-lights.js +112 -18
- package/dist/parsers/parse-gltf-lights.js.map +1 -1
- package/dist/parsers/parse-gltf.d.ts +19 -2
- package/dist/parsers/parse-gltf.d.ts.map +1 -1
- package/dist/parsers/parse-gltf.js +101 -61
- package/dist/parsers/parse-gltf.js.map +1 -1
- package/dist/parsers/parse-pbr-material.d.ts +115 -2
- package/dist/parsers/parse-pbr-material.d.ts.map +1 -1
- package/dist/parsers/parse-pbr-material.js +565 -54
- package/dist/parsers/parse-pbr-material.js.map +1 -1
- package/dist/pbr/pbr-environment.d.ts +6 -0
- package/dist/pbr/pbr-environment.d.ts.map +1 -1
- package/dist/pbr/pbr-environment.js +15 -12
- package/dist/pbr/pbr-environment.js.map +1 -1
- package/dist/pbr/pbr-material.d.ts +13 -3
- package/dist/pbr/pbr-material.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts +12 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.js +3 -0
- package/dist/webgl-to-webgpu/convert-webgl-attribute.js.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts +11 -5
- package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-sampler.js +16 -12
- package/dist/webgl-to-webgpu/convert-webgl-sampler.js.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts +2 -9
- package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.js +2 -14
- package/dist/webgl-to-webgpu/convert-webgl-topology.js.map +1 -1
- package/dist/webgl-to-webgpu/gltf-webgl-constants.d.ts +27 -0
- package/dist/webgl-to-webgpu/gltf-webgl-constants.d.ts.map +1 -0
- package/dist/webgl-to-webgpu/gltf-webgl-constants.js +34 -0
- package/dist/webgl-to-webgpu/gltf-webgl-constants.js.map +1 -0
- package/package.json +8 -9
- package/src/gltf/animations/animations.ts +17 -5
- package/src/gltf/animations/interpolate.ts +49 -68
- package/src/gltf/create-gltf-model.ts +214 -48
- package/src/gltf/create-scenegraph-from-gltf.ts +131 -12
- package/src/gltf/gltf-animator.ts +34 -25
- package/src/gltf/gltf-extension-support.ts +214 -0
- package/src/index.ts +10 -2
- package/src/parsers/parse-gltf-animations.ts +94 -33
- package/src/parsers/parse-gltf-lights.ts +147 -20
- package/src/parsers/parse-gltf.ts +170 -90
- package/src/parsers/parse-pbr-material.ts +865 -80
- package/src/pbr/pbr-environment.ts +38 -15
- package/src/pbr/pbr-material.ts +18 -3
- package/src/webgl-to-webgpu/convert-webgl-attribute.ts +12 -1
- package/src/webgl-to-webgpu/convert-webgl-sampler.ts +38 -29
- package/src/webgl-to-webgpu/convert-webgl-topology.ts +2 -14
- package/src/webgl-to-webgpu/gltf-webgl-constants.ts +35 -0
- package/dist/utils/deep-copy.d.ts +0 -3
- package/dist/utils/deep-copy.d.ts.map +0 -1
- package/dist/utils/deep-copy.js +0 -21
- package/dist/utils/deep-copy.js.map +0 -1
- package/src/utils/deep-copy.ts +0 -22
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// luma.gl
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { Texture, log, textureFormatDecoder } from '@luma.gl/core';
|
|
5
|
+
import { GLEnum } from "../webgl-to-webgpu/gltf-webgl-constants.js";
|
|
6
6
|
import { convertSampler } from "../webgl-to-webgpu/convert-webgl-sampler.js";
|
|
7
7
|
/**
|
|
8
8
|
* Parses a GLTF material definition into uniforms and parameters for the PBR shader module
|
|
@@ -32,7 +32,8 @@ export function parsePBRMaterial(device, material, attributes, options) {
|
|
|
32
32
|
imageBasedLightingEnvironment.diffuseEnvSampler.texture;
|
|
33
33
|
parsedMaterial.bindings.pbr_specularEnvSampler =
|
|
34
34
|
imageBasedLightingEnvironment.specularEnvSampler.texture;
|
|
35
|
-
parsedMaterial.bindings.
|
|
35
|
+
parsedMaterial.bindings.pbr_brdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
|
|
36
|
+
parsedMaterial.uniforms.IBLenabled = true;
|
|
36
37
|
parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
|
|
37
38
|
}
|
|
38
39
|
if (options?.pbrDebug) {
|
|
@@ -47,6 +48,8 @@ export function parsePBRMaterial(device, material, attributes, options) {
|
|
|
47
48
|
parsedMaterial.defines['HAS_TANGENTS'] = true;
|
|
48
49
|
if (attributes['TEXCOORD_0'])
|
|
49
50
|
parsedMaterial.defines['HAS_UV'] = true;
|
|
51
|
+
if (attributes['JOINTS_0'] && attributes['WEIGHTS_0'])
|
|
52
|
+
parsedMaterial.defines['HAS_SKIN'] = true;
|
|
50
53
|
if (attributes['COLOR_0'])
|
|
51
54
|
parsedMaterial.defines['HAS_COLORS'] = true;
|
|
52
55
|
if (options?.imageBasedLightingEnvironment)
|
|
@@ -54,99 +57,601 @@ export function parsePBRMaterial(device, material, attributes, options) {
|
|
|
54
57
|
if (options?.lights)
|
|
55
58
|
parsedMaterial.defines['USE_LIGHTS'] = true;
|
|
56
59
|
if (material) {
|
|
57
|
-
|
|
60
|
+
if (options.validateAttributes !== false) {
|
|
61
|
+
warnOnMissingExpectedAttributes(material, attributes);
|
|
62
|
+
}
|
|
63
|
+
parseMaterial(device, material, parsedMaterial, options.gltf);
|
|
58
64
|
}
|
|
59
65
|
return parsedMaterial;
|
|
60
66
|
}
|
|
67
|
+
function warnOnMissingExpectedAttributes(material, attributes) {
|
|
68
|
+
const uvDependentTextureSlots = getUvDependentTextureSlots(material);
|
|
69
|
+
if (uvDependentTextureSlots.length > 0 && !attributes['TEXCOORD_0']) {
|
|
70
|
+
log.warn(`glTF material uses ${uvDependentTextureSlots.join(', ')} but primitive is missing TEXCOORD_0; textured shading will sample the default UV coordinates`)();
|
|
71
|
+
}
|
|
72
|
+
const isUnlitMaterial = Boolean(material.unlit || material.extensions?.KHR_materials_unlit);
|
|
73
|
+
if (isUnlitMaterial || attributes['NORMAL']) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const missingNormalReason = material.normalTexture
|
|
77
|
+
? 'lit PBR shading with normalTexture'
|
|
78
|
+
: 'lit PBR shading';
|
|
79
|
+
log.warn(`glTF primitive is missing NORMAL while using ${missingNormalReason}; shading will fall back to geometric normals`)();
|
|
80
|
+
}
|
|
81
|
+
function getUvDependentTextureSlots(material) {
|
|
82
|
+
const uvDependentTextureSlots = [];
|
|
83
|
+
if (material.pbrMetallicRoughness?.baseColorTexture) {
|
|
84
|
+
uvDependentTextureSlots.push('baseColorTexture');
|
|
85
|
+
}
|
|
86
|
+
if (material.pbrMetallicRoughness?.metallicRoughnessTexture) {
|
|
87
|
+
uvDependentTextureSlots.push('metallicRoughnessTexture');
|
|
88
|
+
}
|
|
89
|
+
if (material.normalTexture) {
|
|
90
|
+
uvDependentTextureSlots.push('normalTexture');
|
|
91
|
+
}
|
|
92
|
+
if (material.occlusionTexture) {
|
|
93
|
+
uvDependentTextureSlots.push('occlusionTexture');
|
|
94
|
+
}
|
|
95
|
+
if (material.emissiveTexture) {
|
|
96
|
+
uvDependentTextureSlots.push('emissiveTexture');
|
|
97
|
+
}
|
|
98
|
+
if (material.extensions?.KHR_materials_specular?.specularTexture) {
|
|
99
|
+
uvDependentTextureSlots.push('KHR_materials_specular.specularTexture');
|
|
100
|
+
}
|
|
101
|
+
if (material.extensions?.KHR_materials_specular?.specularColorTexture) {
|
|
102
|
+
uvDependentTextureSlots.push('KHR_materials_specular.specularColorTexture');
|
|
103
|
+
}
|
|
104
|
+
if (material.extensions?.KHR_materials_transmission?.transmissionTexture) {
|
|
105
|
+
uvDependentTextureSlots.push('KHR_materials_transmission.transmissionTexture');
|
|
106
|
+
}
|
|
107
|
+
if (material.extensions?.KHR_materials_clearcoat?.clearcoatTexture) {
|
|
108
|
+
uvDependentTextureSlots.push('KHR_materials_clearcoat.clearcoatTexture');
|
|
109
|
+
}
|
|
110
|
+
if (material.extensions?.KHR_materials_clearcoat?.clearcoatRoughnessTexture) {
|
|
111
|
+
uvDependentTextureSlots.push('KHR_materials_clearcoat.clearcoatRoughnessTexture');
|
|
112
|
+
}
|
|
113
|
+
if (material.extensions?.KHR_materials_sheen?.sheenColorTexture) {
|
|
114
|
+
uvDependentTextureSlots.push('KHR_materials_sheen.sheenColorTexture');
|
|
115
|
+
}
|
|
116
|
+
if (material.extensions?.KHR_materials_sheen?.sheenRoughnessTexture) {
|
|
117
|
+
uvDependentTextureSlots.push('KHR_materials_sheen.sheenRoughnessTexture');
|
|
118
|
+
}
|
|
119
|
+
if (material.extensions?.KHR_materials_iridescence?.iridescenceTexture) {
|
|
120
|
+
uvDependentTextureSlots.push('KHR_materials_iridescence.iridescenceTexture');
|
|
121
|
+
}
|
|
122
|
+
if (material.extensions?.KHR_materials_anisotropy?.anisotropyTexture) {
|
|
123
|
+
uvDependentTextureSlots.push('KHR_materials_anisotropy.anisotropyTexture');
|
|
124
|
+
}
|
|
125
|
+
return uvDependentTextureSlots;
|
|
126
|
+
}
|
|
61
127
|
/** Parse GLTF material record */
|
|
62
|
-
function parseMaterial(device, material, parsedMaterial) {
|
|
63
|
-
parsedMaterial.uniforms.unlit = Boolean(material.unlit);
|
|
128
|
+
function parseMaterial(device, material, parsedMaterial, gltf) {
|
|
129
|
+
parsedMaterial.uniforms.unlit = Boolean(material.unlit || material.extensions?.KHR_materials_unlit);
|
|
64
130
|
if (material.pbrMetallicRoughness) {
|
|
65
|
-
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
|
|
131
|
+
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial, gltf);
|
|
66
132
|
}
|
|
67
133
|
if (material.normalTexture) {
|
|
68
|
-
addTexture(device, material.normalTexture, 'pbr_normalSampler',
|
|
134
|
+
addTexture(device, material.normalTexture, 'pbr_normalSampler', parsedMaterial, {
|
|
135
|
+
featureOptions: {
|
|
136
|
+
define: 'HAS_NORMALMAP',
|
|
137
|
+
enabledUniformName: 'normalMapEnabled'
|
|
138
|
+
},
|
|
139
|
+
gltf
|
|
140
|
+
});
|
|
69
141
|
const { scale = 1 } = material.normalTexture;
|
|
70
142
|
parsedMaterial.uniforms.normalScale = scale;
|
|
71
143
|
}
|
|
72
144
|
if (material.occlusionTexture) {
|
|
73
|
-
addTexture(device, material.occlusionTexture, 'pbr_occlusionSampler',
|
|
145
|
+
addTexture(device, material.occlusionTexture, 'pbr_occlusionSampler', parsedMaterial, {
|
|
146
|
+
featureOptions: {
|
|
147
|
+
define: 'HAS_OCCLUSIONMAP',
|
|
148
|
+
enabledUniformName: 'occlusionMapEnabled'
|
|
149
|
+
},
|
|
150
|
+
gltf
|
|
151
|
+
});
|
|
74
152
|
const { strength = 1 } = material.occlusionTexture;
|
|
75
153
|
parsedMaterial.uniforms.occlusionStrength = strength;
|
|
76
154
|
}
|
|
155
|
+
parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
|
|
77
156
|
if (material.emissiveTexture) {
|
|
78
|
-
addTexture(device, material.emissiveTexture, 'pbr_emissiveSampler',
|
|
79
|
-
|
|
157
|
+
addTexture(device, material.emissiveTexture, 'pbr_emissiveSampler', parsedMaterial, {
|
|
158
|
+
featureOptions: {
|
|
159
|
+
define: 'HAS_EMISSIVEMAP',
|
|
160
|
+
enabledUniformName: 'emissiveMapEnabled'
|
|
161
|
+
},
|
|
162
|
+
gltf
|
|
163
|
+
});
|
|
80
164
|
}
|
|
81
|
-
|
|
82
|
-
|
|
165
|
+
parseMaterialExtensions(device, material.extensions, parsedMaterial, gltf);
|
|
166
|
+
switch (material.alphaMode || 'OPAQUE') {
|
|
167
|
+
case 'OPAQUE':
|
|
168
|
+
break;
|
|
169
|
+
case 'MASK': {
|
|
83
170
|
const { alphaCutoff = 0.5 } = material;
|
|
84
171
|
parsedMaterial.defines['ALPHA_CUTOFF'] = true;
|
|
172
|
+
parsedMaterial.uniforms.alphaCutoffEnabled = true;
|
|
85
173
|
parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
|
|
86
174
|
break;
|
|
175
|
+
}
|
|
87
176
|
case 'BLEND':
|
|
88
177
|
log.warn('glTF BLEND alphaMode might not work well because it requires mesh sorting')();
|
|
89
|
-
|
|
90
|
-
parsedMaterial.parameters.blend = true;
|
|
91
|
-
parsedMaterial.parameters.blendColorOperation = 'add';
|
|
92
|
-
parsedMaterial.parameters.blendColorSrcFactor = 'src-alpha';
|
|
93
|
-
parsedMaterial.parameters.blendColorDstFactor = 'one-minus-src-alpha';
|
|
94
|
-
parsedMaterial.parameters.blendAlphaOperation = 'add';
|
|
95
|
-
parsedMaterial.parameters.blendAlphaSrcFactor = 'one';
|
|
96
|
-
parsedMaterial.parameters.blendAlphaDstFactor = 'one-minus-src-alpha';
|
|
97
|
-
// GL parameters
|
|
98
|
-
// TODO - remove in favor of parameters
|
|
99
|
-
parsedMaterial.glParameters['blend'] = true;
|
|
100
|
-
parsedMaterial.glParameters['blendEquation'] = 32774;
|
|
101
|
-
parsedMaterial.glParameters['blendFunc'] = [
|
|
102
|
-
770,
|
|
103
|
-
771,
|
|
104
|
-
1,
|
|
105
|
-
771
|
|
106
|
-
];
|
|
178
|
+
applyAlphaBlendParameters(parsedMaterial);
|
|
107
179
|
break;
|
|
108
180
|
}
|
|
109
181
|
}
|
|
182
|
+
function applyAlphaBlendParameters(parsedMaterial) {
|
|
183
|
+
parsedMaterial.parameters.blend = true;
|
|
184
|
+
parsedMaterial.parameters.blendColorOperation = 'add';
|
|
185
|
+
parsedMaterial.parameters.blendColorSrcFactor = 'src-alpha';
|
|
186
|
+
parsedMaterial.parameters.blendColorDstFactor = 'one-minus-src-alpha';
|
|
187
|
+
parsedMaterial.parameters.blendAlphaOperation = 'add';
|
|
188
|
+
parsedMaterial.parameters.blendAlphaSrcFactor = 'one';
|
|
189
|
+
parsedMaterial.parameters.blendAlphaDstFactor = 'one-minus-src-alpha';
|
|
190
|
+
parsedMaterial.glParameters['blend'] = true;
|
|
191
|
+
parsedMaterial.glParameters['blendEquation'] = GLEnum.FUNC_ADD;
|
|
192
|
+
parsedMaterial.glParameters['blendFunc'] = [
|
|
193
|
+
GLEnum.SRC_ALPHA,
|
|
194
|
+
GLEnum.ONE_MINUS_SRC_ALPHA,
|
|
195
|
+
GLEnum.ONE,
|
|
196
|
+
GLEnum.ONE_MINUS_SRC_ALPHA
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
function applyTransmissionBlendApproximation(parsedMaterial) {
|
|
200
|
+
parsedMaterial.parameters.blend = true;
|
|
201
|
+
parsedMaterial.parameters.depthWriteEnabled = false;
|
|
202
|
+
parsedMaterial.parameters.blendColorOperation = 'add';
|
|
203
|
+
parsedMaterial.parameters.blendColorSrcFactor = 'one';
|
|
204
|
+
parsedMaterial.parameters.blendColorDstFactor = 'one-minus-src-alpha';
|
|
205
|
+
parsedMaterial.parameters.blendAlphaOperation = 'add';
|
|
206
|
+
parsedMaterial.parameters.blendAlphaSrcFactor = 'one';
|
|
207
|
+
parsedMaterial.parameters.blendAlphaDstFactor = 'one-minus-src-alpha';
|
|
208
|
+
parsedMaterial.glParameters['blend'] = true;
|
|
209
|
+
parsedMaterial.glParameters['depthMask'] = false;
|
|
210
|
+
parsedMaterial.glParameters['blendEquation'] = GLEnum.FUNC_ADD;
|
|
211
|
+
parsedMaterial.glParameters['blendFunc'] = [
|
|
212
|
+
GLEnum.ONE,
|
|
213
|
+
GLEnum.ONE_MINUS_SRC_ALPHA,
|
|
214
|
+
GLEnum.ONE,
|
|
215
|
+
GLEnum.ONE_MINUS_SRC_ALPHA
|
|
216
|
+
];
|
|
217
|
+
}
|
|
110
218
|
/** Parse GLTF material sub record */
|
|
111
|
-
function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial) {
|
|
219
|
+
function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial, gltf) {
|
|
112
220
|
if (pbrMetallicRoughness.baseColorTexture) {
|
|
113
|
-
addTexture(device, pbrMetallicRoughness.baseColorTexture, 'pbr_baseColorSampler',
|
|
221
|
+
addTexture(device, pbrMetallicRoughness.baseColorTexture, 'pbr_baseColorSampler', parsedMaterial, {
|
|
222
|
+
featureOptions: {
|
|
223
|
+
define: 'HAS_BASECOLORMAP',
|
|
224
|
+
enabledUniformName: 'baseColorMapEnabled'
|
|
225
|
+
},
|
|
226
|
+
gltf
|
|
227
|
+
});
|
|
114
228
|
}
|
|
115
229
|
parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
|
|
116
230
|
if (pbrMetallicRoughness.metallicRoughnessTexture) {
|
|
117
|
-
addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, 'pbr_metallicRoughnessSampler',
|
|
231
|
+
addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, 'pbr_metallicRoughnessSampler', parsedMaterial, {
|
|
232
|
+
featureOptions: {
|
|
233
|
+
define: 'HAS_METALROUGHNESSMAP',
|
|
234
|
+
enabledUniformName: 'metallicRoughnessMapEnabled'
|
|
235
|
+
},
|
|
236
|
+
gltf
|
|
237
|
+
});
|
|
118
238
|
}
|
|
119
239
|
const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
|
|
120
240
|
parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
|
|
121
241
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
let textureOptions;
|
|
126
|
-
if (image.compressed) {
|
|
127
|
-
textureOptions = image;
|
|
242
|
+
function parseMaterialExtensions(device, extensions, parsedMaterial, gltf) {
|
|
243
|
+
if (!extensions) {
|
|
244
|
+
return;
|
|
128
245
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
246
|
+
if (hasMaterialExtensionShading(extensions)) {
|
|
247
|
+
parsedMaterial.defines['USE_MATERIAL_EXTENSIONS'] = true;
|
|
248
|
+
}
|
|
249
|
+
parseSpecularExtension(device, extensions.KHR_materials_specular, parsedMaterial, gltf);
|
|
250
|
+
parseIorExtension(extensions.KHR_materials_ior, parsedMaterial);
|
|
251
|
+
parseTransmissionExtension(device, extensions.KHR_materials_transmission, parsedMaterial, gltf);
|
|
252
|
+
parseVolumeExtension(device, extensions.KHR_materials_volume, parsedMaterial, gltf);
|
|
253
|
+
parseClearcoatExtension(device, extensions.KHR_materials_clearcoat, parsedMaterial, gltf);
|
|
254
|
+
parseSheenExtension(device, extensions.KHR_materials_sheen, parsedMaterial, gltf);
|
|
255
|
+
parseIridescenceExtension(device, extensions.KHR_materials_iridescence, parsedMaterial, gltf);
|
|
256
|
+
parseAnisotropyExtension(device, extensions.KHR_materials_anisotropy, parsedMaterial, gltf);
|
|
257
|
+
parseEmissiveStrengthExtension(extensions.KHR_materials_emissive_strength, parsedMaterial);
|
|
258
|
+
}
|
|
259
|
+
function hasMaterialExtensionShading(extensions) {
|
|
260
|
+
return Boolean(extensions.KHR_materials_specular ||
|
|
261
|
+
extensions.KHR_materials_ior ||
|
|
262
|
+
extensions.KHR_materials_transmission ||
|
|
263
|
+
extensions.KHR_materials_volume ||
|
|
264
|
+
extensions.KHR_materials_clearcoat ||
|
|
265
|
+
extensions.KHR_materials_sheen ||
|
|
266
|
+
extensions.KHR_materials_iridescence ||
|
|
267
|
+
extensions.KHR_materials_anisotropy);
|
|
268
|
+
}
|
|
269
|
+
function parseSpecularExtension(device, extension, parsedMaterial, gltf) {
|
|
270
|
+
if (!extension) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (extension.specularColorFactor) {
|
|
274
|
+
parsedMaterial.uniforms.specularColorFactor = extension.specularColorFactor;
|
|
275
|
+
}
|
|
276
|
+
if (extension.specularFactor !== undefined) {
|
|
277
|
+
parsedMaterial.uniforms.specularIntensityFactor = extension.specularFactor;
|
|
278
|
+
}
|
|
279
|
+
if (extension.specularColorTexture) {
|
|
280
|
+
addTexture(device, extension.specularColorTexture, 'pbr_specularColorSampler', parsedMaterial, {
|
|
281
|
+
featureOptions: {
|
|
282
|
+
define: 'HAS_SPECULARCOLORMAP',
|
|
283
|
+
enabledUniformName: 'specularColorMapEnabled'
|
|
284
|
+
},
|
|
285
|
+
gltf
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
if (extension.specularTexture) {
|
|
289
|
+
addTexture(device, extension.specularTexture, 'pbr_specularIntensitySampler', parsedMaterial, {
|
|
290
|
+
featureOptions: {
|
|
291
|
+
define: 'HAS_SPECULARINTENSITYMAP',
|
|
292
|
+
enabledUniformName: 'specularIntensityMapEnabled'
|
|
293
|
+
},
|
|
294
|
+
gltf
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function parseIorExtension(extension, parsedMaterial) {
|
|
299
|
+
if (extension?.ior !== undefined) {
|
|
300
|
+
parsedMaterial.uniforms.ior = extension.ior;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function parseTransmissionExtension(device, extension, parsedMaterial, gltf) {
|
|
304
|
+
if (!extension) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (extension.transmissionFactor !== undefined) {
|
|
308
|
+
parsedMaterial.uniforms.transmissionFactor = extension.transmissionFactor;
|
|
309
|
+
}
|
|
310
|
+
if (extension.transmissionTexture) {
|
|
311
|
+
addTexture(device, extension.transmissionTexture, 'pbr_transmissionSampler', parsedMaterial, {
|
|
312
|
+
featureOptions: {
|
|
313
|
+
define: 'HAS_TRANSMISSIONMAP',
|
|
314
|
+
enabledUniformName: 'transmissionMapEnabled'
|
|
315
|
+
},
|
|
316
|
+
gltf
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if ((extension.transmissionFactor ?? 0) > 0 || extension.transmissionTexture) {
|
|
320
|
+
log.warn('KHR_materials_transmission uses a premultiplied-alpha blending approximation and may require mesh sorting')();
|
|
321
|
+
applyTransmissionBlendApproximation(parsedMaterial);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function parseVolumeExtension(device, extension, parsedMaterial, gltf) {
|
|
325
|
+
if (!extension) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (extension.thicknessFactor !== undefined) {
|
|
329
|
+
parsedMaterial.uniforms.thicknessFactor = extension.thicknessFactor;
|
|
330
|
+
}
|
|
331
|
+
if (extension.thicknessTexture) {
|
|
332
|
+
addTexture(device, extension.thicknessTexture, 'pbr_thicknessSampler', parsedMaterial, {
|
|
333
|
+
featureOptions: {
|
|
334
|
+
define: 'HAS_THICKNESSMAP'
|
|
335
|
+
},
|
|
336
|
+
gltf
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
if (extension.attenuationDistance !== undefined) {
|
|
340
|
+
parsedMaterial.uniforms.attenuationDistance = extension.attenuationDistance;
|
|
341
|
+
}
|
|
342
|
+
if (extension.attenuationColor) {
|
|
343
|
+
parsedMaterial.uniforms.attenuationColor = extension.attenuationColor;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
|
|
347
|
+
if (!extension) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (extension.clearcoatFactor !== undefined) {
|
|
351
|
+
parsedMaterial.uniforms.clearcoatFactor = extension.clearcoatFactor;
|
|
352
|
+
}
|
|
353
|
+
if (extension.clearcoatRoughnessFactor !== undefined) {
|
|
354
|
+
parsedMaterial.uniforms.clearcoatRoughnessFactor = extension.clearcoatRoughnessFactor;
|
|
355
|
+
}
|
|
356
|
+
if (extension.clearcoatTexture) {
|
|
357
|
+
addTexture(device, extension.clearcoatTexture, 'pbr_clearcoatSampler', parsedMaterial, {
|
|
358
|
+
featureOptions: {
|
|
359
|
+
define: 'HAS_CLEARCOATMAP',
|
|
360
|
+
enabledUniformName: 'clearcoatMapEnabled'
|
|
361
|
+
},
|
|
362
|
+
gltf
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
if (extension.clearcoatRoughnessTexture) {
|
|
366
|
+
addTexture(device, extension.clearcoatRoughnessTexture, 'pbr_clearcoatRoughnessSampler', parsedMaterial, {
|
|
367
|
+
featureOptions: {
|
|
368
|
+
define: 'HAS_CLEARCOATROUGHNESSMAP',
|
|
369
|
+
enabledUniformName: 'clearcoatRoughnessMapEnabled'
|
|
370
|
+
},
|
|
371
|
+
gltf
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
if (extension.clearcoatNormalTexture) {
|
|
375
|
+
addTexture(device, extension.clearcoatNormalTexture, 'pbr_clearcoatNormalSampler', parsedMaterial, {
|
|
376
|
+
featureOptions: {
|
|
377
|
+
define: 'HAS_CLEARCOATNORMALMAP'
|
|
378
|
+
},
|
|
379
|
+
gltf
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function parseSheenExtension(device, extension, parsedMaterial, gltf) {
|
|
384
|
+
if (!extension) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (extension.sheenColorFactor) {
|
|
388
|
+
parsedMaterial.uniforms.sheenColorFactor = extension.sheenColorFactor;
|
|
389
|
+
}
|
|
390
|
+
if (extension.sheenRoughnessFactor !== undefined) {
|
|
391
|
+
parsedMaterial.uniforms.sheenRoughnessFactor = extension.sheenRoughnessFactor;
|
|
392
|
+
}
|
|
393
|
+
if (extension.sheenColorTexture) {
|
|
394
|
+
addTexture(device, extension.sheenColorTexture, 'pbr_sheenColorSampler', parsedMaterial, {
|
|
395
|
+
featureOptions: {
|
|
396
|
+
define: 'HAS_SHEENCOLORMAP',
|
|
397
|
+
enabledUniformName: 'sheenColorMapEnabled'
|
|
398
|
+
},
|
|
399
|
+
gltf
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
if (extension.sheenRoughnessTexture) {
|
|
403
|
+
addTexture(device, extension.sheenRoughnessTexture, 'pbr_sheenRoughnessSampler', parsedMaterial, {
|
|
404
|
+
featureOptions: {
|
|
405
|
+
define: 'HAS_SHEENROUGHNESSMAP',
|
|
406
|
+
enabledUniformName: 'sheenRoughnessMapEnabled'
|
|
407
|
+
},
|
|
408
|
+
gltf
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function parseIridescenceExtension(device, extension, parsedMaterial, gltf) {
|
|
413
|
+
if (!extension) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (extension.iridescenceFactor !== undefined) {
|
|
417
|
+
parsedMaterial.uniforms.iridescenceFactor = extension.iridescenceFactor;
|
|
418
|
+
}
|
|
419
|
+
if (extension.iridescenceIor !== undefined) {
|
|
420
|
+
parsedMaterial.uniforms.iridescenceIor = extension.iridescenceIor;
|
|
421
|
+
}
|
|
422
|
+
if (extension.iridescenceThicknessMinimum !== undefined ||
|
|
423
|
+
extension.iridescenceThicknessMaximum !== undefined) {
|
|
424
|
+
parsedMaterial.uniforms.iridescenceThicknessRange = [
|
|
425
|
+
extension.iridescenceThicknessMinimum ?? 100,
|
|
426
|
+
extension.iridescenceThicknessMaximum ?? 400
|
|
427
|
+
];
|
|
428
|
+
}
|
|
429
|
+
if (extension.iridescenceTexture) {
|
|
430
|
+
addTexture(device, extension.iridescenceTexture, 'pbr_iridescenceSampler', parsedMaterial, {
|
|
431
|
+
featureOptions: {
|
|
432
|
+
define: 'HAS_IRIDESCENCEMAP',
|
|
433
|
+
enabledUniformName: 'iridescenceMapEnabled'
|
|
434
|
+
},
|
|
435
|
+
gltf
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
if (extension.iridescenceThicknessTexture) {
|
|
439
|
+
addTexture(device, extension.iridescenceThicknessTexture, 'pbr_iridescenceThicknessSampler', parsedMaterial, {
|
|
440
|
+
featureOptions: {
|
|
441
|
+
define: 'HAS_IRIDESCENCETHICKNESSMAP'
|
|
442
|
+
},
|
|
443
|
+
gltf
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function parseAnisotropyExtension(device, extension, parsedMaterial, gltf) {
|
|
448
|
+
if (!extension) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
if (extension.anisotropyStrength !== undefined) {
|
|
452
|
+
parsedMaterial.uniforms.anisotropyStrength = extension.anisotropyStrength;
|
|
453
|
+
}
|
|
454
|
+
if (extension.anisotropyRotation !== undefined) {
|
|
455
|
+
parsedMaterial.uniforms.anisotropyRotation = extension.anisotropyRotation;
|
|
456
|
+
}
|
|
457
|
+
if (extension.anisotropyTexture) {
|
|
458
|
+
addTexture(device, extension.anisotropyTexture, 'pbr_anisotropySampler', parsedMaterial, {
|
|
459
|
+
featureOptions: {
|
|
460
|
+
define: 'HAS_ANISOTROPYMAP',
|
|
461
|
+
enabledUniformName: 'anisotropyMapEnabled'
|
|
462
|
+
},
|
|
463
|
+
gltf
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
function parseEmissiveStrengthExtension(extension, parsedMaterial) {
|
|
468
|
+
if (extension?.emissiveStrength !== undefined) {
|
|
469
|
+
parsedMaterial.uniforms.emissiveStrength = extension.emissiveStrength;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/** Create a texture from a glTF texture/sampler/image combo and add it to bindings */
|
|
473
|
+
function addTexture(device, gltfTexture, uniformName, parsedMaterial, textureParseOptions = {}) {
|
|
474
|
+
const { featureOptions = {}, gltf } = textureParseOptions;
|
|
475
|
+
const { define, enabledUniformName } = featureOptions;
|
|
476
|
+
const resolvedTextureInfo = resolveTextureInfo(gltfTexture, gltf);
|
|
477
|
+
const image = resolvedTextureInfo.texture?.source?.image;
|
|
478
|
+
if (!image) {
|
|
479
|
+
log.warn(`Skipping unresolved glTF texture for ${String(uniformName)}`)();
|
|
480
|
+
return;
|
|
132
481
|
}
|
|
133
482
|
const gltfSampler = {
|
|
134
483
|
wrapS: 10497, // default REPEAT S (U) wrapping mode.
|
|
135
484
|
wrapT: 10497, // default REPEAT T (V) wrapping mode.
|
|
136
485
|
minFilter: 9729, // default LINEAR filtering
|
|
137
486
|
magFilter: 9729, // default LINEAR filtering
|
|
138
|
-
...
|
|
487
|
+
...resolvedTextureInfo?.texture?.sampler
|
|
139
488
|
};
|
|
140
|
-
const
|
|
141
|
-
id:
|
|
142
|
-
sampler: convertSampler(gltfSampler)
|
|
143
|
-
|
|
144
|
-
|
|
489
|
+
const baseOptions = {
|
|
490
|
+
id: resolvedTextureInfo.uniformName || resolvedTextureInfo.id,
|
|
491
|
+
sampler: convertSampler(gltfSampler)
|
|
492
|
+
};
|
|
493
|
+
let texture;
|
|
494
|
+
if (image.compressed) {
|
|
495
|
+
texture = createCompressedTexture(device, image, baseOptions);
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
const { width, height } = device.getExternalImageSize(image);
|
|
499
|
+
texture = device.createTexture({
|
|
500
|
+
...baseOptions,
|
|
501
|
+
width,
|
|
502
|
+
height,
|
|
503
|
+
data: image
|
|
504
|
+
});
|
|
505
|
+
}
|
|
145
506
|
parsedMaterial.bindings[uniformName] = texture;
|
|
146
507
|
if (define)
|
|
147
508
|
parsedMaterial.defines[define] = true;
|
|
509
|
+
if (enabledUniformName) {
|
|
510
|
+
parsedMaterial.uniforms[enabledUniformName] = true;
|
|
511
|
+
}
|
|
148
512
|
parsedMaterial.generatedTextures.push(texture);
|
|
149
513
|
}
|
|
514
|
+
function resolveTextureInfo(gltfTexture, gltf) {
|
|
515
|
+
if (gltfTexture.texture || gltfTexture.index === undefined || !gltf?.textures) {
|
|
516
|
+
return gltfTexture;
|
|
517
|
+
}
|
|
518
|
+
const resolvedTextureEntry = gltf.textures[gltfTexture.index];
|
|
519
|
+
if (!resolvedTextureEntry) {
|
|
520
|
+
return gltfTexture;
|
|
521
|
+
}
|
|
522
|
+
if ('texture' in resolvedTextureEntry && resolvedTextureEntry.texture) {
|
|
523
|
+
return {
|
|
524
|
+
...resolvedTextureEntry,
|
|
525
|
+
...gltfTexture,
|
|
526
|
+
texture: resolvedTextureEntry.texture
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
if (!('source' in resolvedTextureEntry)) {
|
|
530
|
+
return gltfTexture;
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
...gltfTexture,
|
|
534
|
+
texture: resolvedTextureEntry
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function createCompressedTextureFallback(device, baseOptions) {
|
|
538
|
+
return device.createTexture({
|
|
539
|
+
...baseOptions,
|
|
540
|
+
format: 'rgba8unorm',
|
|
541
|
+
width: 1,
|
|
542
|
+
height: 1,
|
|
543
|
+
mipLevels: 1
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
function resolveCompressedTextureFormat(level) {
|
|
547
|
+
return level.textureFormat;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Maximum mip levels that can be filled for a compressed texture.
|
|
551
|
+
* texStorage2D allocates level i at (baseW >> i) × (baseH >> i).
|
|
552
|
+
* Compressed formats can't upload data for levels smaller than one block,
|
|
553
|
+
* so we stop before either dimension drops below the block size.
|
|
554
|
+
*/
|
|
555
|
+
function getMaxCompressedMipLevels(baseWidth, baseHeight, format) {
|
|
556
|
+
const { blockWidth = 1, blockHeight = 1 } = textureFormatDecoder.getInfo(format);
|
|
557
|
+
let count = 1;
|
|
558
|
+
for (let i = 1;; i++) {
|
|
559
|
+
const w = Math.max(1, baseWidth >> i);
|
|
560
|
+
const h = Math.max(1, baseHeight >> i);
|
|
561
|
+
if (w < blockWidth || h < blockHeight)
|
|
562
|
+
break;
|
|
563
|
+
count++;
|
|
564
|
+
}
|
|
565
|
+
return count;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Create a texture from compressed image data produced by loaders.gl.
|
|
569
|
+
* Handles current loaders.gl compressed image layouts:
|
|
570
|
+
*
|
|
571
|
+
* current: {compressed, mipmaps: true, data: [{data, width, height, textureFormat}, ...]}
|
|
572
|
+
* forward: {compressed, mipmaps: [{data, width, height, textureFormat}, ...]}
|
|
573
|
+
*/
|
|
574
|
+
export function createCompressedTexture(device, image, baseOptions) {
|
|
575
|
+
// Normalize mip levels from all known loaders.gl formats
|
|
576
|
+
let levels;
|
|
577
|
+
if (Array.isArray(image.data) && image.data[0]?.data) {
|
|
578
|
+
// loaders.gl current format: image.data is Array of mip-level objects
|
|
579
|
+
levels = image.data;
|
|
580
|
+
}
|
|
581
|
+
else if ('mipmaps' in image && Array.isArray(image.mipmaps)) {
|
|
582
|
+
// Hypothetical future format: image.mipmaps is an Array
|
|
583
|
+
levels = image.mipmaps;
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
levels = [];
|
|
587
|
+
}
|
|
588
|
+
if (levels.length === 0 || !levels[0]?.data) {
|
|
589
|
+
log.warn('createCompressedTexture: compressed image has no valid mip levels, creating fallback')();
|
|
590
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
591
|
+
}
|
|
592
|
+
const baseLevel = levels[0];
|
|
593
|
+
const baseWidth = baseLevel.width ?? image.width ?? 0;
|
|
594
|
+
const baseHeight = baseLevel.height ?? image.height ?? 0;
|
|
595
|
+
if (baseWidth <= 0 || baseHeight <= 0) {
|
|
596
|
+
log.warn('createCompressedTexture: base level has invalid dimensions, creating fallback')();
|
|
597
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
598
|
+
}
|
|
599
|
+
const format = resolveCompressedTextureFormat(baseLevel);
|
|
600
|
+
if (!format) {
|
|
601
|
+
log.warn('createCompressedTexture: compressed image has no textureFormat, creating fallback')();
|
|
602
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
603
|
+
}
|
|
604
|
+
// Validate mip levels: truncate chain at first invalid level.
|
|
605
|
+
// Levels must be contiguous, so we stop at the first level that has
|
|
606
|
+
// a format mismatch, missing data, non-positive dimensions, or
|
|
607
|
+
// dimensions that don't match what texStorage2D will allocate.
|
|
608
|
+
//
|
|
609
|
+
// For block-compressed formats (ASTC, BC, ETC2), texStorage2D allocates
|
|
610
|
+
// mip levels down to 1×1 texels, but compressed data can't be smaller
|
|
611
|
+
// than one block (e.g. 4×4 for ASTC-4x4). Cap the chain so we never
|
|
612
|
+
// try to upload data whose block-aligned size exceeds the allocated level.
|
|
613
|
+
const maxMipLevels = getMaxCompressedMipLevels(baseWidth, baseHeight, format);
|
|
614
|
+
const levelLimit = Math.min(levels.length, maxMipLevels);
|
|
615
|
+
let validLevelCount = 1;
|
|
616
|
+
for (let i = 1; i < levelLimit; i++) {
|
|
617
|
+
const level = levels[i];
|
|
618
|
+
if (!level.data || level.width <= 0 || level.height <= 0) {
|
|
619
|
+
log.warn(`createCompressedTexture: mip level ${i} has invalid data/dimensions, truncating`)();
|
|
620
|
+
break;
|
|
621
|
+
}
|
|
622
|
+
const levelFormat = resolveCompressedTextureFormat(level);
|
|
623
|
+
if (levelFormat && levelFormat !== format) {
|
|
624
|
+
log.warn(`createCompressedTexture: mip level ${i} format '${levelFormat}' differs from base '${format}', truncating`)();
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
const expectedW = Math.max(1, baseWidth >> i);
|
|
628
|
+
const expectedH = Math.max(1, baseHeight >> i);
|
|
629
|
+
if (level.width !== expectedW || level.height !== expectedH) {
|
|
630
|
+
log.warn(`createCompressedTexture: mip level ${i} dimensions ${level.width}x${level.height} ` +
|
|
631
|
+
`don't match expected ${expectedW}x${expectedH}, truncating`)();
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
validLevelCount++;
|
|
635
|
+
}
|
|
636
|
+
const texture = device.createTexture({
|
|
637
|
+
...baseOptions,
|
|
638
|
+
format,
|
|
639
|
+
usage: Texture.TEXTURE | Texture.COPY_DST,
|
|
640
|
+
width: baseWidth,
|
|
641
|
+
height: baseHeight,
|
|
642
|
+
mipLevels: validLevelCount,
|
|
643
|
+
data: baseLevel.data
|
|
644
|
+
});
|
|
645
|
+
// Upload additional validated mip levels
|
|
646
|
+
for (let i = 1; i < validLevelCount; i++) {
|
|
647
|
+
texture.writeData(levels[i].data, {
|
|
648
|
+
width: levels[i].width,
|
|
649
|
+
height: levels[i].height,
|
|
650
|
+
mipLevel: i
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
return texture;
|
|
654
|
+
}
|
|
150
655
|
/*
|
|
151
656
|
/**
|
|
152
657
|
* Parses a GLTF material definition into uniforms and parameters for the PBR shader module
|
|
@@ -192,7 +697,7 @@ export class PBRMaterialParser {
|
|
|
192
697
|
if (imageBasedLightingEnvironment) {
|
|
193
698
|
this.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.getDiffuseEnvSampler();
|
|
194
699
|
this.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.getSpecularEnvSampler();
|
|
195
|
-
this.bindings.
|
|
700
|
+
this.bindings.pbr_brdfLUT = imageBasedLightingEnvironment.getBrdfTexture();
|
|
196
701
|
this.uniforms.scaleIBLAmbient = [1, 1];
|
|
197
702
|
}
|
|
198
703
|
|
|
@@ -262,8 +767,13 @@ export class PBRMaterialParser {
|
|
|
262
767
|
log.warn('BLEND alphaMode might not work well because it requires mesh sorting')();
|
|
263
768
|
Object.assign(this.parameters, {
|
|
264
769
|
blend: true,
|
|
265
|
-
blendEquation:
|
|
266
|
-
blendFunc: [
|
|
770
|
+
blendEquation: GLEnum.FUNC_ADD,
|
|
771
|
+
blendFunc: [
|
|
772
|
+
GLEnum.SRC_ALPHA,
|
|
773
|
+
GLEnum.ONE_MINUS_SRC_ALPHA,
|
|
774
|
+
GLEnum.ONE,
|
|
775
|
+
GLEnum.ONE_MINUS_SRC_ALPHA
|
|
776
|
+
]
|
|
267
777
|
});
|
|
268
778
|
}
|
|
269
779
|
}
|
|
@@ -300,7 +810,8 @@ export class PBRMaterialParser {
|
|
|
300
810
|
if (image.compressed) {
|
|
301
811
|
textureOptions = image;
|
|
302
812
|
specialTextureParameters = {
|
|
303
|
-
[
|
|
813
|
+
[GLEnum.TEXTURE_MIN_FILTER]:
|
|
814
|
+
image.data.length > 1 ? GLEnum.LINEAR_MIPMAP_NEAREST : GLEnum.LINEAR
|
|
304
815
|
};
|
|
305
816
|
} else {
|
|
306
817
|
// Texture2D accepts a promise that returns an image as data (Async Textures)
|
|
@@ -314,7 +825,7 @@ export class PBRMaterialParser {
|
|
|
314
825
|
...specialTextureParameters
|
|
315
826
|
},
|
|
316
827
|
pixelStore: {
|
|
317
|
-
[
|
|
828
|
+
[GLEnum.UNPACK_FLIP_Y_WEBGL]: false
|
|
318
829
|
},
|
|
319
830
|
...textureOptions
|
|
320
831
|
});
|