@luma.gl/shadertools 9.3.0-alpha.4 → 9.3.0-alpha.6
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 +2111 -197
- package/dist/dist.min.js +315 -184
- package/dist/index.cjs +459 -198
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
- package/dist/lib/preprocessor/preprocessor.js +33 -7
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembler.d.ts.map +1 -1
- package/dist/lib/shader-assembler.js +8 -1
- package/dist/lib/shader-assembler.js.map +1 -1
- package/dist/lib/shader-module/shader-module.d.ts +1 -1
- package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
- package/dist/modules/engine/skin/skin.d.ts +29 -0
- package/dist/modules/engine/skin/skin.d.ts.map +1 -0
- package/dist/modules/engine/skin/skin.js +88 -0
- package/dist/modules/engine/skin/skin.js.map +1 -0
- package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
- package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
- package/dist/modules/lighting/lights/lighting-glsl.js +20 -2
- package/dist/modules/lighting/lights/lighting-glsl.js.map +1 -1
- package/dist/modules/lighting/lights/lighting-wgsl.d.ts +1 -1
- package/dist/modules/lighting/lights/lighting-wgsl.d.ts.map +1 -1
- package/dist/modules/lighting/lights/lighting-wgsl.js +63 -13
- package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
- package/dist/modules/lighting/lights/lighting.d.ts +27 -3
- package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
- package/dist/modules/lighting/lights/lighting.js +32 -6
- package/dist/modules/lighting/lights/lighting.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +106 -79
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material.d.ts +20 -4
- package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-projection.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-projection.js +12 -1
- package/dist/modules/lighting/pbr-material/pbr-projection.js.map +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts +1 -40
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts.map +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js +40 -76
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js.map +1 -1
- package/dist/modules/math/random/random.d.ts +1 -1
- package/dist/modules/math/random/random.d.ts.map +1 -1
- package/dist/modules/math/random/random.js +2 -3
- package/dist/modules/math/random/random.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/lib/preprocessor/preprocessor.ts +40 -7
- package/src/lib/shader-assembler.ts +8 -1
- package/src/lib/shader-module/shader-module.ts +1 -1
- package/src/modules/engine/skin/skin.ts +116 -0
- package/src/modules/lighting/lights/lighting-glsl.ts +20 -2
- package/src/modules/lighting/lights/lighting-wgsl.ts +63 -13
- package/src/modules/lighting/lights/lighting.ts +45 -9
- package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +106 -79
- package/src/modules/lighting/pbr-material/pbr-projection.ts +13 -1
- package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +40 -77
- package/src/modules/math/random/random.ts +2 -3
package/dist/index.cjs
CHANGED
|
@@ -57,6 +57,7 @@ __export(dist_exports, {
|
|
|
57
57
|
picking: () => picking,
|
|
58
58
|
preprocess: () => preprocess,
|
|
59
59
|
random: () => random,
|
|
60
|
+
skin: () => skin,
|
|
60
61
|
toHalfFloat: () => toHalfFloat,
|
|
61
62
|
typeToChannelCount: () => typeToChannelCount,
|
|
62
63
|
typeToChannelSuffix: () => typeToChannelSuffix
|
|
@@ -204,7 +205,7 @@ function getHookStage(hook) {
|
|
|
204
205
|
throw new Error(type);
|
|
205
206
|
}
|
|
206
207
|
}
|
|
207
|
-
function injectShader(
|
|
208
|
+
function injectShader(source4, stage, inject, injectStandardStubs = false) {
|
|
208
209
|
const isVertex = stage === "vertex";
|
|
209
210
|
for (const key in inject) {
|
|
210
211
|
const fragmentData = inject[key];
|
|
@@ -218,43 +219,43 @@ function injectShader(source3, stage, inject, injectStandardStubs = false) {
|
|
|
218
219
|
switch (key) {
|
|
219
220
|
case "vs:#decl":
|
|
220
221
|
if (isVertex) {
|
|
221
|
-
|
|
222
|
+
source4 = source4.replace(DECLARATION_INJECT_MARKER, fragmentString);
|
|
222
223
|
}
|
|
223
224
|
break;
|
|
224
225
|
case "vs:#main-start":
|
|
225
226
|
if (isVertex) {
|
|
226
|
-
|
|
227
|
+
source4 = source4.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString);
|
|
227
228
|
}
|
|
228
229
|
break;
|
|
229
230
|
case "vs:#main-end":
|
|
230
231
|
if (isVertex) {
|
|
231
|
-
|
|
232
|
+
source4 = source4.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match);
|
|
232
233
|
}
|
|
233
234
|
break;
|
|
234
235
|
case "fs:#decl":
|
|
235
236
|
if (!isVertex) {
|
|
236
|
-
|
|
237
|
+
source4 = source4.replace(DECLARATION_INJECT_MARKER, fragmentString);
|
|
237
238
|
}
|
|
238
239
|
break;
|
|
239
240
|
case "fs:#main-start":
|
|
240
241
|
if (!isVertex) {
|
|
241
|
-
|
|
242
|
+
source4 = source4.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString);
|
|
242
243
|
}
|
|
243
244
|
break;
|
|
244
245
|
case "fs:#main-end":
|
|
245
246
|
if (!isVertex) {
|
|
246
|
-
|
|
247
|
+
source4 = source4.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match);
|
|
247
248
|
}
|
|
248
249
|
break;
|
|
249
250
|
default:
|
|
250
|
-
|
|
251
|
+
source4 = source4.replace(key, (match) => match + fragmentString);
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
|
-
|
|
254
|
+
source4 = source4.replace(DECLARATION_INJECT_MARKER, "");
|
|
254
255
|
if (injectStandardStubs) {
|
|
255
|
-
|
|
256
|
+
source4 = source4.replace(/\}\s*$/, (match) => match + MODULE_INJECTORS[stage]);
|
|
256
257
|
}
|
|
257
|
-
return
|
|
258
|
+
return source4;
|
|
258
259
|
}
|
|
259
260
|
function combineInjects(injects) {
|
|
260
261
|
const result = {};
|
|
@@ -434,19 +435,19 @@ function getPlatformShaderDefines(platformInfo) {
|
|
|
434
435
|
}
|
|
435
436
|
|
|
436
437
|
// dist/lib/shader-transpiler/transpile-glsl-shader.js
|
|
437
|
-
function transpileGLSLShader(
|
|
438
|
+
function transpileGLSLShader(source4, stage) {
|
|
438
439
|
var _a;
|
|
439
|
-
const sourceGLSLVersion = Number(((_a =
|
|
440
|
+
const sourceGLSLVersion = Number(((_a = source4.match(/^#version[ \t]+(\d+)/m)) == null ? void 0 : _a[1]) || 100);
|
|
440
441
|
if (sourceGLSLVersion !== 300) {
|
|
441
442
|
throw new Error("luma.gl v9 only supports GLSL 3.00 shader sources");
|
|
442
443
|
}
|
|
443
444
|
switch (stage) {
|
|
444
445
|
case "vertex":
|
|
445
|
-
|
|
446
|
-
return
|
|
446
|
+
source4 = convertShader(source4, ES300_VERTEX_REPLACEMENTS);
|
|
447
|
+
return source4;
|
|
447
448
|
case "fragment":
|
|
448
|
-
|
|
449
|
-
return
|
|
449
|
+
source4 = convertShader(source4, ES300_FRAGMENT_REPLACEMENTS);
|
|
450
|
+
return source4;
|
|
450
451
|
default:
|
|
451
452
|
throw new Error(stage);
|
|
452
453
|
}
|
|
@@ -470,11 +471,11 @@ var ES300_FRAGMENT_REPLACEMENTS = [
|
|
|
470
471
|
// `varying` keyword replaced with `in`
|
|
471
472
|
[makeVariableTextRegExp("varying"), "in $1"]
|
|
472
473
|
];
|
|
473
|
-
function convertShader(
|
|
474
|
+
function convertShader(source4, replacements) {
|
|
474
475
|
for (const [pattern, replacement] of replacements) {
|
|
475
|
-
|
|
476
|
+
source4 = source4.replace(pattern, replacement);
|
|
476
477
|
}
|
|
477
|
-
return
|
|
478
|
+
return source4;
|
|
478
479
|
}
|
|
479
480
|
function makeVariableTextRegExp(qualifier) {
|
|
480
481
|
return new RegExp(`\\b${qualifier}[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)`, "g");
|
|
@@ -536,11 +537,11 @@ function normalizeShaderHooks(hookFunctions) {
|
|
|
536
537
|
}
|
|
537
538
|
|
|
538
539
|
// dist/lib/glsl-utils/get-shader-info.js
|
|
539
|
-
function getShaderInfo(
|
|
540
|
+
function getShaderInfo(source4, defaultName) {
|
|
540
541
|
return {
|
|
541
|
-
name: getShaderName(
|
|
542
|
+
name: getShaderName(source4, defaultName),
|
|
542
543
|
language: "glsl",
|
|
543
|
-
version: getShaderVersion(
|
|
544
|
+
version: getShaderVersion(source4)
|
|
544
545
|
};
|
|
545
546
|
}
|
|
546
547
|
function getShaderName(shader, defaultName = "unnamed") {
|
|
@@ -548,9 +549,9 @@ function getShaderName(shader, defaultName = "unnamed") {
|
|
|
548
549
|
const match = SHADER_NAME_REGEXP.exec(shader);
|
|
549
550
|
return match ? match[1] : defaultName;
|
|
550
551
|
}
|
|
551
|
-
function getShaderVersion(
|
|
552
|
+
function getShaderVersion(source4) {
|
|
552
553
|
let version = 100;
|
|
553
|
-
const words =
|
|
554
|
+
const words = source4.match(/[^\s]+/g);
|
|
554
555
|
if (words && words.length >= 2 && words[0] === "#version") {
|
|
555
556
|
const parsedVersion = parseInt(words[1], 10);
|
|
556
557
|
if (Number.isFinite(parsedVersion)) {
|
|
@@ -586,19 +587,19 @@ function assembleWGSLShader(options) {
|
|
|
586
587
|
};
|
|
587
588
|
}
|
|
588
589
|
function assembleGLSLShaderPair(options) {
|
|
589
|
-
const { vs:
|
|
590
|
+
const { vs: vs4, fs: fs5 } = options;
|
|
590
591
|
const modules = getShaderModuleDependencies(options.modules || []);
|
|
591
592
|
return {
|
|
592
593
|
vs: assembleShaderGLSL(options.platformInfo, {
|
|
593
594
|
...options,
|
|
594
|
-
source:
|
|
595
|
+
source: vs4,
|
|
595
596
|
stage: "vertex",
|
|
596
597
|
modules
|
|
597
598
|
}),
|
|
598
599
|
fs: assembleShaderGLSL(options.platformInfo, {
|
|
599
600
|
...options,
|
|
600
601
|
// @ts-expect-error
|
|
601
|
-
source:
|
|
602
|
+
source: fs5,
|
|
602
603
|
stage: "fragment",
|
|
603
604
|
modules
|
|
604
605
|
}),
|
|
@@ -609,7 +610,7 @@ function assembleShaderWGSL(platformInfo, options) {
|
|
|
609
610
|
var _a;
|
|
610
611
|
const {
|
|
611
612
|
// id,
|
|
612
|
-
source:
|
|
613
|
+
source: source4,
|
|
613
614
|
stage,
|
|
614
615
|
modules,
|
|
615
616
|
// defines = {},
|
|
@@ -617,8 +618,8 @@ function assembleShaderWGSL(platformInfo, options) {
|
|
|
617
618
|
inject = {},
|
|
618
619
|
log: log2
|
|
619
620
|
} = options;
|
|
620
|
-
assert(typeof
|
|
621
|
-
const coreSource =
|
|
621
|
+
assert(typeof source4 === "string", "shader source must be a string");
|
|
622
|
+
const coreSource = source4;
|
|
622
623
|
let assembledSource = "";
|
|
623
624
|
const hookFunctionMap = normalizeShaderHooks(hookFunctions);
|
|
624
625
|
const hookInjections = {};
|
|
@@ -673,12 +674,12 @@ function assembleShaderWGSL(platformInfo, options) {
|
|
|
673
674
|
}
|
|
674
675
|
function assembleShaderGLSL(platformInfo, options) {
|
|
675
676
|
var _a;
|
|
676
|
-
const { source:
|
|
677
|
-
assert(typeof
|
|
678
|
-
const sourceVersion = language === "glsl" ? getShaderInfo(
|
|
677
|
+
const { source: source4, stage, language = "glsl", modules, defines = {}, hookFunctions = [], inject = {}, prologue = true, log: log2 } = options;
|
|
678
|
+
assert(typeof source4 === "string", "shader source must be a string");
|
|
679
|
+
const sourceVersion = language === "glsl" ? getShaderInfo(source4).version : -1;
|
|
679
680
|
const targetVersion = platformInfo.shaderLanguageVersion;
|
|
680
681
|
const sourceVersionDirective = sourceVersion === 100 ? "#version 100" : "#version 300 es";
|
|
681
|
-
const sourceLines =
|
|
682
|
+
const sourceLines = source4.split("\n");
|
|
682
683
|
const coreSource = sourceLines.slice(1).join("\n");
|
|
683
684
|
const allDefines = {};
|
|
684
685
|
modules.forEach((module2) => {
|
|
@@ -801,39 +802,61 @@ function getShaderModuleSource(module2, stage) {
|
|
|
801
802
|
throw new Error("Shader module must have a name");
|
|
802
803
|
}
|
|
803
804
|
const moduleName = module2.name.toUpperCase().replace(/[^0-9a-z]/gi, "_");
|
|
804
|
-
let
|
|
805
|
+
let source4 = `// ----- MODULE ${module2.name} ---------------
|
|
805
806
|
|
|
806
807
|
`;
|
|
807
808
|
if (stage !== "wgsl") {
|
|
808
|
-
|
|
809
|
+
source4 += `#define MODULE_${moduleName}
|
|
809
810
|
`;
|
|
810
811
|
}
|
|
811
|
-
|
|
812
|
+
source4 += `${moduleSource}
|
|
812
813
|
`;
|
|
813
|
-
return
|
|
814
|
+
return source4;
|
|
814
815
|
}
|
|
815
816
|
|
|
816
817
|
// dist/lib/preprocessor/preprocessor.js
|
|
817
818
|
var IFDEF_REGEXP = /^\s*\#\s*ifdef\s*([a-zA-Z_]+)\s*$/;
|
|
819
|
+
var IFNDEF_REGEXP = /^\s*\#\s*ifndef\s*([a-zA-Z_]+)\s*(?:\/\/.*)?$/;
|
|
820
|
+
var ELSE_REGEXP = /^\s*\#\s*else\s*(?:\/\/.*)?$/;
|
|
818
821
|
var ENDIF_REGEXP = /^\s*\#\s*endif\s*$/;
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
+
var IFDEF_WITH_COMMENT_REGEXP = /^\s*\#\s*ifdef\s*([a-zA-Z_]+)\s*(?:\/\/.*)?$/;
|
|
823
|
+
var ENDIF_WITH_COMMENT_REGEXP = /^\s*\#\s*endif\s*(?:\/\/.*)?$/;
|
|
824
|
+
function preprocess(source4, options) {
|
|
825
|
+
var _a, _b;
|
|
826
|
+
const lines = source4.split("\n");
|
|
822
827
|
const output = [];
|
|
828
|
+
const conditionalStack = [];
|
|
823
829
|
let conditional = true;
|
|
824
|
-
let currentDefine = null;
|
|
825
830
|
for (const line of lines) {
|
|
826
|
-
const matchIf = line.match(IFDEF_REGEXP);
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
+
const matchIf = line.match(IFDEF_WITH_COMMENT_REGEXP) || line.match(IFDEF_REGEXP);
|
|
832
|
+
const matchIfNot = line.match(IFNDEF_REGEXP);
|
|
833
|
+
const matchElse = line.match(ELSE_REGEXP);
|
|
834
|
+
const matchEnd = line.match(ENDIF_WITH_COMMENT_REGEXP) || line.match(ENDIF_REGEXP);
|
|
835
|
+
if (matchIf || matchIfNot) {
|
|
836
|
+
const defineName = (_a = matchIf || matchIfNot) == null ? void 0 : _a[1];
|
|
837
|
+
const defineValue = Boolean((_b = options == null ? void 0 : options.defines) == null ? void 0 : _b[defineName]);
|
|
838
|
+
const branchTaken = matchIf ? defineValue : !defineValue;
|
|
839
|
+
const active = conditional && branchTaken;
|
|
840
|
+
conditionalStack.push({ parentActive: conditional, branchTaken, active });
|
|
841
|
+
conditional = active;
|
|
842
|
+
} else if (matchElse) {
|
|
843
|
+
const currentConditional = conditionalStack[conditionalStack.length - 1];
|
|
844
|
+
if (!currentConditional) {
|
|
845
|
+
throw new Error("Encountered #else without matching #ifdef or #ifndef");
|
|
846
|
+
}
|
|
847
|
+
currentConditional.active = currentConditional.parentActive && !currentConditional.branchTaken;
|
|
848
|
+
currentConditional.branchTaken = true;
|
|
849
|
+
conditional = currentConditional.active;
|
|
831
850
|
} else if (matchEnd) {
|
|
832
|
-
|
|
851
|
+
conditionalStack.pop();
|
|
852
|
+
conditional = conditionalStack.length ? conditionalStack[conditionalStack.length - 1].active : true;
|
|
833
853
|
} else if (conditional) {
|
|
834
854
|
output.push(line);
|
|
835
855
|
}
|
|
836
856
|
}
|
|
857
|
+
if (conditionalStack.length > 0) {
|
|
858
|
+
throw new Error("Unterminated conditional block in shader source");
|
|
859
|
+
}
|
|
837
860
|
return output.join("\n");
|
|
838
861
|
}
|
|
839
862
|
|
|
@@ -886,14 +909,21 @@ var _ShaderAssembler = class {
|
|
|
886
909
|
assembleWGSLShader(props) {
|
|
887
910
|
const modules = this._getModuleList(props.modules);
|
|
888
911
|
const hookFunctions = this._hookFunctions;
|
|
889
|
-
const { source:
|
|
912
|
+
const { source: source4, getUniforms: getUniforms4 } = assembleWGSLShader({
|
|
890
913
|
...props,
|
|
891
914
|
// @ts-expect-error
|
|
892
915
|
source: props.source,
|
|
893
916
|
modules,
|
|
894
917
|
hookFunctions
|
|
895
918
|
});
|
|
896
|
-
const
|
|
919
|
+
const defines = {
|
|
920
|
+
...modules.reduce((accumulator, module2) => {
|
|
921
|
+
Object.assign(accumulator, module2.defines);
|
|
922
|
+
return accumulator;
|
|
923
|
+
}, {}),
|
|
924
|
+
...props.defines
|
|
925
|
+
};
|
|
926
|
+
const preprocessedSource = props.platformInfo.shaderLanguage === "wgsl" ? preprocess(source4, { defines }) : source4;
|
|
897
927
|
return { source: preprocessedSource, getUniforms: getUniforms4, modules };
|
|
898
928
|
}
|
|
899
929
|
/**
|
|
@@ -1248,9 +1278,8 @@ function fp64ifyMatrix4(matrix) {
|
|
|
1248
1278
|
// dist/modules/math/random/random.js
|
|
1249
1279
|
var source = (
|
|
1250
1280
|
/* wgsl */
|
|
1251
|
-
`fn random(scale: vec3f, seed:
|
|
1252
|
-
|
|
1253
|
-
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
|
|
1281
|
+
`fn random(scale: vec3f, seed: f32) -> f32 {
|
|
1282
|
+
return fract(sin(dot(scale + vec3f(seed), vec3f(12.9898, 78.233, 151.7182))) * 43758.5453 + seed);
|
|
1254
1283
|
}
|
|
1255
1284
|
`
|
|
1256
1285
|
);
|
|
@@ -2490,8 +2519,102 @@ function getUniforms(opts = {}, prevUniforms) {
|
|
|
2490
2519
|
return uniforms;
|
|
2491
2520
|
}
|
|
2492
2521
|
|
|
2522
|
+
// dist/modules/engine/skin/skin.js
|
|
2523
|
+
var import_core2 = require("@math.gl/core");
|
|
2524
|
+
var SKIN_MAX_JOINTS = 20;
|
|
2525
|
+
var source2 = (
|
|
2526
|
+
/* wgsl */
|
|
2527
|
+
`
|
|
2528
|
+
struct skinUniforms {
|
|
2529
|
+
jointMatrix: array<mat4x4<f32>, ${SKIN_MAX_JOINTS}>,
|
|
2530
|
+
};
|
|
2531
|
+
|
|
2532
|
+
@binding(19) @group(0) var<uniform> skin: skinUniforms;
|
|
2533
|
+
|
|
2534
|
+
fn getSkinMatrix(weights: vec4f, joints: vec4u) -> mat4x4<f32> {
|
|
2535
|
+
return (weights.x * skin.jointMatrix[joints.x])
|
|
2536
|
+
+ (weights.y * skin.jointMatrix[joints.y])
|
|
2537
|
+
+ (weights.z * skin.jointMatrix[joints.z])
|
|
2538
|
+
+ (weights.w * skin.jointMatrix[joints.w]);
|
|
2539
|
+
}
|
|
2540
|
+
`
|
|
2541
|
+
);
|
|
2542
|
+
var vs2 = (
|
|
2543
|
+
/* glsl */
|
|
2544
|
+
`
|
|
2545
|
+
uniform skinUniforms {
|
|
2546
|
+
mat4 jointMatrix[SKIN_MAX_JOINTS];
|
|
2547
|
+
} skin;
|
|
2548
|
+
|
|
2549
|
+
mat4 getSkinMatrix(vec4 weights, uvec4 joints) {
|
|
2550
|
+
return (weights.x * skin.jointMatrix[joints.x])
|
|
2551
|
+
+ (weights.y * skin.jointMatrix[joints.y])
|
|
2552
|
+
+ (weights.z * skin.jointMatrix[joints.z])
|
|
2553
|
+
+ (weights.w * skin.jointMatrix[joints.w]);
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
`
|
|
2557
|
+
);
|
|
2558
|
+
var fs3 = (
|
|
2559
|
+
/* glsl */
|
|
2560
|
+
``
|
|
2561
|
+
);
|
|
2562
|
+
var skin = {
|
|
2563
|
+
props: {},
|
|
2564
|
+
uniforms: {},
|
|
2565
|
+
name: "skin",
|
|
2566
|
+
dependencies: [],
|
|
2567
|
+
source: source2,
|
|
2568
|
+
vs: vs2,
|
|
2569
|
+
fs: fs3,
|
|
2570
|
+
defines: {
|
|
2571
|
+
SKIN_MAX_JOINTS
|
|
2572
|
+
},
|
|
2573
|
+
getUniforms: (props = {}, prevUniforms) => {
|
|
2574
|
+
var _a, _b;
|
|
2575
|
+
const { scenegraphsFromGLTF } = props;
|
|
2576
|
+
if (!((_b = (_a = scenegraphsFromGLTF == null ? void 0 : scenegraphsFromGLTF.gltf) == null ? void 0 : _a.skins) == null ? void 0 : _b[0])) {
|
|
2577
|
+
return { jointMatrix: [] };
|
|
2578
|
+
}
|
|
2579
|
+
const { inverseBindMatrices, joints, skeleton } = scenegraphsFromGLTF.gltf.skins[0];
|
|
2580
|
+
const matsib = [];
|
|
2581
|
+
const countib = inverseBindMatrices.value.length / 16;
|
|
2582
|
+
for (let i = 0; i < countib; i++) {
|
|
2583
|
+
const slice = inverseBindMatrices.value.subarray(i * 16, i * 16 + 16);
|
|
2584
|
+
matsib.push(new import_core2.Matrix4(Array.from(slice)));
|
|
2585
|
+
}
|
|
2586
|
+
const top = scenegraphsFromGLTF.gltfNodeIndexToNodeMap.get(skeleton);
|
|
2587
|
+
const matrices = {};
|
|
2588
|
+
top.preorderTraversal((node, { worldMatrix }) => {
|
|
2589
|
+
matrices[node.id] = worldMatrix;
|
|
2590
|
+
});
|
|
2591
|
+
const mats = new Float32Array(SKIN_MAX_JOINTS * 16);
|
|
2592
|
+
for (let i = 0; i < SKIN_MAX_JOINTS; ++i) {
|
|
2593
|
+
const nodeIndex = joints[i];
|
|
2594
|
+
if (nodeIndex === void 0)
|
|
2595
|
+
break;
|
|
2596
|
+
const worldMat = matrices[scenegraphsFromGLTF.gltfNodeIndexToNodeMap.get(nodeIndex).id];
|
|
2597
|
+
const invBindMat = matsib[i];
|
|
2598
|
+
const Z = new import_core2.Matrix4().copy(worldMat).multiplyRight(invBindMat);
|
|
2599
|
+
const off = i * 16;
|
|
2600
|
+
for (let j = 0; j < 16; j++) {
|
|
2601
|
+
mats[off + j] = Z[j];
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
return {
|
|
2605
|
+
jointMatrix: mats
|
|
2606
|
+
};
|
|
2607
|
+
},
|
|
2608
|
+
uniformTypes: {
|
|
2609
|
+
jointMatrix: "mat4x4<f32>"
|
|
2610
|
+
},
|
|
2611
|
+
uniformSizes: {
|
|
2612
|
+
jointMatrix: SKIN_MAX_JOINTS
|
|
2613
|
+
}
|
|
2614
|
+
};
|
|
2615
|
+
|
|
2493
2616
|
// dist/modules/lighting/lights/lighting.js
|
|
2494
|
-
var
|
|
2617
|
+
var import_core3 = require("@luma.gl/core");
|
|
2495
2618
|
|
|
2496
2619
|
// dist/modules/lighting/lights/lighting-glsl.js
|
|
2497
2620
|
var lightingUniformsGLSL = (
|
|
@@ -2537,6 +2660,16 @@ uniform lightingUniforms {
|
|
|
2537
2660
|
vec3 lightPosition2;
|
|
2538
2661
|
vec3 lightDirection2;
|
|
2539
2662
|
vec3 lightAttenuation2;
|
|
2663
|
+
|
|
2664
|
+
vec3 lightColor3;
|
|
2665
|
+
vec3 lightPosition3;
|
|
2666
|
+
vec3 lightDirection3;
|
|
2667
|
+
vec3 lightAttenuation3;
|
|
2668
|
+
|
|
2669
|
+
vec3 lightColor4;
|
|
2670
|
+
vec3 lightPosition4;
|
|
2671
|
+
vec3 lightDirection4;
|
|
2672
|
+
vec3 lightAttenuation4;
|
|
2540
2673
|
} lighting;
|
|
2541
2674
|
|
|
2542
2675
|
PointLight lighting_getPointLight(int index) {
|
|
@@ -2546,8 +2679,12 @@ PointLight lighting_getPointLight(int index) {
|
|
|
2546
2679
|
case 1:
|
|
2547
2680
|
return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
|
|
2548
2681
|
case 2:
|
|
2549
|
-
default:
|
|
2550
2682
|
return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
|
|
2683
|
+
case 3:
|
|
2684
|
+
return PointLight(lighting.lightColor3, lighting.lightPosition3, lighting.lightAttenuation3);
|
|
2685
|
+
case 4:
|
|
2686
|
+
default:
|
|
2687
|
+
return PointLight(lighting.lightColor4, lighting.lightPosition4, lighting.lightAttenuation4);
|
|
2551
2688
|
}
|
|
2552
2689
|
}
|
|
2553
2690
|
|
|
@@ -2558,8 +2695,12 @@ DirectionalLight lighting_getDirectionalLight(int index) {
|
|
|
2558
2695
|
case 1:
|
|
2559
2696
|
return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
|
|
2560
2697
|
case 2:
|
|
2561
|
-
default:
|
|
2562
2698
|
return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
|
|
2699
|
+
case 3:
|
|
2700
|
+
return DirectionalLight(lighting.lightColor3, lighting.lightDirection3);
|
|
2701
|
+
case 4:
|
|
2702
|
+
default:
|
|
2703
|
+
return DirectionalLight(lighting.lightColor4, lighting.lightDirection4);
|
|
2563
2704
|
}
|
|
2564
2705
|
}
|
|
2565
2706
|
|
|
@@ -2577,6 +2718,8 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
|
|
|
2577
2718
|
var lightingUniformsWGSL = (
|
|
2578
2719
|
/* wgsl */
|
|
2579
2720
|
`// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
|
|
2721
|
+
const MAX_LIGHTS: i32 = 5;
|
|
2722
|
+
|
|
2580
2723
|
struct AmbientLight {
|
|
2581
2724
|
color: vec3<f32>,
|
|
2582
2725
|
};
|
|
@@ -2594,32 +2737,80 @@ struct DirectionalLight {
|
|
|
2594
2737
|
|
|
2595
2738
|
struct lightingUniforms {
|
|
2596
2739
|
enabled: i32,
|
|
2597
|
-
|
|
2740
|
+
lightType: i32,
|
|
2741
|
+
|
|
2598
2742
|
directionalLightCount: i32,
|
|
2743
|
+
pointLightCount: i32,
|
|
2599
2744
|
|
|
2600
2745
|
ambientColor: vec3<f32>,
|
|
2601
2746
|
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2747
|
+
lightColor0: vec3<f32>,
|
|
2748
|
+
lightPosition0: vec3<f32>,
|
|
2749
|
+
lightDirection0: vec3<f32>,
|
|
2750
|
+
lightAttenuation0: vec3<f32>,
|
|
2751
|
+
|
|
2752
|
+
lightColor1: vec3<f32>,
|
|
2753
|
+
lightPosition1: vec3<f32>,
|
|
2754
|
+
lightDirection1: vec3<f32>,
|
|
2755
|
+
lightAttenuation1: vec3<f32>,
|
|
2756
|
+
|
|
2757
|
+
lightColor2: vec3<f32>,
|
|
2758
|
+
lightPosition2: vec3<f32>,
|
|
2759
|
+
lightDirection2: vec3<f32>,
|
|
2760
|
+
lightAttenuation2: vec3<f32>,
|
|
2761
|
+
|
|
2762
|
+
lightColor3: vec3<f32>,
|
|
2763
|
+
lightPosition3: vec3<f32>,
|
|
2764
|
+
lightDirection3: vec3<f32>,
|
|
2765
|
+
lightAttenuation3: vec3<f32>,
|
|
2766
|
+
|
|
2767
|
+
lightColor4: vec3<f32>,
|
|
2768
|
+
lightPosition4: vec3<f32>,
|
|
2769
|
+
lightDirection4: vec3<f32>,
|
|
2770
|
+
lightAttenuation4: vec3<f32>,
|
|
2612
2771
|
};
|
|
2613
2772
|
|
|
2614
2773
|
// Binding 0:1 is reserved for lighting (Note: could go into separate bind group as it is stable across draw calls)
|
|
2615
2774
|
@binding(1) @group(0) var<uniform> lighting : lightingUniforms;
|
|
2616
2775
|
|
|
2617
2776
|
fn lighting_getPointLight(index: i32) -> PointLight {
|
|
2618
|
-
|
|
2777
|
+
switch (index) {
|
|
2778
|
+
case 0: {
|
|
2779
|
+
return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
|
|
2780
|
+
}
|
|
2781
|
+
case 1: {
|
|
2782
|
+
return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
|
|
2783
|
+
}
|
|
2784
|
+
case 2: {
|
|
2785
|
+
return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
|
|
2786
|
+
}
|
|
2787
|
+
case 3: {
|
|
2788
|
+
return PointLight(lighting.lightColor3, lighting.lightPosition3, lighting.lightAttenuation3);
|
|
2789
|
+
}
|
|
2790
|
+
case 4, default: {
|
|
2791
|
+
return PointLight(lighting.lightColor4, lighting.lightPosition4, lighting.lightAttenuation4);
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2619
2794
|
}
|
|
2620
2795
|
|
|
2621
2796
|
fn lighting_getDirectionalLight(index: i32) -> DirectionalLight {
|
|
2622
|
-
|
|
2797
|
+
switch (index) {
|
|
2798
|
+
case 0: {
|
|
2799
|
+
return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
|
|
2800
|
+
}
|
|
2801
|
+
case 1: {
|
|
2802
|
+
return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
|
|
2803
|
+
}
|
|
2804
|
+
case 2: {
|
|
2805
|
+
return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
|
|
2806
|
+
}
|
|
2807
|
+
case 3: {
|
|
2808
|
+
return DirectionalLight(lighting.lightColor3, lighting.lightDirection3);
|
|
2809
|
+
}
|
|
2810
|
+
case 4, default: {
|
|
2811
|
+
return DirectionalLight(lighting.lightColor4, lighting.lightDirection4);
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2623
2814
|
}
|
|
2624
2815
|
|
|
2625
2816
|
fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
|
|
@@ -2664,7 +2855,15 @@ var lighting = {
|
|
|
2664
2855
|
lightColor2: "vec3<f32>",
|
|
2665
2856
|
lightPosition2: "vec3<f32>",
|
|
2666
2857
|
lightDirection2: "vec3<f32>",
|
|
2667
|
-
lightAttenuation2: "vec3<f32>"
|
|
2858
|
+
lightAttenuation2: "vec3<f32>",
|
|
2859
|
+
lightColor3: "vec3<f32>",
|
|
2860
|
+
lightPosition3: "vec3<f32>",
|
|
2861
|
+
lightDirection3: "vec3<f32>",
|
|
2862
|
+
lightAttenuation3: "vec3<f32>",
|
|
2863
|
+
lightColor4: "vec3<f32>",
|
|
2864
|
+
lightPosition4: "vec3<f32>",
|
|
2865
|
+
lightDirection4: "vec3<f32>",
|
|
2866
|
+
lightAttenuation4: "vec3<f32>"
|
|
2668
2867
|
},
|
|
2669
2868
|
defaultUniforms: {
|
|
2670
2869
|
enabled: 1,
|
|
@@ -2684,7 +2883,15 @@ var lighting = {
|
|
|
2684
2883
|
lightColor2: [1, 1, 1],
|
|
2685
2884
|
lightPosition2: [1, 1, 2],
|
|
2686
2885
|
lightDirection2: [1, 1, 1],
|
|
2687
|
-
lightAttenuation2: [1, 0, 0]
|
|
2886
|
+
lightAttenuation2: [1, 0, 0],
|
|
2887
|
+
lightColor3: [1, 1, 1],
|
|
2888
|
+
lightPosition3: [1, 1, 2],
|
|
2889
|
+
lightDirection3: [1, 1, 1],
|
|
2890
|
+
lightAttenuation3: [1, 0, 0],
|
|
2891
|
+
lightColor4: [1, 1, 1],
|
|
2892
|
+
lightPosition4: [1, 1, 2],
|
|
2893
|
+
lightDirection4: [1, 1, 1],
|
|
2894
|
+
lightAttenuation4: [1, 0, 0]
|
|
2688
2895
|
},
|
|
2689
2896
|
source: lightingUniformsWGSL,
|
|
2690
2897
|
vs: lightingUniformsGLSL,
|
|
@@ -2718,26 +2925,36 @@ function getLightSourceUniforms({ ambientLight, pointLights = [], directionalLig
|
|
|
2718
2925
|
const lightSourceUniforms = {};
|
|
2719
2926
|
lightSourceUniforms.ambientColor = convertColor(ambientLight);
|
|
2720
2927
|
let currentLight = 0;
|
|
2928
|
+
let pointLightCount = 0;
|
|
2929
|
+
let directionalLightCount = 0;
|
|
2721
2930
|
for (const pointLight of pointLights) {
|
|
2931
|
+
if (currentLight >= MAX_LIGHTS) {
|
|
2932
|
+
break;
|
|
2933
|
+
}
|
|
2722
2934
|
lightSourceUniforms.lightType = LIGHT_TYPE.POINT;
|
|
2723
2935
|
const i = currentLight;
|
|
2724
2936
|
lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight);
|
|
2725
2937
|
lightSourceUniforms[`lightPosition${i}`] = pointLight.position;
|
|
2726
2938
|
lightSourceUniforms[`lightAttenuation${i}`] = pointLight.attenuation || [1, 0, 0];
|
|
2727
2939
|
currentLight++;
|
|
2940
|
+
pointLightCount++;
|
|
2728
2941
|
}
|
|
2729
2942
|
for (const directionalLight of directionalLights) {
|
|
2943
|
+
if (currentLight >= MAX_LIGHTS) {
|
|
2944
|
+
break;
|
|
2945
|
+
}
|
|
2730
2946
|
lightSourceUniforms.lightType = LIGHT_TYPE.DIRECTIONAL;
|
|
2731
2947
|
const i = currentLight;
|
|
2732
2948
|
lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight);
|
|
2733
2949
|
lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction;
|
|
2734
2950
|
currentLight++;
|
|
2951
|
+
directionalLightCount++;
|
|
2735
2952
|
}
|
|
2736
|
-
if (
|
|
2737
|
-
|
|
2953
|
+
if (pointLights.length + directionalLights.length > MAX_LIGHTS) {
|
|
2954
|
+
import_core3.log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
|
|
2738
2955
|
}
|
|
2739
|
-
lightSourceUniforms.directionalLightCount =
|
|
2740
|
-
lightSourceUniforms.pointLightCount =
|
|
2956
|
+
lightSourceUniforms.directionalLightCount = directionalLightCount;
|
|
2957
|
+
lightSourceUniforms.pointLightCount = pointLightCount;
|
|
2741
2958
|
return lightSourceUniforms;
|
|
2742
2959
|
}
|
|
2743
2960
|
function extractLightTypes(lights) {
|
|
@@ -2946,56 +3163,60 @@ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, p
|
|
|
2946
3163
|
let view_direction: vec3<f32> = normalize(cameraPosition - position_worldspace);
|
|
2947
3164
|
lightColor = phongMaterial.ambient * surfaceColor * lighting.ambientColor;
|
|
2948
3165
|
|
|
2949
|
-
|
|
2950
|
-
let pointLight: PointLight
|
|
3166
|
+
for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
|
|
3167
|
+
let pointLight: PointLight = lighting_getPointLight(i);
|
|
2951
3168
|
let light_position_worldspace: vec3<f32> = pointLight.position;
|
|
2952
3169
|
let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
}
|
|
2965
|
-
PointLight pointLight = lighting.pointLight[i];
|
|
2966
|
-
vec3 light_position_worldspace = pointLight.position;
|
|
2967
|
-
vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
|
|
2968
|
-
lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
|
|
3170
|
+
let light_attenuation = getPointLightAttenuation(
|
|
3171
|
+
pointLight,
|
|
3172
|
+
distance(light_position_worldspace, position_worldspace)
|
|
3173
|
+
);
|
|
3174
|
+
lightColor += lighting_getLightColor(
|
|
3175
|
+
surfaceColor,
|
|
3176
|
+
light_direction,
|
|
3177
|
+
view_direction,
|
|
3178
|
+
normal_worldspace,
|
|
3179
|
+
pointLight.color / light_attenuation
|
|
3180
|
+
);
|
|
2969
3181
|
}
|
|
2970
3182
|
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
}
|
|
2975
|
-
DirectionalLight directionalLight = lighting.directionalLight[i];
|
|
3183
|
+
let totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
|
|
3184
|
+
for (var i: i32 = lighting.pointLightCount; i < totalLights; i++) {
|
|
3185
|
+
let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
|
|
2976
3186
|
lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
|
|
2977
|
-
}
|
|
2978
|
-
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
return lightColor;
|
|
2979
3190
|
}
|
|
2980
3191
|
|
|
2981
3192
|
fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32>{
|
|
2982
3193
|
var lightColor = vec3<f32>(0, 0, 0);
|
|
2983
3194
|
let surfaceColor = vec3<f32>(0, 0, 0);
|
|
2984
3195
|
|
|
2985
|
-
if (lighting.enabled
|
|
3196
|
+
if (lighting.enabled != 0) {
|
|
2986
3197
|
let view_direction = normalize(cameraPosition - position_worldspace);
|
|
2987
3198
|
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
3199
|
+
for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
|
|
3200
|
+
let pointLight: PointLight = lighting_getPointLight(i);
|
|
3201
|
+
let light_position_worldspace: vec3<f32> = pointLight.position;
|
|
3202
|
+
let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
|
|
3203
|
+
let light_attenuation = getPointLightAttenuation(
|
|
3204
|
+
pointLight,
|
|
3205
|
+
distance(light_position_worldspace, position_worldspace)
|
|
3206
|
+
);
|
|
3207
|
+
lightColor += lighting_getLightColor(
|
|
3208
|
+
surfaceColor,
|
|
3209
|
+
light_direction,
|
|
3210
|
+
view_direction,
|
|
3211
|
+
normal_worldspace,
|
|
3212
|
+
pointLight.color / light_attenuation
|
|
3213
|
+
);
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
let totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
|
|
3217
|
+
for (var i: i32 = lighting.pointLightCount; i < totalLights; i++) {
|
|
3218
|
+
let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
|
|
2997
3219
|
lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
|
|
2998
|
-
}
|
|
2999
3220
|
}
|
|
3000
3221
|
}
|
|
3001
3222
|
return lightColor;
|
|
@@ -3069,7 +3290,7 @@ var phongMaterial = {
|
|
|
3069
3290
|
};
|
|
3070
3291
|
|
|
3071
3292
|
// dist/modules/lighting/pbr-material/pbr-material-glsl.js
|
|
3072
|
-
var
|
|
3293
|
+
var vs3 = (
|
|
3073
3294
|
/* glsl */
|
|
3074
3295
|
`out vec3 pbr_vPosition;
|
|
3075
3296
|
out vec2 pbr_vUV;
|
|
@@ -3106,7 +3327,7 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
|
|
|
3106
3327
|
}
|
|
3107
3328
|
`
|
|
3108
3329
|
);
|
|
3109
|
-
var
|
|
3330
|
+
var fs4 = (
|
|
3110
3331
|
/* glsl */
|
|
3111
3332
|
`precision highp float;
|
|
3112
3333
|
|
|
@@ -3570,56 +3791,60 @@ vec4 pbr_filterColor(vec4 colorUnused)
|
|
|
3570
3791
|
);
|
|
3571
3792
|
|
|
3572
3793
|
// dist/modules/lighting/pbr-material/pbr-material-wgsl.js
|
|
3573
|
-
var
|
|
3794
|
+
var source3 = (
|
|
3574
3795
|
/* wgsl */
|
|
3575
3796
|
`struct PBRFragmentInputs {
|
|
3576
3797
|
pbr_vPosition: vec3f,
|
|
3577
3798
|
pbr_vUV: vec2f,
|
|
3578
|
-
pbr_vTBN:
|
|
3799
|
+
pbr_vTBN: mat3x3f,
|
|
3579
3800
|
pbr_vNormal: vec3f
|
|
3580
3801
|
};
|
|
3581
3802
|
|
|
3582
|
-
var fragmentInputs: PBRFragmentInputs;
|
|
3803
|
+
var<private> fragmentInputs: PBRFragmentInputs;
|
|
3583
3804
|
|
|
3584
3805
|
fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f, uv: vec2f)
|
|
3585
3806
|
{
|
|
3586
3807
|
var pos: vec4f = pbrProjection.modelMatrix * position;
|
|
3587
|
-
fragmentInputs.pbr_vPosition =
|
|
3808
|
+
fragmentInputs.pbr_vPosition = pos.xyz / pos.w;
|
|
3809
|
+
fragmentInputs.pbr_vNormal = vec3f(0.0, 0.0, 1.0);
|
|
3810
|
+
fragmentInputs.pbr_vTBN = mat3x3f(
|
|
3811
|
+
vec3f(1.0, 0.0, 0.0),
|
|
3812
|
+
vec3f(0.0, 1.0, 0.0),
|
|
3813
|
+
vec3f(0.0, 0.0, 1.0)
|
|
3814
|
+
);
|
|
3815
|
+
fragmentInputs.pbr_vUV = vec2f(0.0, 0.0);
|
|
3588
3816
|
|
|
3589
3817
|
#ifdef HAS_NORMALS
|
|
3818
|
+
let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);
|
|
3819
|
+
fragmentInputs.pbr_vNormal = normalW;
|
|
3590
3820
|
#ifdef HAS_TANGENTS
|
|
3591
|
-
let
|
|
3592
|
-
let tangentW: vec3f = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
|
|
3821
|
+
let tangentW: vec3f = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);
|
|
3593
3822
|
let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;
|
|
3594
|
-
fragmentInputs.pbr_vTBN =
|
|
3595
|
-
#else // HAS_TANGENTS != 1
|
|
3596
|
-
fragmentInputs.pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
|
|
3823
|
+
fragmentInputs.pbr_vTBN = mat3x3f(tangentW, bitangentW, normalW);
|
|
3597
3824
|
#endif
|
|
3598
3825
|
#endif
|
|
3599
3826
|
|
|
3600
3827
|
#ifdef HAS_UV
|
|
3601
3828
|
fragmentInputs.pbr_vUV = uv;
|
|
3602
|
-
#else
|
|
3603
|
-
fragmentInputs.pbr_vUV = vec2(0.,0.);
|
|
3604
3829
|
#endif
|
|
3605
3830
|
}
|
|
3606
3831
|
|
|
3607
3832
|
struct pbrMaterialUniforms {
|
|
3608
3833
|
// Material is unlit
|
|
3609
|
-
unlit:
|
|
3834
|
+
unlit: u32,
|
|
3610
3835
|
|
|
3611
3836
|
// Base color map
|
|
3612
|
-
baseColorMapEnabled:
|
|
3837
|
+
baseColorMapEnabled: u32,
|
|
3613
3838
|
baseColorFactor: vec4f,
|
|
3614
3839
|
|
|
3615
|
-
normalMapEnabled :
|
|
3840
|
+
normalMapEnabled : u32,
|
|
3616
3841
|
normalScale: f32, // #ifdef HAS_NORMALMAP
|
|
3617
3842
|
|
|
3618
|
-
emissiveMapEnabled:
|
|
3843
|
+
emissiveMapEnabled: u32,
|
|
3619
3844
|
emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP
|
|
3620
3845
|
|
|
3621
3846
|
metallicRoughnessValues: vec2f,
|
|
3622
|
-
metallicRoughnessMapEnabled:
|
|
3847
|
+
metallicRoughnessMapEnabled: u32,
|
|
3623
3848
|
|
|
3624
3849
|
occlusionMapEnabled: i32,
|
|
3625
3850
|
occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP
|
|
@@ -3634,7 +3859,7 @@ struct pbrMaterialUniforms {
|
|
|
3634
3859
|
// debugging flags used for shader output of intermediate PBR variables
|
|
3635
3860
|
// #ifdef PBR_DEBUG
|
|
3636
3861
|
scaleDiffBaseMR: vec4f,
|
|
3637
|
-
scaleFGDSpec: vec4f
|
|
3862
|
+
scaleFGDSpec: vec4f,
|
|
3638
3863
|
// #endif
|
|
3639
3864
|
}
|
|
3640
3865
|
|
|
@@ -3642,24 +3867,32 @@ struct pbrMaterialUniforms {
|
|
|
3642
3867
|
|
|
3643
3868
|
// Samplers
|
|
3644
3869
|
#ifdef HAS_BASECOLORMAP
|
|
3645
|
-
|
|
3870
|
+
@binding(3) @group(0) var pbr_baseColorSampler: texture_2d<f32>;
|
|
3871
|
+
@binding(4) @group(0) var pbr_baseColorSamplerSampler: sampler;
|
|
3646
3872
|
#endif
|
|
3647
3873
|
#ifdef HAS_NORMALMAP
|
|
3648
|
-
|
|
3874
|
+
@binding(5) @group(0) var pbr_normalSampler: texture_2d<f32>;
|
|
3875
|
+
@binding(6) @group(0) var pbr_normalSamplerSampler: sampler;
|
|
3649
3876
|
#endif
|
|
3650
3877
|
#ifdef HAS_EMISSIVEMAP
|
|
3651
|
-
|
|
3878
|
+
@binding(7) @group(0) var pbr_emissiveSampler: texture_2d<f32>;
|
|
3879
|
+
@binding(8) @group(0) var pbr_emissiveSamplerSampler: sampler;
|
|
3652
3880
|
#endif
|
|
3653
3881
|
#ifdef HAS_METALROUGHNESSMAP
|
|
3654
|
-
|
|
3882
|
+
@binding(9) @group(0) var pbr_metallicRoughnessSampler: texture_2d<f32>;
|
|
3883
|
+
@binding(10) @group(0) var pbr_metallicRoughnessSamplerSampler: sampler;
|
|
3655
3884
|
#endif
|
|
3656
3885
|
#ifdef HAS_OCCLUSIONMAP
|
|
3657
|
-
|
|
3886
|
+
@binding(11) @group(0) var pbr_occlusionSampler: texture_2d<f32>;
|
|
3887
|
+
@binding(12) @group(0) var pbr_occlusionSamplerSampler: sampler;
|
|
3658
3888
|
#endif
|
|
3659
3889
|
#ifdef USE_IBL
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3890
|
+
@binding(13) @group(0) var pbr_diffuseEnvSampler: texture_cube<f32>;
|
|
3891
|
+
@binding(14) @group(0) var pbr_diffuseEnvSamplerSampler: sampler;
|
|
3892
|
+
@binding(15) @group(0) var pbr_specularEnvSampler: texture_cube<f32>;
|
|
3893
|
+
@binding(16) @group(0) var pbr_specularEnvSamplerSampler: sampler;
|
|
3894
|
+
@binding(17) @group(0) var pbr_BrdfLUT: texture_2d<f32>;
|
|
3895
|
+
@binding(18) @group(0) var pbr_BrdfLUTSampler: sampler;
|
|
3663
3896
|
#endif
|
|
3664
3897
|
|
|
3665
3898
|
// Encapsulate the various inputs used by the various functions in the shading equation
|
|
@@ -3687,17 +3920,19 @@ const c_MinRoughness = 0.04;
|
|
|
3687
3920
|
|
|
3688
3921
|
fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
|
|
3689
3922
|
{
|
|
3923
|
+
var linOut: vec3f = srgbIn.xyz;
|
|
3690
3924
|
#ifdef MANUAL_SRGB
|
|
3925
|
+
let bLess: vec3f = step(vec3f(0.04045), srgbIn.xyz);
|
|
3926
|
+
linOut = mix(
|
|
3927
|
+
srgbIn.xyz / vec3f(12.92),
|
|
3928
|
+
pow((srgbIn.xyz + vec3f(0.055)) / vec3f(1.055), vec3f(2.4)),
|
|
3929
|
+
bLess
|
|
3930
|
+
);
|
|
3691
3931
|
#ifdef SRGB_FAST_APPROXIMATION
|
|
3692
|
-
|
|
3693
|
-
#
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
#endif //SRGB_FAST_APPROXIMATION
|
|
3697
|
-
return vec4f(linOut,srgbIn.w);;
|
|
3698
|
-
#else //MANUAL_SRGB
|
|
3699
|
-
return srgbIn;
|
|
3700
|
-
#endif //MANUAL_SRGB
|
|
3932
|
+
linOut = pow(srgbIn.xyz, vec3f(2.2));
|
|
3933
|
+
#endif
|
|
3934
|
+
#endif
|
|
3935
|
+
return vec4f(linOut, srgbIn.w);
|
|
3701
3936
|
}
|
|
3702
3937
|
|
|
3703
3938
|
// Find the normal for this fragment, pulling either from a predefined normal map
|
|
@@ -3705,32 +3940,28 @@ fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
|
|
|
3705
3940
|
fn getNormal() -> vec3f
|
|
3706
3941
|
{
|
|
3707
3942
|
// Retrieve the tangent space matrix
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
var
|
|
3713
|
-
var t: vec3f = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
|
|
3943
|
+
let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
|
|
3944
|
+
let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
|
|
3945
|
+
let tex_dx: vec3f = dpdx(vec3f(fragmentInputs.pbr_vUV, 0.0));
|
|
3946
|
+
let tex_dy: vec3f = dpdy(vec3f(fragmentInputs.pbr_vUV, 0.0));
|
|
3947
|
+
var t: vec3f = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);
|
|
3714
3948
|
|
|
3715
|
-
#ifdef HAS_NORMALS
|
|
3716
|
-
var ng: vec3f = normalize(fragmentInputs.pbr_vNormal);
|
|
3717
|
-
#else
|
|
3718
3949
|
var ng: vec3f = cross(pos_dx, pos_dy);
|
|
3950
|
+
#ifdef HAS_NORMALS
|
|
3951
|
+
ng = normalize(fragmentInputs.pbr_vNormal);
|
|
3719
3952
|
#endif
|
|
3720
|
-
|
|
3721
3953
|
t = normalize(t - ng * dot(ng, t));
|
|
3722
3954
|
var b: vec3f = normalize(cross(ng, t));
|
|
3723
|
-
var tbn:
|
|
3724
|
-
#
|
|
3725
|
-
|
|
3955
|
+
var tbn: mat3x3f = mat3x3f(t, b, ng);
|
|
3956
|
+
#ifdef HAS_TANGENTS
|
|
3957
|
+
tbn = fragmentInputs.pbr_vTBN;
|
|
3726
3958
|
#endif
|
|
3727
3959
|
|
|
3728
|
-
#ifdef HAS_NORMALMAP
|
|
3729
|
-
vec3 n = texture(pbr_normalSampler, fragmentInputs.pbr_vUV).rgb;
|
|
3730
|
-
n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
|
|
3731
|
-
#else
|
|
3732
3960
|
// The tbn matrix is linearly interpolated, so we need to re-normalize
|
|
3733
|
-
|
|
3961
|
+
var n: vec3f = normalize(tbn[2].xyz);
|
|
3962
|
+
#ifdef HAS_NORMALMAP
|
|
3963
|
+
n = textureSample(pbr_normalSampler, pbr_normalSamplerSampler, fragmentInputs.pbr_vUV).rgb;
|
|
3964
|
+
n = normalize(tbn * ((2.0 * n - 1.0) * vec3f(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
|
|
3734
3965
|
#endif
|
|
3735
3966
|
|
|
3736
3967
|
return n;
|
|
@@ -3740,27 +3971,37 @@ fn getNormal() -> vec3f
|
|
|
3740
3971
|
// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
|
|
3741
3972
|
// See our README.md on Environment Maps [3] for additional discussion.
|
|
3742
3973
|
#ifdef USE_IBL
|
|
3743
|
-
fn getIBLContribution(PBRInfo
|
|
3974
|
+
fn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f
|
|
3744
3975
|
{
|
|
3745
|
-
|
|
3746
|
-
|
|
3976
|
+
let mipCount: f32 = 9.0; // resolution of 512x512
|
|
3977
|
+
let lod: f32 = pbrInfo.perceptualRoughness * mipCount;
|
|
3747
3978
|
// retrieve a scale and bias to F0. See [1], Figure 3
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3979
|
+
let brdf = SRGBtoLINEAR(
|
|
3980
|
+
textureSample(
|
|
3981
|
+
pbr_BrdfLUT,
|
|
3982
|
+
pbr_BrdfLUTSampler,
|
|
3983
|
+
vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness)
|
|
3984
|
+
)
|
|
3985
|
+
).rgb;
|
|
3986
|
+
let diffuseLight =
|
|
3987
|
+
SRGBtoLINEAR(textureSample(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n)).rgb;
|
|
3988
|
+
let specularLightDefault =
|
|
3989
|
+
SRGBtoLINEAR(textureSample(pbr_specularEnvSampler, pbr_specularEnvSamplerSampler, reflection)).rgb;
|
|
3990
|
+
var specularLight = specularLightDefault;
|
|
3752
3991
|
#ifdef USE_TEX_LOD
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3992
|
+
specularLight = SRGBtoLINEAR(
|
|
3993
|
+
textureSampleLevel(
|
|
3994
|
+
pbr_specularEnvSampler,
|
|
3995
|
+
pbr_specularEnvSamplerSampler,
|
|
3996
|
+
reflection,
|
|
3997
|
+
lod
|
|
3998
|
+
)
|
|
3999
|
+
).rgb;
|
|
3756
4000
|
#endif
|
|
3757
4001
|
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
// For presentation, this allows us to disable IBL terms
|
|
3762
|
-
diffuse *= pbrMaterial.scaleIBLAmbient.x;
|
|
3763
|
-
specular *= pbrMaterial.scaleIBLAmbient.y;
|
|
4002
|
+
let diffuse = diffuseLight * pbrInfo.diffuseColor * pbrMaterial.scaleIBLAmbient.x;
|
|
4003
|
+
let specular =
|
|
4004
|
+
specularLight * (pbrInfo.specularColor * brdf.x + brdf.y) * pbrMaterial.scaleIBLAmbient.y;
|
|
3764
4005
|
|
|
3765
4006
|
return diffuse + specular;
|
|
3766
4007
|
}
|
|
@@ -3804,7 +4045,7 @@ fn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {
|
|
|
3804
4045
|
fn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {
|
|
3805
4046
|
let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
|
|
3806
4047
|
let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
|
|
3807
|
-
return roughnessSq / (
|
|
4048
|
+
return roughnessSq / (M_PI * f * f);
|
|
3808
4049
|
}
|
|
3809
4050
|
|
|
3810
4051
|
fn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {
|
|
@@ -3846,11 +4087,11 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
|
|
|
3846
4087
|
|
|
3847
4088
|
fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
|
|
3848
4089
|
// The albedo may be defined from a base texture or a flat color
|
|
3849
|
-
var baseColor: vec4<f32
|
|
4090
|
+
var baseColor: vec4<f32> = pbrMaterial.baseColorFactor;
|
|
3850
4091
|
#ifdef HAS_BASECOLORMAP
|
|
3851
|
-
baseColor = SRGBtoLINEAR(
|
|
3852
|
-
|
|
3853
|
-
|
|
4092
|
+
baseColor = SRGBtoLINEAR(
|
|
4093
|
+
textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, fragmentInputs.pbr_vUV)
|
|
4094
|
+
) * pbrMaterial.baseColorFactor;
|
|
3854
4095
|
#endif
|
|
3855
4096
|
|
|
3856
4097
|
#ifdef ALPHA_CUTOFF
|
|
@@ -3861,7 +4102,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
|
|
|
3861
4102
|
|
|
3862
4103
|
var color = vec3<f32>(0.0, 0.0, 0.0);
|
|
3863
4104
|
|
|
3864
|
-
if (pbrMaterial.unlit) {
|
|
4105
|
+
if (pbrMaterial.unlit != 0u) {
|
|
3865
4106
|
color = baseColor.rgb;
|
|
3866
4107
|
} else {
|
|
3867
4108
|
// Metallic and Roughness material properties are packed together
|
|
@@ -3872,7 +4113,11 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
|
|
|
3872
4113
|
#ifdef HAS_METALROUGHNESSMAP
|
|
3873
4114
|
// Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
|
|
3874
4115
|
// This layout intentionally reserves the 'r' channel for (optional) occlusion map data
|
|
3875
|
-
let mrSample = textureSample(
|
|
4116
|
+
let mrSample = textureSample(
|
|
4117
|
+
pbr_metallicRoughnessSampler,
|
|
4118
|
+
pbr_metallicRoughnessSamplerSampler,
|
|
4119
|
+
fragmentInputs.pbr_vUV
|
|
4120
|
+
);
|
|
3876
4121
|
perceptualRoughness = mrSample.g * perceptualRoughness;
|
|
3877
4122
|
metallic = mrSample.b * metallic;
|
|
3878
4123
|
#endif
|
|
@@ -3949,22 +4194,25 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
|
|
|
3949
4194
|
|
|
3950
4195
|
// Calculate lighting contribution from image based lighting source (IBL)
|
|
3951
4196
|
#ifdef USE_IBL
|
|
3952
|
-
if (pbrMaterial.IBLenabled) {
|
|
4197
|
+
if (pbrMaterial.IBLenabled != 0) {
|
|
3953
4198
|
color += getIBLContribution(pbrInfo, n, reflection);
|
|
3954
4199
|
}
|
|
3955
4200
|
#endif
|
|
3956
4201
|
|
|
3957
4202
|
// Apply optional PBR terms for additional (optional) shading
|
|
3958
4203
|
#ifdef HAS_OCCLUSIONMAP
|
|
3959
|
-
if (pbrMaterial.occlusionMapEnabled) {
|
|
3960
|
-
let ao =
|
|
4204
|
+
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
4205
|
+
let ao =
|
|
4206
|
+
textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
|
|
3961
4207
|
color = mix(color, color * ao, pbrMaterial.occlusionStrength);
|
|
3962
4208
|
}
|
|
3963
4209
|
#endif
|
|
3964
4210
|
|
|
3965
4211
|
#ifdef HAS_EMISSIVEMAP
|
|
3966
|
-
if (pbrMaterial.emissiveMapEnabled) {
|
|
3967
|
-
let emissive = SRGBtoLINEAR(
|
|
4212
|
+
if (pbrMaterial.emissiveMapEnabled != 0u) {
|
|
4213
|
+
let emissive = SRGBtoLINEAR(
|
|
4214
|
+
textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
|
|
4215
|
+
).rgb * pbrMaterial.emissiveFactor;
|
|
3968
4216
|
color += emissive;
|
|
3969
4217
|
}
|
|
3970
4218
|
#endif
|
|
@@ -4002,8 +4250,21 @@ var uniformBlock = (
|
|
|
4002
4250
|
} pbrProjection;
|
|
4003
4251
|
`
|
|
4004
4252
|
);
|
|
4253
|
+
var wgslUniformBlock = (
|
|
4254
|
+
/* wgsl */
|
|
4255
|
+
`struct pbrProjectionUniforms {
|
|
4256
|
+
modelViewProjectionMatrix: mat4x4<f32>,
|
|
4257
|
+
modelMatrix: mat4x4<f32>,
|
|
4258
|
+
normalMatrix: mat4x4<f32>,
|
|
4259
|
+
camera: vec3<f32>
|
|
4260
|
+
};
|
|
4261
|
+
|
|
4262
|
+
@binding(0) @group(0) var<uniform> pbrProjection: pbrProjectionUniforms;
|
|
4263
|
+
`
|
|
4264
|
+
);
|
|
4005
4265
|
var pbrProjection = {
|
|
4006
4266
|
name: "pbrProjection",
|
|
4267
|
+
source: wgslUniformBlock,
|
|
4007
4268
|
vs: uniformBlock,
|
|
4008
4269
|
fs: uniformBlock,
|
|
4009
4270
|
// TODO why is this needed?
|
|
@@ -4012,7 +4273,7 @@ var pbrProjection = {
|
|
|
4012
4273
|
modelViewProjectionMatrix: "mat4x4<f32>",
|
|
4013
4274
|
modelMatrix: "mat4x4<f32>",
|
|
4014
4275
|
normalMatrix: "mat4x4<f32>",
|
|
4015
|
-
camera: "vec3<
|
|
4276
|
+
camera: "vec3<f32>"
|
|
4016
4277
|
}
|
|
4017
4278
|
};
|
|
4018
4279
|
|
|
@@ -4022,9 +4283,9 @@ var pbrMaterial = {
|
|
|
4022
4283
|
uniforms: {},
|
|
4023
4284
|
name: "pbrMaterial",
|
|
4024
4285
|
dependencies: [lighting, pbrProjection],
|
|
4025
|
-
source:
|
|
4026
|
-
vs:
|
|
4027
|
-
fs:
|
|
4286
|
+
source: source3,
|
|
4287
|
+
vs: vs3,
|
|
4288
|
+
fs: fs4,
|
|
4028
4289
|
defines: {
|
|
4029
4290
|
LIGHTING_FRAGMENT: true,
|
|
4030
4291
|
HAS_NORMALMAP: false,
|