@luma.gl/shaders 10.0.0-alpha.10 → 10.0.0-alpha.12
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 +1923 -60
- package/dist/dist.min.js +1499 -148
- package/dist/glsl.cjs.map +1 -1
- package/dist/index.cjs +41 -0
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/lighting/clustered-light-grid/clustered-light-grid.cjs +40 -0
- package/dist/modules/lighting/clustered-light-grid/clustered-light-grid.d.ts +6 -0
- package/dist/modules/lighting/clustered-light-grid/clustered-light-grid.d.ts.map +1 -0
- package/dist/modules/lighting/clustered-light-grid/clustered-light-grid.js +15 -0
- package/dist/modules/lighting/clustered-light-grid/clustered-light-grid.js.map +1 -0
- package/dist/modules/lighting/contact-shadow/contact-shadow.cjs +348 -0
- package/dist/modules/lighting/contact-shadow/contact-shadow.d.ts +188 -0
- package/dist/modules/lighting/contact-shadow/contact-shadow.d.ts.map +1 -0
- package/dist/modules/lighting/contact-shadow/contact-shadow.js +307 -0
- package/dist/modules/lighting/contact-shadow/contact-shadow.js.map +1 -0
- package/dist/modules/lighting/lightmap/lightmap-filter.cjs +93 -0
- package/dist/modules/lighting/lightmap/lightmap-filter.d.ts +35 -0
- package/dist/modules/lighting/lightmap/lightmap-filter.d.ts.map +1 -0
- package/dist/modules/lighting/lightmap/lightmap-filter.js +71 -0
- package/dist/modules/lighting/lightmap/lightmap-filter.js.map +1 -0
- package/dist/modules/lighting/lightmap/lightmap.cjs +89 -0
- package/dist/modules/lighting/lightmap/lightmap.d.ts +405 -0
- package/dist/modules/lighting/lightmap/lightmap.d.ts.map +1 -0
- package/dist/modules/lighting/lightmap/lightmap.js +67 -0
- package/dist/modules/lighting/lightmap/lightmap.js.map +1 -0
- package/dist/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.cjs +87 -0
- package/dist/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.d.ts +21 -0
- package/dist/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.d.ts.map +1 -0
- package/dist/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.js +61 -0
- package/dist/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.js.map +1 -0
- package/dist/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.cjs +87 -0
- package/dist/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.d.ts +21 -0
- package/dist/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.d.ts.map +1 -0
- package/dist/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.js +61 -0
- package/dist/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.js.map +1 -0
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.cjs +33 -11
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +2 -2
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +33 -11
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.cjs +33 -11
- 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 +33 -11
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material.d.ts +3 -3
- package/dist/modules/lighting/pbr-shadow/pbr-shadow.cjs +97 -0
- package/dist/modules/lighting/pbr-shadow/pbr-shadow.d.ts +15 -0
- package/dist/modules/lighting/pbr-shadow/pbr-shadow.d.ts.map +1 -0
- package/dist/modules/lighting/pbr-shadow/pbr-shadow.js +69 -0
- package/dist/modules/lighting/pbr-shadow/pbr-shadow.js.map +1 -0
- package/dist/modules/lighting/pbr-surface/pbr-surface.cjs +114 -0
- package/dist/modules/lighting/pbr-surface/pbr-surface.d.ts +15 -0
- package/dist/modules/lighting/pbr-surface/pbr-surface.d.ts.map +1 -0
- package/dist/modules/lighting/pbr-surface/pbr-surface.js +88 -0
- package/dist/modules/lighting/pbr-surface/pbr-surface.js.map +1 -0
- package/dist/modules/lighting/prefiltered-environment/prefiltered-environment.cjs +379 -0
- package/dist/modules/lighting/prefiltered-environment/prefiltered-environment.d.ts +41 -0
- package/dist/modules/lighting/prefiltered-environment/prefiltered-environment.d.ts.map +1 -0
- package/dist/modules/lighting/prefiltered-environment/prefiltered-environment.js +345 -0
- package/dist/modules/lighting/prefiltered-environment/prefiltered-environment.js.map +1 -0
- package/dist/modules/lighting/shadow/shadow-glsl.cjs +228 -0
- package/dist/modules/lighting/shadow/shadow-glsl.d.ts +3 -0
- package/dist/modules/lighting/shadow/shadow-glsl.d.ts.map +1 -0
- package/dist/modules/lighting/shadow/shadow-glsl.js +204 -0
- package/dist/modules/lighting/shadow/shadow-glsl.js.map +1 -0
- package/dist/modules/lighting/shadow/shadow-types.cjs +15 -0
- package/dist/modules/lighting/shadow/shadow-types.d.ts +63 -0
- package/dist/modules/lighting/shadow/shadow-types.d.ts.map +1 -0
- package/dist/modules/lighting/shadow/shadow-types.js +5 -0
- package/dist/modules/lighting/shadow/shadow-types.js.map +1 -0
- package/dist/modules/lighting/shadow/shadow.cjs +458 -0
- package/dist/modules/lighting/shadow/shadow.d.ts +117 -0
- package/dist/modules/lighting/shadow/shadow.d.ts.map +1 -0
- package/dist/modules/lighting/shadow/shadow.js +450 -0
- package/dist/modules/lighting/shadow/shadow.js.map +1 -0
- package/dist/modules/lighting/unlit-material/unlit-material.cjs +60 -0
- package/dist/modules/lighting/unlit-material/unlit-material.d.ts +9 -0
- package/dist/modules/lighting/unlit-material/unlit-material.d.ts.map +1 -0
- package/dist/modules/lighting/unlit-material/unlit-material.js +40 -0
- package/dist/modules/lighting/unlit-material/unlit-material.js.map +1 -0
- package/dist/types/shader-type-decoder.cjs +12 -2
- package/dist/types/shader-type-decoder.d.ts +7 -7
- package/dist/types/shader-type-decoder.d.ts.map +1 -1
- package/dist/types/shader-type-decoder.js +13 -2
- package/dist/types/shader-type-decoder.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/wgsl.cjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +52 -0
- package/src/modules/lighting/clustered-light-grid/clustered-light-grid.ts +17 -0
- package/src/modules/lighting/contact-shadow/contact-shadow.ts +365 -0
- package/src/modules/lighting/lightmap/lightmap-filter.ts +73 -0
- package/src/modules/lighting/lightmap/lightmap.ts +76 -0
- package/src/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.ts +78 -0
- package/src/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.ts +78 -0
- package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +33 -11
- package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +33 -11
- package/src/modules/lighting/pbr-shadow/pbr-shadow.ts +85 -0
- package/src/modules/lighting/pbr-surface/pbr-surface.ts +103 -0
- package/src/modules/lighting/prefiltered-environment/prefiltered-environment.ts +370 -0
- package/src/modules/lighting/shadow/shadow-glsl.ts +204 -0
- package/src/modules/lighting/shadow/shadow-types.ts +68 -0
- package/src/modules/lighting/shadow/shadow.ts +536 -0
- package/src/modules/lighting/unlit-material/unlit-material.ts +44 -0
- package/src/types/shader-type-decoder.ts +22 -9
package/dist/dist.dev.js
CHANGED
|
@@ -28,6 +28,8 @@ var __exports__ = (() => {
|
|
|
28
28
|
var bundle_exports = {};
|
|
29
29
|
__export(bundle_exports, {
|
|
30
30
|
GLSLShaderAssembler: () => GLSLShaderAssembler,
|
|
31
|
+
PBR_ENVIRONMENT_FRAGMENT_GLSL: () => PBR_ENVIRONMENT_FRAGMENT_GLSL,
|
|
32
|
+
PBR_ENVIRONMENT_FRAGMENT_WGSL: () => PBR_ENVIRONMENT_FRAGMENT_WGSL,
|
|
31
33
|
PBR_TONE_MAP_MODE: () => PBR_TONE_MAP_MODE,
|
|
32
34
|
SKIN_MAX_JOINTS: () => SKIN_MAX_JOINTS,
|
|
33
35
|
STORAGE_COLOR_DEFAULT_BYTE_STRIDES: () => STORAGE_COLOR_DEFAULT_BYTE_STRIDES,
|
|
@@ -43,8 +45,12 @@ var __exports__ = (() => {
|
|
|
43
45
|
checkShaderModuleDeprecations: () => checkShaderModuleDeprecations,
|
|
44
46
|
clipShaderPlugin: () => clipShaderPlugin,
|
|
45
47
|
clouds: () => clouds,
|
|
48
|
+
clusteredLightGrid: () => clusteredLightGrid,
|
|
46
49
|
colors: () => colors,
|
|
47
50
|
combineInjects: () => combineInjects,
|
|
51
|
+
contactShadowBilateralBlur: () => contactShadowBilateralBlur,
|
|
52
|
+
contactShadowComposite: () => contactShadowComposite,
|
|
53
|
+
contactShadowTrace: () => contactShadowTrace,
|
|
48
54
|
convertToVec4: () => convertToVec4,
|
|
49
55
|
dggs: () => dggs,
|
|
50
56
|
dirlight: () => dirlight,
|
|
@@ -80,13 +86,20 @@ var __exports__ = (() => {
|
|
|
80
86
|
integrateSurfaceWeather: () => integrateSurfaceWeather,
|
|
81
87
|
lambertMaterial: () => lambertMaterial,
|
|
82
88
|
lighting: () => lighting,
|
|
89
|
+
lightmapBake: () => lightmapBake,
|
|
90
|
+
lightmapFilter: () => lightmapFilter,
|
|
83
91
|
mergeShaderPluginModules: () => mergeShaderPluginModules,
|
|
84
92
|
normalizeByteColor3: () => normalizeByteColor3,
|
|
85
93
|
normalizeByteColor4: () => normalizeByteColor4,
|
|
86
94
|
pathDash: () => pathDash,
|
|
87
95
|
patternFill: () => patternFill,
|
|
96
|
+
pbrAmbientOcclusion: () => pbrAmbientOcclusion,
|
|
97
|
+
pbrContactShadow: () => pbrContactShadow,
|
|
98
|
+
pbrEnvironmentFilter: () => pbrEnvironmentFilter,
|
|
88
99
|
pbrMaterial: () => pbrMaterial,
|
|
89
100
|
pbrScene: () => pbrScene,
|
|
101
|
+
pbrShadow: () => pbrShadow,
|
|
102
|
+
pbrSurface: () => pbrSurface,
|
|
90
103
|
phongMaterial: () => phongMaterial,
|
|
91
104
|
picking: () => picking,
|
|
92
105
|
pointGlow: () => pointGlow,
|
|
@@ -97,6 +110,7 @@ var __exports__ = (() => {
|
|
|
97
110
|
resolveUseByteColors: () => resolveUseByteColors,
|
|
98
111
|
riverWaterMaterial: () => riverWaterMaterial,
|
|
99
112
|
scanWGSLInterface: () => scanWGSLInterface,
|
|
113
|
+
shadow: () => shadow,
|
|
100
114
|
sketchStroke: () => sketchStroke,
|
|
101
115
|
skin: () => skin,
|
|
102
116
|
storageColors: () => storageColors,
|
|
@@ -104,6 +118,7 @@ var __exports__ = (() => {
|
|
|
104
118
|
toHalfFloat: () => toHalfFloat,
|
|
105
119
|
typeToChannelCount: () => typeToChannelCount,
|
|
106
120
|
typeToChannelSuffix: () => typeToChannelSuffix,
|
|
121
|
+
unlitMaterial: () => unlitMaterial,
|
|
107
122
|
validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout,
|
|
108
123
|
valueNoise: () => valueNoise,
|
|
109
124
|
volumeRaymarch: () => volumeRaymarch,
|
|
@@ -1184,8 +1199,13 @@ ${fragmentString}${source7.slice(insertionIndex)}`;
|
|
|
1184
1199
|
}
|
|
1185
1200
|
return decoded;
|
|
1186
1201
|
}
|
|
1202
|
+
var attributeShaderTypeInfoCache = /* @__PURE__ */ new Map();
|
|
1187
1203
|
function getAttributeShaderTypeInfo(attributeType) {
|
|
1188
1204
|
const resolvedAttributeType = resolveAttributeShaderTypeAlias(attributeType);
|
|
1205
|
+
const cached = attributeShaderTypeInfoCache.get(resolvedAttributeType);
|
|
1206
|
+
if (cached) {
|
|
1207
|
+
return cached;
|
|
1208
|
+
}
|
|
1189
1209
|
const decoded = TYPE_INFO[resolvedAttributeType];
|
|
1190
1210
|
if (!decoded) {
|
|
1191
1211
|
throw new Error(`Unsupported attribute shader type: ${attributeType}`);
|
|
@@ -1194,13 +1214,15 @@ ${fragmentString}${source7.slice(insertionIndex)}`;
|
|
|
1194
1214
|
const integer = primitiveType === "i32" || primitiveType === "u32";
|
|
1195
1215
|
const signed = primitiveType !== "u32";
|
|
1196
1216
|
const byteLength = PRIMITIVE_TYPE_SIZES[primitiveType] * components;
|
|
1197
|
-
|
|
1217
|
+
const result = Object.freeze({
|
|
1198
1218
|
primitiveType,
|
|
1199
1219
|
components,
|
|
1200
1220
|
byteLength,
|
|
1201
1221
|
integer,
|
|
1202
1222
|
signed
|
|
1203
|
-
};
|
|
1223
|
+
});
|
|
1224
|
+
attributeShaderTypeInfoCache.set(resolvedAttributeType, result);
|
|
1225
|
+
return result;
|
|
1204
1226
|
}
|
|
1205
1227
|
var ShaderTypeDecoder = class {
|
|
1206
1228
|
getVariableShaderTypeInfo(format) {
|
|
@@ -1309,6 +1331,9 @@ ${fragmentString}${source7.slice(insertionIndex)}`;
|
|
|
1309
1331
|
"mat4x3<u32>": { type: "u32", components: 12 },
|
|
1310
1332
|
"mat4x4<u32>": { type: "u32", components: 16 }
|
|
1311
1333
|
};
|
|
1334
|
+
for (const info of Object.values(UNIFORM_FORMATS)) {
|
|
1335
|
+
Object.freeze(info);
|
|
1336
|
+
}
|
|
1312
1337
|
var WGSL_ATTRIBUTE_TYPE_ALIAS_MAP = {
|
|
1313
1338
|
vec2i: "vec2<i32>",
|
|
1314
1339
|
vec3i: "vec3<i32>",
|
|
@@ -5137,6 +5162,35 @@ void main() {
|
|
|
5137
5162
|
out[15] = 1;
|
|
5138
5163
|
return out;
|
|
5139
5164
|
}
|
|
5165
|
+
function affineComponents(matrix) {
|
|
5166
|
+
if (matrix.length !== 16 || Array.from(matrix).some((x) => !Number.isFinite(x)) || matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0 || matrix[15] !== 1) {
|
|
5167
|
+
throw new RangeError("Expected a finite affine matrix");
|
|
5168
|
+
}
|
|
5169
|
+
const scale2 = [
|
|
5170
|
+
Math.hypot(matrix[0], matrix[1], matrix[2]),
|
|
5171
|
+
Math.hypot(matrix[4], matrix[5], matrix[6]),
|
|
5172
|
+
Math.hypot(matrix[8], matrix[9], matrix[10])
|
|
5173
|
+
];
|
|
5174
|
+
if (scale2.some((x) => x === 0 || !Number.isFinite(x)))
|
|
5175
|
+
throw new RangeError("Singular transform");
|
|
5176
|
+
const rotation = Array.from({ length: 9 }, (_, i) => matrix[Math.floor(i / 3) * 4 + i % 3] / scale2[Math.floor(i / 3)]);
|
|
5177
|
+
for (const [a, b] of [
|
|
5178
|
+
[0, 3],
|
|
5179
|
+
[0, 6],
|
|
5180
|
+
[3, 6]
|
|
5181
|
+
]) {
|
|
5182
|
+
if (Math.abs(rotation[a] * rotation[b] + rotation[a + 1] * rotation[b + 1] + rotation[a + 2] * rotation[b + 2]) > 1e-7) {
|
|
5183
|
+
throw new RangeError("Sheared transforms do not have a TRS decomposition");
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
const determinant2 = rotation[0] * (rotation[4] * rotation[8] - rotation[5] * rotation[7]) - rotation[3] * (rotation[1] * rotation[8] - rotation[2] * rotation[7]) + rotation[6] * (rotation[1] * rotation[5] - rotation[2] * rotation[4]);
|
|
5187
|
+
if (determinant2 < 0) {
|
|
5188
|
+
scale2[0] = -scale2[0];
|
|
5189
|
+
for (let i = 0; i < 3; i++)
|
|
5190
|
+
rotation[i] = -rotation[i];
|
|
5191
|
+
}
|
|
5192
|
+
return { rotation, scale: scale2, translation: [matrix[12], matrix[13], matrix[14]] };
|
|
5193
|
+
}
|
|
5140
5194
|
|
|
5141
5195
|
// ../../node_modules/@math.gl/core/dist/gl-matrix/vec4.js
|
|
5142
5196
|
function transformMat43(out, a, m) {
|
|
@@ -5431,27 +5485,15 @@ void main() {
|
|
|
5431
5485
|
* @returns self
|
|
5432
5486
|
*/
|
|
5433
5487
|
getRotation(result, scaleResult) {
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
result[3] = 0;
|
|
5444
|
-
result[4] = this[4] * inverseScale0;
|
|
5445
|
-
result[5] = this[5] * inverseScale1;
|
|
5446
|
-
result[6] = this[6] * inverseScale2;
|
|
5447
|
-
result[7] = 0;
|
|
5448
|
-
result[8] = this[8] * inverseScale0;
|
|
5449
|
-
result[9] = this[9] * inverseScale1;
|
|
5450
|
-
result[10] = this[10] * inverseScale2;
|
|
5451
|
-
result[11] = 0;
|
|
5452
|
-
result[12] = 0;
|
|
5453
|
-
result[13] = 0;
|
|
5454
|
-
result[14] = 0;
|
|
5488
|
+
const { rotation, scale: scale2 } = affineComponents(this);
|
|
5489
|
+
result = result || new Array(16);
|
|
5490
|
+
if (scaleResult)
|
|
5491
|
+
for (let i = 0; i < 3; i++)
|
|
5492
|
+
scaleResult[i] = scale2[i];
|
|
5493
|
+
for (let i = 0; i < 16; i++)
|
|
5494
|
+
result[i] = 0;
|
|
5495
|
+
for (let i = 0; i < 9; i++)
|
|
5496
|
+
result[Math.floor(i / 3) * 4 + i % 3] = rotation[i];
|
|
5455
5497
|
result[15] = 1;
|
|
5456
5498
|
return result;
|
|
5457
5499
|
}
|
|
@@ -5462,21 +5504,13 @@ void main() {
|
|
|
5462
5504
|
* @returns self
|
|
5463
5505
|
*/
|
|
5464
5506
|
getRotationMatrix3(result, scaleResult) {
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
result[1] = this[1] * inverseScale1;
|
|
5473
|
-
result[2] = this[2] * inverseScale2;
|
|
5474
|
-
result[3] = this[4] * inverseScale0;
|
|
5475
|
-
result[4] = this[5] * inverseScale1;
|
|
5476
|
-
result[5] = this[6] * inverseScale2;
|
|
5477
|
-
result[6] = this[8] * inverseScale0;
|
|
5478
|
-
result[7] = this[9] * inverseScale1;
|
|
5479
|
-
result[8] = this[10] * inverseScale2;
|
|
5507
|
+
const { rotation, scale: scale2 } = affineComponents(this);
|
|
5508
|
+
result = result || new Array(9);
|
|
5509
|
+
if (scaleResult)
|
|
5510
|
+
for (let i = 0; i < 3; i++)
|
|
5511
|
+
scaleResult[i] = scale2[i];
|
|
5512
|
+
for (let i = 0; i < 9; i++)
|
|
5513
|
+
result[i] = rotation[i];
|
|
5480
5514
|
return result;
|
|
5481
5515
|
}
|
|
5482
5516
|
// Modifiers
|
|
@@ -12913,6 +12947,42 @@ vec4 dirlight_filterColor(vec4 color) {
|
|
|
12913
12947
|
return uniforms2;
|
|
12914
12948
|
}
|
|
12915
12949
|
|
|
12950
|
+
// src/modules/lighting/unlit-material/unlit-material.ts
|
|
12951
|
+
var SOURCE_WGSL2 = (
|
|
12952
|
+
/* wgsl */
|
|
12953
|
+
`fn unlitMaterial_getColor(surfaceColor: vec4<f32>) -> vec4<f32> {
|
|
12954
|
+
return surfaceColor;
|
|
12955
|
+
}
|
|
12956
|
+
|
|
12957
|
+
// Compatibility with the aggregate Phong/Gouraud material evaluation function.
|
|
12958
|
+
fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, positionWorldspace: vec3<f32>, normalWorldspace: vec3<f32>) -> vec3<f32> {
|
|
12959
|
+
return surfaceColor;
|
|
12960
|
+
}
|
|
12961
|
+
`
|
|
12962
|
+
);
|
|
12963
|
+
var SOURCE_GLSL = (
|
|
12964
|
+
/* glsl */
|
|
12965
|
+
`vec4 unlitMaterial_getColor(vec4 surfaceColor) {
|
|
12966
|
+
return surfaceColor;
|
|
12967
|
+
}
|
|
12968
|
+
|
|
12969
|
+
// Compatibility with the aggregate Phong/Gouraud material evaluation function.
|
|
12970
|
+
vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 positionWorldspace, vec3 normalWorldspace) {
|
|
12971
|
+
return surfaceColor;
|
|
12972
|
+
}
|
|
12973
|
+
`
|
|
12974
|
+
);
|
|
12975
|
+
var unlitMaterial = {
|
|
12976
|
+
name: "unlitMaterial",
|
|
12977
|
+
source: SOURCE_WGSL2,
|
|
12978
|
+
vs: SOURCE_GLSL,
|
|
12979
|
+
fs: SOURCE_GLSL,
|
|
12980
|
+
dependencies: [],
|
|
12981
|
+
bindingLayout: [],
|
|
12982
|
+
uniformTypes: {},
|
|
12983
|
+
defaultUniforms: {}
|
|
12984
|
+
};
|
|
12985
|
+
|
|
12916
12986
|
// src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts
|
|
12917
12987
|
var LAMBERT_WGSL = (
|
|
12918
12988
|
/* wgsl */
|
|
@@ -14542,7 +14612,7 @@ void pbr_setPositionNormalTangentUV(
|
|
|
14542
14612
|
vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
|
|
14543
14613
|
pbr_vTBN = mat3(tangentW, bitangentW, normalW);
|
|
14544
14614
|
#else // HAS_TANGENTS != 1
|
|
14545
|
-
pbr_vNormal = normalize(vec3(pbrProjection.
|
|
14615
|
+
pbr_vNormal = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
|
|
14546
14616
|
#endif
|
|
14547
14617
|
#endif
|
|
14548
14618
|
|
|
@@ -15549,7 +15619,9 @@ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
|
|
|
15549
15619
|
}
|
|
15550
15620
|
|
|
15551
15621
|
// Visibility for the first four spotlights; environment and other lights are unaffected.
|
|
15552
|
-
|
|
15622
|
+
float pbr_ambientVisibility = 1.0;
|
|
15623
|
+
|
|
15624
|
+
vec4 pbr_filterColorWithShadows(vec4 vertexColor, float directionalVisibility, vec4 pointVisibility, vec4 spotVisibility)
|
|
15553
15625
|
{
|
|
15554
15626
|
vec2 baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
|
|
15555
15627
|
vec2 metallicRoughnessUV = getMaterialUV(
|
|
@@ -15645,7 +15717,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15645
15717
|
color.rgb = baseColor.rgb;
|
|
15646
15718
|
#ifdef HAS_LIGHTMAP
|
|
15647
15719
|
if (pbrMaterial.lightmapMapEnabled) {
|
|
15648
|
-
color *= lightmapIrradiance / M_PI;
|
|
15720
|
+
color *= lightmapIrradiance / M_PI * pbr_ambientVisibility;
|
|
15649
15721
|
#ifdef HAS_OCCLUSIONMAP
|
|
15650
15722
|
if (pbrMaterial.occlusionMapEnabled) {
|
|
15651
15723
|
float ao = texture(pbr_occlusionSampler, occlusionUV).r;
|
|
@@ -15747,12 +15819,12 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15747
15819
|
|
|
15748
15820
|
#ifdef USE_LIGHTS
|
|
15749
15821
|
PBRInfo_setAmbientLight(pbrInfo);
|
|
15750
|
-
color += calculateFinalColor(pbrInfo, lighting.ambientColor);
|
|
15822
|
+
color += calculateFinalColor(pbrInfo, lighting.ambientColor * pbr_ambientVisibility);
|
|
15751
15823
|
|
|
15752
15824
|
for(int i = 0; i < lighting.directionalLightCount; i++) {
|
|
15753
15825
|
if (i < lighting.directionalLightCount) {
|
|
15754
15826
|
PBRInfo_setDirectionalLight(pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
15755
|
-
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
|
|
15827
|
+
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color * (i == 0 ? clamp(directionalVisibility, 0.0, 1.0) : 1.0));
|
|
15756
15828
|
}
|
|
15757
15829
|
}
|
|
15758
15830
|
|
|
@@ -15760,7 +15832,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15760
15832
|
if (i < lighting.pointLightCount) {
|
|
15761
15833
|
PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
|
|
15762
15834
|
float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
|
|
15763
|
-
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
|
|
15835
|
+
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color * (i < 4 ? clamp(pointVisibility[min(i, 3)], 0.0, 1.0) : 1.0) / attenuation);
|
|
15764
15836
|
}
|
|
15765
15837
|
}
|
|
15766
15838
|
|
|
@@ -15786,6 +15858,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15786
15858
|
}
|
|
15787
15859
|
#endif
|
|
15788
15860
|
|
|
15861
|
+
vec3 indirectBaseColor = color;
|
|
15789
15862
|
#ifdef USE_IBL
|
|
15790
15863
|
if (pbrMaterial.IBLenabled) {
|
|
15791
15864
|
color += getIBLContribution(pbrInfo, n, reflection);
|
|
@@ -15794,6 +15867,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15794
15867
|
|
|
15795
15868
|
// The pinned KHR_lightmap draft explicitly defines c_diff = (1 - metallic) * baseColor.
|
|
15796
15869
|
color += baseColor.rgb * (1.0 - metallic) * lightmapIrradiance / M_PI;
|
|
15870
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
15797
15871
|
|
|
15798
15872
|
#ifdef HAS_OCCLUSIONMAP
|
|
15799
15873
|
if (pbrMaterial.occlusionMapEnabled) {
|
|
@@ -16026,7 +16100,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16026
16100
|
PBRInfo_setAmbientLight(pbrInfo);
|
|
16027
16101
|
color += calculateMaterialLightColor(
|
|
16028
16102
|
pbrInfo,
|
|
16029
|
-
lighting.ambientColor,
|
|
16103
|
+
lighting.ambientColor * pbr_ambientVisibility,
|
|
16030
16104
|
clearcoatNormal,
|
|
16031
16105
|
clearcoatFactor,
|
|
16032
16106
|
clearcoatRoughness,
|
|
@@ -16042,7 +16116,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16042
16116
|
PBRInfo_setDirectionalLight(pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
16043
16117
|
color += calculateMaterialLightColor(
|
|
16044
16118
|
pbrInfo,
|
|
16045
|
-
lighting_getDirectionalLight(i).color,
|
|
16119
|
+
lighting_getDirectionalLight(i).color * (i == 0 ? clamp(directionalVisibility, 0.0, 1.0) : 1.0),
|
|
16046
16120
|
clearcoatNormal,
|
|
16047
16121
|
clearcoatFactor,
|
|
16048
16122
|
clearcoatRoughness,
|
|
@@ -16053,7 +16127,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16053
16127
|
);
|
|
16054
16128
|
color += calculateDiffuseTransmissionLight(
|
|
16055
16129
|
pbrInfo,
|
|
16056
|
-
lighting_getDirectionalLight(i).color,
|
|
16130
|
+
lighting_getDirectionalLight(i).color * (i == 0 ? clamp(directionalVisibility, 0.0, 1.0) : 1.0),
|
|
16057
16131
|
diffuseTransmissionColor,
|
|
16058
16132
|
diffuseTransmission,
|
|
16059
16133
|
multiscatterColor,
|
|
@@ -16069,7 +16143,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16069
16143
|
float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
|
|
16070
16144
|
color += calculateMaterialLightColor(
|
|
16071
16145
|
pbrInfo,
|
|
16072
|
-
lighting_getPointLight(i).color / attenuation,
|
|
16146
|
+
lighting_getPointLight(i).color * (i < 4 ? clamp(pointVisibility[min(i, 3)], 0.0, 1.0) : 1.0) / attenuation,
|
|
16073
16147
|
clearcoatNormal,
|
|
16074
16148
|
clearcoatFactor,
|
|
16075
16149
|
clearcoatRoughness,
|
|
@@ -16080,7 +16154,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16080
16154
|
);
|
|
16081
16155
|
color += calculateDiffuseTransmissionLight(
|
|
16082
16156
|
pbrInfo,
|
|
16083
|
-
lighting_getPointLight(i).color / attenuation,
|
|
16157
|
+
lighting_getPointLight(i).color * (i < 4 ? clamp(pointVisibility[min(i, 3)], 0.0, 1.0) : 1.0) / attenuation,
|
|
16084
16158
|
diffuseTransmissionColor,
|
|
16085
16159
|
diffuseTransmission,
|
|
16086
16160
|
multiscatterColor,
|
|
@@ -16149,6 +16223,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16149
16223
|
}
|
|
16150
16224
|
#endif
|
|
16151
16225
|
|
|
16226
|
+
vec3 indirectBaseColor = color;
|
|
16152
16227
|
// Calculate lighting contribution from image based lighting source (IBL)
|
|
16153
16228
|
#ifdef USE_IBL
|
|
16154
16229
|
if (pbrMaterial.IBLenabled) {
|
|
@@ -16183,6 +16258,8 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16183
16258
|
(1.0 - diffuseTransmission) * baseLayerEnergy * lightmapIrradiance / M_PI;
|
|
16184
16259
|
#endif
|
|
16185
16260
|
|
|
16261
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
16262
|
+
|
|
16186
16263
|
// Apply optional PBR terms for additional (optional) shading
|
|
16187
16264
|
#ifdef HAS_OCCLUSIONMAP
|
|
16188
16265
|
if (pbrMaterial.occlusionMapEnabled) {
|
|
@@ -16244,6 +16321,21 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16244
16321
|
return vec4(applySceneColorManagement(color), alpha);
|
|
16245
16322
|
}
|
|
16246
16323
|
|
|
16324
|
+
// Depth-only passes use the same base-color alpha, vertex color and UV transform.
|
|
16325
|
+
void pbr_discardMaskedFragment(vec4 vertexColor) {
|
|
16326
|
+
#ifdef ALPHA_CUTOFF
|
|
16327
|
+
float alpha = pbrMaterial.baseColorFactor.a * vertexColor.a;
|
|
16328
|
+
#ifdef HAS_BASECOLORMAP
|
|
16329
|
+
alpha *= texture(pbr_baseColorSampler, getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform)).a;
|
|
16330
|
+
#endif
|
|
16331
|
+
if (alpha < pbrMaterial.alphaCutoff) {discard;}
|
|
16332
|
+
#endif
|
|
16333
|
+
}
|
|
16334
|
+
|
|
16335
|
+
vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility) {
|
|
16336
|
+
return pbr_filterColorWithShadows(vertexColor, 1.0, vec4(1.0), spotVisibility);
|
|
16337
|
+
}
|
|
16338
|
+
|
|
16247
16339
|
vec4 pbr_filterColor(vec4 vertexColor) {
|
|
16248
16340
|
return pbr_filterColorWithSpotShadows(vertexColor, vec4(1.0));
|
|
16249
16341
|
}
|
|
@@ -17368,7 +17460,9 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
|
|
|
17368
17460
|
}
|
|
17369
17461
|
|
|
17370
17462
|
// Visibility for the first four spotlights; environment and other lights are unaffected.
|
|
17371
|
-
|
|
17463
|
+
var<private> pbr_ambientVisibility: f32 = 1.0;
|
|
17464
|
+
|
|
17465
|
+
fn pbr_filterColorWithShadows(vertexColor: vec4<f32>, directionalVisibility: f32, pointVisibility: vec4f, spotVisibility: vec4f) -> vec4<f32> {
|
|
17372
17466
|
let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
|
|
17373
17467
|
let metallicRoughnessUV = getMaterialUV(
|
|
17374
17468
|
pbrMaterial.metallicRoughnessUVSet,
|
|
@@ -17461,7 +17555,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17461
17555
|
color = baseColor.rgb;
|
|
17462
17556
|
#ifdef HAS_LIGHTMAP
|
|
17463
17557
|
if (pbrMaterial.lightmapMapEnabled != 0u) {
|
|
17464
|
-
color *= lightmapIrradiance / M_PI;
|
|
17558
|
+
color *= lightmapIrradiance / M_PI * pbr_ambientVisibility;
|
|
17465
17559
|
#ifdef HAS_OCCLUSIONMAP
|
|
17466
17560
|
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
17467
17561
|
let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
|
|
@@ -17564,12 +17658,12 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17564
17658
|
|
|
17565
17659
|
#ifdef USE_LIGHTS
|
|
17566
17660
|
PBRInfo_setAmbientLight(&pbrInfo);
|
|
17567
|
-
color += calculateFinalColor(pbrInfo, lighting.ambientColor);
|
|
17661
|
+
color += calculateFinalColor(pbrInfo, lighting.ambientColor * pbr_ambientVisibility);
|
|
17568
17662
|
|
|
17569
17663
|
for (var i = 0; i < lighting.directionalLightCount; i++) {
|
|
17570
17664
|
if (i < lighting.directionalLightCount) {
|
|
17571
17665
|
PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
17572
|
-
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
|
|
17666
|
+
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color * select(1.0, clamp(directionalVisibility, 0.0, 1.0), i == 0));
|
|
17573
17667
|
}
|
|
17574
17668
|
}
|
|
17575
17669
|
|
|
@@ -17580,7 +17674,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17580
17674
|
lighting_getPointLight(i),
|
|
17581
17675
|
distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
|
|
17582
17676
|
);
|
|
17583
|
-
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
|
|
17677
|
+
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color * select(1.0, clamp(pointVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation);
|
|
17584
17678
|
}
|
|
17585
17679
|
}
|
|
17586
17680
|
|
|
@@ -17609,7 +17703,8 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17609
17703
|
}
|
|
17610
17704
|
#endif
|
|
17611
17705
|
|
|
17612
|
-
|
|
17706
|
+
let indirectBaseColor = color;
|
|
17707
|
+
#ifdef USE_IBL
|
|
17613
17708
|
if (pbrMaterial.IBLenabled != 0) {
|
|
17614
17709
|
color += getIBLContribution(pbrInfo, n, reflection);
|
|
17615
17710
|
}
|
|
@@ -17617,6 +17712,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17617
17712
|
|
|
17618
17713
|
// The pinned KHR_lightmap draft explicitly defines c_diff = (1 - metallic) * baseColor.
|
|
17619
17714
|
color += baseColor.rgb * (1.0 - metallic) * lightmapIrradiance / M_PI;
|
|
17715
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
17620
17716
|
|
|
17621
17717
|
#ifdef HAS_OCCLUSIONMAP
|
|
17622
17718
|
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
@@ -17915,7 +18011,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17915
18011
|
PBRInfo_setAmbientLight(&pbrInfo);
|
|
17916
18012
|
color += calculateMaterialLightColor(
|
|
17917
18013
|
pbrInfo,
|
|
17918
|
-
lighting.ambientColor,
|
|
18014
|
+
lighting.ambientColor * pbr_ambientVisibility,
|
|
17919
18015
|
clearcoatNormal,
|
|
17920
18016
|
clearcoatFactor,
|
|
17921
18017
|
clearcoatRoughness,
|
|
@@ -17931,7 +18027,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17931
18027
|
PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
17932
18028
|
color += calculateMaterialLightColor(
|
|
17933
18029
|
pbrInfo,
|
|
17934
|
-
lighting_getDirectionalLight(i).color,
|
|
18030
|
+
lighting_getDirectionalLight(i).color * select(1.0, clamp(directionalVisibility, 0.0, 1.0), i == 0),
|
|
17935
18031
|
clearcoatNormal,
|
|
17936
18032
|
clearcoatFactor,
|
|
17937
18033
|
clearcoatRoughness,
|
|
@@ -17942,7 +18038,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17942
18038
|
);
|
|
17943
18039
|
color += calculateDiffuseTransmissionLight(
|
|
17944
18040
|
pbrInfo,
|
|
17945
|
-
lighting_getDirectionalLight(i).color,
|
|
18041
|
+
lighting_getDirectionalLight(i).color * select(1.0, clamp(directionalVisibility, 0.0, 1.0), i == 0),
|
|
17946
18042
|
diffuseTransmissionColor,
|
|
17947
18043
|
diffuseTransmission,
|
|
17948
18044
|
multiscatterColor,
|
|
@@ -17961,7 +18057,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17961
18057
|
);
|
|
17962
18058
|
color += calculateMaterialLightColor(
|
|
17963
18059
|
pbrInfo,
|
|
17964
|
-
lighting_getPointLight(i).color / attenuation,
|
|
18060
|
+
lighting_getPointLight(i).color * select(1.0, clamp(pointVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,
|
|
17965
18061
|
clearcoatNormal,
|
|
17966
18062
|
clearcoatFactor,
|
|
17967
18063
|
clearcoatRoughness,
|
|
@@ -17972,7 +18068,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17972
18068
|
);
|
|
17973
18069
|
color += calculateDiffuseTransmissionLight(
|
|
17974
18070
|
pbrInfo,
|
|
17975
|
-
lighting_getPointLight(i).color / attenuation,
|
|
18071
|
+
lighting_getPointLight(i).color * select(1.0, clamp(pointVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,
|
|
17976
18072
|
diffuseTransmissionColor,
|
|
17977
18073
|
diffuseTransmission,
|
|
17978
18074
|
multiscatterColor,
|
|
@@ -18041,6 +18137,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
18041
18137
|
}
|
|
18042
18138
|
#endif
|
|
18043
18139
|
|
|
18140
|
+
let indirectBaseColor = color;
|
|
18044
18141
|
// Calculate lighting contribution from image based lighting source (IBL)
|
|
18045
18142
|
#ifdef USE_IBL
|
|
18046
18143
|
if (pbrMaterial.IBLenabled != 0) {
|
|
@@ -18075,6 +18172,8 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
18075
18172
|
(1.0 - diffuseTransmission) * baseLayerEnergy * lightmapIrradiance / M_PI;
|
|
18076
18173
|
#endif
|
|
18077
18174
|
|
|
18175
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
18176
|
+
|
|
18078
18177
|
// Apply optional PBR terms for additional (optional) shading
|
|
18079
18178
|
#ifdef HAS_OCCLUSIONMAP
|
|
18080
18179
|
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
@@ -18137,6 +18236,21 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
18137
18236
|
return vec4<f32>(applySceneColorManagement(color), alpha);
|
|
18138
18237
|
}
|
|
18139
18238
|
|
|
18239
|
+
// Depth-only passes use the same base-color alpha, vertex color and UV transform.
|
|
18240
|
+
fn pbr_discardMaskedFragment(vertexColor: vec4f) {
|
|
18241
|
+
#ifdef ALPHA_CUTOFF
|
|
18242
|
+
var alpha = pbrMaterial.baseColorFactor.a * vertexColor.a;
|
|
18243
|
+
#ifdef HAS_BASECOLORMAP
|
|
18244
|
+
alpha *= textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform)).a;
|
|
18245
|
+
#endif
|
|
18246
|
+
if (alpha < pbrMaterial.alphaCutoff) {discard;}
|
|
18247
|
+
#endif
|
|
18248
|
+
}
|
|
18249
|
+
|
|
18250
|
+
fn pbr_filterColorWithSpotShadows(vertexColor: vec4f, spotVisibility: vec4f) -> vec4f {
|
|
18251
|
+
return pbr_filterColorWithShadows(vertexColor, 1.0, vec4f(1.0), spotVisibility);
|
|
18252
|
+
}
|
|
18253
|
+
|
|
18140
18254
|
fn pbr_filterColor(vertexColor: vec4<f32>) -> vec4<f32> {
|
|
18141
18255
|
return pbr_filterColorWithSpotShadows(vertexColor, vec4f(1.0));
|
|
18142
18256
|
}
|
|
@@ -19874,6 +19988,1755 @@ fn globeClouds_getColor(camera: vec3f, direction: vec3f) -> vec4f {
|
|
|
19874
19988
|
`
|
|
19875
19989
|
)
|
|
19876
19990
|
};
|
|
19991
|
+
|
|
19992
|
+
// src/modules/lighting/prefiltered-environment/prefiltered-environment.ts
|
|
19993
|
+
var GLSL_UNIFORMS = (
|
|
19994
|
+
/* glsl */
|
|
19995
|
+
`layout(std140) uniform pbrEnvironmentFilterUniforms {
|
|
19996
|
+
int face;
|
|
19997
|
+
float roughness;
|
|
19998
|
+
int mode;
|
|
19999
|
+
int sampleCount;
|
|
20000
|
+
int sourceEncoding;
|
|
20001
|
+
} pbrEnvironmentFilter;
|
|
20002
|
+
|
|
20003
|
+
uniform sampler2D pbrEnvironmentSource;
|
|
20004
|
+
`
|
|
20005
|
+
);
|
|
20006
|
+
var WGSL_UNIFORMS = (
|
|
20007
|
+
/* wgsl */
|
|
20008
|
+
`struct PBREnvironmentFilterUniforms {
|
|
20009
|
+
face: i32,
|
|
20010
|
+
roughness: f32,
|
|
20011
|
+
mode: i32,
|
|
20012
|
+
sampleCount: i32,
|
|
20013
|
+
sourceEncoding: i32,
|
|
20014
|
+
};
|
|
20015
|
+
|
|
20016
|
+
@group(0) @binding(auto) var<uniform> pbrEnvironmentFilter: PBREnvironmentFilterUniforms;
|
|
20017
|
+
@group(0) @binding(auto) var pbrEnvironmentSource: texture_2d<f32>;
|
|
20018
|
+
@group(0) @binding(auto) var pbrEnvironmentSourceSampler: sampler;
|
|
20019
|
+
`
|
|
20020
|
+
);
|
|
20021
|
+
var pbrEnvironmentFilter = {
|
|
20022
|
+
name: "pbrEnvironmentFilter",
|
|
20023
|
+
bindingLayout: [
|
|
20024
|
+
{ name: "pbrEnvironmentFilter", group: 0 },
|
|
20025
|
+
{ name: "pbrEnvironmentSource", group: 0 }
|
|
20026
|
+
],
|
|
20027
|
+
fs: GLSL_UNIFORMS,
|
|
20028
|
+
source: WGSL_UNIFORMS,
|
|
20029
|
+
getUniforms: (properties) => properties,
|
|
20030
|
+
uniformTypes: {
|
|
20031
|
+
face: "i32",
|
|
20032
|
+
roughness: "f32",
|
|
20033
|
+
mode: "i32",
|
|
20034
|
+
sampleCount: "i32",
|
|
20035
|
+
sourceEncoding: "i32"
|
|
20036
|
+
},
|
|
20037
|
+
defaultUniforms: {
|
|
20038
|
+
face: 0,
|
|
20039
|
+
roughness: 0,
|
|
20040
|
+
mode: 0,
|
|
20041
|
+
sampleCount: 64,
|
|
20042
|
+
sourceEncoding: 0
|
|
20043
|
+
}
|
|
20044
|
+
};
|
|
20045
|
+
var PBR_ENVIRONMENT_FRAGMENT_GLSL = (
|
|
20046
|
+
/* glsl */
|
|
20047
|
+
`#version 300 es
|
|
20048
|
+
precision highp float;
|
|
20049
|
+
precision highp int;
|
|
20050
|
+
|
|
20051
|
+
in vec2 uv;
|
|
20052
|
+
out vec4 fragmentColor;
|
|
20053
|
+
|
|
20054
|
+
const float ENVIRONMENT_PI = 3.141592653589793;
|
|
20055
|
+
|
|
20056
|
+
vec2 getEnvironmentHammersley(uint index, uint sampleCount)
|
|
20057
|
+
{
|
|
20058
|
+
uint reversedBits = (index << 16u) | (index >> 16u);
|
|
20059
|
+
reversedBits = ((reversedBits & 0x55555555u) << 1u) |
|
|
20060
|
+
((reversedBits & 0xAAAAAAAAu) >> 1u);
|
|
20061
|
+
reversedBits = ((reversedBits & 0x33333333u) << 2u) |
|
|
20062
|
+
((reversedBits & 0xCCCCCCCCu) >> 2u);
|
|
20063
|
+
reversedBits = ((reversedBits & 0x0F0F0F0Fu) << 4u) |
|
|
20064
|
+
((reversedBits & 0xF0F0F0F0u) >> 4u);
|
|
20065
|
+
reversedBits = ((reversedBits & 0x00FF00FFu) << 8u) |
|
|
20066
|
+
((reversedBits & 0xFF00FF00u) >> 8u);
|
|
20067
|
+
return vec2(
|
|
20068
|
+
float(index) / float(sampleCount),
|
|
20069
|
+
float(reversedBits) * 2.3283064365386963e-10
|
|
20070
|
+
);
|
|
20071
|
+
}
|
|
20072
|
+
|
|
20073
|
+
vec3 getEnvironmentFaceDirection(int face, vec2 textureCoordinate)
|
|
20074
|
+
{
|
|
20075
|
+
vec2 coordinate = textureCoordinate * 2.0 - 1.0;
|
|
20076
|
+
if (face == 0) return normalize(vec3(1.0, -coordinate.y, -coordinate.x));
|
|
20077
|
+
if (face == 1) return normalize(vec3(-1.0, -coordinate.y, coordinate.x));
|
|
20078
|
+
if (face == 2) return normalize(vec3(coordinate.x, 1.0, coordinate.y));
|
|
20079
|
+
if (face == 3) return normalize(vec3(coordinate.x, -1.0, -coordinate.y));
|
|
20080
|
+
if (face == 4) return normalize(vec3(coordinate.x, -coordinate.y, 1.0));
|
|
20081
|
+
return normalize(vec3(-coordinate.x, -coordinate.y, -1.0));
|
|
20082
|
+
}
|
|
20083
|
+
|
|
20084
|
+
mat3 getEnvironmentTangentBasis(vec3 normal)
|
|
20085
|
+
{
|
|
20086
|
+
vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
20087
|
+
vec3 tangent = normalize(cross(up, normal));
|
|
20088
|
+
return mat3(tangent, cross(normal, tangent), normal);
|
|
20089
|
+
}
|
|
20090
|
+
|
|
20091
|
+
vec3 sampleEnvironmentDirection(vec3 direction)
|
|
20092
|
+
{
|
|
20093
|
+
vec3 normalizedDirection = normalize(direction);
|
|
20094
|
+
vec2 textureCoordinate = vec2(
|
|
20095
|
+
atan(normalizedDirection.z, normalizedDirection.x) / (2.0 * ENVIRONMENT_PI) + 0.5,
|
|
20096
|
+
acos(clamp(normalizedDirection.y, -1.0, 1.0)) / ENVIRONMENT_PI
|
|
20097
|
+
);
|
|
20098
|
+
vec3 color = texture(pbrEnvironmentSource, textureCoordinate).rgb;
|
|
20099
|
+
if (pbrEnvironmentFilter.sourceEncoding == 1) {
|
|
20100
|
+
vec3 lower = color / 12.92;
|
|
20101
|
+
vec3 upper = pow((color + 0.055) / 1.055, vec3(2.4));
|
|
20102
|
+
color = mix(lower, upper, step(vec3(0.04045), color));
|
|
20103
|
+
}
|
|
20104
|
+
return color;
|
|
20105
|
+
}
|
|
20106
|
+
|
|
20107
|
+
vec3 importanceSampleEnvironment(vec2 sequence, vec3 normal, float roughness)
|
|
20108
|
+
{
|
|
20109
|
+
float alpha = max(roughness * roughness, 0.0001);
|
|
20110
|
+
float azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20111
|
+
float cosine = sqrt(
|
|
20112
|
+
(1.0 - sequence.y) / max(1.0 + (alpha * alpha - 1.0) * sequence.y, 0.0001)
|
|
20113
|
+
);
|
|
20114
|
+
float sine = sqrt(max(1.0 - cosine * cosine, 0.0));
|
|
20115
|
+
vec3 halfVector = vec3(cos(azimuth) * sine, sin(azimuth) * sine, cosine);
|
|
20116
|
+
return normalize(getEnvironmentTangentBasis(normal) * halfVector);
|
|
20117
|
+
}
|
|
20118
|
+
|
|
20119
|
+
float getEnvironmentGeometry(float normalDotDirection, float roughness)
|
|
20120
|
+
{
|
|
20121
|
+
float alpha = roughness * roughness;
|
|
20122
|
+
float factor = alpha * 0.5;
|
|
20123
|
+
return normalDotDirection / max(normalDotDirection * (1.0 - factor) + factor, 0.0001);
|
|
20124
|
+
}
|
|
20125
|
+
|
|
20126
|
+
vec2 integrateEnvironmentBRDF(vec2 textureCoordinate, int sampleCount)
|
|
20127
|
+
{
|
|
20128
|
+
float normalDotView = max(textureCoordinate.x, 0.001);
|
|
20129
|
+
float roughness = 1.0 - textureCoordinate.y;
|
|
20130
|
+
vec3 viewDirection = vec3(sqrt(max(1.0 - normalDotView * normalDotView, 0.0)), 0.0, normalDotView);
|
|
20131
|
+
vec2 integration = vec2(0.0);
|
|
20132
|
+
|
|
20133
|
+
for (int sampleIndex = 0; sampleIndex < 1024; sampleIndex++) {
|
|
20134
|
+
if (sampleIndex >= sampleCount) break;
|
|
20135
|
+
vec3 halfVector = importanceSampleEnvironment(
|
|
20136
|
+
getEnvironmentHammersley(uint(sampleIndex), uint(sampleCount)),
|
|
20137
|
+
vec3(0.0, 0.0, 1.0),
|
|
20138
|
+
roughness
|
|
20139
|
+
);
|
|
20140
|
+
vec3 lightDirection = normalize(2.0 * dot(viewDirection, halfVector) * halfVector - viewDirection);
|
|
20141
|
+
float normalDotLight = max(lightDirection.z, 0.0);
|
|
20142
|
+
float normalDotHalf = max(halfVector.z, 0.0);
|
|
20143
|
+
float viewDotHalf = max(dot(viewDirection, halfVector), 0.0);
|
|
20144
|
+
if (normalDotLight > 0.0) {
|
|
20145
|
+
float visibility = getEnvironmentGeometry(normalDotView, roughness) *
|
|
20146
|
+
getEnvironmentGeometry(normalDotLight, roughness) * viewDotHalf /
|
|
20147
|
+
max(normalDotHalf * normalDotView, 0.0001);
|
|
20148
|
+
float fresnel = pow(1.0 - viewDotHalf, 5.0);
|
|
20149
|
+
integration += vec2(1.0 - fresnel, fresnel) * visibility;
|
|
20150
|
+
}
|
|
20151
|
+
}
|
|
20152
|
+
return integration / float(sampleCount);
|
|
20153
|
+
}
|
|
20154
|
+
|
|
20155
|
+
vec3 integrateEnvironmentDirection(vec3 normal, int sampleCount)
|
|
20156
|
+
{
|
|
20157
|
+
vec3 accumulatedColor = vec3(0.0);
|
|
20158
|
+
float accumulatedWeight = 0.0;
|
|
20159
|
+
|
|
20160
|
+
for (int sampleIndex = 0; sampleIndex < 1024; sampleIndex++) {
|
|
20161
|
+
if (sampleIndex >= sampleCount) break;
|
|
20162
|
+
vec2 sequence = getEnvironmentHammersley(uint(sampleIndex), uint(sampleCount));
|
|
20163
|
+
vec3 direction;
|
|
20164
|
+
float sampleWeight;
|
|
20165
|
+
|
|
20166
|
+
if (pbrEnvironmentFilter.mode == 1) {
|
|
20167
|
+
float azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20168
|
+
float cosine = sqrt(1.0 - sequence.y);
|
|
20169
|
+
float sine = sqrt(sequence.y);
|
|
20170
|
+
direction = normalize(
|
|
20171
|
+
getEnvironmentTangentBasis(normal) *
|
|
20172
|
+
vec3(cos(azimuth) * sine, sin(azimuth) * sine, cosine)
|
|
20173
|
+
);
|
|
20174
|
+
sampleWeight = 1.0;
|
|
20175
|
+
} else {
|
|
20176
|
+
vec3 halfVector = importanceSampleEnvironment(sequence, normal, pbrEnvironmentFilter.roughness);
|
|
20177
|
+
direction = normalize(2.0 * dot(normal, halfVector) * halfVector - normal);
|
|
20178
|
+
sampleWeight = max(dot(normal, direction), 0.0);
|
|
20179
|
+
}
|
|
20180
|
+
|
|
20181
|
+
accumulatedColor += sampleEnvironmentDirection(direction) * sampleWeight;
|
|
20182
|
+
accumulatedWeight += sampleWeight;
|
|
20183
|
+
}
|
|
20184
|
+
|
|
20185
|
+
return accumulatedColor / max(accumulatedWeight, 0.0001);
|
|
20186
|
+
}
|
|
20187
|
+
|
|
20188
|
+
void main(void)
|
|
20189
|
+
{
|
|
20190
|
+
int sampleCount = max(pbrEnvironmentFilter.sampleCount, 1);
|
|
20191
|
+
if (pbrEnvironmentFilter.mode == 2) {
|
|
20192
|
+
fragmentColor = vec4(integrateEnvironmentBRDF(uv, sampleCount), 0.0, 1.0);
|
|
20193
|
+
return;
|
|
20194
|
+
}
|
|
20195
|
+
|
|
20196
|
+
vec3 direction = getEnvironmentFaceDirection(pbrEnvironmentFilter.face, uv);
|
|
20197
|
+
fragmentColor = vec4(integrateEnvironmentDirection(direction, sampleCount), 1.0);
|
|
20198
|
+
}
|
|
20199
|
+
`
|
|
20200
|
+
);
|
|
20201
|
+
var PBR_ENVIRONMENT_FRAGMENT_WGSL = (
|
|
20202
|
+
/* wgsl */
|
|
20203
|
+
`const ENVIRONMENT_PI: f32 = 3.141592653589793;
|
|
20204
|
+
|
|
20205
|
+
fn getEnvironmentHammersley(index: u32, sampleCount: u32) -> vec2f {
|
|
20206
|
+
return vec2f(f32(index) / f32(sampleCount), f32(reverseBits(index)) * 2.3283064365386963e-10);
|
|
20207
|
+
}
|
|
20208
|
+
|
|
20209
|
+
fn getEnvironmentFaceDirection(face: i32, textureCoordinate: vec2f) -> vec3f {
|
|
20210
|
+
let coordinate = textureCoordinate * 2.0 - 1.0;
|
|
20211
|
+
if (face == 0) { return normalize(vec3f(1.0, -coordinate.y, -coordinate.x)); }
|
|
20212
|
+
if (face == 1) { return normalize(vec3f(-1.0, -coordinate.y, coordinate.x)); }
|
|
20213
|
+
if (face == 2) { return normalize(vec3f(coordinate.x, 1.0, coordinate.y)); }
|
|
20214
|
+
if (face == 3) { return normalize(vec3f(coordinate.x, -1.0, -coordinate.y)); }
|
|
20215
|
+
if (face == 4) { return normalize(vec3f(coordinate.x, -coordinate.y, 1.0)); }
|
|
20216
|
+
return normalize(vec3f(-coordinate.x, -coordinate.y, -1.0));
|
|
20217
|
+
}
|
|
20218
|
+
|
|
20219
|
+
fn getEnvironmentTangentBasis(normal: vec3f) -> mat3x3f {
|
|
20220
|
+
var up = vec3f(1.0, 0.0, 0.0);
|
|
20221
|
+
if (abs(normal.z) < 0.999) {
|
|
20222
|
+
up = vec3f(0.0, 0.0, 1.0);
|
|
20223
|
+
}
|
|
20224
|
+
let tangent = normalize(cross(up, normal));
|
|
20225
|
+
return mat3x3f(tangent, cross(normal, tangent), normal);
|
|
20226
|
+
}
|
|
20227
|
+
|
|
20228
|
+
fn sampleEnvironmentDirection(direction: vec3f) -> vec3f {
|
|
20229
|
+
let normalizedDirection = normalize(direction);
|
|
20230
|
+
let textureCoordinate = vec2f(
|
|
20231
|
+
atan2(normalizedDirection.z, normalizedDirection.x) / (2.0 * ENVIRONMENT_PI) + 0.5,
|
|
20232
|
+
acos(clamp(normalizedDirection.y, -1.0, 1.0)) / ENVIRONMENT_PI
|
|
20233
|
+
);
|
|
20234
|
+
var color = textureSampleLevel(
|
|
20235
|
+
pbrEnvironmentSource,
|
|
20236
|
+
pbrEnvironmentSourceSampler,
|
|
20237
|
+
textureCoordinate,
|
|
20238
|
+
0.0
|
|
20239
|
+
).rgb;
|
|
20240
|
+
if (pbrEnvironmentFilter.sourceEncoding == 1) {
|
|
20241
|
+
let lower = color / 12.92;
|
|
20242
|
+
let upper = pow((color + 0.055) / 1.055, vec3f(2.4));
|
|
20243
|
+
color = mix(lower, upper, step(vec3f(0.04045), color));
|
|
20244
|
+
}
|
|
20245
|
+
return color;
|
|
20246
|
+
}
|
|
20247
|
+
|
|
20248
|
+
fn importanceSampleEnvironment(sequence: vec2f, normal: vec3f, roughness: f32) -> vec3f {
|
|
20249
|
+
let alpha = max(roughness * roughness, 0.0001);
|
|
20250
|
+
let azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20251
|
+
let cosine = sqrt(
|
|
20252
|
+
(1.0 - sequence.y) / max(1.0 + (alpha * alpha - 1.0) * sequence.y, 0.0001)
|
|
20253
|
+
);
|
|
20254
|
+
let sine = sqrt(max(1.0 - cosine * cosine, 0.0));
|
|
20255
|
+
let halfVector = vec3f(cos(azimuth) * sine, sin(azimuth) * sine, cosine);
|
|
20256
|
+
return normalize(getEnvironmentTangentBasis(normal) * halfVector);
|
|
20257
|
+
}
|
|
20258
|
+
|
|
20259
|
+
fn getEnvironmentGeometry(normalDotDirection: f32, roughness: f32) -> f32 {
|
|
20260
|
+
let alpha = roughness * roughness;
|
|
20261
|
+
let factor = alpha * 0.5;
|
|
20262
|
+
return normalDotDirection / max(normalDotDirection * (1.0 - factor) + factor, 0.0001);
|
|
20263
|
+
}
|
|
20264
|
+
|
|
20265
|
+
fn integrateEnvironmentBRDF(textureCoordinate: vec2f, sampleCount: u32) -> vec2f {
|
|
20266
|
+
let normalDotView = max(textureCoordinate.x, 0.001);
|
|
20267
|
+
let roughness = 1.0 - textureCoordinate.y;
|
|
20268
|
+
let viewDirection = vec3f(
|
|
20269
|
+
sqrt(max(1.0 - normalDotView * normalDotView, 0.0)),
|
|
20270
|
+
0.0,
|
|
20271
|
+
normalDotView
|
|
20272
|
+
);
|
|
20273
|
+
var integration = vec2f(0.0);
|
|
20274
|
+
|
|
20275
|
+
for (var sampleIndex = 0u; sampleIndex < sampleCount; sampleIndex++) {
|
|
20276
|
+
let halfVector = importanceSampleEnvironment(
|
|
20277
|
+
getEnvironmentHammersley(sampleIndex, sampleCount),
|
|
20278
|
+
vec3f(0.0, 0.0, 1.0),
|
|
20279
|
+
roughness
|
|
20280
|
+
);
|
|
20281
|
+
let lightDirection = normalize(
|
|
20282
|
+
2.0 * dot(viewDirection, halfVector) * halfVector - viewDirection
|
|
20283
|
+
);
|
|
20284
|
+
let normalDotLight = max(lightDirection.z, 0.0);
|
|
20285
|
+
let normalDotHalf = max(halfVector.z, 0.0);
|
|
20286
|
+
let viewDotHalf = max(dot(viewDirection, halfVector), 0.0);
|
|
20287
|
+
if (normalDotLight > 0.0) {
|
|
20288
|
+
let visibility = getEnvironmentGeometry(normalDotView, roughness) *
|
|
20289
|
+
getEnvironmentGeometry(normalDotLight, roughness) * viewDotHalf /
|
|
20290
|
+
max(normalDotHalf * normalDotView, 0.0001);
|
|
20291
|
+
let fresnel = pow(1.0 - viewDotHalf, 5.0);
|
|
20292
|
+
integration += vec2f(1.0 - fresnel, fresnel) * visibility;
|
|
20293
|
+
}
|
|
20294
|
+
}
|
|
20295
|
+
return integration / f32(sampleCount);
|
|
20296
|
+
}
|
|
20297
|
+
|
|
20298
|
+
fn integrateEnvironmentDirection(normal: vec3f, sampleCount: u32) -> vec3f {
|
|
20299
|
+
var accumulatedColor = vec3f(0.0);
|
|
20300
|
+
var accumulatedWeight = 0.0;
|
|
20301
|
+
|
|
20302
|
+
for (var sampleIndex = 0u; sampleIndex < sampleCount; sampleIndex++) {
|
|
20303
|
+
let sequence = getEnvironmentHammersley(sampleIndex, sampleCount);
|
|
20304
|
+
var direction: vec3f;
|
|
20305
|
+
var sampleWeight: f32;
|
|
20306
|
+
|
|
20307
|
+
if (pbrEnvironmentFilter.mode == 1) {
|
|
20308
|
+
let azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20309
|
+
let cosine = sqrt(1.0 - sequence.y);
|
|
20310
|
+
let sine = sqrt(sequence.y);
|
|
20311
|
+
direction = normalize(
|
|
20312
|
+
getEnvironmentTangentBasis(normal) *
|
|
20313
|
+
vec3f(cos(azimuth) * sine, sin(azimuth) * sine, cosine)
|
|
20314
|
+
);
|
|
20315
|
+
sampleWeight = 1.0;
|
|
20316
|
+
} else {
|
|
20317
|
+
let halfVector = importanceSampleEnvironment(sequence, normal, pbrEnvironmentFilter.roughness);
|
|
20318
|
+
direction = normalize(2.0 * dot(normal, halfVector) * halfVector - normal);
|
|
20319
|
+
sampleWeight = max(dot(normal, direction), 0.0);
|
|
20320
|
+
}
|
|
20321
|
+
|
|
20322
|
+
accumulatedColor += sampleEnvironmentDirection(direction) * sampleWeight;
|
|
20323
|
+
accumulatedWeight += sampleWeight;
|
|
20324
|
+
}
|
|
20325
|
+
return accumulatedColor / max(accumulatedWeight, 0.0001);
|
|
20326
|
+
}
|
|
20327
|
+
|
|
20328
|
+
@fragment
|
|
20329
|
+
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
20330
|
+
// ClipSpace UVs increase upward; WebGPU texture rows increase downward.
|
|
20331
|
+
let textureCoordinate = vec2f(inputs.uv.x, 1.0 - inputs.uv.y);
|
|
20332
|
+
let sampleCount = u32(max(pbrEnvironmentFilter.sampleCount, 1));
|
|
20333
|
+
if (pbrEnvironmentFilter.mode == 2) {
|
|
20334
|
+
return vec4f(integrateEnvironmentBRDF(textureCoordinate, sampleCount), 0.0, 1.0);
|
|
20335
|
+
}
|
|
20336
|
+
|
|
20337
|
+
let direction = getEnvironmentFaceDirection(pbrEnvironmentFilter.face, textureCoordinate);
|
|
20338
|
+
return vec4f(integrateEnvironmentDirection(direction, sampleCount), 1.0);
|
|
20339
|
+
}
|
|
20340
|
+
`
|
|
20341
|
+
);
|
|
20342
|
+
|
|
20343
|
+
// src/modules/lighting/shadow/shadow-glsl.ts
|
|
20344
|
+
var SHADOW_GLSL = (
|
|
20345
|
+
/* glsl */
|
|
20346
|
+
`
|
|
20347
|
+
precision highp sampler2DArray;
|
|
20348
|
+
struct DirectionalShadowLightUniform {
|
|
20349
|
+
vec3 direction;
|
|
20350
|
+
float strength;
|
|
20351
|
+
float normalBias;
|
|
20352
|
+
float sourceAngularRadius;
|
|
20353
|
+
float cascadeBlendFraction;
|
|
20354
|
+
float farFadeFraction;
|
|
20355
|
+
float shadowDistance;
|
|
20356
|
+
};
|
|
20357
|
+
struct SpotShadowLightUniform {
|
|
20358
|
+
vec3 position;
|
|
20359
|
+
float range;
|
|
20360
|
+
vec3 direction;
|
|
20361
|
+
float outerConeCos;
|
|
20362
|
+
float sourceRadius;
|
|
20363
|
+
float normalBias;
|
|
20364
|
+
float strength;
|
|
20365
|
+
float nearPlane;
|
|
20366
|
+
};
|
|
20367
|
+
struct PointShadowLightUniform {
|
|
20368
|
+
vec3 position;
|
|
20369
|
+
float range;
|
|
20370
|
+
float sourceRadius;
|
|
20371
|
+
float normalBias;
|
|
20372
|
+
float strength;
|
|
20373
|
+
float nearPlane;
|
|
20374
|
+
};
|
|
20375
|
+
layout(std140) uniform shadowUniforms {
|
|
20376
|
+
int directionalLightCount;
|
|
20377
|
+
int spotLightCount;
|
|
20378
|
+
int pointLightCount;
|
|
20379
|
+
int cascadeCount;
|
|
20380
|
+
int blockerSampleCount;
|
|
20381
|
+
int filterSampleCount;
|
|
20382
|
+
vec4 cascadeSplits;
|
|
20383
|
+
mat4 directionalViewProjectionMatrices[4];
|
|
20384
|
+
mat4 spotViewProjectionMatrices[4];
|
|
20385
|
+
mat4 pointViewProjectionMatrices[24];
|
|
20386
|
+
DirectionalShadowLightUniform directionalLights[1];
|
|
20387
|
+
SpotShadowLightUniform spotLights[4];
|
|
20388
|
+
PointShadowLightUniform pointLights[4];
|
|
20389
|
+
} shadow;
|
|
20390
|
+
uniform sampler2DArray directionalShadowTexture;
|
|
20391
|
+
uniform sampler2DArray spotShadowTexture;
|
|
20392
|
+
uniform sampler2DArray pointShadowTexture;
|
|
20393
|
+
const float SHADOW_PI = 3.141592653589793;
|
|
20394
|
+
float shadow_hash(vec3 position) {
|
|
20395
|
+
return fract(sin(dot(position, vec3(12.9898, 78.233, 37.719))) * 43758.5453);
|
|
20396
|
+
}
|
|
20397
|
+
vec2 shadow_diskSample(int index, int count, float rotation) {
|
|
20398
|
+
float fraction = (float(index) + 0.5) / max(float(count), 1.0);
|
|
20399
|
+
float angle = float(index) * 2.39996323 + rotation;
|
|
20400
|
+
return sqrt(fraction) * vec2(cos(angle), sin(angle));
|
|
20401
|
+
}
|
|
20402
|
+
vec3 shadow_project(mat4 matrix, vec3 worldPosition) {
|
|
20403
|
+
vec4 clip = matrix * vec4(worldPosition, 1.0);
|
|
20404
|
+
vec3 projected = clip.xyz / max(abs(clip.w), 0.00001);
|
|
20405
|
+
// Shared matrices retain [0,1] depth; WebGL texture rows start at the bottom.
|
|
20406
|
+
return vec3(projected.xy * 0.5 + 0.5, projected.z);
|
|
20407
|
+
}
|
|
20408
|
+
bool shadow_validProjection(vec3 projected) {
|
|
20409
|
+
return all(greaterThanEqual(projected, vec3(0.0))) && all(lessThanEqual(projected, vec3(1.0)));
|
|
20410
|
+
}
|
|
20411
|
+
// Bilinear interpolation of four depth comparisons matches a hardware 2x2 PCF lookup.
|
|
20412
|
+
float shadow_compare(sampler2DArray shadowMap, vec2 coordinate, int layer, float reference) {
|
|
20413
|
+
ivec2 dimensions = textureSize(shadowMap, 0).xy;
|
|
20414
|
+
vec2 position = coordinate * vec2(dimensions) - 0.5;
|
|
20415
|
+
ivec2 base = ivec2(floor(position));
|
|
20416
|
+
vec2 fraction = fract(position);
|
|
20417
|
+
ivec2 maximum = dimensions - 1;
|
|
20418
|
+
float lowerLeft = step(reference, texelFetch(shadowMap, ivec3(clamp(base, ivec2(0), maximum), layer), 0).r);
|
|
20419
|
+
float lowerRight = step(reference, texelFetch(shadowMap, ivec3(clamp(base + ivec2(1,0), ivec2(0), maximum), layer), 0).r);
|
|
20420
|
+
float upperLeft = step(reference, texelFetch(shadowMap, ivec3(clamp(base + ivec2(0,1), ivec2(0), maximum), layer), 0).r);
|
|
20421
|
+
float upperRight = step(reference, texelFetch(shadowMap, ivec3(clamp(base + ivec2(1,1), ivec2(0), maximum), layer), 0).r);
|
|
20422
|
+
return mix(mix(lowerLeft, lowerRight, fraction.x), mix(upperLeft, upperRight, fraction.x), fraction.y);
|
|
20423
|
+
}
|
|
20424
|
+
float shadow_arrayPCSS(sampler2DArray shadowMap, int layer, vec3 projected, float searchRadius, float rotation, float penumbraScale) {
|
|
20425
|
+
if (!shadow_validProjection(projected)) return 1.0;
|
|
20426
|
+
float texel = 1.0 / float(textureSize(shadowMap, 0).x);
|
|
20427
|
+
searchRadius = max(texel, searchRadius);
|
|
20428
|
+
float blockerDepth = 0.0;
|
|
20429
|
+
float blockerCount = 0.0;
|
|
20430
|
+
for (int index = 0; index < 24; index++) {
|
|
20431
|
+
if (index >= shadow.blockerSampleCount) break;
|
|
20432
|
+
vec2 coordinate = clamp(projected.xy + shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius, vec2(0.0), vec2(1.0));
|
|
20433
|
+
float depth = textureLod(shadowMap, vec3(coordinate, float(layer)), 0.0).r;
|
|
20434
|
+
if (depth < projected.z) { blockerDepth += depth; blockerCount += 1.0; }
|
|
20435
|
+
}
|
|
20436
|
+
if (blockerCount == 0.0) return 1.0;
|
|
20437
|
+
float averageBlocker = blockerDepth / blockerCount;
|
|
20438
|
+
float penumbra = clamp((projected.z - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20439
|
+
float radius = max(texel, searchRadius * (1.0 + penumbra * penumbraScale));
|
|
20440
|
+
float visibility = 0.0;
|
|
20441
|
+
for (int index = 0; index < 48; index++) {
|
|
20442
|
+
if (index >= shadow.filterSampleCount) break;
|
|
20443
|
+
vec2 coordinate = clamp(projected.xy + shadow_diskSample(index, shadow.filterSampleCount, rotation) * radius, vec2(0.0), vec2(1.0));
|
|
20444
|
+
visibility += shadow_compare(shadowMap, coordinate, layer, projected.z);
|
|
20445
|
+
}
|
|
20446
|
+
return visibility / max(float(shadow.filterSampleCount), 1.0);
|
|
20447
|
+
}
|
|
20448
|
+
int shadow_directionalCascadeIndex(float viewDepth) {
|
|
20449
|
+
int cascadeIndex = 0;
|
|
20450
|
+
for (int index = 0; index < 4; index++) {
|
|
20451
|
+
if (index >= shadow.cascadeCount) break;
|
|
20452
|
+
cascadeIndex = index;
|
|
20453
|
+
if (viewDepth <= shadow.cascadeSplits[index]) break;
|
|
20454
|
+
}
|
|
20455
|
+
return cascadeIndex;
|
|
20456
|
+
}
|
|
20457
|
+
int shadow_getDirectionalCascadeIndex(float viewDepth) {
|
|
20458
|
+
return shadow.directionalLightCount == 0 ? -1 : shadow_directionalCascadeIndex(viewDepth);
|
|
20459
|
+
}
|
|
20460
|
+
float shadow_directionalPCSS(int cascadeIndex, vec3 worldPosition, float viewDepth) {
|
|
20461
|
+
DirectionalShadowLightUniform light = shadow.directionalLights[0];
|
|
20462
|
+
return shadow_arrayPCSS(directionalShadowTexture, cascadeIndex,
|
|
20463
|
+
shadow_project(shadow.directionalViewProjectionMatrices[cascadeIndex], worldPosition),
|
|
20464
|
+
light.sourceAngularRadius * viewDepth / max(light.shadowDistance, 0.001),
|
|
20465
|
+
shadow_hash(worldPosition) * 2.0 * SHADOW_PI, 18.0);
|
|
20466
|
+
}
|
|
20467
|
+
float shadow_getDirectionalFactor(vec3 worldPosition, vec3 worldNormal, float viewDepth) {
|
|
20468
|
+
if (shadow.directionalLightCount == 0 || viewDepth <= 0.0) return 1.0;
|
|
20469
|
+
DirectionalShadowLightUniform light = shadow.directionalLights[0];
|
|
20470
|
+
if (viewDepth >= light.shadowDistance) return 1.0;
|
|
20471
|
+
vec3 position = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20472
|
+
int cascadeIndex = shadow_directionalCascadeIndex(viewDepth);
|
|
20473
|
+
float visibility = shadow_directionalPCSS(cascadeIndex, position, viewDepth);
|
|
20474
|
+
if (cascadeIndex + 1 < shadow.cascadeCount) {
|
|
20475
|
+
float cascadeStart = cascadeIndex > 0 ? shadow.cascadeSplits[cascadeIndex - 1] : 0.0;
|
|
20476
|
+
float cascadeEnd = shadow.cascadeSplits[cascadeIndex];
|
|
20477
|
+
float blendWidth = max((cascadeEnd - cascadeStart) * light.cascadeBlendFraction, 0.0001);
|
|
20478
|
+
float blend = smoothstep(cascadeEnd - blendWidth, cascadeEnd, viewDepth);
|
|
20479
|
+
if (blend > 0.0) visibility = mix(visibility, shadow_directionalPCSS(cascadeIndex + 1, position, viewDepth), blend);
|
|
20480
|
+
}
|
|
20481
|
+
float fadeWidth = max(light.shadowDistance * light.farFadeFraction, 0.0001);
|
|
20482
|
+
visibility = mix(visibility, 1.0, smoothstep(light.shadowDistance - fadeWidth, light.shadowDistance, viewDepth));
|
|
20483
|
+
return mix(1.0, visibility, light.strength);
|
|
20484
|
+
}
|
|
20485
|
+
float shadow_getSpotFactor(int lightIndex, vec3 worldPosition, vec3 worldNormal) {
|
|
20486
|
+
if (lightIndex < 0 || lightIndex >= shadow.spotLightCount) return 1.0;
|
|
20487
|
+
SpotShadowLightUniform light = shadow.spotLights[lightIndex];
|
|
20488
|
+
vec3 fromLight = worldPosition - light.position;
|
|
20489
|
+
float distanceToLight = length(fromLight);
|
|
20490
|
+
if (distanceToLight >= light.range || dot(normalize(fromLight), normalize(light.direction)) < light.outerConeCos) return 1.0;
|
|
20491
|
+
vec3 position = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20492
|
+
float visibility = shadow_arrayPCSS(spotShadowTexture, lightIndex,
|
|
20493
|
+
shadow_project(shadow.spotViewProjectionMatrices[lightIndex], position),
|
|
20494
|
+
light.sourceRadius / max(distanceToLight, 0.001) * 0.5,
|
|
20495
|
+
shadow_hash(worldPosition) * 2.0 * SHADOW_PI, 16.0);
|
|
20496
|
+
return mix(1.0, visibility, light.strength);
|
|
20497
|
+
}
|
|
20498
|
+
float shadow_pointReferenceDepth(float majorDistance, float nearPlane, float farPlane) {
|
|
20499
|
+
return farPlane / (farPlane - nearPlane) - (farPlane * nearPlane) / ((farPlane - nearPlane) * majorDistance);
|
|
20500
|
+
}
|
|
20501
|
+
vec3 shadow_pointCoordinate(int lightIndex, vec3 direction) {
|
|
20502
|
+
vec3 magnitude = abs(direction);
|
|
20503
|
+
int face = magnitude.x >= magnitude.y && magnitude.x >= magnitude.z ? (direction.x >= 0.0 ? 0 : 1)
|
|
20504
|
+
: magnitude.y >= magnitude.z ? (direction.y >= 0.0 ? 2 : 3) : (direction.z >= 0.0 ? 4 : 5);
|
|
20505
|
+
PointShadowLightUniform light = shadow.pointLights[lightIndex];
|
|
20506
|
+
vec3 projected = shadow_project(shadow.pointViewProjectionMatrices[lightIndex * 6 + face], light.position + direction * light.range * 0.5);
|
|
20507
|
+
return vec3(projected.xy, float(lightIndex * 6 + face));
|
|
20508
|
+
}
|
|
20509
|
+
float shadow_getPointFactor(int lightIndex, vec3 worldPosition, vec3 worldNormal) {
|
|
20510
|
+
if (lightIndex < 0 || lightIndex >= shadow.pointLightCount) return 1.0;
|
|
20511
|
+
PointShadowLightUniform light = shadow.pointLights[lightIndex];
|
|
20512
|
+
vec3 fromLight = worldPosition + normalize(worldNormal) * light.normalBias - light.position;
|
|
20513
|
+
float distanceToLight = length(fromLight);
|
|
20514
|
+
if (distanceToLight >= light.range || distanceToLight <= light.nearPlane) return 1.0;
|
|
20515
|
+
vec3 direction = normalize(fromLight);
|
|
20516
|
+
float referenceDepth = shadow_pointReferenceDepth(max(max(abs(fromLight.x), abs(fromLight.y)), abs(fromLight.z)), light.nearPlane, light.range);
|
|
20517
|
+
vec3 reference = abs(direction.y) > 0.99 ? vec3(0,0,1) : vec3(0,1,0);
|
|
20518
|
+
vec3 tangent = normalize(cross(direction, reference));
|
|
20519
|
+
vec3 bitangent = normalize(cross(direction, tangent));
|
|
20520
|
+
float searchRadius = light.sourceRadius / max(distanceToLight, 0.001);
|
|
20521
|
+
float rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20522
|
+
float blockerDepth = 0.0;
|
|
20523
|
+
float blockerCount = 0.0;
|
|
20524
|
+
for (int index = 0; index < 24; index++) {
|
|
20525
|
+
if (index >= shadow.blockerSampleCount) break;
|
|
20526
|
+
vec2 disk = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20527
|
+
vec3 coordinate = shadow_pointCoordinate(lightIndex, normalize(direction + tangent * disk.x + bitangent * disk.y));
|
|
20528
|
+
float depth = textureLod(pointShadowTexture, coordinate, 0.0).r;
|
|
20529
|
+
if (depth < referenceDepth) { blockerDepth += depth; blockerCount += 1.0; }
|
|
20530
|
+
}
|
|
20531
|
+
if (blockerCount == 0.0) return 1.0;
|
|
20532
|
+
float averageBlocker = blockerDepth / blockerCount;
|
|
20533
|
+
float penumbra = clamp((referenceDepth - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20534
|
+
float radius = searchRadius * (1.0 + penumbra * 12.0);
|
|
20535
|
+
float visibility = 0.0;
|
|
20536
|
+
for (int index = 0; index < 48; index++) {
|
|
20537
|
+
if (index >= shadow.filterSampleCount) break;
|
|
20538
|
+
vec2 disk = shadow_diskSample(index, shadow.filterSampleCount, rotation) * radius;
|
|
20539
|
+
vec3 coordinate = shadow_pointCoordinate(lightIndex, normalize(direction + tangent * disk.x + bitangent * disk.y));
|
|
20540
|
+
visibility += shadow_compare(pointShadowTexture, coordinate.xy, int(coordinate.z), referenceDepth);
|
|
20541
|
+
}
|
|
20542
|
+
return mix(1.0, visibility / max(float(shadow.filterSampleCount), 1.0), light.strength);
|
|
20543
|
+
}
|
|
20544
|
+
`
|
|
20545
|
+
);
|
|
20546
|
+
|
|
20547
|
+
// src/modules/lighting/shadow/shadow.ts
|
|
20548
|
+
var MAX_CASCADES = 4;
|
|
20549
|
+
var MAX_SPOT_LIGHTS = 4;
|
|
20550
|
+
var MAX_POINT_LIGHTS = 4;
|
|
20551
|
+
var MAX_POINT_MATRICES = 24;
|
|
20552
|
+
var DIRECTIONAL_LIGHT_UNIFORM_TYPE = {
|
|
20553
|
+
direction: "vec3<f32>",
|
|
20554
|
+
strength: "f32",
|
|
20555
|
+
normalBias: "f32",
|
|
20556
|
+
sourceAngularRadius: "f32",
|
|
20557
|
+
cascadeBlendFraction: "f32",
|
|
20558
|
+
farFadeFraction: "f32",
|
|
20559
|
+
shadowDistance: "f32"
|
|
20560
|
+
};
|
|
20561
|
+
var SPOT_LIGHT_UNIFORM_TYPE = {
|
|
20562
|
+
position: "vec3<f32>",
|
|
20563
|
+
range: "f32",
|
|
20564
|
+
direction: "vec3<f32>",
|
|
20565
|
+
outerConeCos: "f32",
|
|
20566
|
+
sourceRadius: "f32",
|
|
20567
|
+
normalBias: "f32",
|
|
20568
|
+
strength: "f32",
|
|
20569
|
+
nearPlane: "f32"
|
|
20570
|
+
};
|
|
20571
|
+
var POINT_LIGHT_UNIFORM_TYPE = {
|
|
20572
|
+
position: "vec3<f32>",
|
|
20573
|
+
range: "f32",
|
|
20574
|
+
sourceRadius: "f32",
|
|
20575
|
+
normalBias: "f32",
|
|
20576
|
+
strength: "f32",
|
|
20577
|
+
nearPlane: "f32"
|
|
20578
|
+
};
|
|
20579
|
+
var SHADOW_WGSL = (
|
|
20580
|
+
/* wgsl */
|
|
20581
|
+
`const SHADOW_PI: f32 = 3.141592653589793;
|
|
20582
|
+
|
|
20583
|
+
struct DirectionalShadowLightUniform {
|
|
20584
|
+
direction: vec3f,
|
|
20585
|
+
strength: f32,
|
|
20586
|
+
normalBias: f32,
|
|
20587
|
+
sourceAngularRadius: f32,
|
|
20588
|
+
cascadeBlendFraction: f32,
|
|
20589
|
+
farFadeFraction: f32,
|
|
20590
|
+
shadowDistance: f32,
|
|
20591
|
+
};
|
|
20592
|
+
|
|
20593
|
+
struct SpotShadowLightUniform {
|
|
20594
|
+
position: vec3f,
|
|
20595
|
+
range: f32,
|
|
20596
|
+
direction: vec3f,
|
|
20597
|
+
outerConeCos: f32,
|
|
20598
|
+
sourceRadius: f32,
|
|
20599
|
+
normalBias: f32,
|
|
20600
|
+
strength: f32,
|
|
20601
|
+
nearPlane: f32,
|
|
20602
|
+
};
|
|
20603
|
+
|
|
20604
|
+
struct PointShadowLightUniform {
|
|
20605
|
+
position: vec3f,
|
|
20606
|
+
range: f32,
|
|
20607
|
+
sourceRadius: f32,
|
|
20608
|
+
normalBias: f32,
|
|
20609
|
+
strength: f32,
|
|
20610
|
+
nearPlane: f32,
|
|
20611
|
+
};
|
|
20612
|
+
|
|
20613
|
+
struct ShadowUniforms {
|
|
20614
|
+
directionalLightCount: i32,
|
|
20615
|
+
spotLightCount: i32,
|
|
20616
|
+
pointLightCount: i32,
|
|
20617
|
+
cascadeCount: i32,
|
|
20618
|
+
blockerSampleCount: i32,
|
|
20619
|
+
filterSampleCount: i32,
|
|
20620
|
+
cascadeSplits: vec4f,
|
|
20621
|
+
directionalViewProjectionMatrices: array<mat4x4f, 4>,
|
|
20622
|
+
spotViewProjectionMatrices: array<mat4x4f, 4>,
|
|
20623
|
+
pointViewProjectionMatrices: array<mat4x4f, 24>,
|
|
20624
|
+
directionalLights: array<DirectionalShadowLightUniform, 1>,
|
|
20625
|
+
spotLights: array<SpotShadowLightUniform, 4>,
|
|
20626
|
+
pointLights: array<PointShadowLightUniform, 4>,
|
|
20627
|
+
};
|
|
20628
|
+
|
|
20629
|
+
@group(2) @binding(auto) var<uniform> shadow: ShadowUniforms;
|
|
20630
|
+
@group(2) @binding(auto) var directionalShadowTexture: texture_depth_2d_array;
|
|
20631
|
+
@group(2) @binding(auto) var spotShadowTexture: texture_depth_2d_array;
|
|
20632
|
+
@group(2) @binding(auto) var pointShadowTexture: texture_depth_cube_array;
|
|
20633
|
+
@group(2) @binding(auto) var directionalShadowTextureSampler: sampler;
|
|
20634
|
+
@group(2) @binding(auto) var shadowComparisonSampler: sampler_comparison;
|
|
20635
|
+
|
|
20636
|
+
fn shadow_hash(position: vec3f) -> f32 {
|
|
20637
|
+
return fract(sin(dot(position, vec3f(12.9898, 78.233, 37.719))) * 43758.5453);
|
|
20638
|
+
}
|
|
20639
|
+
|
|
20640
|
+
fn shadow_diskSample(index: i32, count: i32, rotation: f32) -> vec2f {
|
|
20641
|
+
let fraction = (f32(index) + 0.5) / max(f32(count), 1.0);
|
|
20642
|
+
let angle = f32(index) * 2.39996323 + rotation;
|
|
20643
|
+
return sqrt(fraction) * vec2f(cos(angle), sin(angle));
|
|
20644
|
+
}
|
|
20645
|
+
|
|
20646
|
+
fn shadow_project(matrix: mat4x4f, worldPosition: vec3f) -> vec3f {
|
|
20647
|
+
let clip = matrix * vec4f(worldPosition, 1.0);
|
|
20648
|
+
let ndc = clip.xyz / max(abs(clip.w), 0.00001);
|
|
20649
|
+
return vec3f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5, ndc.z);
|
|
20650
|
+
}
|
|
20651
|
+
|
|
20652
|
+
fn shadow_validProjection(projected: vec3f) -> bool {
|
|
20653
|
+
return all(projected.xy >= vec2f(0.0)) && all(projected.xy <= vec2f(1.0)) &&
|
|
20654
|
+
projected.z >= 0.0 && projected.z <= 1.0;
|
|
20655
|
+
}
|
|
20656
|
+
|
|
20657
|
+
fn shadow_directionalCascadeIndex(viewDepth: f32) -> i32 {
|
|
20658
|
+
var cascadeIndex = 0;
|
|
20659
|
+
for (var index: i32 = 0; index < 4; index++) {
|
|
20660
|
+
if (index >= shadow.cascadeCount) { break; }
|
|
20661
|
+
cascadeIndex = index;
|
|
20662
|
+
if (viewDepth <= shadow.cascadeSplits[index]) { break; }
|
|
20663
|
+
}
|
|
20664
|
+
return cascadeIndex;
|
|
20665
|
+
}
|
|
20666
|
+
|
|
20667
|
+
fn shadow_getDirectionalCascadeIndex(viewDepth: f32) -> i32 {
|
|
20668
|
+
if (shadow.directionalLightCount == 0) { return -1; }
|
|
20669
|
+
return shadow_directionalCascadeIndex(viewDepth);
|
|
20670
|
+
}
|
|
20671
|
+
|
|
20672
|
+
fn shadow_directionalPCSS(cascadeIndex: i32, worldPosition: vec3f, viewDepth: f32) -> f32 {
|
|
20673
|
+
let projected = shadow_project(shadow.directionalViewProjectionMatrices[cascadeIndex], worldPosition);
|
|
20674
|
+
if (!shadow_validProjection(projected)) { return 1.0; }
|
|
20675
|
+
let dimensions = vec2f(textureDimensions(directionalShadowTexture));
|
|
20676
|
+
let texel = 1.0 / dimensions;
|
|
20677
|
+
let light = shadow.directionalLights[0];
|
|
20678
|
+
let rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20679
|
+
let searchRadius = max(texel.x, light.sourceAngularRadius * viewDepth / max(light.shadowDistance, 0.001));
|
|
20680
|
+
var blockerDepth = 0.0;
|
|
20681
|
+
var blockerCount = 0.0;
|
|
20682
|
+
for (var index: i32 = 0; index < 24; index++) {
|
|
20683
|
+
if (index >= shadow.blockerSampleCount) { break; }
|
|
20684
|
+
let offset = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20685
|
+
let sampleDepth = textureSampleLevel(
|
|
20686
|
+
directionalShadowTexture,
|
|
20687
|
+
directionalShadowTextureSampler,
|
|
20688
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20689
|
+
cascadeIndex,
|
|
20690
|
+
0
|
|
20691
|
+
);
|
|
20692
|
+
if (sampleDepth < projected.z) {
|
|
20693
|
+
blockerDepth += sampleDepth;
|
|
20694
|
+
blockerCount += 1.0;
|
|
20695
|
+
}
|
|
20696
|
+
}
|
|
20697
|
+
if (blockerCount == 0.0) { return 1.0; }
|
|
20698
|
+
let averageBlocker = blockerDepth / blockerCount;
|
|
20699
|
+
let penumbra = clamp((projected.z - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20700
|
+
let filterRadius = max(texel.x, searchRadius * (1.0 + penumbra * 18.0));
|
|
20701
|
+
var visibility = 0.0;
|
|
20702
|
+
for (var index: i32 = 0; index < 48; index++) {
|
|
20703
|
+
if (index >= shadow.filterSampleCount) { break; }
|
|
20704
|
+
let offset = shadow_diskSample(index, shadow.filterSampleCount, rotation) * filterRadius;
|
|
20705
|
+
visibility += textureSampleCompareLevel(
|
|
20706
|
+
directionalShadowTexture,
|
|
20707
|
+
shadowComparisonSampler,
|
|
20708
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20709
|
+
cascadeIndex,
|
|
20710
|
+
projected.z
|
|
20711
|
+
);
|
|
20712
|
+
}
|
|
20713
|
+
return visibility / max(f32(shadow.filterSampleCount), 1.0);
|
|
20714
|
+
}
|
|
20715
|
+
|
|
20716
|
+
fn shadow_getDirectionalFactor(worldPosition: vec3f, worldNormal: vec3f, viewDepth: f32) -> f32 {
|
|
20717
|
+
if (shadow.directionalLightCount == 0 || viewDepth <= 0.0) { return 1.0; }
|
|
20718
|
+
let light = shadow.directionalLights[0];
|
|
20719
|
+
if (viewDepth >= light.shadowDistance) { return 1.0; }
|
|
20720
|
+
let biasedPosition = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20721
|
+
let cascadeIndex = shadow_directionalCascadeIndex(viewDepth);
|
|
20722
|
+
var visibility = shadow_directionalPCSS(cascadeIndex, biasedPosition, viewDepth);
|
|
20723
|
+
if (cascadeIndex + 1 < shadow.cascadeCount) {
|
|
20724
|
+
var cascadeStart = 0.0;
|
|
20725
|
+
if (cascadeIndex > 0) { cascadeStart = shadow.cascadeSplits[cascadeIndex - 1]; }
|
|
20726
|
+
let cascadeEnd = shadow.cascadeSplits[cascadeIndex];
|
|
20727
|
+
let blendWidth = max((cascadeEnd - cascadeStart) * light.cascadeBlendFraction, 0.0001);
|
|
20728
|
+
let blend = smoothstep(cascadeEnd - blendWidth, cascadeEnd, viewDepth);
|
|
20729
|
+
if (blend > 0.0) {
|
|
20730
|
+
visibility = mix(
|
|
20731
|
+
visibility,
|
|
20732
|
+
shadow_directionalPCSS(cascadeIndex + 1, biasedPosition, viewDepth),
|
|
20733
|
+
blend
|
|
20734
|
+
);
|
|
20735
|
+
}
|
|
20736
|
+
}
|
|
20737
|
+
let fadeWidth = max(light.shadowDistance * light.farFadeFraction, 0.0001);
|
|
20738
|
+
let farFade = smoothstep(light.shadowDistance - fadeWidth, light.shadowDistance, viewDepth);
|
|
20739
|
+
visibility = mix(visibility, 1.0, farFade);
|
|
20740
|
+
return mix(1.0, visibility, light.strength);
|
|
20741
|
+
}
|
|
20742
|
+
|
|
20743
|
+
fn shadow_spotPCSS(lightIndex: i32, worldPosition: vec3f) -> f32 {
|
|
20744
|
+
let projected = shadow_project(shadow.spotViewProjectionMatrices[lightIndex], worldPosition);
|
|
20745
|
+
if (!shadow_validProjection(projected)) { return 1.0; }
|
|
20746
|
+
let light = shadow.spotLights[lightIndex];
|
|
20747
|
+
let dimensions = vec2f(textureDimensions(spotShadowTexture));
|
|
20748
|
+
let texel = 1.0 / dimensions;
|
|
20749
|
+
let distanceToLight = length(worldPosition - light.position);
|
|
20750
|
+
let searchRadius = max(texel.x, light.sourceRadius / max(distanceToLight, 0.001) * 0.5);
|
|
20751
|
+
let rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20752
|
+
var blockerDepth = 0.0;
|
|
20753
|
+
var blockerCount = 0.0;
|
|
20754
|
+
for (var index: i32 = 0; index < 24; index++) {
|
|
20755
|
+
if (index >= shadow.blockerSampleCount) { break; }
|
|
20756
|
+
let offset = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20757
|
+
let sampleDepth = textureSampleLevel(
|
|
20758
|
+
spotShadowTexture,
|
|
20759
|
+
directionalShadowTextureSampler,
|
|
20760
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20761
|
+
lightIndex,
|
|
20762
|
+
0
|
|
20763
|
+
);
|
|
20764
|
+
if (sampleDepth < projected.z) { blockerDepth += sampleDepth; blockerCount += 1.0; }
|
|
20765
|
+
}
|
|
20766
|
+
if (blockerCount == 0.0) { return 1.0; }
|
|
20767
|
+
let averageBlocker = blockerDepth / blockerCount;
|
|
20768
|
+
let penumbra = clamp((projected.z - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20769
|
+
let filterRadius = max(texel.x, searchRadius * (1.0 + penumbra * 16.0));
|
|
20770
|
+
var visibility = 0.0;
|
|
20771
|
+
for (var index: i32 = 0; index < 48; index++) {
|
|
20772
|
+
if (index >= shadow.filterSampleCount) { break; }
|
|
20773
|
+
let offset = shadow_diskSample(index, shadow.filterSampleCount, rotation) * filterRadius;
|
|
20774
|
+
visibility += textureSampleCompareLevel(
|
|
20775
|
+
spotShadowTexture,
|
|
20776
|
+
shadowComparisonSampler,
|
|
20777
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20778
|
+
lightIndex,
|
|
20779
|
+
projected.z
|
|
20780
|
+
);
|
|
20781
|
+
}
|
|
20782
|
+
return visibility / max(f32(shadow.filterSampleCount), 1.0);
|
|
20783
|
+
}
|
|
20784
|
+
|
|
20785
|
+
fn shadow_getSpotFactor(lightIndex: i32, worldPosition: vec3f, worldNormal: vec3f) -> f32 {
|
|
20786
|
+
if (lightIndex < 0 || lightIndex >= shadow.spotLightCount) { return 1.0; }
|
|
20787
|
+
let light = shadow.spotLights[lightIndex];
|
|
20788
|
+
let fromLight = worldPosition - light.position;
|
|
20789
|
+
let distanceToLight = length(fromLight);
|
|
20790
|
+
let coneCos = dot(normalize(fromLight), normalize(light.direction));
|
|
20791
|
+
if (distanceToLight >= light.range || coneCos < light.outerConeCos) { return 1.0; }
|
|
20792
|
+
let biasedPosition = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20793
|
+
return mix(1.0, shadow_spotPCSS(lightIndex, biasedPosition), light.strength);
|
|
20794
|
+
}
|
|
20795
|
+
|
|
20796
|
+
fn shadow_pointReferenceDepth(majorDistance: f32, nearPlane: f32, farPlane: f32) -> f32 {
|
|
20797
|
+
// Match the cube-face projection and stored WebGPU depth in [0, 1].
|
|
20798
|
+
return farPlane / (farPlane - nearPlane) -
|
|
20799
|
+
(farPlane * nearPlane) / ((farPlane - nearPlane) * majorDistance);
|
|
20800
|
+
}
|
|
20801
|
+
|
|
20802
|
+
fn shadow_pointBasis(direction: vec3f) -> mat2x3f {
|
|
20803
|
+
let reference = select(vec3f(0.0, 1.0, 0.0), vec3f(0.0, 0.0, 1.0), abs(direction.y) > 0.99);
|
|
20804
|
+
let tangent = normalize(cross(direction, reference));
|
|
20805
|
+
return mat2x3f(tangent, normalize(cross(direction, tangent)));
|
|
20806
|
+
}
|
|
20807
|
+
|
|
20808
|
+
fn shadow_getPointFactor(lightIndex: i32, worldPosition: vec3f, worldNormal: vec3f) -> f32 {
|
|
20809
|
+
if (lightIndex < 0 || lightIndex >= shadow.pointLightCount) { return 1.0; }
|
|
20810
|
+
let light = shadow.pointLights[lightIndex];
|
|
20811
|
+
let biasedPosition = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20812
|
+
let fromLight = biasedPosition - light.position;
|
|
20813
|
+
let distanceToLight = length(fromLight);
|
|
20814
|
+
if (distanceToLight >= light.range || distanceToLight <= light.nearPlane) { return 1.0; }
|
|
20815
|
+
let direction = normalize(fromLight);
|
|
20816
|
+
let majorDistance = max(max(abs(fromLight.x), abs(fromLight.y)), abs(fromLight.z));
|
|
20817
|
+
let referenceDepth = shadow_pointReferenceDepth(majorDistance, light.nearPlane, light.range);
|
|
20818
|
+
let searchRadius = light.sourceRadius / max(distanceToLight, 0.001);
|
|
20819
|
+
let rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20820
|
+
let basis = shadow_pointBasis(direction);
|
|
20821
|
+
var blockerDepth = 0.0;
|
|
20822
|
+
var blockerCount = 0.0;
|
|
20823
|
+
for (var index: i32 = 0; index < 24; index++) {
|
|
20824
|
+
if (index >= shadow.blockerSampleCount) { break; }
|
|
20825
|
+
let disk = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20826
|
+
let sampleDirection = normalize(direction + basis[0] * disk.x + basis[1] * disk.y);
|
|
20827
|
+
let sampleDepth = textureSampleLevel(
|
|
20828
|
+
pointShadowTexture,
|
|
20829
|
+
directionalShadowTextureSampler,
|
|
20830
|
+
sampleDirection,
|
|
20831
|
+
lightIndex,
|
|
20832
|
+
0
|
|
20833
|
+
);
|
|
20834
|
+
if (sampleDepth < referenceDepth) { blockerDepth += sampleDepth; blockerCount += 1.0; }
|
|
20835
|
+
}
|
|
20836
|
+
if (blockerCount == 0.0) { return 1.0; }
|
|
20837
|
+
let averageBlocker = blockerDepth / blockerCount;
|
|
20838
|
+
let penumbra = clamp((referenceDepth - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20839
|
+
let filterRadius = searchRadius * (1.0 + penumbra * 12.0);
|
|
20840
|
+
var visibility = 0.0;
|
|
20841
|
+
for (var index: i32 = 0; index < 48; index++) {
|
|
20842
|
+
if (index >= shadow.filterSampleCount) { break; }
|
|
20843
|
+
let disk = shadow_diskSample(index, shadow.filterSampleCount, rotation) * filterRadius;
|
|
20844
|
+
let sampleDirection = normalize(direction + basis[0] * disk.x + basis[1] * disk.y);
|
|
20845
|
+
visibility += textureSampleCompareLevel(
|
|
20846
|
+
pointShadowTexture,
|
|
20847
|
+
shadowComparisonSampler,
|
|
20848
|
+
sampleDirection,
|
|
20849
|
+
lightIndex,
|
|
20850
|
+
referenceDepth
|
|
20851
|
+
);
|
|
20852
|
+
}
|
|
20853
|
+
visibility /= max(f32(shadow.filterSampleCount), 1.0);
|
|
20854
|
+
return mix(1.0, visibility, light.strength);
|
|
20855
|
+
}
|
|
20856
|
+
`
|
|
20857
|
+
);
|
|
20858
|
+
var shadow = {
|
|
20859
|
+
name: "shadow",
|
|
20860
|
+
source: SHADOW_WGSL,
|
|
20861
|
+
fs: SHADOW_GLSL,
|
|
20862
|
+
props: {},
|
|
20863
|
+
uniforms: {},
|
|
20864
|
+
bindings: {},
|
|
20865
|
+
uniformTypes: {
|
|
20866
|
+
directionalLightCount: "i32",
|
|
20867
|
+
spotLightCount: "i32",
|
|
20868
|
+
pointLightCount: "i32",
|
|
20869
|
+
cascadeCount: "i32",
|
|
20870
|
+
blockerSampleCount: "i32",
|
|
20871
|
+
filterSampleCount: "i32",
|
|
20872
|
+
cascadeSplits: "vec4<f32>",
|
|
20873
|
+
directionalViewProjectionMatrices: ["mat4x4<f32>", MAX_CASCADES],
|
|
20874
|
+
spotViewProjectionMatrices: ["mat4x4<f32>", MAX_SPOT_LIGHTS],
|
|
20875
|
+
pointViewProjectionMatrices: ["mat4x4<f32>", MAX_POINT_MATRICES],
|
|
20876
|
+
directionalLights: [DIRECTIONAL_LIGHT_UNIFORM_TYPE, 1],
|
|
20877
|
+
spotLights: [SPOT_LIGHT_UNIFORM_TYPE, MAX_SPOT_LIGHTS],
|
|
20878
|
+
pointLights: [POINT_LIGHT_UNIFORM_TYPE, MAX_POINT_LIGHTS]
|
|
20879
|
+
},
|
|
20880
|
+
bindingLayout: [
|
|
20881
|
+
{ name: "shadow", group: 2 },
|
|
20882
|
+
{ name: "directionalShadowTexture", group: 2 },
|
|
20883
|
+
{ name: "spotShadowTexture", group: 2 },
|
|
20884
|
+
{ name: "pointShadowTexture", group: 2 },
|
|
20885
|
+
{ name: "shadowComparisonSampler", group: 2 }
|
|
20886
|
+
],
|
|
20887
|
+
getUniforms(props) {
|
|
20888
|
+
if (!props.directionalLights || !props.spotLights || !props.pointLights || !props.cascadeSplits || !props.directionalViewProjectionMatrices || !props.spotViewProjectionMatrices || !props.pointViewProjectionMatrices || !props.directionalShadowTexture || !props.spotShadowTexture || !props.pointShadowTexture || !props.nonFilteringSampler || !props.comparisonSampler) {
|
|
20889
|
+
return {};
|
|
20890
|
+
}
|
|
20891
|
+
return {
|
|
20892
|
+
directionalLightCount: props.directionalLights.length,
|
|
20893
|
+
spotLightCount: props.spotLights.length,
|
|
20894
|
+
pointLightCount: props.pointLights.length,
|
|
20895
|
+
cascadeCount: props.cascadeCount,
|
|
20896
|
+
blockerSampleCount: props.blockerSampleCount,
|
|
20897
|
+
filterSampleCount: props.filterSampleCount,
|
|
20898
|
+
cascadeSplits: props.cascadeSplits,
|
|
20899
|
+
directionalViewProjectionMatrices: props.directionalViewProjectionMatrices,
|
|
20900
|
+
spotViewProjectionMatrices: props.spotViewProjectionMatrices,
|
|
20901
|
+
pointViewProjectionMatrices: props.pointViewProjectionMatrices,
|
|
20902
|
+
directionalLights: padDirectionalLights(props.directionalLights),
|
|
20903
|
+
spotLights: padSpotLights(props.spotLights),
|
|
20904
|
+
pointLights: padPointLights(props.pointLights),
|
|
20905
|
+
directionalShadowTexture: props.directionalShadowTexture,
|
|
20906
|
+
spotShadowTexture: props.spotShadowTexture,
|
|
20907
|
+
pointShadowTexture: props.pointShadowTexture,
|
|
20908
|
+
...props.directionalShadowTexture.device.type === "webgpu" ? { shadowComparisonSampler: props.comparisonSampler } : {}
|
|
20909
|
+
};
|
|
20910
|
+
}
|
|
20911
|
+
};
|
|
20912
|
+
function padDirectionalLights(lights) {
|
|
20913
|
+
const light = lights[0];
|
|
20914
|
+
return [
|
|
20915
|
+
light ? {
|
|
20916
|
+
direction: light.direction,
|
|
20917
|
+
strength: light.strength ?? 1,
|
|
20918
|
+
normalBias: light.normalBias ?? 0.04,
|
|
20919
|
+
sourceAngularRadius: light.sourceAngularRadius ?? 465e-5,
|
|
20920
|
+
cascadeBlendFraction: light.cascadeBlendFraction ?? 0.1,
|
|
20921
|
+
farFadeFraction: light.farFadeFraction ?? 0.1,
|
|
20922
|
+
shadowDistance: light.shadowDistance ?? 1
|
|
20923
|
+
} : {
|
|
20924
|
+
direction: [0, 1, 0],
|
|
20925
|
+
strength: 0,
|
|
20926
|
+
normalBias: 0,
|
|
20927
|
+
sourceAngularRadius: 0,
|
|
20928
|
+
cascadeBlendFraction: 0,
|
|
20929
|
+
farFadeFraction: 0,
|
|
20930
|
+
shadowDistance: 1
|
|
20931
|
+
}
|
|
20932
|
+
];
|
|
20933
|
+
}
|
|
20934
|
+
function padSpotLights(lights) {
|
|
20935
|
+
return padArray(
|
|
20936
|
+
lights.map((light) => ({
|
|
20937
|
+
position: light.position,
|
|
20938
|
+
range: light.range,
|
|
20939
|
+
direction: light.direction,
|
|
20940
|
+
outerConeCos: Math.cos(light.outerConeAngle),
|
|
20941
|
+
sourceRadius: light.sourceRadius ?? 0.2,
|
|
20942
|
+
normalBias: light.normalBias ?? 0.025,
|
|
20943
|
+
strength: light.strength ?? 1,
|
|
20944
|
+
nearPlane: light.nearPlane ?? 0.1
|
|
20945
|
+
})),
|
|
20946
|
+
MAX_SPOT_LIGHTS,
|
|
20947
|
+
{
|
|
20948
|
+
position: [0, 0, 0],
|
|
20949
|
+
range: 1,
|
|
20950
|
+
direction: [0, -1, 0],
|
|
20951
|
+
outerConeCos: 1,
|
|
20952
|
+
sourceRadius: 0,
|
|
20953
|
+
normalBias: 0,
|
|
20954
|
+
strength: 0,
|
|
20955
|
+
nearPlane: 0.1
|
|
20956
|
+
}
|
|
20957
|
+
);
|
|
20958
|
+
}
|
|
20959
|
+
function padPointLights(lights) {
|
|
20960
|
+
return padArray(
|
|
20961
|
+
lights.map((light) => ({
|
|
20962
|
+
position: light.position,
|
|
20963
|
+
range: light.range,
|
|
20964
|
+
sourceRadius: light.sourceRadius ?? 0.2,
|
|
20965
|
+
normalBias: light.normalBias ?? 0.025,
|
|
20966
|
+
strength: light.strength ?? 1,
|
|
20967
|
+
nearPlane: light.nearPlane ?? 0.1
|
|
20968
|
+
})),
|
|
20969
|
+
MAX_POINT_LIGHTS,
|
|
20970
|
+
{
|
|
20971
|
+
position: [0, 0, 0],
|
|
20972
|
+
range: 1,
|
|
20973
|
+
sourceRadius: 0,
|
|
20974
|
+
normalBias: 0,
|
|
20975
|
+
strength: 0,
|
|
20976
|
+
nearPlane: 0.1
|
|
20977
|
+
}
|
|
20978
|
+
);
|
|
20979
|
+
}
|
|
20980
|
+
function padArray(values, length, fallback) {
|
|
20981
|
+
const result = values.slice(0, length);
|
|
20982
|
+
while (result.length < length) {
|
|
20983
|
+
result.push(fallback);
|
|
20984
|
+
}
|
|
20985
|
+
return result;
|
|
20986
|
+
}
|
|
20987
|
+
|
|
20988
|
+
// src/modules/lighting/pbr-shadow/pbr-shadow.ts
|
|
20989
|
+
var pbrShadow = {
|
|
20990
|
+
name: "pbrShadow",
|
|
20991
|
+
dependencies: [pbrMaterial, shadow],
|
|
20992
|
+
bindingLayout: [{ name: "pbrShadow", group: 0 }],
|
|
20993
|
+
uniformTypes: { viewMatrix: "mat4x4<f32>", enabled: "i32" },
|
|
20994
|
+
defaultUniforms: {
|
|
20995
|
+
viewMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
|
|
20996
|
+
enabled: 1
|
|
20997
|
+
},
|
|
20998
|
+
getUniforms(properties = {}) {
|
|
20999
|
+
return {
|
|
21000
|
+
...properties.viewMatrix ? { viewMatrix: properties.viewMatrix } : {},
|
|
21001
|
+
...properties.enabled === void 0 ? {} : { enabled: Number(properties.enabled) }
|
|
21002
|
+
};
|
|
21003
|
+
},
|
|
21004
|
+
source: (
|
|
21005
|
+
/* wgsl */
|
|
21006
|
+
`
|
|
21007
|
+
struct PBRShadowUniforms {
|
|
21008
|
+
viewMatrix: mat4x4f,
|
|
21009
|
+
enabled: i32,
|
|
21010
|
+
};
|
|
21011
|
+
@group(0) @binding(auto) var<uniform> pbrShadow: PBRShadowUniforms;
|
|
21012
|
+
fn pbrShadow_filterColorWithDirectionalContact(vertexColor: vec4f, worldPosition: vec3f, worldNormal: vec3f, contactVisibility: f32) -> vec4f {
|
|
21013
|
+
var directionalVisibility = 1.0;
|
|
21014
|
+
var pointVisibility = vec4f(1.0);
|
|
21015
|
+
var spotVisibility = vec4f(1.0);
|
|
21016
|
+
if (pbrShadow.enabled != 0) {
|
|
21017
|
+
let normal = normalize(worldNormal);
|
|
21018
|
+
let viewDepth = -(pbrShadow.viewMatrix * vec4f(worldPosition, 1.0)).z;
|
|
21019
|
+
directionalVisibility = shadow_getDirectionalFactor(worldPosition, normal, viewDepth);
|
|
21020
|
+
for (var index = 0; index < 4; index++) {
|
|
21021
|
+
pointVisibility[index] = shadow_getPointFactor(index, worldPosition, normal);
|
|
21022
|
+
spotVisibility[index] = shadow_getSpotFactor(index, worldPosition, normal);
|
|
21023
|
+
}
|
|
21024
|
+
}
|
|
21025
|
+
return pbr_filterColorWithShadows(vertexColor, min(directionalVisibility, contactVisibility), pointVisibility, spotVisibility);
|
|
21026
|
+
}
|
|
21027
|
+
fn pbrShadow_filterColor(vertexColor: vec4f, worldPosition: vec3f, worldNormal: vec3f) -> vec4f {
|
|
21028
|
+
return pbrShadow_filterColorWithDirectionalContact(vertexColor, worldPosition, worldNormal, 1.0);
|
|
21029
|
+
}`
|
|
21030
|
+
),
|
|
21031
|
+
fs: (
|
|
21032
|
+
/* glsl */
|
|
21033
|
+
`
|
|
21034
|
+
layout(std140) uniform pbrShadowUniforms {
|
|
21035
|
+
mat4 viewMatrix;
|
|
21036
|
+
int enabled;
|
|
21037
|
+
} pbrShadow;
|
|
21038
|
+
vec4 pbrShadow_filterColorWithDirectionalContact(vec4 vertexColor, vec3 worldPosition, vec3 worldNormal, float contactVisibility) {
|
|
21039
|
+
float directionalVisibility = 1.0;
|
|
21040
|
+
vec4 pointVisibility = vec4(1.0);
|
|
21041
|
+
vec4 spotVisibility = vec4(1.0);
|
|
21042
|
+
if (pbrShadow.enabled != 0) {
|
|
21043
|
+
vec3 normal = normalize(worldNormal);
|
|
21044
|
+
float viewDepth = -(pbrShadow.viewMatrix * vec4(worldPosition, 1.0)).z;
|
|
21045
|
+
directionalVisibility = shadow_getDirectionalFactor(worldPosition, normal, viewDepth);
|
|
21046
|
+
for (int index = 0; index < 4; index++) {
|
|
21047
|
+
pointVisibility[index] = shadow_getPointFactor(index, worldPosition, normal);
|
|
21048
|
+
spotVisibility[index] = shadow_getSpotFactor(index, worldPosition, normal);
|
|
21049
|
+
}
|
|
21050
|
+
}
|
|
21051
|
+
return pbr_filterColorWithShadows(vertexColor, min(directionalVisibility, contactVisibility), pointVisibility, spotVisibility);
|
|
21052
|
+
}
|
|
21053
|
+
vec4 pbrShadow_filterColor(vec4 vertexColor, vec3 worldPosition, vec3 worldNormal) {
|
|
21054
|
+
return pbrShadow_filterColorWithDirectionalContact(vertexColor, worldPosition, worldNormal, 1.0);
|
|
21055
|
+
}`
|
|
21056
|
+
)
|
|
21057
|
+
};
|
|
21058
|
+
|
|
21059
|
+
// src/modules/lighting/pbr-surface/pbr-surface.ts
|
|
21060
|
+
var pbrSurface = {
|
|
21061
|
+
name: "pbrSurface",
|
|
21062
|
+
dependencies: [pbrMaterial],
|
|
21063
|
+
bindingLayout: [{ name: "pbrSurface", group: 0 }],
|
|
21064
|
+
uniformTypes: { viewMatrix: "mat4x4<f32>", useMaterialNormals: "i32" },
|
|
21065
|
+
defaultUniforms: {
|
|
21066
|
+
viewMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
|
|
21067
|
+
useMaterialNormals: 0
|
|
21068
|
+
},
|
|
21069
|
+
getUniforms(properties = {}) {
|
|
21070
|
+
return {
|
|
21071
|
+
...properties.viewMatrix ? { viewMatrix: properties.viewMatrix } : {},
|
|
21072
|
+
...properties.useMaterialNormals === void 0 ? {} : { useMaterialNormals: Number(properties.useMaterialNormals) }
|
|
21073
|
+
};
|
|
21074
|
+
},
|
|
21075
|
+
source: (
|
|
21076
|
+
/* wgsl */
|
|
21077
|
+
`
|
|
21078
|
+
struct PBRSurfaceUniforms {
|
|
21079
|
+
viewMatrix: mat4x4f,
|
|
21080
|
+
useMaterialNormals: i32,
|
|
21081
|
+
};
|
|
21082
|
+
@group(0) @binding(auto) var<uniform> pbrSurface: PBRSurfaceUniforms;
|
|
21083
|
+
fn pbrSurface_getColor() -> vec4f {
|
|
21084
|
+
#ifdef HAS_NORMALS
|
|
21085
|
+
var normal = normalize(fragmentInputs.pbr_vNormal);
|
|
21086
|
+
#ifdef DOUBLE_SIDED
|
|
21087
|
+
if (!pbr_frontFacing) {normal = -normal;}
|
|
21088
|
+
#endif
|
|
21089
|
+
#else
|
|
21090
|
+
var normal = normalize(cross(dpdy(fragmentInputs.pbr_vPosition), dpdx(fragmentInputs.pbr_vPosition)));
|
|
21091
|
+
#endif
|
|
21092
|
+
#ifdef HAS_NORMALMAP
|
|
21093
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21094
|
+
let coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21095
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21096
|
+
}
|
|
21097
|
+
#else
|
|
21098
|
+
#ifdef HAS_BUMPMAP
|
|
21099
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21100
|
+
let coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21101
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21102
|
+
}
|
|
21103
|
+
#endif
|
|
21104
|
+
#endif
|
|
21105
|
+
let viewNormal = normalize((pbrSurface.viewMatrix * vec4f(normal, 0.0)).xyz);
|
|
21106
|
+
return vec4f(viewNormal * 0.5 + vec3f(0.5), 1.0);
|
|
21107
|
+
}`
|
|
21108
|
+
),
|
|
21109
|
+
fs: (
|
|
21110
|
+
/* glsl */
|
|
21111
|
+
`
|
|
21112
|
+
layout(std140) uniform pbrSurfaceUniforms {
|
|
21113
|
+
mat4 viewMatrix;
|
|
21114
|
+
int useMaterialNormals;
|
|
21115
|
+
} pbrSurface;
|
|
21116
|
+
vec4 pbrSurface_getColor() {
|
|
21117
|
+
#ifdef HAS_NORMALS
|
|
21118
|
+
#ifdef HAS_TANGENTS
|
|
21119
|
+
vec3 normal = normalize(pbr_vTBN[2]);
|
|
21120
|
+
#else
|
|
21121
|
+
vec3 normal = normalize(pbr_vNormal);
|
|
21122
|
+
#endif
|
|
21123
|
+
#ifdef DOUBLE_SIDED
|
|
21124
|
+
if (!gl_FrontFacing) normal = -normal;
|
|
21125
|
+
#endif
|
|
21126
|
+
#else
|
|
21127
|
+
vec3 normal = normalize(cross(dFdx(pbr_vPosition), dFdy(pbr_vPosition)));
|
|
21128
|
+
#endif
|
|
21129
|
+
#ifdef HAS_NORMALMAP
|
|
21130
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21131
|
+
vec2 coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21132
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21133
|
+
}
|
|
21134
|
+
#else
|
|
21135
|
+
#ifdef HAS_BUMPMAP
|
|
21136
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21137
|
+
vec2 coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21138
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21139
|
+
}
|
|
21140
|
+
#endif
|
|
21141
|
+
#endif
|
|
21142
|
+
vec3 viewNormal = normalize((pbrSurface.viewMatrix * vec4(normal, 0.0)).xyz);
|
|
21143
|
+
return vec4(viewNormal * 0.5 + 0.5, 1.0);
|
|
21144
|
+
}`
|
|
21145
|
+
)
|
|
21146
|
+
};
|
|
21147
|
+
|
|
21148
|
+
// src/modules/lighting/contact-shadow/contact-shadow.ts
|
|
21149
|
+
var IDENTITY_MATRIX3 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
21150
|
+
var contactShadowTrace = {
|
|
21151
|
+
name: "contactShadowTrace",
|
|
21152
|
+
source: (
|
|
21153
|
+
/* wgsl */
|
|
21154
|
+
`struct contactShadowTraceUniforms {
|
|
21155
|
+
projectionMatrix: mat4x4f,
|
|
21156
|
+
inverseProjectionMatrix: mat4x4f,
|
|
21157
|
+
lightDirectionView: vec3f,
|
|
21158
|
+
maxDistance: f32,
|
|
21159
|
+
thickness: f32,
|
|
21160
|
+
stepCount: f32,
|
|
21161
|
+
frameIndex: f32,
|
|
21162
|
+
normalBias: f32,
|
|
21163
|
+
};
|
|
21164
|
+
@group(0) @binding(auto) var<uniform> contactShadowTrace: contactShadowTraceUniforms;
|
|
21165
|
+
@group(0) @binding(auto) var depthTexture: texture_depth_2d;
|
|
21166
|
+
@group(0) @binding(auto) var depthTextureSampler: sampler;
|
|
21167
|
+
@group(0) @binding(auto) var normalTexture: texture_2d<f32>;
|
|
21168
|
+
@group(0) @binding(auto) var normalTextureSampler: sampler;
|
|
21169
|
+
|
|
21170
|
+
fn contactShadow_reconstructViewPosition(uv: vec2f, depth: f32) -> vec3f {
|
|
21171
|
+
let clip = vec4f(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, depth, 1.0);
|
|
21172
|
+
let view = contactShadowTrace.inverseProjectionMatrix * clip;
|
|
21173
|
+
return view.xyz / max(abs(view.w), 0.00001);
|
|
21174
|
+
}
|
|
21175
|
+
|
|
21176
|
+
fn contactShadow_projectViewPosition(position: vec3f) -> vec2f {
|
|
21177
|
+
let clip = contactShadowTrace.projectionMatrix * vec4f(position, 1.0);
|
|
21178
|
+
let ndc = clip.xy / max(abs(clip.w), 0.00001);
|
|
21179
|
+
return vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
|
|
21180
|
+
}
|
|
21181
|
+
|
|
21182
|
+
fn contactShadowTrace_sampleColor(
|
|
21183
|
+
sourceTexture: texture_2d<f32>, sourceTextureSampler: sampler, texSize: vec2f, texCoord: vec2f
|
|
21184
|
+
) -> vec4f {
|
|
21185
|
+
let centerDepth = textureSampleLevel(depthTexture, depthTextureSampler, texCoord, 0);
|
|
21186
|
+
if (centerDepth >= 0.99999) { return vec4f(1.0); }
|
|
21187
|
+
let centerNormal = normalize(textureSampleLevel(normalTexture, normalTextureSampler, texCoord, 0.0).xyz * 2.0 - 1.0);
|
|
21188
|
+
let centerPosition = contactShadow_reconstructViewPosition(texCoord, centerDepth) + centerNormal * contactShadowTrace.normalBias;
|
|
21189
|
+
let rayDirection = normalize(contactShadowTrace.lightDirectionView);
|
|
21190
|
+
let noise = fract(sin(dot(texCoord * texSize + contactShadowTrace.frameIndex, vec2f(12.9898, 78.233))) * 43758.5453);
|
|
21191
|
+
for (var index: i32 = 0; index < 40; index++) {
|
|
21192
|
+
if (f32(index) >= contactShadowTrace.stepCount) { break; }
|
|
21193
|
+
let fraction = (f32(index) + 0.35 + noise * 0.5) / max(contactShadowTrace.stepCount, 1.0);
|
|
21194
|
+
let travel = contactShadowTrace.maxDistance * fraction * fraction;
|
|
21195
|
+
let rayPosition = centerPosition + rayDirection * travel;
|
|
21196
|
+
let sampleUv = contactShadow_projectViewPosition(rayPosition);
|
|
21197
|
+
if (any(sampleUv <= vec2f(0.0)) || any(sampleUv >= vec2f(1.0))) { break; }
|
|
21198
|
+
let sampleDepth = textureSampleLevel(depthTexture, depthTextureSampler, sampleUv, 0);
|
|
21199
|
+
if (sampleDepth >= 0.99999) { continue; }
|
|
21200
|
+
let scenePosition = contactShadow_reconstructViewPosition(sampleUv, sampleDepth);
|
|
21201
|
+
let depthDelta = (-rayPosition.z) - (-scenePosition.z);
|
|
21202
|
+
let hitThickness = contactShadowTrace.thickness + travel * 0.02;
|
|
21203
|
+
if (depthDelta >= 0.0 && depthDelta <= hitThickness) {
|
|
21204
|
+
let distanceFade = 1.0 - clamp(travel / contactShadowTrace.maxDistance, 0.0, 1.0);
|
|
21205
|
+
return vec4f(vec3f(1.0 - distanceFade), 1.0);
|
|
21206
|
+
}
|
|
21207
|
+
if (depthDelta > hitThickness * 8.0) { break; }
|
|
21208
|
+
}
|
|
21209
|
+
return vec4f(1.0);
|
|
21210
|
+
}`
|
|
21211
|
+
),
|
|
21212
|
+
fs: (
|
|
21213
|
+
/* glsl */
|
|
21214
|
+
`
|
|
21215
|
+
layout(std140) uniform contactShadowTraceUniforms {
|
|
21216
|
+
mat4 projectionMatrix;
|
|
21217
|
+
mat4 inverseProjectionMatrix;
|
|
21218
|
+
vec3 lightDirectionView;
|
|
21219
|
+
float maxDistance;
|
|
21220
|
+
float thickness;
|
|
21221
|
+
float stepCount;
|
|
21222
|
+
float frameIndex;
|
|
21223
|
+
float normalBias;
|
|
21224
|
+
} contactShadowTrace;
|
|
21225
|
+
uniform sampler2D depthTexture;
|
|
21226
|
+
uniform sampler2D normalTexture;
|
|
21227
|
+
vec3 contactShadow_reconstructViewPosition(vec2 uv, float depth) {
|
|
21228
|
+
vec4 view = contactShadowTrace.inverseProjectionMatrix * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
21229
|
+
return view.xyz / max(abs(view.w), 0.00001);
|
|
21230
|
+
}
|
|
21231
|
+
vec2 contactShadow_projectViewPosition(vec3 position) {
|
|
21232
|
+
vec4 clip = contactShadowTrace.projectionMatrix * vec4(position,1.0);
|
|
21233
|
+
return clip.xy / max(abs(clip.w),0.00001) * 0.5 + 0.5;
|
|
21234
|
+
}
|
|
21235
|
+
vec4 contactShadowTrace_sampleColor(sampler2D sourceTexture,vec2 texSize,vec2 texCoord) {
|
|
21236
|
+
float centerDepth = texture(depthTexture,texCoord).r;
|
|
21237
|
+
if(centerDepth >= 0.99999) return vec4(1.0);
|
|
21238
|
+
vec3 centerNormal = normalize(texture(normalTexture,texCoord).xyz * 2.0 - 1.0);
|
|
21239
|
+
vec3 centerPosition = contactShadow_reconstructViewPosition(texCoord,centerDepth) + centerNormal * contactShadowTrace.normalBias;
|
|
21240
|
+
vec3 rayDirection = normalize(contactShadowTrace.lightDirectionView);
|
|
21241
|
+
float noise = fract(sin(dot(texCoord * texSize + contactShadowTrace.frameIndex,vec2(12.9898,78.233))) * 43758.5453);
|
|
21242
|
+
for(int index=0;index<40;index++) {
|
|
21243
|
+
if(float(index)>=contactShadowTrace.stepCount) break;
|
|
21244
|
+
float fraction=(float(index)+0.35+noise*0.5)/max(contactShadowTrace.stepCount,1.0);
|
|
21245
|
+
float travel=contactShadowTrace.maxDistance*fraction*fraction;
|
|
21246
|
+
vec3 rayPosition=centerPosition+rayDirection*travel;
|
|
21247
|
+
vec2 sampleUv=contactShadow_projectViewPosition(rayPosition);
|
|
21248
|
+
if(any(lessThanEqual(sampleUv,vec2(0.0)))||any(greaterThanEqual(sampleUv,vec2(1.0))))break;
|
|
21249
|
+
float sampleDepth=texture(depthTexture,sampleUv).r;
|
|
21250
|
+
if(sampleDepth>=0.99999)continue;
|
|
21251
|
+
vec3 scenePosition=contactShadow_reconstructViewPosition(sampleUv,sampleDepth);
|
|
21252
|
+
float depthDelta=(-rayPosition.z)-(-scenePosition.z);
|
|
21253
|
+
float hitThickness=contactShadowTrace.thickness+travel*0.02;
|
|
21254
|
+
if(depthDelta>=0.0&&depthDelta<=hitThickness) {
|
|
21255
|
+
float distanceFade=1.0-clamp(travel/contactShadowTrace.maxDistance,0.0,1.0);
|
|
21256
|
+
return vec4(vec3(1.0-distanceFade),1.0);
|
|
21257
|
+
}
|
|
21258
|
+
if(depthDelta>hitThickness*8.0)break;
|
|
21259
|
+
}
|
|
21260
|
+
return vec4(1.0);
|
|
21261
|
+
}
|
|
21262
|
+
`
|
|
21263
|
+
),
|
|
21264
|
+
bindingLayout: [
|
|
21265
|
+
{ name: "depthTexture", group: 0 },
|
|
21266
|
+
{ name: "normalTexture", group: 0 }
|
|
21267
|
+
],
|
|
21268
|
+
props: {},
|
|
21269
|
+
uniforms: {},
|
|
21270
|
+
bindings: {},
|
|
21271
|
+
uniformTypes: {
|
|
21272
|
+
projectionMatrix: "mat4x4<f32>",
|
|
21273
|
+
inverseProjectionMatrix: "mat4x4<f32>",
|
|
21274
|
+
lightDirectionView: "vec3<f32>",
|
|
21275
|
+
maxDistance: "f32",
|
|
21276
|
+
thickness: "f32",
|
|
21277
|
+
stepCount: "f32",
|
|
21278
|
+
frameIndex: "f32",
|
|
21279
|
+
normalBias: "f32"
|
|
21280
|
+
},
|
|
21281
|
+
propTypes: {
|
|
21282
|
+
projectionMatrix: { value: IDENTITY_MATRIX3, private: true },
|
|
21283
|
+
inverseProjectionMatrix: { value: IDENTITY_MATRIX3, private: true },
|
|
21284
|
+
lightDirectionView: { value: [0, 1, 0], private: true },
|
|
21285
|
+
maxDistance: { value: 4, min: 0.1, softMax: 16 },
|
|
21286
|
+
thickness: { value: 0.12, min: 5e-3, softMax: 1 },
|
|
21287
|
+
stepCount: { value: 24, min: 1, max: 40 },
|
|
21288
|
+
frameIndex: { value: 0, private: true },
|
|
21289
|
+
normalBias: { value: 0.035, min: 0, softMax: 0.2 }
|
|
21290
|
+
},
|
|
21291
|
+
passes: [{ sampler: true }]
|
|
21292
|
+
};
|
|
21293
|
+
var contactShadowBilateralBlur = {
|
|
21294
|
+
name: "contactShadowBilateralBlur",
|
|
21295
|
+
source: (
|
|
21296
|
+
/* wgsl */
|
|
21297
|
+
`struct contactShadowBilateralBlurUniforms {
|
|
21298
|
+
direction: vec2f,
|
|
21299
|
+
radius: f32,
|
|
21300
|
+
depthSigma: f32,
|
|
21301
|
+
normalPower: f32,
|
|
21302
|
+
};
|
|
21303
|
+
@group(0) @binding(auto) var<uniform> contactShadowBilateralBlur: contactShadowBilateralBlurUniforms;
|
|
21304
|
+
@group(0) @binding(auto) var depthTexture: texture_depth_2d;
|
|
21305
|
+
@group(0) @binding(auto) var depthTextureSampler: sampler;
|
|
21306
|
+
@group(0) @binding(auto) var normalTexture: texture_2d<f32>;
|
|
21307
|
+
@group(0) @binding(auto) var normalTextureSampler: sampler;
|
|
21308
|
+
|
|
21309
|
+
fn contactShadowBilateralBlur_sampleColor(
|
|
21310
|
+
sourceTexture: texture_2d<f32>, sourceTextureSampler: sampler, texSize: vec2f, texCoord: vec2f
|
|
21311
|
+
) -> vec4f {
|
|
21312
|
+
let sourceDimensions = vec2f(textureDimensions(sourceTexture));
|
|
21313
|
+
let texel = contactShadowBilateralBlur.direction / sourceDimensions;
|
|
21314
|
+
let centerDepth = textureSampleLevel(depthTexture, depthTextureSampler, texCoord, 0);
|
|
21315
|
+
let centerNormal = normalize(textureSampleLevel(normalTexture, normalTextureSampler, texCoord, 0.0).xyz * 2.0 - 1.0);
|
|
21316
|
+
var result = textureSampleLevel(sourceTexture, sourceTextureSampler, texCoord, 0.0).r;
|
|
21317
|
+
var totalWeight = 1.0;
|
|
21318
|
+
for (var index: i32 = 1; index <= 6; index++) {
|
|
21319
|
+
if (f32(index) > contactShadowBilateralBlur.radius) { break; }
|
|
21320
|
+
for (var side: i32 = -1; side <= 1; side += 2) {
|
|
21321
|
+
let sampleUv = clamp(texCoord + texel * f32(index * side), vec2f(0.0), vec2f(1.0));
|
|
21322
|
+
let sampleDepth = textureSampleLevel(depthTexture, depthTextureSampler, sampleUv, 0);
|
|
21323
|
+
let sampleNormal = normalize(textureSampleLevel(normalTexture, normalTextureSampler, sampleUv, 0.0).xyz * 2.0 - 1.0);
|
|
21324
|
+
let depthDelta = abs(sampleDepth - centerDepth);
|
|
21325
|
+
let depthWeight = exp(-(depthDelta * depthDelta) / max(2.0 * contactShadowBilateralBlur.depthSigma * contactShadowBilateralBlur.depthSigma, 0.000001));
|
|
21326
|
+
let normalWeight = pow(max(dot(centerNormal, sampleNormal), 0.0), contactShadowBilateralBlur.normalPower);
|
|
21327
|
+
let spatialWeight = exp(-f32(index * index) / 8.0);
|
|
21328
|
+
let weight = depthWeight * normalWeight * spatialWeight;
|
|
21329
|
+
result += textureSampleLevel(sourceTexture, sourceTextureSampler, sampleUv, 0.0).r * weight;
|
|
21330
|
+
totalWeight += weight;
|
|
21331
|
+
}
|
|
21332
|
+
}
|
|
21333
|
+
let visibility = result / totalWeight;
|
|
21334
|
+
return vec4f(vec3f(visibility), 1.0);
|
|
21335
|
+
}`
|
|
21336
|
+
),
|
|
21337
|
+
fs: (
|
|
21338
|
+
/* glsl */
|
|
21339
|
+
`
|
|
21340
|
+
layout(std140) uniform contactShadowBilateralBlurUniforms {
|
|
21341
|
+
vec2 direction;
|
|
21342
|
+
float radius;
|
|
21343
|
+
float depthSigma;
|
|
21344
|
+
float normalPower;
|
|
21345
|
+
} contactShadowBilateralBlur;
|
|
21346
|
+
uniform sampler2D depthTexture;
|
|
21347
|
+
uniform sampler2D normalTexture;
|
|
21348
|
+
vec4 contactShadowBilateralBlur_sampleColor(sampler2D sourceTexture,vec2 texSize,vec2 texCoord) {
|
|
21349
|
+
vec2 texel=contactShadowBilateralBlur.direction/vec2(textureSize(sourceTexture,0));
|
|
21350
|
+
float centerDepth=texture(depthTexture,texCoord).r;
|
|
21351
|
+
vec3 centerNormal=normalize(texture(normalTexture,texCoord).xyz*2.0-1.0);
|
|
21352
|
+
float result=texture(sourceTexture,texCoord).r;
|
|
21353
|
+
float totalWeight=1.0;
|
|
21354
|
+
for(int index=1;index<=6;index++) {
|
|
21355
|
+
if(float(index)>contactShadowBilateralBlur.radius)break;
|
|
21356
|
+
for(int side=-1;side<=1;side+=2) {
|
|
21357
|
+
vec2 sampleUv=clamp(texCoord+texel*float(index*side),vec2(0.0),vec2(1.0));
|
|
21358
|
+
float sampleDepth=texture(depthTexture,sampleUv).r;
|
|
21359
|
+
vec3 sampleNormal=normalize(texture(normalTexture,sampleUv).xyz*2.0-1.0);
|
|
21360
|
+
float depthDelta=abs(sampleDepth-centerDepth);
|
|
21361
|
+
float depthWeight=exp(-(depthDelta*depthDelta)/max(2.0*contactShadowBilateralBlur.depthSigma*contactShadowBilateralBlur.depthSigma,0.000001));
|
|
21362
|
+
float normalWeight=pow(max(dot(centerNormal,sampleNormal),0.0),contactShadowBilateralBlur.normalPower);
|
|
21363
|
+
float spatialWeight=exp(-float(index*index)/8.0);
|
|
21364
|
+
float weight=depthWeight*normalWeight*spatialWeight;
|
|
21365
|
+
result+=texture(sourceTexture,sampleUv).r*weight;totalWeight+=weight;
|
|
21366
|
+
}
|
|
21367
|
+
}
|
|
21368
|
+
return vec4(vec3(result/totalWeight),1.0);
|
|
21369
|
+
}
|
|
21370
|
+
`
|
|
21371
|
+
),
|
|
21372
|
+
bindingLayout: [
|
|
21373
|
+
{ name: "depthTexture", group: 0 },
|
|
21374
|
+
{ name: "normalTexture", group: 0 }
|
|
21375
|
+
],
|
|
21376
|
+
props: {},
|
|
21377
|
+
uniforms: {},
|
|
21378
|
+
bindings: {},
|
|
21379
|
+
uniformTypes: {
|
|
21380
|
+
direction: "vec2<f32>",
|
|
21381
|
+
radius: "f32",
|
|
21382
|
+
depthSigma: "f32",
|
|
21383
|
+
normalPower: "f32"
|
|
21384
|
+
},
|
|
21385
|
+
propTypes: {
|
|
21386
|
+
direction: { value: [1, 0], private: true },
|
|
21387
|
+
radius: { value: 4, min: 1, max: 6 },
|
|
21388
|
+
depthSigma: { value: 6e-3, min: 1e-4, softMax: 0.05 },
|
|
21389
|
+
normalPower: { value: 24, min: 1, softMax: 64 }
|
|
21390
|
+
},
|
|
21391
|
+
passes: [{ sampler: true }]
|
|
21392
|
+
};
|
|
21393
|
+
var contactShadowComposite = {
|
|
21394
|
+
name: "contactShadowComposite",
|
|
21395
|
+
source: (
|
|
21396
|
+
/* wgsl */
|
|
21397
|
+
`struct contactShadowCompositeUniforms {
|
|
21398
|
+
strength: f32,
|
|
21399
|
+
debugMode: f32,
|
|
21400
|
+
};
|
|
21401
|
+
@group(0) @binding(auto) var<uniform> contactShadowComposite: contactShadowCompositeUniforms;
|
|
21402
|
+
@group(0) @binding(auto) var contactShadowTexture: texture_2d<f32>;
|
|
21403
|
+
@group(0) @binding(auto) var contactShadowTextureSampler: sampler;
|
|
21404
|
+
@group(0) @binding(auto) var directionalDirectTexture: texture_2d<f32>;
|
|
21405
|
+
@group(0) @binding(auto) var directionalDirectTextureSampler: sampler;
|
|
21406
|
+
@group(0) @binding(auto) var shadowDebugTexture: texture_2d<f32>;
|
|
21407
|
+
@group(0) @binding(auto) var shadowDebugTextureSampler: sampler;
|
|
21408
|
+
|
|
21409
|
+
fn contactShadowComposite_sampleColor(
|
|
21410
|
+
sourceTexture: texture_2d<f32>, sourceTextureSampler: sampler, texSize: vec2f, texCoord: vec2f
|
|
21411
|
+
) -> vec4f {
|
|
21412
|
+
let color = textureSampleLevel(sourceTexture, sourceTextureSampler, texCoord, 0.0);
|
|
21413
|
+
let contact = textureSampleLevel(contactShadowTexture, contactShadowTextureSampler, texCoord, 0.0).r;
|
|
21414
|
+
let appliedContact = mix(1.0, contact, contactShadowComposite.strength);
|
|
21415
|
+
if (contactShadowComposite.debugMode > 0.5 && contactShadowComposite.debugMode < 1.5) {
|
|
21416
|
+
return vec4f(vec3f(contact), 1.0);
|
|
21417
|
+
}
|
|
21418
|
+
if (contactShadowComposite.debugMode >= 1.5) {
|
|
21419
|
+
let factors = textureSampleLevel(shadowDebugTexture, shadowDebugTextureSampler, texCoord, 0.0).rgb;
|
|
21420
|
+
return vec4f(vec3f(factors.x * factors.y * factors.z * contact), 1.0);
|
|
21421
|
+
}
|
|
21422
|
+
let directionalDirect = textureSampleLevel(
|
|
21423
|
+
directionalDirectTexture,
|
|
21424
|
+
directionalDirectTextureSampler,
|
|
21425
|
+
texCoord,
|
|
21426
|
+
0.0
|
|
21427
|
+
).rgb;
|
|
21428
|
+
return vec4f(max(color.rgb - directionalDirect * (1.0 - appliedContact), vec3f(0.0)), color.a);
|
|
21429
|
+
}`
|
|
21430
|
+
),
|
|
21431
|
+
fs: (
|
|
21432
|
+
/* glsl */
|
|
21433
|
+
`
|
|
21434
|
+
layout(std140) uniform contactShadowCompositeUniforms {
|
|
21435
|
+
float strength;
|
|
21436
|
+
float debugMode;
|
|
21437
|
+
} contactShadowComposite;
|
|
21438
|
+
uniform sampler2D contactShadowTexture;
|
|
21439
|
+
uniform sampler2D directionalDirectTexture;
|
|
21440
|
+
uniform sampler2D shadowDebugTexture;
|
|
21441
|
+
vec4 contactShadowComposite_sampleColor(sampler2D sourceTexture,vec2 texSize,vec2 texCoord) {
|
|
21442
|
+
vec4 color=texture(sourceTexture,texCoord);
|
|
21443
|
+
float contact=texture(contactShadowTexture,texCoord).r;
|
|
21444
|
+
float appliedContact=mix(1.0,contact,contactShadowComposite.strength);
|
|
21445
|
+
if(contactShadowComposite.debugMode>0.5&&contactShadowComposite.debugMode<1.5)return vec4(vec3(contact),1.0);
|
|
21446
|
+
if(contactShadowComposite.debugMode>=1.5){vec3 factors=texture(shadowDebugTexture,texCoord).rgb;return vec4(vec3(factors.x*factors.y*factors.z*contact),1.0);}
|
|
21447
|
+
vec3 directionalDirect=texture(directionalDirectTexture,texCoord).rgb;
|
|
21448
|
+
return vec4(max(color.rgb-directionalDirect*(1.0-appliedContact),vec3(0.0)),color.a);
|
|
21449
|
+
}
|
|
21450
|
+
`
|
|
21451
|
+
),
|
|
21452
|
+
bindingLayout: [
|
|
21453
|
+
{ name: "contactShadowTexture", group: 0 },
|
|
21454
|
+
{ name: "directionalDirectTexture", group: 0 },
|
|
21455
|
+
{ name: "shadowDebugTexture", group: 0 }
|
|
21456
|
+
],
|
|
21457
|
+
props: {},
|
|
21458
|
+
uniforms: {},
|
|
21459
|
+
bindings: {},
|
|
21460
|
+
uniformTypes: { strength: "f32", debugMode: "f32" },
|
|
21461
|
+
propTypes: {
|
|
21462
|
+
strength: { value: 1, min: 0, max: 1 },
|
|
21463
|
+
debugMode: { value: 0, min: 0, max: 2, private: true }
|
|
21464
|
+
},
|
|
21465
|
+
passes: [{ sampler: true }]
|
|
21466
|
+
};
|
|
21467
|
+
|
|
21468
|
+
// src/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.ts
|
|
21469
|
+
var pbrContactShadow = {
|
|
21470
|
+
name: "pbrContactShadow",
|
|
21471
|
+
dependencies: [pbrMaterial],
|
|
21472
|
+
bindingLayout: [
|
|
21473
|
+
{ name: "pbrContactShadow", group: 0 },
|
|
21474
|
+
{ name: "contactShadowTexture", group: 2 }
|
|
21475
|
+
],
|
|
21476
|
+
uniformTypes: { viewport: "vec4<f32>", strength: "f32", enabled: "i32" },
|
|
21477
|
+
defaultUniforms: { viewport: [0, 0, 1, 1], strength: 1, enabled: 1 },
|
|
21478
|
+
getUniforms(properties = {}) {
|
|
21479
|
+
return {
|
|
21480
|
+
...properties.viewport ? { viewport: properties.viewport } : {},
|
|
21481
|
+
...properties.strength === void 0 ? {} : { strength: properties.strength },
|
|
21482
|
+
...properties.enabled === void 0 ? {} : { enabled: Number(properties.enabled) },
|
|
21483
|
+
...properties.contactShadowTexture ? { contactShadowTexture: properties.contactShadowTexture } : {}
|
|
21484
|
+
};
|
|
21485
|
+
},
|
|
21486
|
+
source: (
|
|
21487
|
+
/* wgsl */
|
|
21488
|
+
`
|
|
21489
|
+
struct PBRContactShadowUniforms {
|
|
21490
|
+
viewport: vec4f,
|
|
21491
|
+
strength: f32,
|
|
21492
|
+
enabled: i32,
|
|
21493
|
+
};
|
|
21494
|
+
@group(0) @binding(auto) var<uniform> pbrContactShadow: PBRContactShadowUniforms;
|
|
21495
|
+
@group(2) @binding(auto) var contactShadowTexture: texture_2d<f32>;
|
|
21496
|
+
@group(2) @binding(auto) var contactShadowTextureSampler: sampler;
|
|
21497
|
+
fn pbrContactShadow_getFactor(pixelPosition:vec2f)->f32 {
|
|
21498
|
+
if(pbrContactShadow.enabled==0){return 1.0;}
|
|
21499
|
+
let coordinates=(pixelPosition-pbrContactShadow.viewport.xy)/pbrContactShadow.viewport.zw;
|
|
21500
|
+
if(any(coordinates<vec2f(0.0))||any(coordinates>vec2f(1.0))){return 1.0;}
|
|
21501
|
+
let visibility=textureSampleLevel(contactShadowTexture,contactShadowTextureSampler,coordinates,0.0).r;
|
|
21502
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrContactShadow.strength,0.0,1.0));
|
|
21503
|
+
}
|
|
21504
|
+
fn pbrContactShadow_filterColor(vertexColor:vec4f,pixelPosition:vec2f)->vec4f {
|
|
21505
|
+
return pbr_filterColorWithShadows(vertexColor,pbrContactShadow_getFactor(pixelPosition),vec4f(1.0),vec4f(1.0));
|
|
21506
|
+
}`
|
|
21507
|
+
),
|
|
21508
|
+
fs: (
|
|
21509
|
+
/* glsl */
|
|
21510
|
+
`
|
|
21511
|
+
layout(std140) uniform pbrContactShadowUniforms {
|
|
21512
|
+
vec4 viewport;
|
|
21513
|
+
float strength;
|
|
21514
|
+
int enabled;
|
|
21515
|
+
} pbrContactShadow;
|
|
21516
|
+
uniform sampler2D contactShadowTexture;
|
|
21517
|
+
float pbrContactShadow_getFactor(vec2 pixelPosition) {
|
|
21518
|
+
if(pbrContactShadow.enabled==0)return 1.0;
|
|
21519
|
+
vec2 coordinates=(pixelPosition-pbrContactShadow.viewport.xy)/pbrContactShadow.viewport.zw;
|
|
21520
|
+
if(any(lessThan(coordinates,vec2(0.0)))||any(greaterThan(coordinates,vec2(1.0))))return 1.0;
|
|
21521
|
+
float visibility=texture(contactShadowTexture,coordinates).r;
|
|
21522
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrContactShadow.strength,0.0,1.0));
|
|
21523
|
+
}
|
|
21524
|
+
vec4 pbrContactShadow_filterColor(vec4 vertexColor,vec2 pixelPosition) {
|
|
21525
|
+
return pbr_filterColorWithShadows(vertexColor,pbrContactShadow_getFactor(pixelPosition),vec4(1.0),vec4(1.0));
|
|
21526
|
+
}`
|
|
21527
|
+
)
|
|
21528
|
+
};
|
|
21529
|
+
|
|
21530
|
+
// src/modules/lighting/clustered-light-grid/clustered-light-grid.ts
|
|
21531
|
+
var clusteredLightGrid = {
|
|
21532
|
+
name: "clusteredLightGrid",
|
|
21533
|
+
source: (
|
|
21534
|
+
/* wgsl */
|
|
21535
|
+
`
|
|
21536
|
+
fn clusteredLightGrid_getIndex(coordinates: vec2f, viewDepth: f32, dimensions: vec3u, nearPlane: f32, farPlane: f32) -> u32 {
|
|
21537
|
+
let tile = min(vec2u(clamp(coordinates, vec2f(0.0), vec2f(0.999999)) * vec2f(dimensions.xy)), dimensions.xy - vec2u(1));
|
|
21538
|
+
let normalizedDepth = clamp(log(clamp(viewDepth, nearPlane, farPlane) / nearPlane) / log(farPlane / nearPlane), 0.0, 0.999999);
|
|
21539
|
+
let depthSlice = min(u32(normalizedDepth * f32(dimensions.z)), dimensions.z - 1u);
|
|
21540
|
+
return (depthSlice * dimensions.y + tile.y) * dimensions.x + tile.x;
|
|
21541
|
+
}
|
|
21542
|
+
`
|
|
21543
|
+
)
|
|
21544
|
+
};
|
|
21545
|
+
|
|
21546
|
+
// src/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.ts
|
|
21547
|
+
var pbrAmbientOcclusion = {
|
|
21548
|
+
name: "pbrAmbientOcclusion",
|
|
21549
|
+
dependencies: [pbrMaterial],
|
|
21550
|
+
bindingLayout: [
|
|
21551
|
+
{ name: "pbrAmbientOcclusion", group: 0 },
|
|
21552
|
+
{ name: "ambientOcclusionTexture", group: 2 }
|
|
21553
|
+
],
|
|
21554
|
+
uniformTypes: { viewport: "vec4<f32>", strength: "f32", enabled: "i32" },
|
|
21555
|
+
defaultUniforms: { viewport: [0, 0, 1, 1], strength: 1, enabled: 1 },
|
|
21556
|
+
getUniforms(properties = {}) {
|
|
21557
|
+
return {
|
|
21558
|
+
...properties.viewport ? { viewport: properties.viewport } : {},
|
|
21559
|
+
...properties.strength === void 0 ? {} : { strength: properties.strength },
|
|
21560
|
+
...properties.enabled === void 0 ? {} : { enabled: Number(properties.enabled) },
|
|
21561
|
+
...properties.ambientOcclusionTexture ? { ambientOcclusionTexture: properties.ambientOcclusionTexture } : {}
|
|
21562
|
+
};
|
|
21563
|
+
},
|
|
21564
|
+
source: (
|
|
21565
|
+
/* wgsl */
|
|
21566
|
+
`
|
|
21567
|
+
struct PBRAmbientOcclusionUniforms {
|
|
21568
|
+
viewport: vec4f,
|
|
21569
|
+
strength: f32,
|
|
21570
|
+
enabled: i32,
|
|
21571
|
+
};
|
|
21572
|
+
@group(0) @binding(auto) var<uniform> pbrAmbientOcclusion: PBRAmbientOcclusionUniforms;
|
|
21573
|
+
@group(2) @binding(auto) var ambientOcclusionTexture: texture_2d<f32>;
|
|
21574
|
+
@group(2) @binding(auto) var ambientOcclusionTextureSampler: sampler;
|
|
21575
|
+
fn pbrAmbientOcclusion_getFactor(pixelPosition:vec2f)->f32 {
|
|
21576
|
+
if(pbrAmbientOcclusion.enabled==0){return 1.0;}
|
|
21577
|
+
let coordinates=(pixelPosition-pbrAmbientOcclusion.viewport.xy)/pbrAmbientOcclusion.viewport.zw;
|
|
21578
|
+
if(any(coordinates<vec2f(0.0))||any(coordinates>vec2f(1.0))){return 1.0;}
|
|
21579
|
+
let visibility=textureSampleLevel(ambientOcclusionTexture,ambientOcclusionTextureSampler,coordinates,0.0).r;
|
|
21580
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrAmbientOcclusion.strength,0.0,1.0));
|
|
21581
|
+
}
|
|
21582
|
+
fn pbrAmbientOcclusion_setFactor(pixelPosition:vec2f) {
|
|
21583
|
+
pbr_ambientVisibility = pbrAmbientOcclusion_getFactor(pixelPosition);
|
|
21584
|
+
}`
|
|
21585
|
+
),
|
|
21586
|
+
fs: (
|
|
21587
|
+
/* glsl */
|
|
21588
|
+
`
|
|
21589
|
+
layout(std140) uniform pbrAmbientOcclusionUniforms {
|
|
21590
|
+
vec4 viewport;
|
|
21591
|
+
float strength;
|
|
21592
|
+
int enabled;
|
|
21593
|
+
} pbrAmbientOcclusion;
|
|
21594
|
+
uniform sampler2D ambientOcclusionTexture;
|
|
21595
|
+
float pbrAmbientOcclusion_getFactor(vec2 pixelPosition) {
|
|
21596
|
+
if(pbrAmbientOcclusion.enabled==0)return 1.0;
|
|
21597
|
+
vec2 coordinates=(pixelPosition-pbrAmbientOcclusion.viewport.xy)/pbrAmbientOcclusion.viewport.zw;
|
|
21598
|
+
if(any(lessThan(coordinates,vec2(0.0)))||any(greaterThan(coordinates,vec2(1.0))))return 1.0;
|
|
21599
|
+
float visibility=texture(ambientOcclusionTexture,coordinates).r;
|
|
21600
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrAmbientOcclusion.strength,0.0,1.0));
|
|
21601
|
+
}
|
|
21602
|
+
void pbrAmbientOcclusion_setFactor(vec2 pixelPosition) {
|
|
21603
|
+
pbr_ambientVisibility = pbrAmbientOcclusion_getFactor(pixelPosition);
|
|
21604
|
+
}`
|
|
21605
|
+
)
|
|
21606
|
+
};
|
|
21607
|
+
|
|
21608
|
+
// src/modules/lighting/lightmap/lightmap.ts
|
|
21609
|
+
var lightmapBake = {
|
|
21610
|
+
name: "lightmapBake",
|
|
21611
|
+
dependencies: [pbrMaterial],
|
|
21612
|
+
bindingLayout: [{ name: "lightmapBake", group: 0 }],
|
|
21613
|
+
uniformTypes: { uvSet: "i32", uvTransform: "mat3x3<f32>", chartId: "f32" },
|
|
21614
|
+
defaultUniforms: { uvSet: 1, uvTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1], chartId: 1 },
|
|
21615
|
+
getUniforms: (props) => props,
|
|
21616
|
+
source: `
|
|
21617
|
+
struct LightmapBakeUniforms {uvSet: i32, uvTransform: mat3x3f, chartId: f32};
|
|
21618
|
+
@group(0) @binding(auto) var<uniform> lightmapBake: LightmapBakeUniforms;
|
|
21619
|
+
|
|
21620
|
+
fn lightmap_getIrradiance(position: vec3f, normal: vec3f, directionalVisibility: f32, pointVisibility: vec4f, spotVisibility: vec4f) -> vec3f {
|
|
21621
|
+
if (lighting.enabled == 0) {return vec3f(0.0);}
|
|
21622
|
+
var irradiance = lighting.ambientColor;
|
|
21623
|
+
for (var index = 0; index < lighting.directionalLightCount; index++) {
|
|
21624
|
+
let light = lighting_getDirectionalLight(index);
|
|
21625
|
+
irradiance += light.color * max(dot(normal, -normalize(light.direction)), 0.0) * select(1.0, directionalVisibility, index == 0);
|
|
21626
|
+
}
|
|
21627
|
+
for (var index = 0; index < lighting.pointLightCount; index++) {
|
|
21628
|
+
let light = lighting_getPointLight(index);
|
|
21629
|
+
let offset = light.position - position;
|
|
21630
|
+
let visibility = select(1.0, pointVisibility[min(index, 3)], index < 4);
|
|
21631
|
+
irradiance += light.color * max(dot(normal, normalize(offset)), 0.0) * visibility / max(getPointLightAttenuation(light, length(offset)), 0.0001);
|
|
21632
|
+
}
|
|
21633
|
+
for (var index = 0; index < lighting.spotLightCount; index++) {
|
|
21634
|
+
let light = lighting_getSpotLight(index);
|
|
21635
|
+
irradiance += light.color * max(dot(normal, normalize(light.position - position)), 0.0) * select(1.0, spotVisibility[min(index, 3)], index < 4) / max(getSpotLightAttenuation(light, position), 0.0001);
|
|
21636
|
+
}
|
|
21637
|
+
return irradiance;
|
|
21638
|
+
}
|
|
21639
|
+
`,
|
|
21640
|
+
vs: `layout(std140) uniform lightmapBakeUniforms {
|
|
21641
|
+
int uvSet;
|
|
21642
|
+
mat3 uvTransform;
|
|
21643
|
+
float chartId;
|
|
21644
|
+
} lightmapBake;`,
|
|
21645
|
+
fs: `layout(std140) uniform lightmapBakeUniforms {
|
|
21646
|
+
int uvSet;
|
|
21647
|
+
mat3 uvTransform;
|
|
21648
|
+
float chartId;
|
|
21649
|
+
} lightmapBake;
|
|
21650
|
+
|
|
21651
|
+
vec3 lightmap_getIrradiance(vec3 position, vec3 normal, float directionalVisibility, vec4 pointVisibility, vec4 spotVisibility) {
|
|
21652
|
+
if (lighting.enabled == 0) {return vec3(0.0);}
|
|
21653
|
+
vec3 irradiance = lighting.ambientColor;
|
|
21654
|
+
for (int index = 0; index < lighting.directionalLightCount; index++) {
|
|
21655
|
+
DirectionalLight light = lighting_getDirectionalLight(index);
|
|
21656
|
+
irradiance += light.color * max(dot(normal, -normalize(light.direction)), 0.0) * (index == 0 ? directionalVisibility : 1.0);
|
|
21657
|
+
}
|
|
21658
|
+
for (int index = 0; index < lighting.pointLightCount; index++) {
|
|
21659
|
+
PointLight light = lighting_getPointLight(index);
|
|
21660
|
+
vec3 offset = light.position - position;
|
|
21661
|
+
irradiance += light.color * max(dot(normal, normalize(offset)), 0.0) * (index < 4 ? pointVisibility[index] : 1.0) / max(getPointLightAttenuation(light, length(offset)), 0.0001);
|
|
21662
|
+
}
|
|
21663
|
+
for (int index = 0; index < lighting.spotLightCount; index++) {
|
|
21664
|
+
SpotLight light = lighting_getSpotLight(index);
|
|
21665
|
+
irradiance += light.color * max(dot(normal, normalize(light.position - position)), 0.0) * (index < 4 ? spotVisibility[index] : 1.0) / max(getSpotLightAttenuation(light, position), 0.0001);
|
|
21666
|
+
}
|
|
21667
|
+
return irradiance;
|
|
21668
|
+
}
|
|
21669
|
+
`
|
|
21670
|
+
};
|
|
21671
|
+
|
|
21672
|
+
// src/modules/lighting/lightmap/lightmap-filter.ts
|
|
21673
|
+
var lightmapFilter = {
|
|
21674
|
+
name: "lightmapFilter",
|
|
21675
|
+
bindingLayout: [
|
|
21676
|
+
{ name: "lightmapFilter", group: 0 },
|
|
21677
|
+
{ name: "currentTexture", group: 0 },
|
|
21678
|
+
{ name: "previousTexture", group: 0 },
|
|
21679
|
+
{ name: "chartTexture", group: 0 }
|
|
21680
|
+
],
|
|
21681
|
+
uniformTypes: { weight: "f32", mode: "i32" },
|
|
21682
|
+
defaultUniforms: { weight: 1, mode: 0 },
|
|
21683
|
+
getUniforms: (props) => props,
|
|
21684
|
+
source: `
|
|
21685
|
+
struct LightmapFilterUniforms {weight: f32, mode: i32};
|
|
21686
|
+
@group(0) @binding(auto) var<uniform> lightmapFilter: LightmapFilterUniforms;
|
|
21687
|
+
@group(0) @binding(auto) var currentTexture: texture_2d<f32>;
|
|
21688
|
+
@group(0) @binding(auto) var previousTexture: texture_2d<f32>;
|
|
21689
|
+
@group(0) @binding(auto) var chartTexture: texture_2d<f32>;
|
|
21690
|
+
fn lightmapFilter_getColor(coordinates: vec2i) -> vec4f {
|
|
21691
|
+
let current = textureLoad(currentTexture, coordinates, 0);
|
|
21692
|
+
if (lightmapFilter.mode == 0) {
|
|
21693
|
+
let previous = textureLoad(previousTexture, coordinates, 0);
|
|
21694
|
+
return vec4f(mix(previous.rgb, current.rgb, lightmapFilter.weight), current.a);
|
|
21695
|
+
}
|
|
21696
|
+
if (lightmapFilter.mode == 2 || current.a > 0.0) {return current;}
|
|
21697
|
+
let chart = textureLoad(chartTexture, coordinates, 0).r;
|
|
21698
|
+
if (chart <= 0.0) {return current;}
|
|
21699
|
+
let size = vec2i(textureDimensions(currentTexture));
|
|
21700
|
+
for (var y = -1; y <= 1; y++) {
|
|
21701
|
+
for (var x = -1; x <= 1; x++) {
|
|
21702
|
+
let neighbor = coordinates + vec2i(x, y);
|
|
21703
|
+
if (all(neighbor >= vec2i(0)) && all(neighbor < size)) {
|
|
21704
|
+
let candidate = textureLoad(currentTexture, neighbor, 0);
|
|
21705
|
+
if (candidate.a == chart) {return candidate;}
|
|
21706
|
+
}
|
|
21707
|
+
}
|
|
21708
|
+
}
|
|
21709
|
+
return current;
|
|
21710
|
+
}`,
|
|
21711
|
+
fs: `
|
|
21712
|
+
layout(std140) uniform lightmapFilterUniforms {
|
|
21713
|
+
float weight;
|
|
21714
|
+
int mode;
|
|
21715
|
+
} lightmapFilter;
|
|
21716
|
+
uniform sampler2D currentTexture;
|
|
21717
|
+
uniform sampler2D previousTexture;
|
|
21718
|
+
uniform sampler2D chartTexture;
|
|
21719
|
+
vec4 lightmapFilter_getColor(ivec2 coordinates) {
|
|
21720
|
+
vec4 current = texelFetch(currentTexture, coordinates, 0);
|
|
21721
|
+
if (lightmapFilter.mode == 0) {
|
|
21722
|
+
return vec4(mix(texelFetch(previousTexture, coordinates, 0).rgb, current.rgb, lightmapFilter.weight), current.a);
|
|
21723
|
+
}
|
|
21724
|
+
if (lightmapFilter.mode == 2 || current.a > 0.0) {return current;}
|
|
21725
|
+
float chart = texelFetch(chartTexture, coordinates, 0).r;
|
|
21726
|
+
ivec2 size = textureSize(currentTexture, 0);
|
|
21727
|
+
if (chart <= 0.0) return current;
|
|
21728
|
+
for (int y = -1; y <= 1; y++) {
|
|
21729
|
+
for (int x = -1; x <= 1; x++) {
|
|
21730
|
+
ivec2 neighbor = coordinates + ivec2(x,y);
|
|
21731
|
+
if (all(greaterThanEqual(neighbor, ivec2(0))) && all(lessThan(neighbor,size))) {
|
|
21732
|
+
vec4 candidate = texelFetch(currentTexture, neighbor, 0);
|
|
21733
|
+
if (candidate.a == chart) {return candidate;}
|
|
21734
|
+
}
|
|
21735
|
+
}
|
|
21736
|
+
}
|
|
21737
|
+
return current;
|
|
21738
|
+
}`
|
|
21739
|
+
};
|
|
19877
21740
|
return __toCommonJS(bundle_exports);
|
|
19878
21741
|
})();
|
|
19879
21742
|
return __exports__;
|