@luma.gl/shaders 10.0.0-alpha.10 → 10.0.0-alpha.11
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 +1776 -58
- package/dist/dist.min.js +1394 -147
- package/dist/index.cjs +35 -0
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -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/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/package.json +3 -3
- package/src/index.ts +48 -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/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/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,
|
|
@@ -85,8 +91,13 @@ var __exports__ = (() => {
|
|
|
85
91
|
normalizeByteColor4: () => normalizeByteColor4,
|
|
86
92
|
pathDash: () => pathDash,
|
|
87
93
|
patternFill: () => patternFill,
|
|
94
|
+
pbrAmbientOcclusion: () => pbrAmbientOcclusion,
|
|
95
|
+
pbrContactShadow: () => pbrContactShadow,
|
|
96
|
+
pbrEnvironmentFilter: () => pbrEnvironmentFilter,
|
|
88
97
|
pbrMaterial: () => pbrMaterial,
|
|
89
98
|
pbrScene: () => pbrScene,
|
|
99
|
+
pbrShadow: () => pbrShadow,
|
|
100
|
+
pbrSurface: () => pbrSurface,
|
|
90
101
|
phongMaterial: () => phongMaterial,
|
|
91
102
|
picking: () => picking,
|
|
92
103
|
pointGlow: () => pointGlow,
|
|
@@ -97,6 +108,7 @@ var __exports__ = (() => {
|
|
|
97
108
|
resolveUseByteColors: () => resolveUseByteColors,
|
|
98
109
|
riverWaterMaterial: () => riverWaterMaterial,
|
|
99
110
|
scanWGSLInterface: () => scanWGSLInterface,
|
|
111
|
+
shadow: () => shadow,
|
|
100
112
|
sketchStroke: () => sketchStroke,
|
|
101
113
|
skin: () => skin,
|
|
102
114
|
storageColors: () => storageColors,
|
|
@@ -104,6 +116,7 @@ var __exports__ = (() => {
|
|
|
104
116
|
toHalfFloat: () => toHalfFloat,
|
|
105
117
|
typeToChannelCount: () => typeToChannelCount,
|
|
106
118
|
typeToChannelSuffix: () => typeToChannelSuffix,
|
|
119
|
+
unlitMaterial: () => unlitMaterial,
|
|
107
120
|
validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout,
|
|
108
121
|
valueNoise: () => valueNoise,
|
|
109
122
|
volumeRaymarch: () => volumeRaymarch,
|
|
@@ -5137,6 +5150,35 @@ void main() {
|
|
|
5137
5150
|
out[15] = 1;
|
|
5138
5151
|
return out;
|
|
5139
5152
|
}
|
|
5153
|
+
function affineComponents(matrix) {
|
|
5154
|
+
if (matrix.length !== 16 || Array.from(matrix).some((x) => !Number.isFinite(x)) || matrix[3] !== 0 || matrix[7] !== 0 || matrix[11] !== 0 || matrix[15] !== 1) {
|
|
5155
|
+
throw new RangeError("Expected a finite affine matrix");
|
|
5156
|
+
}
|
|
5157
|
+
const scale2 = [
|
|
5158
|
+
Math.hypot(matrix[0], matrix[1], matrix[2]),
|
|
5159
|
+
Math.hypot(matrix[4], matrix[5], matrix[6]),
|
|
5160
|
+
Math.hypot(matrix[8], matrix[9], matrix[10])
|
|
5161
|
+
];
|
|
5162
|
+
if (scale2.some((x) => x === 0 || !Number.isFinite(x)))
|
|
5163
|
+
throw new RangeError("Singular transform");
|
|
5164
|
+
const rotation = Array.from({ length: 9 }, (_, i) => matrix[Math.floor(i / 3) * 4 + i % 3] / scale2[Math.floor(i / 3)]);
|
|
5165
|
+
for (const [a, b] of [
|
|
5166
|
+
[0, 3],
|
|
5167
|
+
[0, 6],
|
|
5168
|
+
[3, 6]
|
|
5169
|
+
]) {
|
|
5170
|
+
if (Math.abs(rotation[a] * rotation[b] + rotation[a + 1] * rotation[b + 1] + rotation[a + 2] * rotation[b + 2]) > 1e-7) {
|
|
5171
|
+
throw new RangeError("Sheared transforms do not have a TRS decomposition");
|
|
5172
|
+
}
|
|
5173
|
+
}
|
|
5174
|
+
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]);
|
|
5175
|
+
if (determinant2 < 0) {
|
|
5176
|
+
scale2[0] = -scale2[0];
|
|
5177
|
+
for (let i = 0; i < 3; i++)
|
|
5178
|
+
rotation[i] = -rotation[i];
|
|
5179
|
+
}
|
|
5180
|
+
return { rotation, scale: scale2, translation: [matrix[12], matrix[13], matrix[14]] };
|
|
5181
|
+
}
|
|
5140
5182
|
|
|
5141
5183
|
// ../../node_modules/@math.gl/core/dist/gl-matrix/vec4.js
|
|
5142
5184
|
function transformMat43(out, a, m) {
|
|
@@ -5431,27 +5473,15 @@ void main() {
|
|
|
5431
5473
|
* @returns self
|
|
5432
5474
|
*/
|
|
5433
5475
|
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;
|
|
5476
|
+
const { rotation, scale: scale2 } = affineComponents(this);
|
|
5477
|
+
result = result || new Array(16);
|
|
5478
|
+
if (scaleResult)
|
|
5479
|
+
for (let i = 0; i < 3; i++)
|
|
5480
|
+
scaleResult[i] = scale2[i];
|
|
5481
|
+
for (let i = 0; i < 16; i++)
|
|
5482
|
+
result[i] = 0;
|
|
5483
|
+
for (let i = 0; i < 9; i++)
|
|
5484
|
+
result[Math.floor(i / 3) * 4 + i % 3] = rotation[i];
|
|
5455
5485
|
result[15] = 1;
|
|
5456
5486
|
return result;
|
|
5457
5487
|
}
|
|
@@ -5462,21 +5492,13 @@ void main() {
|
|
|
5462
5492
|
* @returns self
|
|
5463
5493
|
*/
|
|
5464
5494
|
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;
|
|
5495
|
+
const { rotation, scale: scale2 } = affineComponents(this);
|
|
5496
|
+
result = result || new Array(9);
|
|
5497
|
+
if (scaleResult)
|
|
5498
|
+
for (let i = 0; i < 3; i++)
|
|
5499
|
+
scaleResult[i] = scale2[i];
|
|
5500
|
+
for (let i = 0; i < 9; i++)
|
|
5501
|
+
result[i] = rotation[i];
|
|
5480
5502
|
return result;
|
|
5481
5503
|
}
|
|
5482
5504
|
// Modifiers
|
|
@@ -12913,6 +12935,42 @@ vec4 dirlight_filterColor(vec4 color) {
|
|
|
12913
12935
|
return uniforms2;
|
|
12914
12936
|
}
|
|
12915
12937
|
|
|
12938
|
+
// src/modules/lighting/unlit-material/unlit-material.ts
|
|
12939
|
+
var SOURCE_WGSL2 = (
|
|
12940
|
+
/* wgsl */
|
|
12941
|
+
`fn unlitMaterial_getColor(surfaceColor: vec4<f32>) -> vec4<f32> {
|
|
12942
|
+
return surfaceColor;
|
|
12943
|
+
}
|
|
12944
|
+
|
|
12945
|
+
// Compatibility with the aggregate Phong/Gouraud material evaluation function.
|
|
12946
|
+
fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, positionWorldspace: vec3<f32>, normalWorldspace: vec3<f32>) -> vec3<f32> {
|
|
12947
|
+
return surfaceColor;
|
|
12948
|
+
}
|
|
12949
|
+
`
|
|
12950
|
+
);
|
|
12951
|
+
var SOURCE_GLSL = (
|
|
12952
|
+
/* glsl */
|
|
12953
|
+
`vec4 unlitMaterial_getColor(vec4 surfaceColor) {
|
|
12954
|
+
return surfaceColor;
|
|
12955
|
+
}
|
|
12956
|
+
|
|
12957
|
+
// Compatibility with the aggregate Phong/Gouraud material evaluation function.
|
|
12958
|
+
vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 positionWorldspace, vec3 normalWorldspace) {
|
|
12959
|
+
return surfaceColor;
|
|
12960
|
+
}
|
|
12961
|
+
`
|
|
12962
|
+
);
|
|
12963
|
+
var unlitMaterial = {
|
|
12964
|
+
name: "unlitMaterial",
|
|
12965
|
+
source: SOURCE_WGSL2,
|
|
12966
|
+
vs: SOURCE_GLSL,
|
|
12967
|
+
fs: SOURCE_GLSL,
|
|
12968
|
+
dependencies: [],
|
|
12969
|
+
bindingLayout: [],
|
|
12970
|
+
uniformTypes: {},
|
|
12971
|
+
defaultUniforms: {}
|
|
12972
|
+
};
|
|
12973
|
+
|
|
12916
12974
|
// src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts
|
|
12917
12975
|
var LAMBERT_WGSL = (
|
|
12918
12976
|
/* wgsl */
|
|
@@ -14542,7 +14600,7 @@ void pbr_setPositionNormalTangentUV(
|
|
|
14542
14600
|
vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
|
|
14543
14601
|
pbr_vTBN = mat3(tangentW, bitangentW, normalW);
|
|
14544
14602
|
#else // HAS_TANGENTS != 1
|
|
14545
|
-
pbr_vNormal = normalize(vec3(pbrProjection.
|
|
14603
|
+
pbr_vNormal = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
|
|
14546
14604
|
#endif
|
|
14547
14605
|
#endif
|
|
14548
14606
|
|
|
@@ -15549,7 +15607,9 @@ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
|
|
|
15549
15607
|
}
|
|
15550
15608
|
|
|
15551
15609
|
// Visibility for the first four spotlights; environment and other lights are unaffected.
|
|
15552
|
-
|
|
15610
|
+
float pbr_ambientVisibility = 1.0;
|
|
15611
|
+
|
|
15612
|
+
vec4 pbr_filterColorWithShadows(vec4 vertexColor, float directionalVisibility, vec4 pointVisibility, vec4 spotVisibility)
|
|
15553
15613
|
{
|
|
15554
15614
|
vec2 baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
|
|
15555
15615
|
vec2 metallicRoughnessUV = getMaterialUV(
|
|
@@ -15645,7 +15705,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15645
15705
|
color.rgb = baseColor.rgb;
|
|
15646
15706
|
#ifdef HAS_LIGHTMAP
|
|
15647
15707
|
if (pbrMaterial.lightmapMapEnabled) {
|
|
15648
|
-
color *= lightmapIrradiance / M_PI;
|
|
15708
|
+
color *= lightmapIrradiance / M_PI * pbr_ambientVisibility;
|
|
15649
15709
|
#ifdef HAS_OCCLUSIONMAP
|
|
15650
15710
|
if (pbrMaterial.occlusionMapEnabled) {
|
|
15651
15711
|
float ao = texture(pbr_occlusionSampler, occlusionUV).r;
|
|
@@ -15747,12 +15807,12 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15747
15807
|
|
|
15748
15808
|
#ifdef USE_LIGHTS
|
|
15749
15809
|
PBRInfo_setAmbientLight(pbrInfo);
|
|
15750
|
-
color += calculateFinalColor(pbrInfo, lighting.ambientColor);
|
|
15810
|
+
color += calculateFinalColor(pbrInfo, lighting.ambientColor * pbr_ambientVisibility);
|
|
15751
15811
|
|
|
15752
15812
|
for(int i = 0; i < lighting.directionalLightCount; i++) {
|
|
15753
15813
|
if (i < lighting.directionalLightCount) {
|
|
15754
15814
|
PBRInfo_setDirectionalLight(pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
15755
|
-
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
|
|
15815
|
+
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color * (i == 0 ? clamp(directionalVisibility, 0.0, 1.0) : 1.0));
|
|
15756
15816
|
}
|
|
15757
15817
|
}
|
|
15758
15818
|
|
|
@@ -15760,7 +15820,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15760
15820
|
if (i < lighting.pointLightCount) {
|
|
15761
15821
|
PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
|
|
15762
15822
|
float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
|
|
15763
|
-
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
|
|
15823
|
+
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color * (i < 4 ? clamp(pointVisibility[min(i, 3)], 0.0, 1.0) : 1.0) / attenuation);
|
|
15764
15824
|
}
|
|
15765
15825
|
}
|
|
15766
15826
|
|
|
@@ -15786,6 +15846,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15786
15846
|
}
|
|
15787
15847
|
#endif
|
|
15788
15848
|
|
|
15849
|
+
vec3 indirectBaseColor = color;
|
|
15789
15850
|
#ifdef USE_IBL
|
|
15790
15851
|
if (pbrMaterial.IBLenabled) {
|
|
15791
15852
|
color += getIBLContribution(pbrInfo, n, reflection);
|
|
@@ -15794,6 +15855,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
15794
15855
|
|
|
15795
15856
|
// The pinned KHR_lightmap draft explicitly defines c_diff = (1 - metallic) * baseColor.
|
|
15796
15857
|
color += baseColor.rgb * (1.0 - metallic) * lightmapIrradiance / M_PI;
|
|
15858
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
15797
15859
|
|
|
15798
15860
|
#ifdef HAS_OCCLUSIONMAP
|
|
15799
15861
|
if (pbrMaterial.occlusionMapEnabled) {
|
|
@@ -16026,7 +16088,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16026
16088
|
PBRInfo_setAmbientLight(pbrInfo);
|
|
16027
16089
|
color += calculateMaterialLightColor(
|
|
16028
16090
|
pbrInfo,
|
|
16029
|
-
lighting.ambientColor,
|
|
16091
|
+
lighting.ambientColor * pbr_ambientVisibility,
|
|
16030
16092
|
clearcoatNormal,
|
|
16031
16093
|
clearcoatFactor,
|
|
16032
16094
|
clearcoatRoughness,
|
|
@@ -16042,7 +16104,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16042
16104
|
PBRInfo_setDirectionalLight(pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
16043
16105
|
color += calculateMaterialLightColor(
|
|
16044
16106
|
pbrInfo,
|
|
16045
|
-
lighting_getDirectionalLight(i).color,
|
|
16107
|
+
lighting_getDirectionalLight(i).color * (i == 0 ? clamp(directionalVisibility, 0.0, 1.0) : 1.0),
|
|
16046
16108
|
clearcoatNormal,
|
|
16047
16109
|
clearcoatFactor,
|
|
16048
16110
|
clearcoatRoughness,
|
|
@@ -16053,7 +16115,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16053
16115
|
);
|
|
16054
16116
|
color += calculateDiffuseTransmissionLight(
|
|
16055
16117
|
pbrInfo,
|
|
16056
|
-
lighting_getDirectionalLight(i).color,
|
|
16118
|
+
lighting_getDirectionalLight(i).color * (i == 0 ? clamp(directionalVisibility, 0.0, 1.0) : 1.0),
|
|
16057
16119
|
diffuseTransmissionColor,
|
|
16058
16120
|
diffuseTransmission,
|
|
16059
16121
|
multiscatterColor,
|
|
@@ -16069,7 +16131,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16069
16131
|
float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
|
|
16070
16132
|
color += calculateMaterialLightColor(
|
|
16071
16133
|
pbrInfo,
|
|
16072
|
-
lighting_getPointLight(i).color / attenuation,
|
|
16134
|
+
lighting_getPointLight(i).color * (i < 4 ? clamp(pointVisibility[min(i, 3)], 0.0, 1.0) : 1.0) / attenuation,
|
|
16073
16135
|
clearcoatNormal,
|
|
16074
16136
|
clearcoatFactor,
|
|
16075
16137
|
clearcoatRoughness,
|
|
@@ -16080,7 +16142,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16080
16142
|
);
|
|
16081
16143
|
color += calculateDiffuseTransmissionLight(
|
|
16082
16144
|
pbrInfo,
|
|
16083
|
-
lighting_getPointLight(i).color / attenuation,
|
|
16145
|
+
lighting_getPointLight(i).color * (i < 4 ? clamp(pointVisibility[min(i, 3)], 0.0, 1.0) : 1.0) / attenuation,
|
|
16084
16146
|
diffuseTransmissionColor,
|
|
16085
16147
|
diffuseTransmission,
|
|
16086
16148
|
multiscatterColor,
|
|
@@ -16149,6 +16211,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16149
16211
|
}
|
|
16150
16212
|
#endif
|
|
16151
16213
|
|
|
16214
|
+
vec3 indirectBaseColor = color;
|
|
16152
16215
|
// Calculate lighting contribution from image based lighting source (IBL)
|
|
16153
16216
|
#ifdef USE_IBL
|
|
16154
16217
|
if (pbrMaterial.IBLenabled) {
|
|
@@ -16183,6 +16246,8 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16183
16246
|
(1.0 - diffuseTransmission) * baseLayerEnergy * lightmapIrradiance / M_PI;
|
|
16184
16247
|
#endif
|
|
16185
16248
|
|
|
16249
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
16250
|
+
|
|
16186
16251
|
// Apply optional PBR terms for additional (optional) shading
|
|
16187
16252
|
#ifdef HAS_OCCLUSIONMAP
|
|
16188
16253
|
if (pbrMaterial.occlusionMapEnabled) {
|
|
@@ -16244,6 +16309,21 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
|
|
|
16244
16309
|
return vec4(applySceneColorManagement(color), alpha);
|
|
16245
16310
|
}
|
|
16246
16311
|
|
|
16312
|
+
// Depth-only passes use the same base-color alpha, vertex color and UV transform.
|
|
16313
|
+
void pbr_discardMaskedFragment(vec4 vertexColor) {
|
|
16314
|
+
#ifdef ALPHA_CUTOFF
|
|
16315
|
+
float alpha = pbrMaterial.baseColorFactor.a * vertexColor.a;
|
|
16316
|
+
#ifdef HAS_BASECOLORMAP
|
|
16317
|
+
alpha *= texture(pbr_baseColorSampler, getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform)).a;
|
|
16318
|
+
#endif
|
|
16319
|
+
if (alpha < pbrMaterial.alphaCutoff) {discard;}
|
|
16320
|
+
#endif
|
|
16321
|
+
}
|
|
16322
|
+
|
|
16323
|
+
vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility) {
|
|
16324
|
+
return pbr_filterColorWithShadows(vertexColor, 1.0, vec4(1.0), spotVisibility);
|
|
16325
|
+
}
|
|
16326
|
+
|
|
16247
16327
|
vec4 pbr_filterColor(vec4 vertexColor) {
|
|
16248
16328
|
return pbr_filterColorWithSpotShadows(vertexColor, vec4(1.0));
|
|
16249
16329
|
}
|
|
@@ -17368,7 +17448,9 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
|
|
|
17368
17448
|
}
|
|
17369
17449
|
|
|
17370
17450
|
// Visibility for the first four spotlights; environment and other lights are unaffected.
|
|
17371
|
-
|
|
17451
|
+
var<private> pbr_ambientVisibility: f32 = 1.0;
|
|
17452
|
+
|
|
17453
|
+
fn pbr_filterColorWithShadows(vertexColor: vec4<f32>, directionalVisibility: f32, pointVisibility: vec4f, spotVisibility: vec4f) -> vec4<f32> {
|
|
17372
17454
|
let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
|
|
17373
17455
|
let metallicRoughnessUV = getMaterialUV(
|
|
17374
17456
|
pbrMaterial.metallicRoughnessUVSet,
|
|
@@ -17461,7 +17543,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17461
17543
|
color = baseColor.rgb;
|
|
17462
17544
|
#ifdef HAS_LIGHTMAP
|
|
17463
17545
|
if (pbrMaterial.lightmapMapEnabled != 0u) {
|
|
17464
|
-
color *= lightmapIrradiance / M_PI;
|
|
17546
|
+
color *= lightmapIrradiance / M_PI * pbr_ambientVisibility;
|
|
17465
17547
|
#ifdef HAS_OCCLUSIONMAP
|
|
17466
17548
|
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
17467
17549
|
let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
|
|
@@ -17564,12 +17646,12 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17564
17646
|
|
|
17565
17647
|
#ifdef USE_LIGHTS
|
|
17566
17648
|
PBRInfo_setAmbientLight(&pbrInfo);
|
|
17567
|
-
color += calculateFinalColor(pbrInfo, lighting.ambientColor);
|
|
17649
|
+
color += calculateFinalColor(pbrInfo, lighting.ambientColor * pbr_ambientVisibility);
|
|
17568
17650
|
|
|
17569
17651
|
for (var i = 0; i < lighting.directionalLightCount; i++) {
|
|
17570
17652
|
if (i < lighting.directionalLightCount) {
|
|
17571
17653
|
PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
17572
|
-
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
|
|
17654
|
+
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color * select(1.0, clamp(directionalVisibility, 0.0, 1.0), i == 0));
|
|
17573
17655
|
}
|
|
17574
17656
|
}
|
|
17575
17657
|
|
|
@@ -17580,7 +17662,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17580
17662
|
lighting_getPointLight(i),
|
|
17581
17663
|
distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
|
|
17582
17664
|
);
|
|
17583
|
-
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
|
|
17665
|
+
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color * select(1.0, clamp(pointVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation);
|
|
17584
17666
|
}
|
|
17585
17667
|
}
|
|
17586
17668
|
|
|
@@ -17609,7 +17691,8 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17609
17691
|
}
|
|
17610
17692
|
#endif
|
|
17611
17693
|
|
|
17612
|
-
|
|
17694
|
+
let indirectBaseColor = color;
|
|
17695
|
+
#ifdef USE_IBL
|
|
17613
17696
|
if (pbrMaterial.IBLenabled != 0) {
|
|
17614
17697
|
color += getIBLContribution(pbrInfo, n, reflection);
|
|
17615
17698
|
}
|
|
@@ -17617,6 +17700,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17617
17700
|
|
|
17618
17701
|
// The pinned KHR_lightmap draft explicitly defines c_diff = (1 - metallic) * baseColor.
|
|
17619
17702
|
color += baseColor.rgb * (1.0 - metallic) * lightmapIrradiance / M_PI;
|
|
17703
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
17620
17704
|
|
|
17621
17705
|
#ifdef HAS_OCCLUSIONMAP
|
|
17622
17706
|
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
@@ -17915,7 +17999,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17915
17999
|
PBRInfo_setAmbientLight(&pbrInfo);
|
|
17916
18000
|
color += calculateMaterialLightColor(
|
|
17917
18001
|
pbrInfo,
|
|
17918
|
-
lighting.ambientColor,
|
|
18002
|
+
lighting.ambientColor * pbr_ambientVisibility,
|
|
17919
18003
|
clearcoatNormal,
|
|
17920
18004
|
clearcoatFactor,
|
|
17921
18005
|
clearcoatRoughness,
|
|
@@ -17931,7 +18015,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17931
18015
|
PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
|
|
17932
18016
|
color += calculateMaterialLightColor(
|
|
17933
18017
|
pbrInfo,
|
|
17934
|
-
lighting_getDirectionalLight(i).color,
|
|
18018
|
+
lighting_getDirectionalLight(i).color * select(1.0, clamp(directionalVisibility, 0.0, 1.0), i == 0),
|
|
17935
18019
|
clearcoatNormal,
|
|
17936
18020
|
clearcoatFactor,
|
|
17937
18021
|
clearcoatRoughness,
|
|
@@ -17942,7 +18026,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17942
18026
|
);
|
|
17943
18027
|
color += calculateDiffuseTransmissionLight(
|
|
17944
18028
|
pbrInfo,
|
|
17945
|
-
lighting_getDirectionalLight(i).color,
|
|
18029
|
+
lighting_getDirectionalLight(i).color * select(1.0, clamp(directionalVisibility, 0.0, 1.0), i == 0),
|
|
17946
18030
|
diffuseTransmissionColor,
|
|
17947
18031
|
diffuseTransmission,
|
|
17948
18032
|
multiscatterColor,
|
|
@@ -17961,7 +18045,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17961
18045
|
);
|
|
17962
18046
|
color += calculateMaterialLightColor(
|
|
17963
18047
|
pbrInfo,
|
|
17964
|
-
lighting_getPointLight(i).color / attenuation,
|
|
18048
|
+
lighting_getPointLight(i).color * select(1.0, clamp(pointVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,
|
|
17965
18049
|
clearcoatNormal,
|
|
17966
18050
|
clearcoatFactor,
|
|
17967
18051
|
clearcoatRoughness,
|
|
@@ -17972,7 +18056,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
17972
18056
|
);
|
|
17973
18057
|
color += calculateDiffuseTransmissionLight(
|
|
17974
18058
|
pbrInfo,
|
|
17975
|
-
lighting_getPointLight(i).color / attenuation,
|
|
18059
|
+
lighting_getPointLight(i).color * select(1.0, clamp(pointVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,
|
|
17976
18060
|
diffuseTransmissionColor,
|
|
17977
18061
|
diffuseTransmission,
|
|
17978
18062
|
multiscatterColor,
|
|
@@ -18041,6 +18125,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
18041
18125
|
}
|
|
18042
18126
|
#endif
|
|
18043
18127
|
|
|
18128
|
+
let indirectBaseColor = color;
|
|
18044
18129
|
// Calculate lighting contribution from image based lighting source (IBL)
|
|
18045
18130
|
#ifdef USE_IBL
|
|
18046
18131
|
if (pbrMaterial.IBLenabled != 0) {
|
|
@@ -18075,6 +18160,8 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
18075
18160
|
(1.0 - diffuseTransmission) * baseLayerEnergy * lightmapIrradiance / M_PI;
|
|
18076
18161
|
#endif
|
|
18077
18162
|
|
|
18163
|
+
color = indirectBaseColor + (color - indirectBaseColor) * pbr_ambientVisibility;
|
|
18164
|
+
|
|
18078
18165
|
// Apply optional PBR terms for additional (optional) shading
|
|
18079
18166
|
#ifdef HAS_OCCLUSIONMAP
|
|
18080
18167
|
if (pbrMaterial.occlusionMapEnabled != 0) {
|
|
@@ -18137,6 +18224,21 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
|
|
|
18137
18224
|
return vec4<f32>(applySceneColorManagement(color), alpha);
|
|
18138
18225
|
}
|
|
18139
18226
|
|
|
18227
|
+
// Depth-only passes use the same base-color alpha, vertex color and UV transform.
|
|
18228
|
+
fn pbr_discardMaskedFragment(vertexColor: vec4f) {
|
|
18229
|
+
#ifdef ALPHA_CUTOFF
|
|
18230
|
+
var alpha = pbrMaterial.baseColorFactor.a * vertexColor.a;
|
|
18231
|
+
#ifdef HAS_BASECOLORMAP
|
|
18232
|
+
alpha *= textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform)).a;
|
|
18233
|
+
#endif
|
|
18234
|
+
if (alpha < pbrMaterial.alphaCutoff) {discard;}
|
|
18235
|
+
#endif
|
|
18236
|
+
}
|
|
18237
|
+
|
|
18238
|
+
fn pbr_filterColorWithSpotShadows(vertexColor: vec4f, spotVisibility: vec4f) -> vec4f {
|
|
18239
|
+
return pbr_filterColorWithShadows(vertexColor, 1.0, vec4f(1.0), spotVisibility);
|
|
18240
|
+
}
|
|
18241
|
+
|
|
18140
18242
|
fn pbr_filterColor(vertexColor: vec4<f32>) -> vec4<f32> {
|
|
18141
18243
|
return pbr_filterColorWithSpotShadows(vertexColor, vec4f(1.0));
|
|
18142
18244
|
}
|
|
@@ -19874,6 +19976,1622 @@ fn globeClouds_getColor(camera: vec3f, direction: vec3f) -> vec4f {
|
|
|
19874
19976
|
`
|
|
19875
19977
|
)
|
|
19876
19978
|
};
|
|
19979
|
+
|
|
19980
|
+
// src/modules/lighting/prefiltered-environment/prefiltered-environment.ts
|
|
19981
|
+
var GLSL_UNIFORMS = (
|
|
19982
|
+
/* glsl */
|
|
19983
|
+
`layout(std140) uniform pbrEnvironmentFilterUniforms {
|
|
19984
|
+
int face;
|
|
19985
|
+
float roughness;
|
|
19986
|
+
int mode;
|
|
19987
|
+
int sampleCount;
|
|
19988
|
+
int sourceEncoding;
|
|
19989
|
+
} pbrEnvironmentFilter;
|
|
19990
|
+
|
|
19991
|
+
uniform sampler2D pbrEnvironmentSource;
|
|
19992
|
+
`
|
|
19993
|
+
);
|
|
19994
|
+
var WGSL_UNIFORMS = (
|
|
19995
|
+
/* wgsl */
|
|
19996
|
+
`struct PBREnvironmentFilterUniforms {
|
|
19997
|
+
face: i32,
|
|
19998
|
+
roughness: f32,
|
|
19999
|
+
mode: i32,
|
|
20000
|
+
sampleCount: i32,
|
|
20001
|
+
sourceEncoding: i32,
|
|
20002
|
+
};
|
|
20003
|
+
|
|
20004
|
+
@group(0) @binding(auto) var<uniform> pbrEnvironmentFilter: PBREnvironmentFilterUniforms;
|
|
20005
|
+
@group(0) @binding(auto) var pbrEnvironmentSource: texture_2d<f32>;
|
|
20006
|
+
@group(0) @binding(auto) var pbrEnvironmentSourceSampler: sampler;
|
|
20007
|
+
`
|
|
20008
|
+
);
|
|
20009
|
+
var pbrEnvironmentFilter = {
|
|
20010
|
+
name: "pbrEnvironmentFilter",
|
|
20011
|
+
bindingLayout: [
|
|
20012
|
+
{ name: "pbrEnvironmentFilter", group: 0 },
|
|
20013
|
+
{ name: "pbrEnvironmentSource", group: 0 }
|
|
20014
|
+
],
|
|
20015
|
+
fs: GLSL_UNIFORMS,
|
|
20016
|
+
source: WGSL_UNIFORMS,
|
|
20017
|
+
getUniforms: (properties) => properties,
|
|
20018
|
+
uniformTypes: {
|
|
20019
|
+
face: "i32",
|
|
20020
|
+
roughness: "f32",
|
|
20021
|
+
mode: "i32",
|
|
20022
|
+
sampleCount: "i32",
|
|
20023
|
+
sourceEncoding: "i32"
|
|
20024
|
+
},
|
|
20025
|
+
defaultUniforms: {
|
|
20026
|
+
face: 0,
|
|
20027
|
+
roughness: 0,
|
|
20028
|
+
mode: 0,
|
|
20029
|
+
sampleCount: 64,
|
|
20030
|
+
sourceEncoding: 0
|
|
20031
|
+
}
|
|
20032
|
+
};
|
|
20033
|
+
var PBR_ENVIRONMENT_FRAGMENT_GLSL = (
|
|
20034
|
+
/* glsl */
|
|
20035
|
+
`#version 300 es
|
|
20036
|
+
precision highp float;
|
|
20037
|
+
precision highp int;
|
|
20038
|
+
|
|
20039
|
+
in vec2 uv;
|
|
20040
|
+
out vec4 fragmentColor;
|
|
20041
|
+
|
|
20042
|
+
const float ENVIRONMENT_PI = 3.141592653589793;
|
|
20043
|
+
|
|
20044
|
+
vec2 getEnvironmentHammersley(uint index, uint sampleCount)
|
|
20045
|
+
{
|
|
20046
|
+
uint reversedBits = (index << 16u) | (index >> 16u);
|
|
20047
|
+
reversedBits = ((reversedBits & 0x55555555u) << 1u) |
|
|
20048
|
+
((reversedBits & 0xAAAAAAAAu) >> 1u);
|
|
20049
|
+
reversedBits = ((reversedBits & 0x33333333u) << 2u) |
|
|
20050
|
+
((reversedBits & 0xCCCCCCCCu) >> 2u);
|
|
20051
|
+
reversedBits = ((reversedBits & 0x0F0F0F0Fu) << 4u) |
|
|
20052
|
+
((reversedBits & 0xF0F0F0F0u) >> 4u);
|
|
20053
|
+
reversedBits = ((reversedBits & 0x00FF00FFu) << 8u) |
|
|
20054
|
+
((reversedBits & 0xFF00FF00u) >> 8u);
|
|
20055
|
+
return vec2(
|
|
20056
|
+
float(index) / float(sampleCount),
|
|
20057
|
+
float(reversedBits) * 2.3283064365386963e-10
|
|
20058
|
+
);
|
|
20059
|
+
}
|
|
20060
|
+
|
|
20061
|
+
vec3 getEnvironmentFaceDirection(int face, vec2 textureCoordinate)
|
|
20062
|
+
{
|
|
20063
|
+
vec2 coordinate = textureCoordinate * 2.0 - 1.0;
|
|
20064
|
+
if (face == 0) return normalize(vec3(1.0, -coordinate.y, -coordinate.x));
|
|
20065
|
+
if (face == 1) return normalize(vec3(-1.0, -coordinate.y, coordinate.x));
|
|
20066
|
+
if (face == 2) return normalize(vec3(coordinate.x, 1.0, coordinate.y));
|
|
20067
|
+
if (face == 3) return normalize(vec3(coordinate.x, -1.0, -coordinate.y));
|
|
20068
|
+
if (face == 4) return normalize(vec3(coordinate.x, -coordinate.y, 1.0));
|
|
20069
|
+
return normalize(vec3(-coordinate.x, -coordinate.y, -1.0));
|
|
20070
|
+
}
|
|
20071
|
+
|
|
20072
|
+
mat3 getEnvironmentTangentBasis(vec3 normal)
|
|
20073
|
+
{
|
|
20074
|
+
vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
20075
|
+
vec3 tangent = normalize(cross(up, normal));
|
|
20076
|
+
return mat3(tangent, cross(normal, tangent), normal);
|
|
20077
|
+
}
|
|
20078
|
+
|
|
20079
|
+
vec3 sampleEnvironmentDirection(vec3 direction)
|
|
20080
|
+
{
|
|
20081
|
+
vec3 normalizedDirection = normalize(direction);
|
|
20082
|
+
vec2 textureCoordinate = vec2(
|
|
20083
|
+
atan(normalizedDirection.z, normalizedDirection.x) / (2.0 * ENVIRONMENT_PI) + 0.5,
|
|
20084
|
+
acos(clamp(normalizedDirection.y, -1.0, 1.0)) / ENVIRONMENT_PI
|
|
20085
|
+
);
|
|
20086
|
+
vec3 color = texture(pbrEnvironmentSource, textureCoordinate).rgb;
|
|
20087
|
+
if (pbrEnvironmentFilter.sourceEncoding == 1) {
|
|
20088
|
+
vec3 lower = color / 12.92;
|
|
20089
|
+
vec3 upper = pow((color + 0.055) / 1.055, vec3(2.4));
|
|
20090
|
+
color = mix(lower, upper, step(vec3(0.04045), color));
|
|
20091
|
+
}
|
|
20092
|
+
return color;
|
|
20093
|
+
}
|
|
20094
|
+
|
|
20095
|
+
vec3 importanceSampleEnvironment(vec2 sequence, vec3 normal, float roughness)
|
|
20096
|
+
{
|
|
20097
|
+
float alpha = max(roughness * roughness, 0.0001);
|
|
20098
|
+
float azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20099
|
+
float cosine = sqrt(
|
|
20100
|
+
(1.0 - sequence.y) / max(1.0 + (alpha * alpha - 1.0) * sequence.y, 0.0001)
|
|
20101
|
+
);
|
|
20102
|
+
float sine = sqrt(max(1.0 - cosine * cosine, 0.0));
|
|
20103
|
+
vec3 halfVector = vec3(cos(azimuth) * sine, sin(azimuth) * sine, cosine);
|
|
20104
|
+
return normalize(getEnvironmentTangentBasis(normal) * halfVector);
|
|
20105
|
+
}
|
|
20106
|
+
|
|
20107
|
+
float getEnvironmentGeometry(float normalDotDirection, float roughness)
|
|
20108
|
+
{
|
|
20109
|
+
float alpha = roughness * roughness;
|
|
20110
|
+
float factor = alpha * 0.5;
|
|
20111
|
+
return normalDotDirection / max(normalDotDirection * (1.0 - factor) + factor, 0.0001);
|
|
20112
|
+
}
|
|
20113
|
+
|
|
20114
|
+
vec2 integrateEnvironmentBRDF(vec2 textureCoordinate, int sampleCount)
|
|
20115
|
+
{
|
|
20116
|
+
float normalDotView = max(textureCoordinate.x, 0.001);
|
|
20117
|
+
float roughness = 1.0 - textureCoordinate.y;
|
|
20118
|
+
vec3 viewDirection = vec3(sqrt(max(1.0 - normalDotView * normalDotView, 0.0)), 0.0, normalDotView);
|
|
20119
|
+
vec2 integration = vec2(0.0);
|
|
20120
|
+
|
|
20121
|
+
for (int sampleIndex = 0; sampleIndex < 1024; sampleIndex++) {
|
|
20122
|
+
if (sampleIndex >= sampleCount) break;
|
|
20123
|
+
vec3 halfVector = importanceSampleEnvironment(
|
|
20124
|
+
getEnvironmentHammersley(uint(sampleIndex), uint(sampleCount)),
|
|
20125
|
+
vec3(0.0, 0.0, 1.0),
|
|
20126
|
+
roughness
|
|
20127
|
+
);
|
|
20128
|
+
vec3 lightDirection = normalize(2.0 * dot(viewDirection, halfVector) * halfVector - viewDirection);
|
|
20129
|
+
float normalDotLight = max(lightDirection.z, 0.0);
|
|
20130
|
+
float normalDotHalf = max(halfVector.z, 0.0);
|
|
20131
|
+
float viewDotHalf = max(dot(viewDirection, halfVector), 0.0);
|
|
20132
|
+
if (normalDotLight > 0.0) {
|
|
20133
|
+
float visibility = getEnvironmentGeometry(normalDotView, roughness) *
|
|
20134
|
+
getEnvironmentGeometry(normalDotLight, roughness) * viewDotHalf /
|
|
20135
|
+
max(normalDotHalf * normalDotView, 0.0001);
|
|
20136
|
+
float fresnel = pow(1.0 - viewDotHalf, 5.0);
|
|
20137
|
+
integration += vec2(1.0 - fresnel, fresnel) * visibility;
|
|
20138
|
+
}
|
|
20139
|
+
}
|
|
20140
|
+
return integration / float(sampleCount);
|
|
20141
|
+
}
|
|
20142
|
+
|
|
20143
|
+
vec3 integrateEnvironmentDirection(vec3 normal, int sampleCount)
|
|
20144
|
+
{
|
|
20145
|
+
vec3 accumulatedColor = vec3(0.0);
|
|
20146
|
+
float accumulatedWeight = 0.0;
|
|
20147
|
+
|
|
20148
|
+
for (int sampleIndex = 0; sampleIndex < 1024; sampleIndex++) {
|
|
20149
|
+
if (sampleIndex >= sampleCount) break;
|
|
20150
|
+
vec2 sequence = getEnvironmentHammersley(uint(sampleIndex), uint(sampleCount));
|
|
20151
|
+
vec3 direction;
|
|
20152
|
+
float sampleWeight;
|
|
20153
|
+
|
|
20154
|
+
if (pbrEnvironmentFilter.mode == 1) {
|
|
20155
|
+
float azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20156
|
+
float cosine = sqrt(1.0 - sequence.y);
|
|
20157
|
+
float sine = sqrt(sequence.y);
|
|
20158
|
+
direction = normalize(
|
|
20159
|
+
getEnvironmentTangentBasis(normal) *
|
|
20160
|
+
vec3(cos(azimuth) * sine, sin(azimuth) * sine, cosine)
|
|
20161
|
+
);
|
|
20162
|
+
sampleWeight = 1.0;
|
|
20163
|
+
} else {
|
|
20164
|
+
vec3 halfVector = importanceSampleEnvironment(sequence, normal, pbrEnvironmentFilter.roughness);
|
|
20165
|
+
direction = normalize(2.0 * dot(normal, halfVector) * halfVector - normal);
|
|
20166
|
+
sampleWeight = max(dot(normal, direction), 0.0);
|
|
20167
|
+
}
|
|
20168
|
+
|
|
20169
|
+
accumulatedColor += sampleEnvironmentDirection(direction) * sampleWeight;
|
|
20170
|
+
accumulatedWeight += sampleWeight;
|
|
20171
|
+
}
|
|
20172
|
+
|
|
20173
|
+
return accumulatedColor / max(accumulatedWeight, 0.0001);
|
|
20174
|
+
}
|
|
20175
|
+
|
|
20176
|
+
void main(void)
|
|
20177
|
+
{
|
|
20178
|
+
int sampleCount = max(pbrEnvironmentFilter.sampleCount, 1);
|
|
20179
|
+
if (pbrEnvironmentFilter.mode == 2) {
|
|
20180
|
+
fragmentColor = vec4(integrateEnvironmentBRDF(uv, sampleCount), 0.0, 1.0);
|
|
20181
|
+
return;
|
|
20182
|
+
}
|
|
20183
|
+
|
|
20184
|
+
vec3 direction = getEnvironmentFaceDirection(pbrEnvironmentFilter.face, uv);
|
|
20185
|
+
fragmentColor = vec4(integrateEnvironmentDirection(direction, sampleCount), 1.0);
|
|
20186
|
+
}
|
|
20187
|
+
`
|
|
20188
|
+
);
|
|
20189
|
+
var PBR_ENVIRONMENT_FRAGMENT_WGSL = (
|
|
20190
|
+
/* wgsl */
|
|
20191
|
+
`const ENVIRONMENT_PI: f32 = 3.141592653589793;
|
|
20192
|
+
|
|
20193
|
+
fn getEnvironmentHammersley(index: u32, sampleCount: u32) -> vec2f {
|
|
20194
|
+
return vec2f(f32(index) / f32(sampleCount), f32(reverseBits(index)) * 2.3283064365386963e-10);
|
|
20195
|
+
}
|
|
20196
|
+
|
|
20197
|
+
fn getEnvironmentFaceDirection(face: i32, textureCoordinate: vec2f) -> vec3f {
|
|
20198
|
+
let coordinate = textureCoordinate * 2.0 - 1.0;
|
|
20199
|
+
if (face == 0) { return normalize(vec3f(1.0, -coordinate.y, -coordinate.x)); }
|
|
20200
|
+
if (face == 1) { return normalize(vec3f(-1.0, -coordinate.y, coordinate.x)); }
|
|
20201
|
+
if (face == 2) { return normalize(vec3f(coordinate.x, 1.0, coordinate.y)); }
|
|
20202
|
+
if (face == 3) { return normalize(vec3f(coordinate.x, -1.0, -coordinate.y)); }
|
|
20203
|
+
if (face == 4) { return normalize(vec3f(coordinate.x, -coordinate.y, 1.0)); }
|
|
20204
|
+
return normalize(vec3f(-coordinate.x, -coordinate.y, -1.0));
|
|
20205
|
+
}
|
|
20206
|
+
|
|
20207
|
+
fn getEnvironmentTangentBasis(normal: vec3f) -> mat3x3f {
|
|
20208
|
+
var up = vec3f(1.0, 0.0, 0.0);
|
|
20209
|
+
if (abs(normal.z) < 0.999) {
|
|
20210
|
+
up = vec3f(0.0, 0.0, 1.0);
|
|
20211
|
+
}
|
|
20212
|
+
let tangent = normalize(cross(up, normal));
|
|
20213
|
+
return mat3x3f(tangent, cross(normal, tangent), normal);
|
|
20214
|
+
}
|
|
20215
|
+
|
|
20216
|
+
fn sampleEnvironmentDirection(direction: vec3f) -> vec3f {
|
|
20217
|
+
let normalizedDirection = normalize(direction);
|
|
20218
|
+
let textureCoordinate = vec2f(
|
|
20219
|
+
atan2(normalizedDirection.z, normalizedDirection.x) / (2.0 * ENVIRONMENT_PI) + 0.5,
|
|
20220
|
+
acos(clamp(normalizedDirection.y, -1.0, 1.0)) / ENVIRONMENT_PI
|
|
20221
|
+
);
|
|
20222
|
+
var color = textureSampleLevel(
|
|
20223
|
+
pbrEnvironmentSource,
|
|
20224
|
+
pbrEnvironmentSourceSampler,
|
|
20225
|
+
textureCoordinate,
|
|
20226
|
+
0.0
|
|
20227
|
+
).rgb;
|
|
20228
|
+
if (pbrEnvironmentFilter.sourceEncoding == 1) {
|
|
20229
|
+
let lower = color / 12.92;
|
|
20230
|
+
let upper = pow((color + 0.055) / 1.055, vec3f(2.4));
|
|
20231
|
+
color = mix(lower, upper, step(vec3f(0.04045), color));
|
|
20232
|
+
}
|
|
20233
|
+
return color;
|
|
20234
|
+
}
|
|
20235
|
+
|
|
20236
|
+
fn importanceSampleEnvironment(sequence: vec2f, normal: vec3f, roughness: f32) -> vec3f {
|
|
20237
|
+
let alpha = max(roughness * roughness, 0.0001);
|
|
20238
|
+
let azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20239
|
+
let cosine = sqrt(
|
|
20240
|
+
(1.0 - sequence.y) / max(1.0 + (alpha * alpha - 1.0) * sequence.y, 0.0001)
|
|
20241
|
+
);
|
|
20242
|
+
let sine = sqrt(max(1.0 - cosine * cosine, 0.0));
|
|
20243
|
+
let halfVector = vec3f(cos(azimuth) * sine, sin(azimuth) * sine, cosine);
|
|
20244
|
+
return normalize(getEnvironmentTangentBasis(normal) * halfVector);
|
|
20245
|
+
}
|
|
20246
|
+
|
|
20247
|
+
fn getEnvironmentGeometry(normalDotDirection: f32, roughness: f32) -> f32 {
|
|
20248
|
+
let alpha = roughness * roughness;
|
|
20249
|
+
let factor = alpha * 0.5;
|
|
20250
|
+
return normalDotDirection / max(normalDotDirection * (1.0 - factor) + factor, 0.0001);
|
|
20251
|
+
}
|
|
20252
|
+
|
|
20253
|
+
fn integrateEnvironmentBRDF(textureCoordinate: vec2f, sampleCount: u32) -> vec2f {
|
|
20254
|
+
let normalDotView = max(textureCoordinate.x, 0.001);
|
|
20255
|
+
let roughness = 1.0 - textureCoordinate.y;
|
|
20256
|
+
let viewDirection = vec3f(
|
|
20257
|
+
sqrt(max(1.0 - normalDotView * normalDotView, 0.0)),
|
|
20258
|
+
0.0,
|
|
20259
|
+
normalDotView
|
|
20260
|
+
);
|
|
20261
|
+
var integration = vec2f(0.0);
|
|
20262
|
+
|
|
20263
|
+
for (var sampleIndex = 0u; sampleIndex < sampleCount; sampleIndex++) {
|
|
20264
|
+
let halfVector = importanceSampleEnvironment(
|
|
20265
|
+
getEnvironmentHammersley(sampleIndex, sampleCount),
|
|
20266
|
+
vec3f(0.0, 0.0, 1.0),
|
|
20267
|
+
roughness
|
|
20268
|
+
);
|
|
20269
|
+
let lightDirection = normalize(
|
|
20270
|
+
2.0 * dot(viewDirection, halfVector) * halfVector - viewDirection
|
|
20271
|
+
);
|
|
20272
|
+
let normalDotLight = max(lightDirection.z, 0.0);
|
|
20273
|
+
let normalDotHalf = max(halfVector.z, 0.0);
|
|
20274
|
+
let viewDotHalf = max(dot(viewDirection, halfVector), 0.0);
|
|
20275
|
+
if (normalDotLight > 0.0) {
|
|
20276
|
+
let visibility = getEnvironmentGeometry(normalDotView, roughness) *
|
|
20277
|
+
getEnvironmentGeometry(normalDotLight, roughness) * viewDotHalf /
|
|
20278
|
+
max(normalDotHalf * normalDotView, 0.0001);
|
|
20279
|
+
let fresnel = pow(1.0 - viewDotHalf, 5.0);
|
|
20280
|
+
integration += vec2f(1.0 - fresnel, fresnel) * visibility;
|
|
20281
|
+
}
|
|
20282
|
+
}
|
|
20283
|
+
return integration / f32(sampleCount);
|
|
20284
|
+
}
|
|
20285
|
+
|
|
20286
|
+
fn integrateEnvironmentDirection(normal: vec3f, sampleCount: u32) -> vec3f {
|
|
20287
|
+
var accumulatedColor = vec3f(0.0);
|
|
20288
|
+
var accumulatedWeight = 0.0;
|
|
20289
|
+
|
|
20290
|
+
for (var sampleIndex = 0u; sampleIndex < sampleCount; sampleIndex++) {
|
|
20291
|
+
let sequence = getEnvironmentHammersley(sampleIndex, sampleCount);
|
|
20292
|
+
var direction: vec3f;
|
|
20293
|
+
var sampleWeight: f32;
|
|
20294
|
+
|
|
20295
|
+
if (pbrEnvironmentFilter.mode == 1) {
|
|
20296
|
+
let azimuth = 2.0 * ENVIRONMENT_PI * sequence.x;
|
|
20297
|
+
let cosine = sqrt(1.0 - sequence.y);
|
|
20298
|
+
let sine = sqrt(sequence.y);
|
|
20299
|
+
direction = normalize(
|
|
20300
|
+
getEnvironmentTangentBasis(normal) *
|
|
20301
|
+
vec3f(cos(azimuth) * sine, sin(azimuth) * sine, cosine)
|
|
20302
|
+
);
|
|
20303
|
+
sampleWeight = 1.0;
|
|
20304
|
+
} else {
|
|
20305
|
+
let halfVector = importanceSampleEnvironment(sequence, normal, pbrEnvironmentFilter.roughness);
|
|
20306
|
+
direction = normalize(2.0 * dot(normal, halfVector) * halfVector - normal);
|
|
20307
|
+
sampleWeight = max(dot(normal, direction), 0.0);
|
|
20308
|
+
}
|
|
20309
|
+
|
|
20310
|
+
accumulatedColor += sampleEnvironmentDirection(direction) * sampleWeight;
|
|
20311
|
+
accumulatedWeight += sampleWeight;
|
|
20312
|
+
}
|
|
20313
|
+
return accumulatedColor / max(accumulatedWeight, 0.0001);
|
|
20314
|
+
}
|
|
20315
|
+
|
|
20316
|
+
@fragment
|
|
20317
|
+
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
20318
|
+
// ClipSpace UVs increase upward; WebGPU texture rows increase downward.
|
|
20319
|
+
let textureCoordinate = vec2f(inputs.uv.x, 1.0 - inputs.uv.y);
|
|
20320
|
+
let sampleCount = u32(max(pbrEnvironmentFilter.sampleCount, 1));
|
|
20321
|
+
if (pbrEnvironmentFilter.mode == 2) {
|
|
20322
|
+
return vec4f(integrateEnvironmentBRDF(textureCoordinate, sampleCount), 0.0, 1.0);
|
|
20323
|
+
}
|
|
20324
|
+
|
|
20325
|
+
let direction = getEnvironmentFaceDirection(pbrEnvironmentFilter.face, textureCoordinate);
|
|
20326
|
+
return vec4f(integrateEnvironmentDirection(direction, sampleCount), 1.0);
|
|
20327
|
+
}
|
|
20328
|
+
`
|
|
20329
|
+
);
|
|
20330
|
+
|
|
20331
|
+
// src/modules/lighting/shadow/shadow-glsl.ts
|
|
20332
|
+
var SHADOW_GLSL = (
|
|
20333
|
+
/* glsl */
|
|
20334
|
+
`
|
|
20335
|
+
precision highp sampler2DArray;
|
|
20336
|
+
struct DirectionalShadowLightUniform {
|
|
20337
|
+
vec3 direction;
|
|
20338
|
+
float strength;
|
|
20339
|
+
float normalBias;
|
|
20340
|
+
float sourceAngularRadius;
|
|
20341
|
+
float cascadeBlendFraction;
|
|
20342
|
+
float farFadeFraction;
|
|
20343
|
+
float shadowDistance;
|
|
20344
|
+
};
|
|
20345
|
+
struct SpotShadowLightUniform {
|
|
20346
|
+
vec3 position;
|
|
20347
|
+
float range;
|
|
20348
|
+
vec3 direction;
|
|
20349
|
+
float outerConeCos;
|
|
20350
|
+
float sourceRadius;
|
|
20351
|
+
float normalBias;
|
|
20352
|
+
float strength;
|
|
20353
|
+
float nearPlane;
|
|
20354
|
+
};
|
|
20355
|
+
struct PointShadowLightUniform {
|
|
20356
|
+
vec3 position;
|
|
20357
|
+
float range;
|
|
20358
|
+
float sourceRadius;
|
|
20359
|
+
float normalBias;
|
|
20360
|
+
float strength;
|
|
20361
|
+
float nearPlane;
|
|
20362
|
+
};
|
|
20363
|
+
layout(std140) uniform shadowUniforms {
|
|
20364
|
+
int directionalLightCount;
|
|
20365
|
+
int spotLightCount;
|
|
20366
|
+
int pointLightCount;
|
|
20367
|
+
int cascadeCount;
|
|
20368
|
+
int blockerSampleCount;
|
|
20369
|
+
int filterSampleCount;
|
|
20370
|
+
vec4 cascadeSplits;
|
|
20371
|
+
mat4 directionalViewProjectionMatrices[4];
|
|
20372
|
+
mat4 spotViewProjectionMatrices[4];
|
|
20373
|
+
mat4 pointViewProjectionMatrices[24];
|
|
20374
|
+
DirectionalShadowLightUniform directionalLights[1];
|
|
20375
|
+
SpotShadowLightUniform spotLights[4];
|
|
20376
|
+
PointShadowLightUniform pointLights[4];
|
|
20377
|
+
} shadow;
|
|
20378
|
+
uniform sampler2DArray directionalShadowTexture;
|
|
20379
|
+
uniform sampler2DArray spotShadowTexture;
|
|
20380
|
+
uniform sampler2DArray pointShadowTexture;
|
|
20381
|
+
const float SHADOW_PI = 3.141592653589793;
|
|
20382
|
+
float shadow_hash(vec3 position) {
|
|
20383
|
+
return fract(sin(dot(position, vec3(12.9898, 78.233, 37.719))) * 43758.5453);
|
|
20384
|
+
}
|
|
20385
|
+
vec2 shadow_diskSample(int index, int count, float rotation) {
|
|
20386
|
+
float fraction = (float(index) + 0.5) / max(float(count), 1.0);
|
|
20387
|
+
float angle = float(index) * 2.39996323 + rotation;
|
|
20388
|
+
return sqrt(fraction) * vec2(cos(angle), sin(angle));
|
|
20389
|
+
}
|
|
20390
|
+
vec3 shadow_project(mat4 matrix, vec3 worldPosition) {
|
|
20391
|
+
vec4 clip = matrix * vec4(worldPosition, 1.0);
|
|
20392
|
+
vec3 projected = clip.xyz / max(abs(clip.w), 0.00001);
|
|
20393
|
+
// Shared matrices retain [0,1] depth; WebGL texture rows start at the bottom.
|
|
20394
|
+
return vec3(projected.xy * 0.5 + 0.5, projected.z);
|
|
20395
|
+
}
|
|
20396
|
+
bool shadow_validProjection(vec3 projected) {
|
|
20397
|
+
return all(greaterThanEqual(projected, vec3(0.0))) && all(lessThanEqual(projected, vec3(1.0)));
|
|
20398
|
+
}
|
|
20399
|
+
// Bilinear interpolation of four depth comparisons matches a hardware 2x2 PCF lookup.
|
|
20400
|
+
float shadow_compare(sampler2DArray shadowMap, vec2 coordinate, int layer, float reference) {
|
|
20401
|
+
ivec2 dimensions = textureSize(shadowMap, 0).xy;
|
|
20402
|
+
vec2 position = coordinate * vec2(dimensions) - 0.5;
|
|
20403
|
+
ivec2 base = ivec2(floor(position));
|
|
20404
|
+
vec2 fraction = fract(position);
|
|
20405
|
+
ivec2 maximum = dimensions - 1;
|
|
20406
|
+
float lowerLeft = step(reference, texelFetch(shadowMap, ivec3(clamp(base, ivec2(0), maximum), layer), 0).r);
|
|
20407
|
+
float lowerRight = step(reference, texelFetch(shadowMap, ivec3(clamp(base + ivec2(1,0), ivec2(0), maximum), layer), 0).r);
|
|
20408
|
+
float upperLeft = step(reference, texelFetch(shadowMap, ivec3(clamp(base + ivec2(0,1), ivec2(0), maximum), layer), 0).r);
|
|
20409
|
+
float upperRight = step(reference, texelFetch(shadowMap, ivec3(clamp(base + ivec2(1,1), ivec2(0), maximum), layer), 0).r);
|
|
20410
|
+
return mix(mix(lowerLeft, lowerRight, fraction.x), mix(upperLeft, upperRight, fraction.x), fraction.y);
|
|
20411
|
+
}
|
|
20412
|
+
float shadow_arrayPCSS(sampler2DArray shadowMap, int layer, vec3 projected, float searchRadius, float rotation, float penumbraScale) {
|
|
20413
|
+
if (!shadow_validProjection(projected)) return 1.0;
|
|
20414
|
+
float texel = 1.0 / float(textureSize(shadowMap, 0).x);
|
|
20415
|
+
searchRadius = max(texel, searchRadius);
|
|
20416
|
+
float blockerDepth = 0.0;
|
|
20417
|
+
float blockerCount = 0.0;
|
|
20418
|
+
for (int index = 0; index < 24; index++) {
|
|
20419
|
+
if (index >= shadow.blockerSampleCount) break;
|
|
20420
|
+
vec2 coordinate = clamp(projected.xy + shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius, vec2(0.0), vec2(1.0));
|
|
20421
|
+
float depth = textureLod(shadowMap, vec3(coordinate, float(layer)), 0.0).r;
|
|
20422
|
+
if (depth < projected.z) { blockerDepth += depth; blockerCount += 1.0; }
|
|
20423
|
+
}
|
|
20424
|
+
if (blockerCount == 0.0) return 1.0;
|
|
20425
|
+
float averageBlocker = blockerDepth / blockerCount;
|
|
20426
|
+
float penumbra = clamp((projected.z - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20427
|
+
float radius = max(texel, searchRadius * (1.0 + penumbra * penumbraScale));
|
|
20428
|
+
float visibility = 0.0;
|
|
20429
|
+
for (int index = 0; index < 48; index++) {
|
|
20430
|
+
if (index >= shadow.filterSampleCount) break;
|
|
20431
|
+
vec2 coordinate = clamp(projected.xy + shadow_diskSample(index, shadow.filterSampleCount, rotation) * radius, vec2(0.0), vec2(1.0));
|
|
20432
|
+
visibility += shadow_compare(shadowMap, coordinate, layer, projected.z);
|
|
20433
|
+
}
|
|
20434
|
+
return visibility / max(float(shadow.filterSampleCount), 1.0);
|
|
20435
|
+
}
|
|
20436
|
+
int shadow_directionalCascadeIndex(float viewDepth) {
|
|
20437
|
+
int cascadeIndex = 0;
|
|
20438
|
+
for (int index = 0; index < 4; index++) {
|
|
20439
|
+
if (index >= shadow.cascadeCount) break;
|
|
20440
|
+
cascadeIndex = index;
|
|
20441
|
+
if (viewDepth <= shadow.cascadeSplits[index]) break;
|
|
20442
|
+
}
|
|
20443
|
+
return cascadeIndex;
|
|
20444
|
+
}
|
|
20445
|
+
int shadow_getDirectionalCascadeIndex(float viewDepth) {
|
|
20446
|
+
return shadow.directionalLightCount == 0 ? -1 : shadow_directionalCascadeIndex(viewDepth);
|
|
20447
|
+
}
|
|
20448
|
+
float shadow_directionalPCSS(int cascadeIndex, vec3 worldPosition, float viewDepth) {
|
|
20449
|
+
DirectionalShadowLightUniform light = shadow.directionalLights[0];
|
|
20450
|
+
return shadow_arrayPCSS(directionalShadowTexture, cascadeIndex,
|
|
20451
|
+
shadow_project(shadow.directionalViewProjectionMatrices[cascadeIndex], worldPosition),
|
|
20452
|
+
light.sourceAngularRadius * viewDepth / max(light.shadowDistance, 0.001),
|
|
20453
|
+
shadow_hash(worldPosition) * 2.0 * SHADOW_PI, 18.0);
|
|
20454
|
+
}
|
|
20455
|
+
float shadow_getDirectionalFactor(vec3 worldPosition, vec3 worldNormal, float viewDepth) {
|
|
20456
|
+
if (shadow.directionalLightCount == 0 || viewDepth <= 0.0) return 1.0;
|
|
20457
|
+
DirectionalShadowLightUniform light = shadow.directionalLights[0];
|
|
20458
|
+
if (viewDepth >= light.shadowDistance) return 1.0;
|
|
20459
|
+
vec3 position = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20460
|
+
int cascadeIndex = shadow_directionalCascadeIndex(viewDepth);
|
|
20461
|
+
float visibility = shadow_directionalPCSS(cascadeIndex, position, viewDepth);
|
|
20462
|
+
if (cascadeIndex + 1 < shadow.cascadeCount) {
|
|
20463
|
+
float cascadeStart = cascadeIndex > 0 ? shadow.cascadeSplits[cascadeIndex - 1] : 0.0;
|
|
20464
|
+
float cascadeEnd = shadow.cascadeSplits[cascadeIndex];
|
|
20465
|
+
float blendWidth = max((cascadeEnd - cascadeStart) * light.cascadeBlendFraction, 0.0001);
|
|
20466
|
+
float blend = smoothstep(cascadeEnd - blendWidth, cascadeEnd, viewDepth);
|
|
20467
|
+
if (blend > 0.0) visibility = mix(visibility, shadow_directionalPCSS(cascadeIndex + 1, position, viewDepth), blend);
|
|
20468
|
+
}
|
|
20469
|
+
float fadeWidth = max(light.shadowDistance * light.farFadeFraction, 0.0001);
|
|
20470
|
+
visibility = mix(visibility, 1.0, smoothstep(light.shadowDistance - fadeWidth, light.shadowDistance, viewDepth));
|
|
20471
|
+
return mix(1.0, visibility, light.strength);
|
|
20472
|
+
}
|
|
20473
|
+
float shadow_getSpotFactor(int lightIndex, vec3 worldPosition, vec3 worldNormal) {
|
|
20474
|
+
if (lightIndex < 0 || lightIndex >= shadow.spotLightCount) return 1.0;
|
|
20475
|
+
SpotShadowLightUniform light = shadow.spotLights[lightIndex];
|
|
20476
|
+
vec3 fromLight = worldPosition - light.position;
|
|
20477
|
+
float distanceToLight = length(fromLight);
|
|
20478
|
+
if (distanceToLight >= light.range || dot(normalize(fromLight), normalize(light.direction)) < light.outerConeCos) return 1.0;
|
|
20479
|
+
vec3 position = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20480
|
+
float visibility = shadow_arrayPCSS(spotShadowTexture, lightIndex,
|
|
20481
|
+
shadow_project(shadow.spotViewProjectionMatrices[lightIndex], position),
|
|
20482
|
+
light.sourceRadius / max(distanceToLight, 0.001) * 0.5,
|
|
20483
|
+
shadow_hash(worldPosition) * 2.0 * SHADOW_PI, 16.0);
|
|
20484
|
+
return mix(1.0, visibility, light.strength);
|
|
20485
|
+
}
|
|
20486
|
+
float shadow_pointReferenceDepth(float majorDistance, float nearPlane, float farPlane) {
|
|
20487
|
+
return farPlane / (farPlane - nearPlane) - (farPlane * nearPlane) / ((farPlane - nearPlane) * majorDistance);
|
|
20488
|
+
}
|
|
20489
|
+
vec3 shadow_pointCoordinate(int lightIndex, vec3 direction) {
|
|
20490
|
+
vec3 magnitude = abs(direction);
|
|
20491
|
+
int face = magnitude.x >= magnitude.y && magnitude.x >= magnitude.z ? (direction.x >= 0.0 ? 0 : 1)
|
|
20492
|
+
: magnitude.y >= magnitude.z ? (direction.y >= 0.0 ? 2 : 3) : (direction.z >= 0.0 ? 4 : 5);
|
|
20493
|
+
PointShadowLightUniform light = shadow.pointLights[lightIndex];
|
|
20494
|
+
vec3 projected = shadow_project(shadow.pointViewProjectionMatrices[lightIndex * 6 + face], light.position + direction * light.range * 0.5);
|
|
20495
|
+
return vec3(projected.xy, float(lightIndex * 6 + face));
|
|
20496
|
+
}
|
|
20497
|
+
float shadow_getPointFactor(int lightIndex, vec3 worldPosition, vec3 worldNormal) {
|
|
20498
|
+
if (lightIndex < 0 || lightIndex >= shadow.pointLightCount) return 1.0;
|
|
20499
|
+
PointShadowLightUniform light = shadow.pointLights[lightIndex];
|
|
20500
|
+
vec3 fromLight = worldPosition + normalize(worldNormal) * light.normalBias - light.position;
|
|
20501
|
+
float distanceToLight = length(fromLight);
|
|
20502
|
+
if (distanceToLight >= light.range || distanceToLight <= light.nearPlane) return 1.0;
|
|
20503
|
+
vec3 direction = normalize(fromLight);
|
|
20504
|
+
float referenceDepth = shadow_pointReferenceDepth(max(max(abs(fromLight.x), abs(fromLight.y)), abs(fromLight.z)), light.nearPlane, light.range);
|
|
20505
|
+
vec3 reference = abs(direction.y) > 0.99 ? vec3(0,0,1) : vec3(0,1,0);
|
|
20506
|
+
vec3 tangent = normalize(cross(direction, reference));
|
|
20507
|
+
vec3 bitangent = normalize(cross(direction, tangent));
|
|
20508
|
+
float searchRadius = light.sourceRadius / max(distanceToLight, 0.001);
|
|
20509
|
+
float rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20510
|
+
float blockerDepth = 0.0;
|
|
20511
|
+
float blockerCount = 0.0;
|
|
20512
|
+
for (int index = 0; index < 24; index++) {
|
|
20513
|
+
if (index >= shadow.blockerSampleCount) break;
|
|
20514
|
+
vec2 disk = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20515
|
+
vec3 coordinate = shadow_pointCoordinate(lightIndex, normalize(direction + tangent * disk.x + bitangent * disk.y));
|
|
20516
|
+
float depth = textureLod(pointShadowTexture, coordinate, 0.0).r;
|
|
20517
|
+
if (depth < referenceDepth) { blockerDepth += depth; blockerCount += 1.0; }
|
|
20518
|
+
}
|
|
20519
|
+
if (blockerCount == 0.0) return 1.0;
|
|
20520
|
+
float averageBlocker = blockerDepth / blockerCount;
|
|
20521
|
+
float penumbra = clamp((referenceDepth - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20522
|
+
float radius = searchRadius * (1.0 + penumbra * 12.0);
|
|
20523
|
+
float visibility = 0.0;
|
|
20524
|
+
for (int index = 0; index < 48; index++) {
|
|
20525
|
+
if (index >= shadow.filterSampleCount) break;
|
|
20526
|
+
vec2 disk = shadow_diskSample(index, shadow.filterSampleCount, rotation) * radius;
|
|
20527
|
+
vec3 coordinate = shadow_pointCoordinate(lightIndex, normalize(direction + tangent * disk.x + bitangent * disk.y));
|
|
20528
|
+
visibility += shadow_compare(pointShadowTexture, coordinate.xy, int(coordinate.z), referenceDepth);
|
|
20529
|
+
}
|
|
20530
|
+
return mix(1.0, visibility / max(float(shadow.filterSampleCount), 1.0), light.strength);
|
|
20531
|
+
}
|
|
20532
|
+
`
|
|
20533
|
+
);
|
|
20534
|
+
|
|
20535
|
+
// src/modules/lighting/shadow/shadow.ts
|
|
20536
|
+
var MAX_CASCADES = 4;
|
|
20537
|
+
var MAX_SPOT_LIGHTS = 4;
|
|
20538
|
+
var MAX_POINT_LIGHTS = 4;
|
|
20539
|
+
var MAX_POINT_MATRICES = 24;
|
|
20540
|
+
var DIRECTIONAL_LIGHT_UNIFORM_TYPE = {
|
|
20541
|
+
direction: "vec3<f32>",
|
|
20542
|
+
strength: "f32",
|
|
20543
|
+
normalBias: "f32",
|
|
20544
|
+
sourceAngularRadius: "f32",
|
|
20545
|
+
cascadeBlendFraction: "f32",
|
|
20546
|
+
farFadeFraction: "f32",
|
|
20547
|
+
shadowDistance: "f32"
|
|
20548
|
+
};
|
|
20549
|
+
var SPOT_LIGHT_UNIFORM_TYPE = {
|
|
20550
|
+
position: "vec3<f32>",
|
|
20551
|
+
range: "f32",
|
|
20552
|
+
direction: "vec3<f32>",
|
|
20553
|
+
outerConeCos: "f32",
|
|
20554
|
+
sourceRadius: "f32",
|
|
20555
|
+
normalBias: "f32",
|
|
20556
|
+
strength: "f32",
|
|
20557
|
+
nearPlane: "f32"
|
|
20558
|
+
};
|
|
20559
|
+
var POINT_LIGHT_UNIFORM_TYPE = {
|
|
20560
|
+
position: "vec3<f32>",
|
|
20561
|
+
range: "f32",
|
|
20562
|
+
sourceRadius: "f32",
|
|
20563
|
+
normalBias: "f32",
|
|
20564
|
+
strength: "f32",
|
|
20565
|
+
nearPlane: "f32"
|
|
20566
|
+
};
|
|
20567
|
+
var SHADOW_WGSL = (
|
|
20568
|
+
/* wgsl */
|
|
20569
|
+
`const SHADOW_PI: f32 = 3.141592653589793;
|
|
20570
|
+
|
|
20571
|
+
struct DirectionalShadowLightUniform {
|
|
20572
|
+
direction: vec3f,
|
|
20573
|
+
strength: f32,
|
|
20574
|
+
normalBias: f32,
|
|
20575
|
+
sourceAngularRadius: f32,
|
|
20576
|
+
cascadeBlendFraction: f32,
|
|
20577
|
+
farFadeFraction: f32,
|
|
20578
|
+
shadowDistance: f32,
|
|
20579
|
+
};
|
|
20580
|
+
|
|
20581
|
+
struct SpotShadowLightUniform {
|
|
20582
|
+
position: vec3f,
|
|
20583
|
+
range: f32,
|
|
20584
|
+
direction: vec3f,
|
|
20585
|
+
outerConeCos: f32,
|
|
20586
|
+
sourceRadius: f32,
|
|
20587
|
+
normalBias: f32,
|
|
20588
|
+
strength: f32,
|
|
20589
|
+
nearPlane: f32,
|
|
20590
|
+
};
|
|
20591
|
+
|
|
20592
|
+
struct PointShadowLightUniform {
|
|
20593
|
+
position: vec3f,
|
|
20594
|
+
range: f32,
|
|
20595
|
+
sourceRadius: f32,
|
|
20596
|
+
normalBias: f32,
|
|
20597
|
+
strength: f32,
|
|
20598
|
+
nearPlane: f32,
|
|
20599
|
+
};
|
|
20600
|
+
|
|
20601
|
+
struct ShadowUniforms {
|
|
20602
|
+
directionalLightCount: i32,
|
|
20603
|
+
spotLightCount: i32,
|
|
20604
|
+
pointLightCount: i32,
|
|
20605
|
+
cascadeCount: i32,
|
|
20606
|
+
blockerSampleCount: i32,
|
|
20607
|
+
filterSampleCount: i32,
|
|
20608
|
+
cascadeSplits: vec4f,
|
|
20609
|
+
directionalViewProjectionMatrices: array<mat4x4f, 4>,
|
|
20610
|
+
spotViewProjectionMatrices: array<mat4x4f, 4>,
|
|
20611
|
+
pointViewProjectionMatrices: array<mat4x4f, 24>,
|
|
20612
|
+
directionalLights: array<DirectionalShadowLightUniform, 1>,
|
|
20613
|
+
spotLights: array<SpotShadowLightUniform, 4>,
|
|
20614
|
+
pointLights: array<PointShadowLightUniform, 4>,
|
|
20615
|
+
};
|
|
20616
|
+
|
|
20617
|
+
@group(2) @binding(auto) var<uniform> shadow: ShadowUniforms;
|
|
20618
|
+
@group(2) @binding(auto) var directionalShadowTexture: texture_depth_2d_array;
|
|
20619
|
+
@group(2) @binding(auto) var spotShadowTexture: texture_depth_2d_array;
|
|
20620
|
+
@group(2) @binding(auto) var pointShadowTexture: texture_depth_cube_array;
|
|
20621
|
+
@group(2) @binding(auto) var directionalShadowTextureSampler: sampler;
|
|
20622
|
+
@group(2) @binding(auto) var shadowComparisonSampler: sampler_comparison;
|
|
20623
|
+
|
|
20624
|
+
fn shadow_hash(position: vec3f) -> f32 {
|
|
20625
|
+
return fract(sin(dot(position, vec3f(12.9898, 78.233, 37.719))) * 43758.5453);
|
|
20626
|
+
}
|
|
20627
|
+
|
|
20628
|
+
fn shadow_diskSample(index: i32, count: i32, rotation: f32) -> vec2f {
|
|
20629
|
+
let fraction = (f32(index) + 0.5) / max(f32(count), 1.0);
|
|
20630
|
+
let angle = f32(index) * 2.39996323 + rotation;
|
|
20631
|
+
return sqrt(fraction) * vec2f(cos(angle), sin(angle));
|
|
20632
|
+
}
|
|
20633
|
+
|
|
20634
|
+
fn shadow_project(matrix: mat4x4f, worldPosition: vec3f) -> vec3f {
|
|
20635
|
+
let clip = matrix * vec4f(worldPosition, 1.0);
|
|
20636
|
+
let ndc = clip.xyz / max(abs(clip.w), 0.00001);
|
|
20637
|
+
return vec3f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5, ndc.z);
|
|
20638
|
+
}
|
|
20639
|
+
|
|
20640
|
+
fn shadow_validProjection(projected: vec3f) -> bool {
|
|
20641
|
+
return all(projected.xy >= vec2f(0.0)) && all(projected.xy <= vec2f(1.0)) &&
|
|
20642
|
+
projected.z >= 0.0 && projected.z <= 1.0;
|
|
20643
|
+
}
|
|
20644
|
+
|
|
20645
|
+
fn shadow_directionalCascadeIndex(viewDepth: f32) -> i32 {
|
|
20646
|
+
var cascadeIndex = 0;
|
|
20647
|
+
for (var index: i32 = 0; index < 4; index++) {
|
|
20648
|
+
if (index >= shadow.cascadeCount) { break; }
|
|
20649
|
+
cascadeIndex = index;
|
|
20650
|
+
if (viewDepth <= shadow.cascadeSplits[index]) { break; }
|
|
20651
|
+
}
|
|
20652
|
+
return cascadeIndex;
|
|
20653
|
+
}
|
|
20654
|
+
|
|
20655
|
+
fn shadow_getDirectionalCascadeIndex(viewDepth: f32) -> i32 {
|
|
20656
|
+
if (shadow.directionalLightCount == 0) { return -1; }
|
|
20657
|
+
return shadow_directionalCascadeIndex(viewDepth);
|
|
20658
|
+
}
|
|
20659
|
+
|
|
20660
|
+
fn shadow_directionalPCSS(cascadeIndex: i32, worldPosition: vec3f, viewDepth: f32) -> f32 {
|
|
20661
|
+
let projected = shadow_project(shadow.directionalViewProjectionMatrices[cascadeIndex], worldPosition);
|
|
20662
|
+
if (!shadow_validProjection(projected)) { return 1.0; }
|
|
20663
|
+
let dimensions = vec2f(textureDimensions(directionalShadowTexture));
|
|
20664
|
+
let texel = 1.0 / dimensions;
|
|
20665
|
+
let light = shadow.directionalLights[0];
|
|
20666
|
+
let rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20667
|
+
let searchRadius = max(texel.x, light.sourceAngularRadius * viewDepth / max(light.shadowDistance, 0.001));
|
|
20668
|
+
var blockerDepth = 0.0;
|
|
20669
|
+
var blockerCount = 0.0;
|
|
20670
|
+
for (var index: i32 = 0; index < 24; index++) {
|
|
20671
|
+
if (index >= shadow.blockerSampleCount) { break; }
|
|
20672
|
+
let offset = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20673
|
+
let sampleDepth = textureSampleLevel(
|
|
20674
|
+
directionalShadowTexture,
|
|
20675
|
+
directionalShadowTextureSampler,
|
|
20676
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20677
|
+
cascadeIndex,
|
|
20678
|
+
0
|
|
20679
|
+
);
|
|
20680
|
+
if (sampleDepth < projected.z) {
|
|
20681
|
+
blockerDepth += sampleDepth;
|
|
20682
|
+
blockerCount += 1.0;
|
|
20683
|
+
}
|
|
20684
|
+
}
|
|
20685
|
+
if (blockerCount == 0.0) { return 1.0; }
|
|
20686
|
+
let averageBlocker = blockerDepth / blockerCount;
|
|
20687
|
+
let penumbra = clamp((projected.z - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20688
|
+
let filterRadius = max(texel.x, searchRadius * (1.0 + penumbra * 18.0));
|
|
20689
|
+
var visibility = 0.0;
|
|
20690
|
+
for (var index: i32 = 0; index < 48; index++) {
|
|
20691
|
+
if (index >= shadow.filterSampleCount) { break; }
|
|
20692
|
+
let offset = shadow_diskSample(index, shadow.filterSampleCount, rotation) * filterRadius;
|
|
20693
|
+
visibility += textureSampleCompareLevel(
|
|
20694
|
+
directionalShadowTexture,
|
|
20695
|
+
shadowComparisonSampler,
|
|
20696
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20697
|
+
cascadeIndex,
|
|
20698
|
+
projected.z
|
|
20699
|
+
);
|
|
20700
|
+
}
|
|
20701
|
+
return visibility / max(f32(shadow.filterSampleCount), 1.0);
|
|
20702
|
+
}
|
|
20703
|
+
|
|
20704
|
+
fn shadow_getDirectionalFactor(worldPosition: vec3f, worldNormal: vec3f, viewDepth: f32) -> f32 {
|
|
20705
|
+
if (shadow.directionalLightCount == 0 || viewDepth <= 0.0) { return 1.0; }
|
|
20706
|
+
let light = shadow.directionalLights[0];
|
|
20707
|
+
if (viewDepth >= light.shadowDistance) { return 1.0; }
|
|
20708
|
+
let biasedPosition = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20709
|
+
let cascadeIndex = shadow_directionalCascadeIndex(viewDepth);
|
|
20710
|
+
var visibility = shadow_directionalPCSS(cascadeIndex, biasedPosition, viewDepth);
|
|
20711
|
+
if (cascadeIndex + 1 < shadow.cascadeCount) {
|
|
20712
|
+
var cascadeStart = 0.0;
|
|
20713
|
+
if (cascadeIndex > 0) { cascadeStart = shadow.cascadeSplits[cascadeIndex - 1]; }
|
|
20714
|
+
let cascadeEnd = shadow.cascadeSplits[cascadeIndex];
|
|
20715
|
+
let blendWidth = max((cascadeEnd - cascadeStart) * light.cascadeBlendFraction, 0.0001);
|
|
20716
|
+
let blend = smoothstep(cascadeEnd - blendWidth, cascadeEnd, viewDepth);
|
|
20717
|
+
if (blend > 0.0) {
|
|
20718
|
+
visibility = mix(
|
|
20719
|
+
visibility,
|
|
20720
|
+
shadow_directionalPCSS(cascadeIndex + 1, biasedPosition, viewDepth),
|
|
20721
|
+
blend
|
|
20722
|
+
);
|
|
20723
|
+
}
|
|
20724
|
+
}
|
|
20725
|
+
let fadeWidth = max(light.shadowDistance * light.farFadeFraction, 0.0001);
|
|
20726
|
+
let farFade = smoothstep(light.shadowDistance - fadeWidth, light.shadowDistance, viewDepth);
|
|
20727
|
+
visibility = mix(visibility, 1.0, farFade);
|
|
20728
|
+
return mix(1.0, visibility, light.strength);
|
|
20729
|
+
}
|
|
20730
|
+
|
|
20731
|
+
fn shadow_spotPCSS(lightIndex: i32, worldPosition: vec3f) -> f32 {
|
|
20732
|
+
let projected = shadow_project(shadow.spotViewProjectionMatrices[lightIndex], worldPosition);
|
|
20733
|
+
if (!shadow_validProjection(projected)) { return 1.0; }
|
|
20734
|
+
let light = shadow.spotLights[lightIndex];
|
|
20735
|
+
let dimensions = vec2f(textureDimensions(spotShadowTexture));
|
|
20736
|
+
let texel = 1.0 / dimensions;
|
|
20737
|
+
let distanceToLight = length(worldPosition - light.position);
|
|
20738
|
+
let searchRadius = max(texel.x, light.sourceRadius / max(distanceToLight, 0.001) * 0.5);
|
|
20739
|
+
let rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20740
|
+
var blockerDepth = 0.0;
|
|
20741
|
+
var blockerCount = 0.0;
|
|
20742
|
+
for (var index: i32 = 0; index < 24; index++) {
|
|
20743
|
+
if (index >= shadow.blockerSampleCount) { break; }
|
|
20744
|
+
let offset = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20745
|
+
let sampleDepth = textureSampleLevel(
|
|
20746
|
+
spotShadowTexture,
|
|
20747
|
+
directionalShadowTextureSampler,
|
|
20748
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20749
|
+
lightIndex,
|
|
20750
|
+
0
|
|
20751
|
+
);
|
|
20752
|
+
if (sampleDepth < projected.z) { blockerDepth += sampleDepth; blockerCount += 1.0; }
|
|
20753
|
+
}
|
|
20754
|
+
if (blockerCount == 0.0) { return 1.0; }
|
|
20755
|
+
let averageBlocker = blockerDepth / blockerCount;
|
|
20756
|
+
let penumbra = clamp((projected.z - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20757
|
+
let filterRadius = max(texel.x, searchRadius * (1.0 + penumbra * 16.0));
|
|
20758
|
+
var visibility = 0.0;
|
|
20759
|
+
for (var index: i32 = 0; index < 48; index++) {
|
|
20760
|
+
if (index >= shadow.filterSampleCount) { break; }
|
|
20761
|
+
let offset = shadow_diskSample(index, shadow.filterSampleCount, rotation) * filterRadius;
|
|
20762
|
+
visibility += textureSampleCompareLevel(
|
|
20763
|
+
spotShadowTexture,
|
|
20764
|
+
shadowComparisonSampler,
|
|
20765
|
+
clamp(projected.xy + offset, vec2f(0.0), vec2f(1.0)),
|
|
20766
|
+
lightIndex,
|
|
20767
|
+
projected.z
|
|
20768
|
+
);
|
|
20769
|
+
}
|
|
20770
|
+
return visibility / max(f32(shadow.filterSampleCount), 1.0);
|
|
20771
|
+
}
|
|
20772
|
+
|
|
20773
|
+
fn shadow_getSpotFactor(lightIndex: i32, worldPosition: vec3f, worldNormal: vec3f) -> f32 {
|
|
20774
|
+
if (lightIndex < 0 || lightIndex >= shadow.spotLightCount) { return 1.0; }
|
|
20775
|
+
let light = shadow.spotLights[lightIndex];
|
|
20776
|
+
let fromLight = worldPosition - light.position;
|
|
20777
|
+
let distanceToLight = length(fromLight);
|
|
20778
|
+
let coneCos = dot(normalize(fromLight), normalize(light.direction));
|
|
20779
|
+
if (distanceToLight >= light.range || coneCos < light.outerConeCos) { return 1.0; }
|
|
20780
|
+
let biasedPosition = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20781
|
+
return mix(1.0, shadow_spotPCSS(lightIndex, biasedPosition), light.strength);
|
|
20782
|
+
}
|
|
20783
|
+
|
|
20784
|
+
fn shadow_pointReferenceDepth(majorDistance: f32, nearPlane: f32, farPlane: f32) -> f32 {
|
|
20785
|
+
// Match the cube-face projection and stored WebGPU depth in [0, 1].
|
|
20786
|
+
return farPlane / (farPlane - nearPlane) -
|
|
20787
|
+
(farPlane * nearPlane) / ((farPlane - nearPlane) * majorDistance);
|
|
20788
|
+
}
|
|
20789
|
+
|
|
20790
|
+
fn shadow_pointBasis(direction: vec3f) -> mat2x3f {
|
|
20791
|
+
let reference = select(vec3f(0.0, 1.0, 0.0), vec3f(0.0, 0.0, 1.0), abs(direction.y) > 0.99);
|
|
20792
|
+
let tangent = normalize(cross(direction, reference));
|
|
20793
|
+
return mat2x3f(tangent, normalize(cross(direction, tangent)));
|
|
20794
|
+
}
|
|
20795
|
+
|
|
20796
|
+
fn shadow_getPointFactor(lightIndex: i32, worldPosition: vec3f, worldNormal: vec3f) -> f32 {
|
|
20797
|
+
if (lightIndex < 0 || lightIndex >= shadow.pointLightCount) { return 1.0; }
|
|
20798
|
+
let light = shadow.pointLights[lightIndex];
|
|
20799
|
+
let biasedPosition = worldPosition + normalize(worldNormal) * light.normalBias;
|
|
20800
|
+
let fromLight = biasedPosition - light.position;
|
|
20801
|
+
let distanceToLight = length(fromLight);
|
|
20802
|
+
if (distanceToLight >= light.range || distanceToLight <= light.nearPlane) { return 1.0; }
|
|
20803
|
+
let direction = normalize(fromLight);
|
|
20804
|
+
let majorDistance = max(max(abs(fromLight.x), abs(fromLight.y)), abs(fromLight.z));
|
|
20805
|
+
let referenceDepth = shadow_pointReferenceDepth(majorDistance, light.nearPlane, light.range);
|
|
20806
|
+
let searchRadius = light.sourceRadius / max(distanceToLight, 0.001);
|
|
20807
|
+
let rotation = shadow_hash(worldPosition) * 2.0 * SHADOW_PI;
|
|
20808
|
+
let basis = shadow_pointBasis(direction);
|
|
20809
|
+
var blockerDepth = 0.0;
|
|
20810
|
+
var blockerCount = 0.0;
|
|
20811
|
+
for (var index: i32 = 0; index < 24; index++) {
|
|
20812
|
+
if (index >= shadow.blockerSampleCount) { break; }
|
|
20813
|
+
let disk = shadow_diskSample(index, shadow.blockerSampleCount, rotation) * searchRadius;
|
|
20814
|
+
let sampleDirection = normalize(direction + basis[0] * disk.x + basis[1] * disk.y);
|
|
20815
|
+
let sampleDepth = textureSampleLevel(
|
|
20816
|
+
pointShadowTexture,
|
|
20817
|
+
directionalShadowTextureSampler,
|
|
20818
|
+
sampleDirection,
|
|
20819
|
+
lightIndex,
|
|
20820
|
+
0
|
|
20821
|
+
);
|
|
20822
|
+
if (sampleDepth < referenceDepth) { blockerDepth += sampleDepth; blockerCount += 1.0; }
|
|
20823
|
+
}
|
|
20824
|
+
if (blockerCount == 0.0) { return 1.0; }
|
|
20825
|
+
let averageBlocker = blockerDepth / blockerCount;
|
|
20826
|
+
let penumbra = clamp((referenceDepth - averageBlocker) / max(abs(averageBlocker), 0.001), 0.0, 1.0);
|
|
20827
|
+
let filterRadius = searchRadius * (1.0 + penumbra * 12.0);
|
|
20828
|
+
var visibility = 0.0;
|
|
20829
|
+
for (var index: i32 = 0; index < 48; index++) {
|
|
20830
|
+
if (index >= shadow.filterSampleCount) { break; }
|
|
20831
|
+
let disk = shadow_diskSample(index, shadow.filterSampleCount, rotation) * filterRadius;
|
|
20832
|
+
let sampleDirection = normalize(direction + basis[0] * disk.x + basis[1] * disk.y);
|
|
20833
|
+
visibility += textureSampleCompareLevel(
|
|
20834
|
+
pointShadowTexture,
|
|
20835
|
+
shadowComparisonSampler,
|
|
20836
|
+
sampleDirection,
|
|
20837
|
+
lightIndex,
|
|
20838
|
+
referenceDepth
|
|
20839
|
+
);
|
|
20840
|
+
}
|
|
20841
|
+
visibility /= max(f32(shadow.filterSampleCount), 1.0);
|
|
20842
|
+
return mix(1.0, visibility, light.strength);
|
|
20843
|
+
}
|
|
20844
|
+
`
|
|
20845
|
+
);
|
|
20846
|
+
var shadow = {
|
|
20847
|
+
name: "shadow",
|
|
20848
|
+
source: SHADOW_WGSL,
|
|
20849
|
+
fs: SHADOW_GLSL,
|
|
20850
|
+
props: {},
|
|
20851
|
+
uniforms: {},
|
|
20852
|
+
bindings: {},
|
|
20853
|
+
uniformTypes: {
|
|
20854
|
+
directionalLightCount: "i32",
|
|
20855
|
+
spotLightCount: "i32",
|
|
20856
|
+
pointLightCount: "i32",
|
|
20857
|
+
cascadeCount: "i32",
|
|
20858
|
+
blockerSampleCount: "i32",
|
|
20859
|
+
filterSampleCount: "i32",
|
|
20860
|
+
cascadeSplits: "vec4<f32>",
|
|
20861
|
+
directionalViewProjectionMatrices: ["mat4x4<f32>", MAX_CASCADES],
|
|
20862
|
+
spotViewProjectionMatrices: ["mat4x4<f32>", MAX_SPOT_LIGHTS],
|
|
20863
|
+
pointViewProjectionMatrices: ["mat4x4<f32>", MAX_POINT_MATRICES],
|
|
20864
|
+
directionalLights: [DIRECTIONAL_LIGHT_UNIFORM_TYPE, 1],
|
|
20865
|
+
spotLights: [SPOT_LIGHT_UNIFORM_TYPE, MAX_SPOT_LIGHTS],
|
|
20866
|
+
pointLights: [POINT_LIGHT_UNIFORM_TYPE, MAX_POINT_LIGHTS]
|
|
20867
|
+
},
|
|
20868
|
+
bindingLayout: [
|
|
20869
|
+
{ name: "shadow", group: 2 },
|
|
20870
|
+
{ name: "directionalShadowTexture", group: 2 },
|
|
20871
|
+
{ name: "spotShadowTexture", group: 2 },
|
|
20872
|
+
{ name: "pointShadowTexture", group: 2 },
|
|
20873
|
+
{ name: "shadowComparisonSampler", group: 2 }
|
|
20874
|
+
],
|
|
20875
|
+
getUniforms(props) {
|
|
20876
|
+
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) {
|
|
20877
|
+
return {};
|
|
20878
|
+
}
|
|
20879
|
+
return {
|
|
20880
|
+
directionalLightCount: props.directionalLights.length,
|
|
20881
|
+
spotLightCount: props.spotLights.length,
|
|
20882
|
+
pointLightCount: props.pointLights.length,
|
|
20883
|
+
cascadeCount: props.cascadeCount,
|
|
20884
|
+
blockerSampleCount: props.blockerSampleCount,
|
|
20885
|
+
filterSampleCount: props.filterSampleCount,
|
|
20886
|
+
cascadeSplits: props.cascadeSplits,
|
|
20887
|
+
directionalViewProjectionMatrices: props.directionalViewProjectionMatrices,
|
|
20888
|
+
spotViewProjectionMatrices: props.spotViewProjectionMatrices,
|
|
20889
|
+
pointViewProjectionMatrices: props.pointViewProjectionMatrices,
|
|
20890
|
+
directionalLights: padDirectionalLights(props.directionalLights),
|
|
20891
|
+
spotLights: padSpotLights(props.spotLights),
|
|
20892
|
+
pointLights: padPointLights(props.pointLights),
|
|
20893
|
+
directionalShadowTexture: props.directionalShadowTexture,
|
|
20894
|
+
spotShadowTexture: props.spotShadowTexture,
|
|
20895
|
+
pointShadowTexture: props.pointShadowTexture,
|
|
20896
|
+
...props.directionalShadowTexture.device.type === "webgpu" ? { shadowComparisonSampler: props.comparisonSampler } : {}
|
|
20897
|
+
};
|
|
20898
|
+
}
|
|
20899
|
+
};
|
|
20900
|
+
function padDirectionalLights(lights) {
|
|
20901
|
+
const light = lights[0];
|
|
20902
|
+
return [
|
|
20903
|
+
light ? {
|
|
20904
|
+
direction: light.direction,
|
|
20905
|
+
strength: light.strength ?? 1,
|
|
20906
|
+
normalBias: light.normalBias ?? 0.04,
|
|
20907
|
+
sourceAngularRadius: light.sourceAngularRadius ?? 465e-5,
|
|
20908
|
+
cascadeBlendFraction: light.cascadeBlendFraction ?? 0.1,
|
|
20909
|
+
farFadeFraction: light.farFadeFraction ?? 0.1,
|
|
20910
|
+
shadowDistance: light.shadowDistance ?? 1
|
|
20911
|
+
} : {
|
|
20912
|
+
direction: [0, 1, 0],
|
|
20913
|
+
strength: 0,
|
|
20914
|
+
normalBias: 0,
|
|
20915
|
+
sourceAngularRadius: 0,
|
|
20916
|
+
cascadeBlendFraction: 0,
|
|
20917
|
+
farFadeFraction: 0,
|
|
20918
|
+
shadowDistance: 1
|
|
20919
|
+
}
|
|
20920
|
+
];
|
|
20921
|
+
}
|
|
20922
|
+
function padSpotLights(lights) {
|
|
20923
|
+
return padArray(
|
|
20924
|
+
lights.map((light) => ({
|
|
20925
|
+
position: light.position,
|
|
20926
|
+
range: light.range,
|
|
20927
|
+
direction: light.direction,
|
|
20928
|
+
outerConeCos: Math.cos(light.outerConeAngle),
|
|
20929
|
+
sourceRadius: light.sourceRadius ?? 0.2,
|
|
20930
|
+
normalBias: light.normalBias ?? 0.025,
|
|
20931
|
+
strength: light.strength ?? 1,
|
|
20932
|
+
nearPlane: light.nearPlane ?? 0.1
|
|
20933
|
+
})),
|
|
20934
|
+
MAX_SPOT_LIGHTS,
|
|
20935
|
+
{
|
|
20936
|
+
position: [0, 0, 0],
|
|
20937
|
+
range: 1,
|
|
20938
|
+
direction: [0, -1, 0],
|
|
20939
|
+
outerConeCos: 1,
|
|
20940
|
+
sourceRadius: 0,
|
|
20941
|
+
normalBias: 0,
|
|
20942
|
+
strength: 0,
|
|
20943
|
+
nearPlane: 0.1
|
|
20944
|
+
}
|
|
20945
|
+
);
|
|
20946
|
+
}
|
|
20947
|
+
function padPointLights(lights) {
|
|
20948
|
+
return padArray(
|
|
20949
|
+
lights.map((light) => ({
|
|
20950
|
+
position: light.position,
|
|
20951
|
+
range: light.range,
|
|
20952
|
+
sourceRadius: light.sourceRadius ?? 0.2,
|
|
20953
|
+
normalBias: light.normalBias ?? 0.025,
|
|
20954
|
+
strength: light.strength ?? 1,
|
|
20955
|
+
nearPlane: light.nearPlane ?? 0.1
|
|
20956
|
+
})),
|
|
20957
|
+
MAX_POINT_LIGHTS,
|
|
20958
|
+
{
|
|
20959
|
+
position: [0, 0, 0],
|
|
20960
|
+
range: 1,
|
|
20961
|
+
sourceRadius: 0,
|
|
20962
|
+
normalBias: 0,
|
|
20963
|
+
strength: 0,
|
|
20964
|
+
nearPlane: 0.1
|
|
20965
|
+
}
|
|
20966
|
+
);
|
|
20967
|
+
}
|
|
20968
|
+
function padArray(values, length, fallback) {
|
|
20969
|
+
const result = values.slice(0, length);
|
|
20970
|
+
while (result.length < length) {
|
|
20971
|
+
result.push(fallback);
|
|
20972
|
+
}
|
|
20973
|
+
return result;
|
|
20974
|
+
}
|
|
20975
|
+
|
|
20976
|
+
// src/modules/lighting/pbr-shadow/pbr-shadow.ts
|
|
20977
|
+
var pbrShadow = {
|
|
20978
|
+
name: "pbrShadow",
|
|
20979
|
+
dependencies: [pbrMaterial, shadow],
|
|
20980
|
+
bindingLayout: [{ name: "pbrShadow", group: 0 }],
|
|
20981
|
+
uniformTypes: { viewMatrix: "mat4x4<f32>", enabled: "i32" },
|
|
20982
|
+
defaultUniforms: {
|
|
20983
|
+
viewMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
|
|
20984
|
+
enabled: 1
|
|
20985
|
+
},
|
|
20986
|
+
getUniforms(properties = {}) {
|
|
20987
|
+
return {
|
|
20988
|
+
...properties.viewMatrix ? { viewMatrix: properties.viewMatrix } : {},
|
|
20989
|
+
...properties.enabled === void 0 ? {} : { enabled: Number(properties.enabled) }
|
|
20990
|
+
};
|
|
20991
|
+
},
|
|
20992
|
+
source: (
|
|
20993
|
+
/* wgsl */
|
|
20994
|
+
`
|
|
20995
|
+
struct PBRShadowUniforms {
|
|
20996
|
+
viewMatrix: mat4x4f,
|
|
20997
|
+
enabled: i32,
|
|
20998
|
+
};
|
|
20999
|
+
@group(0) @binding(auto) var<uniform> pbrShadow: PBRShadowUniforms;
|
|
21000
|
+
fn pbrShadow_filterColorWithDirectionalContact(vertexColor: vec4f, worldPosition: vec3f, worldNormal: vec3f, contactVisibility: f32) -> vec4f {
|
|
21001
|
+
var directionalVisibility = 1.0;
|
|
21002
|
+
var pointVisibility = vec4f(1.0);
|
|
21003
|
+
var spotVisibility = vec4f(1.0);
|
|
21004
|
+
if (pbrShadow.enabled != 0) {
|
|
21005
|
+
let normal = normalize(worldNormal);
|
|
21006
|
+
let viewDepth = -(pbrShadow.viewMatrix * vec4f(worldPosition, 1.0)).z;
|
|
21007
|
+
directionalVisibility = shadow_getDirectionalFactor(worldPosition, normal, viewDepth);
|
|
21008
|
+
for (var index = 0; index < 4; index++) {
|
|
21009
|
+
pointVisibility[index] = shadow_getPointFactor(index, worldPosition, normal);
|
|
21010
|
+
spotVisibility[index] = shadow_getSpotFactor(index, worldPosition, normal);
|
|
21011
|
+
}
|
|
21012
|
+
}
|
|
21013
|
+
return pbr_filterColorWithShadows(vertexColor, min(directionalVisibility, contactVisibility), pointVisibility, spotVisibility);
|
|
21014
|
+
}
|
|
21015
|
+
fn pbrShadow_filterColor(vertexColor: vec4f, worldPosition: vec3f, worldNormal: vec3f) -> vec4f {
|
|
21016
|
+
return pbrShadow_filterColorWithDirectionalContact(vertexColor, worldPosition, worldNormal, 1.0);
|
|
21017
|
+
}`
|
|
21018
|
+
),
|
|
21019
|
+
fs: (
|
|
21020
|
+
/* glsl */
|
|
21021
|
+
`
|
|
21022
|
+
layout(std140) uniform pbrShadowUniforms {
|
|
21023
|
+
mat4 viewMatrix;
|
|
21024
|
+
int enabled;
|
|
21025
|
+
} pbrShadow;
|
|
21026
|
+
vec4 pbrShadow_filterColorWithDirectionalContact(vec4 vertexColor, vec3 worldPosition, vec3 worldNormal, float contactVisibility) {
|
|
21027
|
+
float directionalVisibility = 1.0;
|
|
21028
|
+
vec4 pointVisibility = vec4(1.0);
|
|
21029
|
+
vec4 spotVisibility = vec4(1.0);
|
|
21030
|
+
if (pbrShadow.enabled != 0) {
|
|
21031
|
+
vec3 normal = normalize(worldNormal);
|
|
21032
|
+
float viewDepth = -(pbrShadow.viewMatrix * vec4(worldPosition, 1.0)).z;
|
|
21033
|
+
directionalVisibility = shadow_getDirectionalFactor(worldPosition, normal, viewDepth);
|
|
21034
|
+
for (int index = 0; index < 4; index++) {
|
|
21035
|
+
pointVisibility[index] = shadow_getPointFactor(index, worldPosition, normal);
|
|
21036
|
+
spotVisibility[index] = shadow_getSpotFactor(index, worldPosition, normal);
|
|
21037
|
+
}
|
|
21038
|
+
}
|
|
21039
|
+
return pbr_filterColorWithShadows(vertexColor, min(directionalVisibility, contactVisibility), pointVisibility, spotVisibility);
|
|
21040
|
+
}
|
|
21041
|
+
vec4 pbrShadow_filterColor(vec4 vertexColor, vec3 worldPosition, vec3 worldNormal) {
|
|
21042
|
+
return pbrShadow_filterColorWithDirectionalContact(vertexColor, worldPosition, worldNormal, 1.0);
|
|
21043
|
+
}`
|
|
21044
|
+
)
|
|
21045
|
+
};
|
|
21046
|
+
|
|
21047
|
+
// src/modules/lighting/pbr-surface/pbr-surface.ts
|
|
21048
|
+
var pbrSurface = {
|
|
21049
|
+
name: "pbrSurface",
|
|
21050
|
+
dependencies: [pbrMaterial],
|
|
21051
|
+
bindingLayout: [{ name: "pbrSurface", group: 0 }],
|
|
21052
|
+
uniformTypes: { viewMatrix: "mat4x4<f32>", useMaterialNormals: "i32" },
|
|
21053
|
+
defaultUniforms: {
|
|
21054
|
+
viewMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
|
|
21055
|
+
useMaterialNormals: 0
|
|
21056
|
+
},
|
|
21057
|
+
getUniforms(properties = {}) {
|
|
21058
|
+
return {
|
|
21059
|
+
...properties.viewMatrix ? { viewMatrix: properties.viewMatrix } : {},
|
|
21060
|
+
...properties.useMaterialNormals === void 0 ? {} : { useMaterialNormals: Number(properties.useMaterialNormals) }
|
|
21061
|
+
};
|
|
21062
|
+
},
|
|
21063
|
+
source: (
|
|
21064
|
+
/* wgsl */
|
|
21065
|
+
`
|
|
21066
|
+
struct PBRSurfaceUniforms {
|
|
21067
|
+
viewMatrix: mat4x4f,
|
|
21068
|
+
useMaterialNormals: i32,
|
|
21069
|
+
};
|
|
21070
|
+
@group(0) @binding(auto) var<uniform> pbrSurface: PBRSurfaceUniforms;
|
|
21071
|
+
fn pbrSurface_getColor() -> vec4f {
|
|
21072
|
+
#ifdef HAS_NORMALS
|
|
21073
|
+
var normal = normalize(fragmentInputs.pbr_vNormal);
|
|
21074
|
+
#ifdef DOUBLE_SIDED
|
|
21075
|
+
if (!pbr_frontFacing) {normal = -normal;}
|
|
21076
|
+
#endif
|
|
21077
|
+
#else
|
|
21078
|
+
var normal = normalize(cross(dpdy(fragmentInputs.pbr_vPosition), dpdx(fragmentInputs.pbr_vPosition)));
|
|
21079
|
+
#endif
|
|
21080
|
+
#ifdef HAS_NORMALMAP
|
|
21081
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21082
|
+
let coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21083
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21084
|
+
}
|
|
21085
|
+
#else
|
|
21086
|
+
#ifdef HAS_BUMPMAP
|
|
21087
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21088
|
+
let coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21089
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21090
|
+
}
|
|
21091
|
+
#endif
|
|
21092
|
+
#endif
|
|
21093
|
+
let viewNormal = normalize((pbrSurface.viewMatrix * vec4f(normal, 0.0)).xyz);
|
|
21094
|
+
return vec4f(viewNormal * 0.5 + vec3f(0.5), 1.0);
|
|
21095
|
+
}`
|
|
21096
|
+
),
|
|
21097
|
+
fs: (
|
|
21098
|
+
/* glsl */
|
|
21099
|
+
`
|
|
21100
|
+
layout(std140) uniform pbrSurfaceUniforms {
|
|
21101
|
+
mat4 viewMatrix;
|
|
21102
|
+
int useMaterialNormals;
|
|
21103
|
+
} pbrSurface;
|
|
21104
|
+
vec4 pbrSurface_getColor() {
|
|
21105
|
+
#ifdef HAS_NORMALS
|
|
21106
|
+
#ifdef HAS_TANGENTS
|
|
21107
|
+
vec3 normal = normalize(pbr_vTBN[2]);
|
|
21108
|
+
#else
|
|
21109
|
+
vec3 normal = normalize(pbr_vNormal);
|
|
21110
|
+
#endif
|
|
21111
|
+
#ifdef DOUBLE_SIDED
|
|
21112
|
+
if (!gl_FrontFacing) normal = -normal;
|
|
21113
|
+
#endif
|
|
21114
|
+
#else
|
|
21115
|
+
vec3 normal = normalize(cross(dFdx(pbr_vPosition), dFdy(pbr_vPosition)));
|
|
21116
|
+
#endif
|
|
21117
|
+
#ifdef HAS_NORMALMAP
|
|
21118
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21119
|
+
vec2 coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21120
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21121
|
+
}
|
|
21122
|
+
#else
|
|
21123
|
+
#ifdef HAS_BUMPMAP
|
|
21124
|
+
if (pbrSurface.useMaterialNormals != 0) {
|
|
21125
|
+
vec2 coordinates = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
|
|
21126
|
+
normal = getNormal(getTBN(coordinates), coordinates);
|
|
21127
|
+
}
|
|
21128
|
+
#endif
|
|
21129
|
+
#endif
|
|
21130
|
+
vec3 viewNormal = normalize((pbrSurface.viewMatrix * vec4(normal, 0.0)).xyz);
|
|
21131
|
+
return vec4(viewNormal * 0.5 + 0.5, 1.0);
|
|
21132
|
+
}`
|
|
21133
|
+
)
|
|
21134
|
+
};
|
|
21135
|
+
|
|
21136
|
+
// src/modules/lighting/contact-shadow/contact-shadow.ts
|
|
21137
|
+
var IDENTITY_MATRIX3 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
21138
|
+
var contactShadowTrace = {
|
|
21139
|
+
name: "contactShadowTrace",
|
|
21140
|
+
source: (
|
|
21141
|
+
/* wgsl */
|
|
21142
|
+
`struct contactShadowTraceUniforms {
|
|
21143
|
+
projectionMatrix: mat4x4f,
|
|
21144
|
+
inverseProjectionMatrix: mat4x4f,
|
|
21145
|
+
lightDirectionView: vec3f,
|
|
21146
|
+
maxDistance: f32,
|
|
21147
|
+
thickness: f32,
|
|
21148
|
+
stepCount: f32,
|
|
21149
|
+
frameIndex: f32,
|
|
21150
|
+
normalBias: f32,
|
|
21151
|
+
};
|
|
21152
|
+
@group(0) @binding(auto) var<uniform> contactShadowTrace: contactShadowTraceUniforms;
|
|
21153
|
+
@group(0) @binding(auto) var depthTexture: texture_depth_2d;
|
|
21154
|
+
@group(0) @binding(auto) var depthTextureSampler: sampler;
|
|
21155
|
+
@group(0) @binding(auto) var normalTexture: texture_2d<f32>;
|
|
21156
|
+
@group(0) @binding(auto) var normalTextureSampler: sampler;
|
|
21157
|
+
|
|
21158
|
+
fn contactShadow_reconstructViewPosition(uv: vec2f, depth: f32) -> vec3f {
|
|
21159
|
+
let clip = vec4f(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, depth, 1.0);
|
|
21160
|
+
let view = contactShadowTrace.inverseProjectionMatrix * clip;
|
|
21161
|
+
return view.xyz / max(abs(view.w), 0.00001);
|
|
21162
|
+
}
|
|
21163
|
+
|
|
21164
|
+
fn contactShadow_projectViewPosition(position: vec3f) -> vec2f {
|
|
21165
|
+
let clip = contactShadowTrace.projectionMatrix * vec4f(position, 1.0);
|
|
21166
|
+
let ndc = clip.xy / max(abs(clip.w), 0.00001);
|
|
21167
|
+
return vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);
|
|
21168
|
+
}
|
|
21169
|
+
|
|
21170
|
+
fn contactShadowTrace_sampleColor(
|
|
21171
|
+
sourceTexture: texture_2d<f32>, sourceTextureSampler: sampler, texSize: vec2f, texCoord: vec2f
|
|
21172
|
+
) -> vec4f {
|
|
21173
|
+
let centerDepth = textureSampleLevel(depthTexture, depthTextureSampler, texCoord, 0);
|
|
21174
|
+
if (centerDepth >= 0.99999) { return vec4f(1.0); }
|
|
21175
|
+
let centerNormal = normalize(textureSampleLevel(normalTexture, normalTextureSampler, texCoord, 0.0).xyz * 2.0 - 1.0);
|
|
21176
|
+
let centerPosition = contactShadow_reconstructViewPosition(texCoord, centerDepth) + centerNormal * contactShadowTrace.normalBias;
|
|
21177
|
+
let rayDirection = normalize(contactShadowTrace.lightDirectionView);
|
|
21178
|
+
let noise = fract(sin(dot(texCoord * texSize + contactShadowTrace.frameIndex, vec2f(12.9898, 78.233))) * 43758.5453);
|
|
21179
|
+
for (var index: i32 = 0; index < 40; index++) {
|
|
21180
|
+
if (f32(index) >= contactShadowTrace.stepCount) { break; }
|
|
21181
|
+
let fraction = (f32(index) + 0.35 + noise * 0.5) / max(contactShadowTrace.stepCount, 1.0);
|
|
21182
|
+
let travel = contactShadowTrace.maxDistance * fraction * fraction;
|
|
21183
|
+
let rayPosition = centerPosition + rayDirection * travel;
|
|
21184
|
+
let sampleUv = contactShadow_projectViewPosition(rayPosition);
|
|
21185
|
+
if (any(sampleUv <= vec2f(0.0)) || any(sampleUv >= vec2f(1.0))) { break; }
|
|
21186
|
+
let sampleDepth = textureSampleLevel(depthTexture, depthTextureSampler, sampleUv, 0);
|
|
21187
|
+
if (sampleDepth >= 0.99999) { continue; }
|
|
21188
|
+
let scenePosition = contactShadow_reconstructViewPosition(sampleUv, sampleDepth);
|
|
21189
|
+
let depthDelta = (-rayPosition.z) - (-scenePosition.z);
|
|
21190
|
+
let hitThickness = contactShadowTrace.thickness + travel * 0.02;
|
|
21191
|
+
if (depthDelta >= 0.0 && depthDelta <= hitThickness) {
|
|
21192
|
+
let distanceFade = 1.0 - clamp(travel / contactShadowTrace.maxDistance, 0.0, 1.0);
|
|
21193
|
+
return vec4f(vec3f(1.0 - distanceFade), 1.0);
|
|
21194
|
+
}
|
|
21195
|
+
if (depthDelta > hitThickness * 8.0) { break; }
|
|
21196
|
+
}
|
|
21197
|
+
return vec4f(1.0);
|
|
21198
|
+
}`
|
|
21199
|
+
),
|
|
21200
|
+
fs: (
|
|
21201
|
+
/* glsl */
|
|
21202
|
+
`
|
|
21203
|
+
layout(std140) uniform contactShadowTraceUniforms {
|
|
21204
|
+
mat4 projectionMatrix;
|
|
21205
|
+
mat4 inverseProjectionMatrix;
|
|
21206
|
+
vec3 lightDirectionView;
|
|
21207
|
+
float maxDistance;
|
|
21208
|
+
float thickness;
|
|
21209
|
+
float stepCount;
|
|
21210
|
+
float frameIndex;
|
|
21211
|
+
float normalBias;
|
|
21212
|
+
} contactShadowTrace;
|
|
21213
|
+
uniform sampler2D depthTexture;
|
|
21214
|
+
uniform sampler2D normalTexture;
|
|
21215
|
+
vec3 contactShadow_reconstructViewPosition(vec2 uv, float depth) {
|
|
21216
|
+
vec4 view = contactShadowTrace.inverseProjectionMatrix * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
21217
|
+
return view.xyz / max(abs(view.w), 0.00001);
|
|
21218
|
+
}
|
|
21219
|
+
vec2 contactShadow_projectViewPosition(vec3 position) {
|
|
21220
|
+
vec4 clip = contactShadowTrace.projectionMatrix * vec4(position,1.0);
|
|
21221
|
+
return clip.xy / max(abs(clip.w),0.00001) * 0.5 + 0.5;
|
|
21222
|
+
}
|
|
21223
|
+
vec4 contactShadowTrace_sampleColor(sampler2D sourceTexture,vec2 texSize,vec2 texCoord) {
|
|
21224
|
+
float centerDepth = texture(depthTexture,texCoord).r;
|
|
21225
|
+
if(centerDepth >= 0.99999) return vec4(1.0);
|
|
21226
|
+
vec3 centerNormal = normalize(texture(normalTexture,texCoord).xyz * 2.0 - 1.0);
|
|
21227
|
+
vec3 centerPosition = contactShadow_reconstructViewPosition(texCoord,centerDepth) + centerNormal * contactShadowTrace.normalBias;
|
|
21228
|
+
vec3 rayDirection = normalize(contactShadowTrace.lightDirectionView);
|
|
21229
|
+
float noise = fract(sin(dot(texCoord * texSize + contactShadowTrace.frameIndex,vec2(12.9898,78.233))) * 43758.5453);
|
|
21230
|
+
for(int index=0;index<40;index++) {
|
|
21231
|
+
if(float(index)>=contactShadowTrace.stepCount) break;
|
|
21232
|
+
float fraction=(float(index)+0.35+noise*0.5)/max(contactShadowTrace.stepCount,1.0);
|
|
21233
|
+
float travel=contactShadowTrace.maxDistance*fraction*fraction;
|
|
21234
|
+
vec3 rayPosition=centerPosition+rayDirection*travel;
|
|
21235
|
+
vec2 sampleUv=contactShadow_projectViewPosition(rayPosition);
|
|
21236
|
+
if(any(lessThanEqual(sampleUv,vec2(0.0)))||any(greaterThanEqual(sampleUv,vec2(1.0))))break;
|
|
21237
|
+
float sampleDepth=texture(depthTexture,sampleUv).r;
|
|
21238
|
+
if(sampleDepth>=0.99999)continue;
|
|
21239
|
+
vec3 scenePosition=contactShadow_reconstructViewPosition(sampleUv,sampleDepth);
|
|
21240
|
+
float depthDelta=(-rayPosition.z)-(-scenePosition.z);
|
|
21241
|
+
float hitThickness=contactShadowTrace.thickness+travel*0.02;
|
|
21242
|
+
if(depthDelta>=0.0&&depthDelta<=hitThickness) {
|
|
21243
|
+
float distanceFade=1.0-clamp(travel/contactShadowTrace.maxDistance,0.0,1.0);
|
|
21244
|
+
return vec4(vec3(1.0-distanceFade),1.0);
|
|
21245
|
+
}
|
|
21246
|
+
if(depthDelta>hitThickness*8.0)break;
|
|
21247
|
+
}
|
|
21248
|
+
return vec4(1.0);
|
|
21249
|
+
}
|
|
21250
|
+
`
|
|
21251
|
+
),
|
|
21252
|
+
bindingLayout: [
|
|
21253
|
+
{ name: "depthTexture", group: 0 },
|
|
21254
|
+
{ name: "normalTexture", group: 0 }
|
|
21255
|
+
],
|
|
21256
|
+
props: {},
|
|
21257
|
+
uniforms: {},
|
|
21258
|
+
bindings: {},
|
|
21259
|
+
uniformTypes: {
|
|
21260
|
+
projectionMatrix: "mat4x4<f32>",
|
|
21261
|
+
inverseProjectionMatrix: "mat4x4<f32>",
|
|
21262
|
+
lightDirectionView: "vec3<f32>",
|
|
21263
|
+
maxDistance: "f32",
|
|
21264
|
+
thickness: "f32",
|
|
21265
|
+
stepCount: "f32",
|
|
21266
|
+
frameIndex: "f32",
|
|
21267
|
+
normalBias: "f32"
|
|
21268
|
+
},
|
|
21269
|
+
propTypes: {
|
|
21270
|
+
projectionMatrix: { value: IDENTITY_MATRIX3, private: true },
|
|
21271
|
+
inverseProjectionMatrix: { value: IDENTITY_MATRIX3, private: true },
|
|
21272
|
+
lightDirectionView: { value: [0, 1, 0], private: true },
|
|
21273
|
+
maxDistance: { value: 4, min: 0.1, softMax: 16 },
|
|
21274
|
+
thickness: { value: 0.12, min: 5e-3, softMax: 1 },
|
|
21275
|
+
stepCount: { value: 24, min: 1, max: 40 },
|
|
21276
|
+
frameIndex: { value: 0, private: true },
|
|
21277
|
+
normalBias: { value: 0.035, min: 0, softMax: 0.2 }
|
|
21278
|
+
},
|
|
21279
|
+
passes: [{ sampler: true }]
|
|
21280
|
+
};
|
|
21281
|
+
var contactShadowBilateralBlur = {
|
|
21282
|
+
name: "contactShadowBilateralBlur",
|
|
21283
|
+
source: (
|
|
21284
|
+
/* wgsl */
|
|
21285
|
+
`struct contactShadowBilateralBlurUniforms {
|
|
21286
|
+
direction: vec2f,
|
|
21287
|
+
radius: f32,
|
|
21288
|
+
depthSigma: f32,
|
|
21289
|
+
normalPower: f32,
|
|
21290
|
+
};
|
|
21291
|
+
@group(0) @binding(auto) var<uniform> contactShadowBilateralBlur: contactShadowBilateralBlurUniforms;
|
|
21292
|
+
@group(0) @binding(auto) var depthTexture: texture_depth_2d;
|
|
21293
|
+
@group(0) @binding(auto) var depthTextureSampler: sampler;
|
|
21294
|
+
@group(0) @binding(auto) var normalTexture: texture_2d<f32>;
|
|
21295
|
+
@group(0) @binding(auto) var normalTextureSampler: sampler;
|
|
21296
|
+
|
|
21297
|
+
fn contactShadowBilateralBlur_sampleColor(
|
|
21298
|
+
sourceTexture: texture_2d<f32>, sourceTextureSampler: sampler, texSize: vec2f, texCoord: vec2f
|
|
21299
|
+
) -> vec4f {
|
|
21300
|
+
let sourceDimensions = vec2f(textureDimensions(sourceTexture));
|
|
21301
|
+
let texel = contactShadowBilateralBlur.direction / sourceDimensions;
|
|
21302
|
+
let centerDepth = textureSampleLevel(depthTexture, depthTextureSampler, texCoord, 0);
|
|
21303
|
+
let centerNormal = normalize(textureSampleLevel(normalTexture, normalTextureSampler, texCoord, 0.0).xyz * 2.0 - 1.0);
|
|
21304
|
+
var result = textureSampleLevel(sourceTexture, sourceTextureSampler, texCoord, 0.0).r;
|
|
21305
|
+
var totalWeight = 1.0;
|
|
21306
|
+
for (var index: i32 = 1; index <= 6; index++) {
|
|
21307
|
+
if (f32(index) > contactShadowBilateralBlur.radius) { break; }
|
|
21308
|
+
for (var side: i32 = -1; side <= 1; side += 2) {
|
|
21309
|
+
let sampleUv = clamp(texCoord + texel * f32(index * side), vec2f(0.0), vec2f(1.0));
|
|
21310
|
+
let sampleDepth = textureSampleLevel(depthTexture, depthTextureSampler, sampleUv, 0);
|
|
21311
|
+
let sampleNormal = normalize(textureSampleLevel(normalTexture, normalTextureSampler, sampleUv, 0.0).xyz * 2.0 - 1.0);
|
|
21312
|
+
let depthDelta = abs(sampleDepth - centerDepth);
|
|
21313
|
+
let depthWeight = exp(-(depthDelta * depthDelta) / max(2.0 * contactShadowBilateralBlur.depthSigma * contactShadowBilateralBlur.depthSigma, 0.000001));
|
|
21314
|
+
let normalWeight = pow(max(dot(centerNormal, sampleNormal), 0.0), contactShadowBilateralBlur.normalPower);
|
|
21315
|
+
let spatialWeight = exp(-f32(index * index) / 8.0);
|
|
21316
|
+
let weight = depthWeight * normalWeight * spatialWeight;
|
|
21317
|
+
result += textureSampleLevel(sourceTexture, sourceTextureSampler, sampleUv, 0.0).r * weight;
|
|
21318
|
+
totalWeight += weight;
|
|
21319
|
+
}
|
|
21320
|
+
}
|
|
21321
|
+
let visibility = result / totalWeight;
|
|
21322
|
+
return vec4f(vec3f(visibility), 1.0);
|
|
21323
|
+
}`
|
|
21324
|
+
),
|
|
21325
|
+
fs: (
|
|
21326
|
+
/* glsl */
|
|
21327
|
+
`
|
|
21328
|
+
layout(std140) uniform contactShadowBilateralBlurUniforms {
|
|
21329
|
+
vec2 direction;
|
|
21330
|
+
float radius;
|
|
21331
|
+
float depthSigma;
|
|
21332
|
+
float normalPower;
|
|
21333
|
+
} contactShadowBilateralBlur;
|
|
21334
|
+
uniform sampler2D depthTexture;
|
|
21335
|
+
uniform sampler2D normalTexture;
|
|
21336
|
+
vec4 contactShadowBilateralBlur_sampleColor(sampler2D sourceTexture,vec2 texSize,vec2 texCoord) {
|
|
21337
|
+
vec2 texel=contactShadowBilateralBlur.direction/vec2(textureSize(sourceTexture,0));
|
|
21338
|
+
float centerDepth=texture(depthTexture,texCoord).r;
|
|
21339
|
+
vec3 centerNormal=normalize(texture(normalTexture,texCoord).xyz*2.0-1.0);
|
|
21340
|
+
float result=texture(sourceTexture,texCoord).r;
|
|
21341
|
+
float totalWeight=1.0;
|
|
21342
|
+
for(int index=1;index<=6;index++) {
|
|
21343
|
+
if(float(index)>contactShadowBilateralBlur.radius)break;
|
|
21344
|
+
for(int side=-1;side<=1;side+=2) {
|
|
21345
|
+
vec2 sampleUv=clamp(texCoord+texel*float(index*side),vec2(0.0),vec2(1.0));
|
|
21346
|
+
float sampleDepth=texture(depthTexture,sampleUv).r;
|
|
21347
|
+
vec3 sampleNormal=normalize(texture(normalTexture,sampleUv).xyz*2.0-1.0);
|
|
21348
|
+
float depthDelta=abs(sampleDepth-centerDepth);
|
|
21349
|
+
float depthWeight=exp(-(depthDelta*depthDelta)/max(2.0*contactShadowBilateralBlur.depthSigma*contactShadowBilateralBlur.depthSigma,0.000001));
|
|
21350
|
+
float normalWeight=pow(max(dot(centerNormal,sampleNormal),0.0),contactShadowBilateralBlur.normalPower);
|
|
21351
|
+
float spatialWeight=exp(-float(index*index)/8.0);
|
|
21352
|
+
float weight=depthWeight*normalWeight*spatialWeight;
|
|
21353
|
+
result+=texture(sourceTexture,sampleUv).r*weight;totalWeight+=weight;
|
|
21354
|
+
}
|
|
21355
|
+
}
|
|
21356
|
+
return vec4(vec3(result/totalWeight),1.0);
|
|
21357
|
+
}
|
|
21358
|
+
`
|
|
21359
|
+
),
|
|
21360
|
+
bindingLayout: [
|
|
21361
|
+
{ name: "depthTexture", group: 0 },
|
|
21362
|
+
{ name: "normalTexture", group: 0 }
|
|
21363
|
+
],
|
|
21364
|
+
props: {},
|
|
21365
|
+
uniforms: {},
|
|
21366
|
+
bindings: {},
|
|
21367
|
+
uniformTypes: {
|
|
21368
|
+
direction: "vec2<f32>",
|
|
21369
|
+
radius: "f32",
|
|
21370
|
+
depthSigma: "f32",
|
|
21371
|
+
normalPower: "f32"
|
|
21372
|
+
},
|
|
21373
|
+
propTypes: {
|
|
21374
|
+
direction: { value: [1, 0], private: true },
|
|
21375
|
+
radius: { value: 4, min: 1, max: 6 },
|
|
21376
|
+
depthSigma: { value: 6e-3, min: 1e-4, softMax: 0.05 },
|
|
21377
|
+
normalPower: { value: 24, min: 1, softMax: 64 }
|
|
21378
|
+
},
|
|
21379
|
+
passes: [{ sampler: true }]
|
|
21380
|
+
};
|
|
21381
|
+
var contactShadowComposite = {
|
|
21382
|
+
name: "contactShadowComposite",
|
|
21383
|
+
source: (
|
|
21384
|
+
/* wgsl */
|
|
21385
|
+
`struct contactShadowCompositeUniforms {
|
|
21386
|
+
strength: f32,
|
|
21387
|
+
debugMode: f32,
|
|
21388
|
+
};
|
|
21389
|
+
@group(0) @binding(auto) var<uniform> contactShadowComposite: contactShadowCompositeUniforms;
|
|
21390
|
+
@group(0) @binding(auto) var contactShadowTexture: texture_2d<f32>;
|
|
21391
|
+
@group(0) @binding(auto) var contactShadowTextureSampler: sampler;
|
|
21392
|
+
@group(0) @binding(auto) var directionalDirectTexture: texture_2d<f32>;
|
|
21393
|
+
@group(0) @binding(auto) var directionalDirectTextureSampler: sampler;
|
|
21394
|
+
@group(0) @binding(auto) var shadowDebugTexture: texture_2d<f32>;
|
|
21395
|
+
@group(0) @binding(auto) var shadowDebugTextureSampler: sampler;
|
|
21396
|
+
|
|
21397
|
+
fn contactShadowComposite_sampleColor(
|
|
21398
|
+
sourceTexture: texture_2d<f32>, sourceTextureSampler: sampler, texSize: vec2f, texCoord: vec2f
|
|
21399
|
+
) -> vec4f {
|
|
21400
|
+
let color = textureSampleLevel(sourceTexture, sourceTextureSampler, texCoord, 0.0);
|
|
21401
|
+
let contact = textureSampleLevel(contactShadowTexture, contactShadowTextureSampler, texCoord, 0.0).r;
|
|
21402
|
+
let appliedContact = mix(1.0, contact, contactShadowComposite.strength);
|
|
21403
|
+
if (contactShadowComposite.debugMode > 0.5 && contactShadowComposite.debugMode < 1.5) {
|
|
21404
|
+
return vec4f(vec3f(contact), 1.0);
|
|
21405
|
+
}
|
|
21406
|
+
if (contactShadowComposite.debugMode >= 1.5) {
|
|
21407
|
+
let factors = textureSampleLevel(shadowDebugTexture, shadowDebugTextureSampler, texCoord, 0.0).rgb;
|
|
21408
|
+
return vec4f(vec3f(factors.x * factors.y * factors.z * contact), 1.0);
|
|
21409
|
+
}
|
|
21410
|
+
let directionalDirect = textureSampleLevel(
|
|
21411
|
+
directionalDirectTexture,
|
|
21412
|
+
directionalDirectTextureSampler,
|
|
21413
|
+
texCoord,
|
|
21414
|
+
0.0
|
|
21415
|
+
).rgb;
|
|
21416
|
+
return vec4f(max(color.rgb - directionalDirect * (1.0 - appliedContact), vec3f(0.0)), color.a);
|
|
21417
|
+
}`
|
|
21418
|
+
),
|
|
21419
|
+
fs: (
|
|
21420
|
+
/* glsl */
|
|
21421
|
+
`
|
|
21422
|
+
layout(std140) uniform contactShadowCompositeUniforms {
|
|
21423
|
+
float strength;
|
|
21424
|
+
float debugMode;
|
|
21425
|
+
} contactShadowComposite;
|
|
21426
|
+
uniform sampler2D contactShadowTexture;
|
|
21427
|
+
uniform sampler2D directionalDirectTexture;
|
|
21428
|
+
uniform sampler2D shadowDebugTexture;
|
|
21429
|
+
vec4 contactShadowComposite_sampleColor(sampler2D sourceTexture,vec2 texSize,vec2 texCoord) {
|
|
21430
|
+
vec4 color=texture(sourceTexture,texCoord);
|
|
21431
|
+
float contact=texture(contactShadowTexture,texCoord).r;
|
|
21432
|
+
float appliedContact=mix(1.0,contact,contactShadowComposite.strength);
|
|
21433
|
+
if(contactShadowComposite.debugMode>0.5&&contactShadowComposite.debugMode<1.5)return vec4(vec3(contact),1.0);
|
|
21434
|
+
if(contactShadowComposite.debugMode>=1.5){vec3 factors=texture(shadowDebugTexture,texCoord).rgb;return vec4(vec3(factors.x*factors.y*factors.z*contact),1.0);}
|
|
21435
|
+
vec3 directionalDirect=texture(directionalDirectTexture,texCoord).rgb;
|
|
21436
|
+
return vec4(max(color.rgb-directionalDirect*(1.0-appliedContact),vec3(0.0)),color.a);
|
|
21437
|
+
}
|
|
21438
|
+
`
|
|
21439
|
+
),
|
|
21440
|
+
bindingLayout: [
|
|
21441
|
+
{ name: "contactShadowTexture", group: 0 },
|
|
21442
|
+
{ name: "directionalDirectTexture", group: 0 },
|
|
21443
|
+
{ name: "shadowDebugTexture", group: 0 }
|
|
21444
|
+
],
|
|
21445
|
+
props: {},
|
|
21446
|
+
uniforms: {},
|
|
21447
|
+
bindings: {},
|
|
21448
|
+
uniformTypes: { strength: "f32", debugMode: "f32" },
|
|
21449
|
+
propTypes: {
|
|
21450
|
+
strength: { value: 1, min: 0, max: 1 },
|
|
21451
|
+
debugMode: { value: 0, min: 0, max: 2, private: true }
|
|
21452
|
+
},
|
|
21453
|
+
passes: [{ sampler: true }]
|
|
21454
|
+
};
|
|
21455
|
+
|
|
21456
|
+
// src/modules/lighting/pbr-contact-shadow/pbr-contact-shadow.ts
|
|
21457
|
+
var pbrContactShadow = {
|
|
21458
|
+
name: "pbrContactShadow",
|
|
21459
|
+
dependencies: [pbrMaterial],
|
|
21460
|
+
bindingLayout: [
|
|
21461
|
+
{ name: "pbrContactShadow", group: 0 },
|
|
21462
|
+
{ name: "contactShadowTexture", group: 2 }
|
|
21463
|
+
],
|
|
21464
|
+
uniformTypes: { viewport: "vec4<f32>", strength: "f32", enabled: "i32" },
|
|
21465
|
+
defaultUniforms: { viewport: [0, 0, 1, 1], strength: 1, enabled: 1 },
|
|
21466
|
+
getUniforms(properties = {}) {
|
|
21467
|
+
return {
|
|
21468
|
+
...properties.viewport ? { viewport: properties.viewport } : {},
|
|
21469
|
+
...properties.strength === void 0 ? {} : { strength: properties.strength },
|
|
21470
|
+
...properties.enabled === void 0 ? {} : { enabled: Number(properties.enabled) },
|
|
21471
|
+
...properties.contactShadowTexture ? { contactShadowTexture: properties.contactShadowTexture } : {}
|
|
21472
|
+
};
|
|
21473
|
+
},
|
|
21474
|
+
source: (
|
|
21475
|
+
/* wgsl */
|
|
21476
|
+
`
|
|
21477
|
+
struct PBRContactShadowUniforms {
|
|
21478
|
+
viewport: vec4f,
|
|
21479
|
+
strength: f32,
|
|
21480
|
+
enabled: i32,
|
|
21481
|
+
};
|
|
21482
|
+
@group(0) @binding(auto) var<uniform> pbrContactShadow: PBRContactShadowUniforms;
|
|
21483
|
+
@group(2) @binding(auto) var contactShadowTexture: texture_2d<f32>;
|
|
21484
|
+
@group(2) @binding(auto) var contactShadowTextureSampler: sampler;
|
|
21485
|
+
fn pbrContactShadow_getFactor(pixelPosition:vec2f)->f32 {
|
|
21486
|
+
if(pbrContactShadow.enabled==0){return 1.0;}
|
|
21487
|
+
let coordinates=(pixelPosition-pbrContactShadow.viewport.xy)/pbrContactShadow.viewport.zw;
|
|
21488
|
+
if(any(coordinates<vec2f(0.0))||any(coordinates>vec2f(1.0))){return 1.0;}
|
|
21489
|
+
let visibility=textureSampleLevel(contactShadowTexture,contactShadowTextureSampler,coordinates,0.0).r;
|
|
21490
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrContactShadow.strength,0.0,1.0));
|
|
21491
|
+
}
|
|
21492
|
+
fn pbrContactShadow_filterColor(vertexColor:vec4f,pixelPosition:vec2f)->vec4f {
|
|
21493
|
+
return pbr_filterColorWithShadows(vertexColor,pbrContactShadow_getFactor(pixelPosition),vec4f(1.0),vec4f(1.0));
|
|
21494
|
+
}`
|
|
21495
|
+
),
|
|
21496
|
+
fs: (
|
|
21497
|
+
/* glsl */
|
|
21498
|
+
`
|
|
21499
|
+
layout(std140) uniform pbrContactShadowUniforms {
|
|
21500
|
+
vec4 viewport;
|
|
21501
|
+
float strength;
|
|
21502
|
+
int enabled;
|
|
21503
|
+
} pbrContactShadow;
|
|
21504
|
+
uniform sampler2D contactShadowTexture;
|
|
21505
|
+
float pbrContactShadow_getFactor(vec2 pixelPosition) {
|
|
21506
|
+
if(pbrContactShadow.enabled==0)return 1.0;
|
|
21507
|
+
vec2 coordinates=(pixelPosition-pbrContactShadow.viewport.xy)/pbrContactShadow.viewport.zw;
|
|
21508
|
+
if(any(lessThan(coordinates,vec2(0.0)))||any(greaterThan(coordinates,vec2(1.0))))return 1.0;
|
|
21509
|
+
float visibility=texture(contactShadowTexture,coordinates).r;
|
|
21510
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrContactShadow.strength,0.0,1.0));
|
|
21511
|
+
}
|
|
21512
|
+
vec4 pbrContactShadow_filterColor(vec4 vertexColor,vec2 pixelPosition) {
|
|
21513
|
+
return pbr_filterColorWithShadows(vertexColor,pbrContactShadow_getFactor(pixelPosition),vec4(1.0),vec4(1.0));
|
|
21514
|
+
}`
|
|
21515
|
+
)
|
|
21516
|
+
};
|
|
21517
|
+
|
|
21518
|
+
// src/modules/lighting/clustered-light-grid/clustered-light-grid.ts
|
|
21519
|
+
var clusteredLightGrid = {
|
|
21520
|
+
name: "clusteredLightGrid",
|
|
21521
|
+
source: (
|
|
21522
|
+
/* wgsl */
|
|
21523
|
+
`
|
|
21524
|
+
fn clusteredLightGrid_getIndex(coordinates: vec2f, viewDepth: f32, dimensions: vec3u, nearPlane: f32, farPlane: f32) -> u32 {
|
|
21525
|
+
let tile = min(vec2u(clamp(coordinates, vec2f(0.0), vec2f(0.999999)) * vec2f(dimensions.xy)), dimensions.xy - vec2u(1));
|
|
21526
|
+
let normalizedDepth = clamp(log(clamp(viewDepth, nearPlane, farPlane) / nearPlane) / log(farPlane / nearPlane), 0.0, 0.999999);
|
|
21527
|
+
let depthSlice = min(u32(normalizedDepth * f32(dimensions.z)), dimensions.z - 1u);
|
|
21528
|
+
return (depthSlice * dimensions.y + tile.y) * dimensions.x + tile.x;
|
|
21529
|
+
}
|
|
21530
|
+
`
|
|
21531
|
+
)
|
|
21532
|
+
};
|
|
21533
|
+
|
|
21534
|
+
// src/modules/lighting/pbr-ambient-occlusion/pbr-ambient-occlusion.ts
|
|
21535
|
+
var pbrAmbientOcclusion = {
|
|
21536
|
+
name: "pbrAmbientOcclusion",
|
|
21537
|
+
dependencies: [pbrMaterial],
|
|
21538
|
+
bindingLayout: [
|
|
21539
|
+
{ name: "pbrAmbientOcclusion", group: 0 },
|
|
21540
|
+
{ name: "ambientOcclusionTexture", group: 2 }
|
|
21541
|
+
],
|
|
21542
|
+
uniformTypes: { viewport: "vec4<f32>", strength: "f32", enabled: "i32" },
|
|
21543
|
+
defaultUniforms: { viewport: [0, 0, 1, 1], strength: 1, enabled: 1 },
|
|
21544
|
+
getUniforms(properties = {}) {
|
|
21545
|
+
return {
|
|
21546
|
+
...properties.viewport ? { viewport: properties.viewport } : {},
|
|
21547
|
+
...properties.strength === void 0 ? {} : { strength: properties.strength },
|
|
21548
|
+
...properties.enabled === void 0 ? {} : { enabled: Number(properties.enabled) },
|
|
21549
|
+
...properties.ambientOcclusionTexture ? { ambientOcclusionTexture: properties.ambientOcclusionTexture } : {}
|
|
21550
|
+
};
|
|
21551
|
+
},
|
|
21552
|
+
source: (
|
|
21553
|
+
/* wgsl */
|
|
21554
|
+
`
|
|
21555
|
+
struct PBRAmbientOcclusionUniforms {
|
|
21556
|
+
viewport: vec4f,
|
|
21557
|
+
strength: f32,
|
|
21558
|
+
enabled: i32,
|
|
21559
|
+
};
|
|
21560
|
+
@group(0) @binding(auto) var<uniform> pbrAmbientOcclusion: PBRAmbientOcclusionUniforms;
|
|
21561
|
+
@group(2) @binding(auto) var ambientOcclusionTexture: texture_2d<f32>;
|
|
21562
|
+
@group(2) @binding(auto) var ambientOcclusionTextureSampler: sampler;
|
|
21563
|
+
fn pbrAmbientOcclusion_getFactor(pixelPosition:vec2f)->f32 {
|
|
21564
|
+
if(pbrAmbientOcclusion.enabled==0){return 1.0;}
|
|
21565
|
+
let coordinates=(pixelPosition-pbrAmbientOcclusion.viewport.xy)/pbrAmbientOcclusion.viewport.zw;
|
|
21566
|
+
if(any(coordinates<vec2f(0.0))||any(coordinates>vec2f(1.0))){return 1.0;}
|
|
21567
|
+
let visibility=textureSampleLevel(ambientOcclusionTexture,ambientOcclusionTextureSampler,coordinates,0.0).r;
|
|
21568
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrAmbientOcclusion.strength,0.0,1.0));
|
|
21569
|
+
}
|
|
21570
|
+
fn pbrAmbientOcclusion_setFactor(pixelPosition:vec2f) {
|
|
21571
|
+
pbr_ambientVisibility = pbrAmbientOcclusion_getFactor(pixelPosition);
|
|
21572
|
+
}`
|
|
21573
|
+
),
|
|
21574
|
+
fs: (
|
|
21575
|
+
/* glsl */
|
|
21576
|
+
`
|
|
21577
|
+
layout(std140) uniform pbrAmbientOcclusionUniforms {
|
|
21578
|
+
vec4 viewport;
|
|
21579
|
+
float strength;
|
|
21580
|
+
int enabled;
|
|
21581
|
+
} pbrAmbientOcclusion;
|
|
21582
|
+
uniform sampler2D ambientOcclusionTexture;
|
|
21583
|
+
float pbrAmbientOcclusion_getFactor(vec2 pixelPosition) {
|
|
21584
|
+
if(pbrAmbientOcclusion.enabled==0)return 1.0;
|
|
21585
|
+
vec2 coordinates=(pixelPosition-pbrAmbientOcclusion.viewport.xy)/pbrAmbientOcclusion.viewport.zw;
|
|
21586
|
+
if(any(lessThan(coordinates,vec2(0.0)))||any(greaterThan(coordinates,vec2(1.0))))return 1.0;
|
|
21587
|
+
float visibility=texture(ambientOcclusionTexture,coordinates).r;
|
|
21588
|
+
return mix(1.0,clamp(visibility,0.0,1.0),clamp(pbrAmbientOcclusion.strength,0.0,1.0));
|
|
21589
|
+
}
|
|
21590
|
+
void pbrAmbientOcclusion_setFactor(vec2 pixelPosition) {
|
|
21591
|
+
pbr_ambientVisibility = pbrAmbientOcclusion_getFactor(pixelPosition);
|
|
21592
|
+
}`
|
|
21593
|
+
)
|
|
21594
|
+
};
|
|
19877
21595
|
return __toCommonJS(bundle_exports);
|
|
19878
21596
|
})();
|
|
19879
21597
|
return __exports__;
|