@forgeax/engine-shader 0.1.20 → 0.1.23
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/README.md +10 -0
- package/dist/ShaderRegistry.d.ts.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +33070 -8
- package/dist/index.mjs.map +1 -1
- package/dist/ltc/provenance.d.ts +17 -0
- package/dist/ltc/provenance.d.ts.map +1 -0
- package/dist/ltc/tables.d.ts +22 -0
- package/dist/ltc/tables.d.ts.map +1 -0
- package/dist/material/artifact-types.d.ts +52 -0
- package/dist/material/artifact-types.d.ts.map +1 -1
- package/dist/material-schemas.d.ts +5 -0
- package/dist/material-schemas.d.ts.map +1 -1
- package/dist/register-default-sprite-lit.d.ts +3 -6
- package/dist/register-default-sprite-lit.d.ts.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ShaderRegistry.ts +65 -0
- package/src/__tests__/bloom-fxaa-tonemap.unit.test.ts +30 -4
- package/src/__tests__/default-standard-pbr-alpha.unit.test.ts +7 -0
- package/src/__tests__/default-standard-pbr-transmission.unit.test.ts +138 -30
- package/src/__tests__/direct-light-layout.unit.test.ts +40 -0
- package/src/__tests__/ibl-irradiance.unit.test.ts +7 -4
- package/src/__tests__/ibl-sampling.unit.test.ts +3 -4
- package/src/__tests__/lighting-point-spot-volume.unit.test.ts +16 -2
- package/src/__tests__/lighting-punctual.unit.test.ts +61 -8
- package/src/__tests__/lighting-spot-volume-attenuation.unit.test.ts +1 -1
- package/src/__tests__/ltc-provenance.unit.test.ts +33 -0
- package/src/__tests__/manifest.fixture.json +33 -0
- package/src/__tests__/material-contract.unit.test.ts +61 -1
- package/src/__tests__/material-derived-builtins.integration.test.ts +27 -0
- package/src/__tests__/probe-lighting-composition.unit.test.ts +38 -0
- package/src/__tests__/rect-area-brdf.unit.test.ts +36 -0
- package/src/__tests__/reflection-probe-sampling.unit.test.ts +45 -0
- package/src/__tests__/scene-temporal.unit.test.ts +20 -0
- package/src/__tests__/shader.unit.test.ts +40 -15
- package/src/__tests__/shadow-pcss.unit.test.ts +131 -0
- package/src/__tests__/spot-cookie-composition.unit.test.ts +57 -0
- package/src/__tests__/spot-modifier-composition.unit.test.ts +19 -0
- package/src/__tests__/sprite-lit-shader.test.ts +24 -11
- package/src/__tests__/sprite-variants.unit.test.ts +5 -1
- package/src/__tests__/transmission-thickness-scale.unit.test.ts +7 -1
- package/src/__tests__/transparent-pbr.unit.test.ts +7 -0
- package/src/brdf.wgsl +115 -1
- package/src/common.wgsl +95 -91
- package/src/default-standard-pbr-skin.wgsl +108 -92
- package/src/default-standard-pbr.wgsl +189 -191
- package/src/fxaa.wgsl +27 -6
- package/src/ibl-irradiance.wgsl +4 -1
- package/src/ibl-sampling.wgsl +56 -2
- package/src/index.ts +23 -0
- package/src/lighting-directional.wgsl +161 -132
- package/src/lighting-probe.wgsl +51 -0
- package/src/lighting-punctual.wgsl +69 -29
- package/src/lighting-rect-area.wgsl +162 -0
- package/src/lighting-spot-modifiers.wgsl +93 -0
- package/src/ltc/provenance.ts +19 -0
- package/src/ltc/tables.ts +2831 -0
- package/src/material/artifact-types.ts +137 -0
- package/src/material-schemas.ts +12 -0
- package/src/register-default-sprite-lit.ts +3 -6
- package/src/scene-temporal.wgsl +14 -8
- package/src/shadow-pcf.wgsl +44 -1
- package/src/sprite-lit.wgsl +37 -53
- package/src/sprite.wgsl +1 -1
- package/src/standard-cluster.wgsl +274 -0
- package/src/tonemap.wgsl +8 -3
- package/src/types.ts +2 -1
- package/src/volume/volume-inject.wgsl +48 -38
- package/src/volume/volume-integrate.wgsl +47 -42
- package/dist/.tsbuildinfo +0 -1
- package/src/hdrp-cluster-forward.wgsl +0 -224
package/src/ibl-sampling.wgsl
CHANGED
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
// - sampleIblDiffuse(N, irradianceMap, irradianceSampler)
|
|
17
17
|
// - sampleIblSpecular(N, V, roughness, F0, prefilterMap, prefilterSampler,
|
|
18
18
|
// brdfLut, brdfLutSampler)
|
|
19
|
+
// - box_project(worldPosition, direction, boxCenter, boxExtents)
|
|
20
|
+
// - sampleReflectionProbeSpecular(..., probeMap, probeSampler, ...)
|
|
19
21
|
|
|
20
|
-
#import forgeax_pbr::ibl_shared::{
|
|
22
|
+
#import forgeax_pbr::ibl_shared::{fresnelSchlickRoughness, inverseRotateEnvironment}
|
|
21
23
|
|
|
22
24
|
// Sample pre-convolved irradiance from the irradiance cubemap.
|
|
23
25
|
// Y is negated to compensate for WebGPU's top-left texture origin vs the
|
|
@@ -31,7 +33,7 @@ fn sampleIblDiffuse(
|
|
|
31
33
|
let rotated = inverseRotateEnvironment(normal, rotation);
|
|
32
34
|
let dir = vec3<f32>(rotated.x, -rotated.y, rotated.z);
|
|
33
35
|
let irradianceEOverPi = textureSample(irradianceMap, irradianceSampler, dir).rgb;
|
|
34
|
-
return irradianceEOverPi
|
|
36
|
+
return irradianceEOverPi;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
// Split-sum specular IBL: prefiltered env * (F0 * scale + bias).
|
|
@@ -56,3 +58,55 @@ fn sampleIblSpecular(
|
|
|
56
58
|
let F = fresnelSchlickRoughness(NdotV, F0, roughness);
|
|
57
59
|
return prefilteredColor * (F * envBRDF.r + envBRDF.g);
|
|
58
60
|
}
|
|
61
|
+
|
|
62
|
+
// Project a reflection ray from a point inside a probe box onto the box
|
|
63
|
+
// boundary. The helper is binding-free so the scene table and the material
|
|
64
|
+
// resource projection remain owned by the host record stage.
|
|
65
|
+
fn box_project(
|
|
66
|
+
worldPosition: vec3<f32>,
|
|
67
|
+
direction: vec3<f32>,
|
|
68
|
+
boxCenter: vec3<f32>,
|
|
69
|
+
boxExtents: vec3<f32>,
|
|
70
|
+
) -> vec3<f32> {
|
|
71
|
+
let safeExtents = max(boxExtents, vec3<f32>(0.0001));
|
|
72
|
+
let safeDirection = select(
|
|
73
|
+
vec3<f32>(0.0001),
|
|
74
|
+
direction,
|
|
75
|
+
abs(direction) >= vec3<f32>(0.0001),
|
|
76
|
+
);
|
|
77
|
+
let localPosition = worldPosition - boxCenter;
|
|
78
|
+
let edgeSign = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));
|
|
79
|
+
let edge = edgeSign * safeExtents;
|
|
80
|
+
let distances = (edge - localPosition) / safeDirection;
|
|
81
|
+
let travel = min(distances.x, min(distances.y, distances.z));
|
|
82
|
+
return normalize(localPosition + direction * max(travel, 0.0));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Split-sum probe sample. The probe texture is supplied by the caller so a
|
|
86
|
+
// missing scene candidate can keep using sampleIblSpecular with the Skylight
|
|
87
|
+
// resources already present in the Standard material layout.
|
|
88
|
+
fn sampleReflectionProbeSpecular(
|
|
89
|
+
normal: vec3<f32>,
|
|
90
|
+
view: vec3<f32>,
|
|
91
|
+
roughness: f32,
|
|
92
|
+
F0: vec3<f32>,
|
|
93
|
+
worldPosition: vec3<f32>,
|
|
94
|
+
boxCenter: vec3<f32>,
|
|
95
|
+
boxExtents: vec3<f32>,
|
|
96
|
+
rotation: vec4<f32>,
|
|
97
|
+
probeMap: texture_cube<f32>,
|
|
98
|
+
probeSampler: sampler,
|
|
99
|
+
brdfLut: texture_2d<f32>,
|
|
100
|
+
brdfLutSampler: sampler,
|
|
101
|
+
) -> vec3<f32> {
|
|
102
|
+
let NdotV = max(dot(normal, view), 0.001);
|
|
103
|
+
let reflection = reflect(-view, normal);
|
|
104
|
+
let projected = box_project(worldPosition, reflection, boxCenter, boxExtents);
|
|
105
|
+
let rotated = inverseRotateEnvironment(projected, rotation);
|
|
106
|
+
let probeDirection = vec3<f32>(rotated.x, -rotated.y, rotated.z);
|
|
107
|
+
let mip = roughness * 4.0;
|
|
108
|
+
let prefilteredColor = textureSampleLevel(probeMap, probeSampler, probeDirection, mip).rgb;
|
|
109
|
+
let envBRDF = textureSample(brdfLut, brdfLutSampler, vec2<f32>(NdotV, roughness)).rg;
|
|
110
|
+
let F = fresnelSchlickRoughness(NdotV, F0, roughness);
|
|
111
|
+
return prefilteredColor * (F * envBRDF.r + envBRDF.g);
|
|
112
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -39,6 +39,16 @@ export {
|
|
|
39
39
|
type ShaderErrorDetail,
|
|
40
40
|
shaderNotFound,
|
|
41
41
|
} from './errors.js';
|
|
42
|
+
export {
|
|
43
|
+
generateLtcTables,
|
|
44
|
+
hashLtcTable,
|
|
45
|
+
LTC_SOURCE_PROVENANCE,
|
|
46
|
+
LTC_TABLE_HASHES,
|
|
47
|
+
LTC_TABLE_HEIGHT,
|
|
48
|
+
LTC_TABLE_INPUT_HASHES,
|
|
49
|
+
LTC_TABLE_WIDTH,
|
|
50
|
+
LTC_TABLES,
|
|
51
|
+
} from './ltc/tables.js';
|
|
42
52
|
export {
|
|
43
53
|
type MaterialArtifactConflictError,
|
|
44
54
|
type MaterialArtifactInspection,
|
|
@@ -46,8 +56,12 @@ export {
|
|
|
46
56
|
type MaterialRuntimeArtifact,
|
|
47
57
|
} from './material/artifact-registry.js';
|
|
48
58
|
export {
|
|
59
|
+
createStandardPbrArtifactReceipt,
|
|
49
60
|
isMaterialShaderArtifact,
|
|
50
61
|
type MaterialShaderArtifact,
|
|
62
|
+
type MaterialShaderArtifactReceipt,
|
|
63
|
+
type MaterialShaderResourceSlot,
|
|
64
|
+
type MaterialShaderVertexInput,
|
|
51
65
|
} from './material/artifact-types.js';
|
|
52
66
|
export {
|
|
53
67
|
DEFAULT_MSDF_TEXT_PARAM_SCHEMA,
|
|
@@ -55,12 +69,15 @@ export {
|
|
|
55
69
|
DEFAULT_STANDARD_PBR_PARAM_SCHEMA,
|
|
56
70
|
DEFAULT_UNLIT_PARAM_SCHEMA,
|
|
57
71
|
STANDARD_PBR_ALPHA_CUTOFF_DEFAULT,
|
|
72
|
+
STANDARD_PBR_ARTIFACT_RECEIPT,
|
|
73
|
+
STANDARD_PBR_SKIN_ARTIFACT_RECEIPT,
|
|
58
74
|
} from './material-schemas.js';
|
|
59
75
|
export {
|
|
60
76
|
registerDefaultSpriteLit,
|
|
61
77
|
type SpriteLitCaps,
|
|
62
78
|
} from './register-default-sprite-lit.js';
|
|
63
79
|
export { registerDefaultStandardPbrSkin } from './register-default-standard-pbr-skin.js';
|
|
80
|
+
export const RECT_AREA_LTC_SHADER_MODULE = 'forgeax::lighting-rect-area' as const;
|
|
64
81
|
export {
|
|
65
82
|
FORGEAX_RESERVED_PATH_PREFIX,
|
|
66
83
|
type MaterialShaderEntry,
|
|
@@ -108,6 +125,12 @@ export const ENGINE_MATERIAL_MODULES = [
|
|
|
108
125
|
'forgeax_material::sprite-lit',
|
|
109
126
|
] as const;
|
|
110
127
|
|
|
128
|
+
/** Names of the zero-binding Standard reflection-probe shader helpers. */
|
|
129
|
+
export const REFLECTION_PROBE_SHADER_HELPERS = Object.freeze([
|
|
130
|
+
'box_project',
|
|
131
|
+
'sampleReflectionProbeSpecular',
|
|
132
|
+
] as const);
|
|
133
|
+
|
|
111
134
|
export function isEngineMaterialModule(module: string): boolean {
|
|
112
135
|
return (ENGINE_MATERIAL_MODULES as readonly string[]).includes(module);
|
|
113
136
|
}
|
|
@@ -46,128 +46,43 @@
|
|
|
46
46
|
// layered BRDFs such as base + clearcoat)
|
|
47
47
|
|
|
48
48
|
#import forgeax_view::common::{view, shadowMap, shadowSampler}
|
|
49
|
-
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx}
|
|
49
|
+
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx, threeR184DirectMultiScatter}
|
|
50
50
|
#import forgeax_pbr::shadow_pcf::{sample_shadow_2d}
|
|
51
|
+
#ifdef DIRECTIONAL_PCSS_AVAILABLE
|
|
52
|
+
#import forgeax_pbr::shadow_pcf::{shadow_biased_receiver_depth, shadow_clamp_texel_to_tile, shadow_load_raw_depth, shadow_sample_compare}
|
|
53
|
+
#endif
|
|
51
54
|
|
|
52
55
|
// feat-20260621-learn-render-5-3-production-shadow-demos M0 / AC-14:
|
|
53
56
|
// compile-time upper bound on the PCF half-extent so the WGSL tap loops keep
|
|
54
57
|
// a constant trip count (no dynamic loop bounds / shader variants). half=2
|
|
55
|
-
// covers
|
|
56
|
-
// the runtime radius
|
|
58
|
+
// covers the PCF1/3/5 profiles -> {1,9,25} taps; the profile carrier selects
|
|
59
|
+
// the runtime radius while keeping the receiver variant-free.
|
|
57
60
|
const MAX_PCF_HALF : u32 = 2u;
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const THREE_R184_DFG_LUT : array<vec2<f32>, 256> = array<vec2<f32>, 256>(
|
|
65
|
-
vec2<f32>(0.1470947265625, 0.85205078125), vec2<f32>(0.16552734375, 0.78759765625), vec2<f32>(0.244384765625, 0.638671875), vec2<f32>(0.370849609375, 0.51953125),
|
|
66
|
-
vec2<f32>(0.496826171875, 0.41552734375), vec2<f32>(0.60205078125, 0.326416015625), vec2<f32>(0.68408203125, 0.25390625), vec2<f32>(0.74609375, 0.197509765625),
|
|
67
|
-
vec2<f32>(0.79052734375, 0.154296875), vec2<f32>(0.822265625, 0.12164306640625), vec2<f32>(0.84326171875, 0.09698486328125), vec2<f32>(0.8564453125, 0.07843017578125),
|
|
68
|
-
vec2<f32>(0.86328125, 0.06439208984375), vec2<f32>(0.86572265625, 0.0537109375), vec2<f32>(0.8642578125, 0.045440673828125), vec2<f32>(0.85986328125, 0.039031982421875),
|
|
69
|
-
vec2<f32>(0.388671875, 0.611328125), vec2<f32>(0.39306640625, 0.6005859375), vec2<f32>(0.412353515625, 0.5458984375), vec2<f32>(0.45654296875, 0.4482421875),
|
|
70
|
-
vec2<f32>(0.52783203125, 0.3525390625), vec2<f32>(0.607421875, 0.27392578125), vec2<f32>(0.6787109375, 0.21142578125), vec2<f32>(0.7333984375, 0.16259765625),
|
|
71
|
-
vec2<f32>(0.77099609375, 0.1253662109375), vec2<f32>(0.79345703125, 0.0972900390625), vec2<f32>(0.80322265625, 0.07623291015625), vec2<f32>(0.8037109375, 0.06036376953125),
|
|
72
|
-
vec2<f32>(0.79638671875, 0.048431396484375), vec2<f32>(0.78564453125, 0.03936767578125), vec2<f32>(0.77197265625, 0.03240966796875), vec2<f32>(0.7548828125, 0.0269775390625),
|
|
73
|
-
vec2<f32>(0.572265625, 0.427490234375), vec2<f32>(0.57373046875, 0.424072265625), vec2<f32>(0.57958984375, 0.403564453125), vec2<f32>(0.591796875, 0.3544921875),
|
|
74
|
-
vec2<f32>(0.6162109375, 0.2880859375), vec2<f32>(0.6552734375, 0.224853515625), vec2<f32>(0.69873046875, 0.172607421875), vec2<f32>(0.7353515625, 0.1318359375),
|
|
75
|
-
vec2<f32>(0.75927734375, 0.10089111328125), vec2<f32>(0.77001953125, 0.07745361328125), vec2<f32>(0.77197265625, 0.0599365234375), vec2<f32>(0.76611328125, 0.046844482421875),
|
|
76
|
-
vec2<f32>(0.751953125, 0.0369873046875), vec2<f32>(0.732421875, 0.029541015625), vec2<f32>(0.70947265625, 0.023834228515625), vec2<f32>(0.68359375, 0.019439697265625),
|
|
77
|
-
vec2<f32>(0.708984375, 0.291015625), vec2<f32>(0.708984375, 0.289794921875), vec2<f32>(0.7099609375, 0.28125), vec2<f32>(0.7099609375, 0.258544921875),
|
|
78
|
-
vec2<f32>(0.71142578125, 0.220458984375), vec2<f32>(0.7197265625, 0.1768798828125), vec2<f32>(0.734375, 0.1370849609375), vec2<f32>(0.748046875, 0.10479736328125),
|
|
79
|
-
vec2<f32>(0.755859375, 0.07989501953125), vec2<f32>(0.759765625, 0.061004638671875), vec2<f32>(0.75341796875, 0.046844482421875), vec2<f32>(0.73876953125, 0.036224365234375),
|
|
80
|
-
vec2<f32>(0.7177734375, 0.02825927734375), vec2<f32>(0.69189453125, 0.0222625732421875), vec2<f32>(0.6611328125, 0.0177001953125), vec2<f32>(0.62841796875, 0.01419830322265625),
|
|
81
|
-
vec2<f32>(0.80810546875, 0.1917724609375), vec2<f32>(0.8076171875, 0.1912841796875), vec2<f32>(0.80615234375, 0.18798828125), vec2<f32>(0.8017578125, 0.1781005859375),
|
|
82
|
-
vec2<f32>(0.79296875, 0.15869140625), vec2<f32>(0.78369140625, 0.1322021484375), vec2<f32>(0.775390625, 0.1048583984375), vec2<f32>(0.7685546875, 0.08111572265625),
|
|
83
|
-
vec2<f32>(0.7646484375, 0.061981201171875), vec2<f32>(0.75537109375, 0.047271728515625), vec2<f32>(0.740234375, 0.036163330078125), vec2<f32>(0.71875, 0.0277557373046875),
|
|
84
|
-
vec2<f32>(0.69091796875, 0.021484375), vec2<f32>(0.658203125, 0.0167388916015625), vec2<f32>(0.6220703125, 0.01316070556640625), vec2<f32>(0.583984375, 0.01041412353515625),
|
|
85
|
-
vec2<f32>(0.87841796875, 0.1217041015625), vec2<f32>(0.8779296875, 0.1217041015625), vec2<f32>(0.875, 0.12060546875), vec2<f32>(0.869140625, 0.116943359375),
|
|
86
|
-
vec2<f32>(0.85693359375, 0.1080322265625), vec2<f32>(0.837890625, 0.09375), vec2<f32>(0.81494140625, 0.076904296875), vec2<f32>(0.7958984375, 0.060699462890625),
|
|
87
|
-
vec2<f32>(0.7763671875, 0.046875), vec2<f32>(0.75634765625, 0.035919189453125), vec2<f32>(0.732421875, 0.0274505615234375), vec2<f32>(0.703125, 0.021026611328125),
|
|
88
|
-
vec2<f32>(0.6689453125, 0.01617431640625), vec2<f32>(0.63037109375, 0.01251220703125), vec2<f32>(0.58935546875, 0.00974273681640625), vec2<f32>(0.54638671875, 0.007633209228515625),
|
|
89
|
-
vec2<f32>(0.92626953125, 0.07379150390625), vec2<f32>(0.92578125, 0.07391357421875), vec2<f32>(0.9228515625, 0.07391357421875), vec2<f32>(0.9169921875, 0.0731201171875),
|
|
90
|
-
vec2<f32>(0.90380859375, 0.06982421875), vec2<f32>(0.88134765625, 0.0631103515625), vec2<f32>(0.85107421875, 0.053802490234375), vec2<f32>(0.8212890625, 0.043701171875),
|
|
91
|
-
vec2<f32>(0.791015625, 0.034393310546875), vec2<f32>(0.76123046875, 0.026611328125), vec2<f32>(0.72802734375, 0.02044677734375), vec2<f32>(0.69189453125, 0.015655517578125),
|
|
92
|
-
vec2<f32>(0.65087890625, 0.0120086669921875), vec2<f32>(0.607421875, 0.00925445556640625), vec2<f32>(0.56103515625, 0.0071563720703125), vec2<f32>(0.51416015625, 0.005565643310546875),
|
|
93
|
-
vec2<f32>(0.95751953125, 0.042327880859375), vec2<f32>(0.95703125, 0.042449951171875), vec2<f32>(0.95458984375, 0.042816162109375), vec2<f32>(0.94921875, 0.043182373046875),
|
|
94
|
-
vec2<f32>(0.93701171875, 0.04266357421875), vec2<f32>(0.9130859375, 0.040252685546875), vec2<f32>(0.8818359375, 0.035797119140625), vec2<f32>(0.8447265625, 0.0301361083984375),
|
|
95
|
-
vec2<f32>(0.80615234375, 0.0243377685546875), vec2<f32>(0.76708984375, 0.0191497802734375), vec2<f32>(0.7265625, 0.01485443115234375), vec2<f32>(0.6826171875, 0.01142120361328125),
|
|
96
|
-
vec2<f32>(0.63623046875, 0.0087738037109375), vec2<f32>(0.5869140625, 0.006740570068359375), vec2<f32>(0.53662109375, 0.005199432373046875), vec2<f32>(0.486083984375, 0.00402069091796875),
|
|
97
|
-
vec2<f32>(0.9775390625, 0.0226287841796875), vec2<f32>(0.97705078125, 0.0227508544921875), vec2<f32>(0.97509765625, 0.023193359375), vec2<f32>(0.9697265625, 0.0239105224609375),
|
|
98
|
-
vec2<f32>(0.95947265625, 0.0244903564453125), vec2<f32>(0.93603515625, 0.0241241455078125), vec2<f32>(0.9052734375, 0.02252197265625), vec2<f32>(0.865234375, 0.0197601318359375),
|
|
99
|
-
vec2<f32>(0.82177734375, 0.016510009765625), vec2<f32>(0.7744140625, 0.0132904052734375), vec2<f32>(0.7265625, 0.01045989990234375), vec2<f32>(0.67626953125, 0.0081329345703125),
|
|
100
|
-
vec2<f32>(0.6240234375, 0.00627899169921875), vec2<f32>(0.56982421875, 0.004825592041015625), vec2<f32>(0.51513671875, 0.0037136077880859375), vec2<f32>(0.46142578125, 0.0028629302978515625),
|
|
101
|
-
vec2<f32>(0.98876953125, 0.01107025146484375), vec2<f32>(0.98876953125, 0.01116180419921875), vec2<f32>(0.98681640625, 0.01151275634765625), vec2<f32>(0.98291015625, 0.01221466064453125),
|
|
102
|
-
vec2<f32>(0.97314453125, 0.01299285888671875), vec2<f32>(0.953125, 0.013519287109375), vec2<f32>(0.9228515625, 0.01328277587890625), vec2<f32>(0.88232421875, 0.01226043701171875),
|
|
103
|
-
vec2<f32>(0.8349609375, 0.01065826416015625), vec2<f32>(0.783203125, 0.00885009765625), vec2<f32>(0.728515625, 0.007114410400390625), vec2<f32>(0.671875, 0.00560760498046875),
|
|
104
|
-
vec2<f32>(0.61376953125, 0.004360198974609375), vec2<f32>(0.5546875, 0.0033721923828125), vec2<f32>(0.496337890625, 0.0025997161865234375), vec2<f32>(0.439453125, 0.0020046234130859375),
|
|
105
|
-
vec2<f32>(0.9951171875, 0.00479888916015625), vec2<f32>(0.9951171875, 0.004863739013671875), vec2<f32>(0.99365234375, 0.005096435546875), vec2<f32>(0.990234375, 0.005603790283203125),
|
|
106
|
-
vec2<f32>(0.9814453125, 0.0063323974609375), vec2<f32>(0.96435546875, 0.006977081298828125), vec2<f32>(0.93603515625, 0.007297515869140625), vec2<f32>(0.896484375, 0.0071258544921875),
|
|
107
|
-
vec2<f32>(0.8466796875, 0.00649261474609375), vec2<f32>(0.79150390625, 0.005596160888671875), vec2<f32>(0.7314453125, 0.004627227783203125), vec2<f32>(0.6689453125, 0.0037174224853515625),
|
|
108
|
-
vec2<f32>(0.60546875, 0.0029296875), vec2<f32>(0.54150390625, 0.00228118896484375), vec2<f32>(0.479248046875, 0.001766204833984375), vec2<f32>(0.419677734375, 0.00136566162109375),
|
|
109
|
-
vec2<f32>(0.998046875, 0.0017604827880859375), vec2<f32>(0.998046875, 0.0017938613891601562), vec2<f32>(0.99658203125, 0.0019292831420898438), vec2<f32>(0.994140625, 0.002239227294921875),
|
|
110
|
-
vec2<f32>(0.986328125, 0.0027294158935546875), vec2<f32>(0.9716796875, 0.0032501220703125), vec2<f32>(0.94580078125, 0.00366973876953125), vec2<f32>(0.90771484375, 0.003818511962890625),
|
|
111
|
-
vec2<f32>(0.8583984375, 0.003681182861328125), vec2<f32>(0.79931640625, 0.0033206939697265625), vec2<f32>(0.7353515625, 0.0028438568115234375), vec2<f32>(0.66748046875, 0.0023441314697265625),
|
|
112
|
-
vec2<f32>(0.5986328125, 0.0018796920776367188), vec2<f32>(0.5302734375, 0.0014829635620117188), vec2<f32>(0.464111328125, 0.0011587142944335938), vec2<f32>(0.402099609375, 0.0008993148803710938),
|
|
113
|
-
vec2<f32>(0.99951171875, 0.0005011558532714844), vec2<f32>(0.99951171875, 0.0005154609680175781), vec2<f32>(0.998046875, 0.000583648681640625), vec2<f32>(0.99658203125, 0.0007505416870117188),
|
|
114
|
-
vec2<f32>(0.9892578125, 0.00101470947265625), vec2<f32>(0.97607421875, 0.001346588134765625), vec2<f32>(0.95263671875, 0.0016527175903320312), vec2<f32>(0.916015625, 0.0018558502197265625),
|
|
115
|
-
vec2<f32>(0.8671875, 0.0019054412841796875), vec2<f32>(0.8076171875, 0.0018167495727539062), vec2<f32>(0.7392578125, 0.001621246337890625), vec2<f32>(0.6669921875, 0.0013799667358398438),
|
|
116
|
-
vec2<f32>(0.59326171875, 0.0011358261108398438), vec2<f32>(0.52001953125, 0.0009121894836425781), vec2<f32>(0.450439453125, 0.0007219314575195312), vec2<f32>(0.385986328125, 0.0005650520324707031),
|
|
117
|
-
vec2<f32>(1.0, 0.00009316205978393555), vec2<f32>(1.0, 0.0000978708267211914), vec2<f32>(0.9990234375, 0.00012540817260742188), vec2<f32>(0.9970703125, 0.00019216537475585938),
|
|
118
|
-
vec2<f32>(0.99072265625, 0.0003104209899902344), vec2<f32>(0.97900390625, 0.0004699230194091797), vec2<f32>(0.95751953125, 0.0006470680236816406), vec2<f32>(0.92333984375, 0.0007915496826171875),
|
|
119
|
-
vec2<f32>(0.87548828125, 0.0008769035339355469), vec2<f32>(0.81494140625, 0.0008869171142578125), vec2<f32>(0.744140625, 0.0008325576782226562), vec2<f32>(0.66748046875, 0.0007386207580566406),
|
|
120
|
-
vec2<f32>(0.58837890625, 0.0006265640258789062), vec2<f32>(0.51123046875, 0.0005168914794921875), vec2<f32>(0.438232421875, 0.0004165172576904297), vec2<f32>(0.37109375, 0.0003311634063720703),
|
|
121
|
-
vec2<f32>(1.0, 0.000007271766662597656), vec2<f32>(1.0, 0.000008165836334228516), vec2<f32>(0.9990234375, 0.000016987323760986328), vec2<f32>(0.99755859375, 0.00003790855407714844),
|
|
122
|
-
vec2<f32>(0.9921875, 0.00007593631744384766), vec2<f32>(0.9814453125, 0.00013744831085205078), vec2<f32>(0.96142578125, 0.00020754337310791016), vec2<f32>(0.92919921875, 0.00028014183044433594),
|
|
123
|
-
vec2<f32>(0.8828125, 0.0003345012664794922), vec2<f32>(0.82177734375, 0.00036263465881347656), vec2<f32>(0.7490234375, 0.00036215782165527344), vec2<f32>(0.66845703125, 0.0003380775451660156),
|
|
124
|
-
vec2<f32>(0.58544921875, 0.00029969215393066406), vec2<f32>(0.50390625, 0.00025582313537597656), vec2<f32>(0.427001953125, 0.0002117156982421875), vec2<f32>(0.357666015625, 0.00017201900482177734),
|
|
125
|
-
vec2<f32>(1.0, 0.0), vec2<f32>(1.0, 5.960464477539063e-8), vec2<f32>(0.99951171875, 0.0000012516975402832031), vec2<f32>(0.99755859375, 0.000005304813385009766),
|
|
126
|
-
vec2<f32>(0.9931640625, 0.000015079975128173828), vec2<f32>(0.98291015625, 0.00002855062484741211), vec2<f32>(0.96435546875, 0.00004744529724121094), vec2<f32>(0.93408203125, 0.00006842613220214844),
|
|
127
|
-
vec2<f32>(0.88916015625, 0.00008893013000488281), vec2<f32>(0.828125, 0.0001042485237121582), vec2<f32>(0.75390625, 0.00011217594146728516), vec2<f32>(0.67041015625, 0.00011241436004638672),
|
|
128
|
-
vec2<f32>(0.5830078125, 0.00010627508163452148), vec2<f32>(0.4970703125, 0.00009584426879882812), vec2<f32>(0.4169921875, 0.0000833272933959961), vec2<f32>(0.34521484375, 0.00007051229476928711),
|
|
129
|
-
);
|
|
62
|
+
#ifdef DIRECTIONAL_PCSS_AVAILABLE
|
|
63
|
+
const PCSS_MEDIUM_RAW_TAPS : u32 = 8u;
|
|
64
|
+
const PCSS_MEDIUM_COMPARE_TAPS : u32 = 16u;
|
|
65
|
+
const PCSS_HIGH_RAW_TAPS : u32 = 16u;
|
|
66
|
+
const PCSS_HIGH_COMPARE_TAPS : u32 = 32u;
|
|
130
67
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
THREE_R184_DFG_LUT[u32(hi.y) * THREE_R184_DFG_LUT_SIZE + u32(lo.x)],
|
|
146
|
-
THREE_R184_DFG_LUT[u32(hi.y) * THREE_R184_DFG_LUT_SIZE + u32(hi.x)],
|
|
147
|
-
weight.x,
|
|
148
|
-
);
|
|
149
|
-
return mix(rowLo, rowHi, weight.y);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
fn _threeR184DirectMultiScatter(
|
|
153
|
-
roughness : f32,
|
|
154
|
-
nDotV : f32,
|
|
155
|
-
nDotL : f32,
|
|
156
|
-
F0 : vec3<f32>,
|
|
157
|
-
) -> vec3<f32> {
|
|
158
|
-
let dfgV = _sampleThreeR184DfgLut(roughness, nDotV);
|
|
159
|
-
let dfgL = _sampleThreeR184DfgLut(roughness, nDotL);
|
|
160
|
-
let fssEssV = F0 * dfgV.x + vec3<f32>(dfgV.y);
|
|
161
|
-
let fssEssL = F0 * dfgL.x + vec3<f32>(dfgL.y);
|
|
162
|
-
let emsV = 1.0 - dfgV.x - dfgV.y;
|
|
163
|
-
let emsL = 1.0 - dfgL.x - dfgL.y;
|
|
164
|
-
let favg = F0 + (vec3<f32>(1.0) - F0) * 0.047619;
|
|
165
|
-
let energyLoss = emsV * emsL;
|
|
166
|
-
let fms = fssEssV * fssEssL * favg
|
|
167
|
-
/ (vec3<f32>(1.0) - energyLoss * favg * favg + vec3<f32>(1e-6));
|
|
168
|
-
return fms * energyLoss;
|
|
169
|
-
}
|
|
68
|
+
// Cascade-local disk points are fixed, bounded, and shared by raw and compare
|
|
69
|
+
// phases. A rotation derived from the integer receiver texel and cascade keeps
|
|
70
|
+
// the pattern stable without a temporal input.
|
|
71
|
+
const PCSS_DISK_OFFSETS : array<vec2<f32>, 32> = array<vec2<f32>, 32>(
|
|
72
|
+
vec2<f32>(-0.326, -0.945), vec2<f32>(0.236, -0.873), vec2<f32>(0.891, -0.404), vec2<f32>(-0.761, -0.581),
|
|
73
|
+
vec2<f32>(0.612, 0.146), vec2<f32>(-0.148, 0.514), vec2<f32>(-0.527, -0.109), vec2<f32>(0.074, 0.911),
|
|
74
|
+
vec2<f32>(-0.944, 0.238), vec2<f32>(0.444, -0.736), vec2<f32>(0.707, 0.641), vec2<f32>(-0.184, -0.342),
|
|
75
|
+
vec2<f32>(0.318, 0.382), vec2<f32>(-0.638, 0.526), vec2<f32>(0.955, -0.083), vec2<f32>(-0.401, 0.816),
|
|
76
|
+
vec2<f32>(-0.083, -0.632), vec2<f32>(0.539, -0.262), vec2<f32>(-0.735, -0.168), vec2<f32>(0.162, 0.719),
|
|
77
|
+
vec2<f32>(-0.841, 0.003), vec2<f32>(0.791, 0.332), vec2<f32>(-0.291, -0.791), vec2<f32>(0.021, -0.224),
|
|
78
|
+
vec2<f32>(0.386, 0.799), vec2<f32>(-0.558, 0.134), vec2<f32>(0.638, -0.555), vec2<f32>(-0.189, 0.957),
|
|
79
|
+
vec2<f32>(-0.977, -0.117), vec2<f32>(0.271, 0.589), vec2<f32>(0.819, -0.719), vec2<f32>(-0.472, -0.409),
|
|
80
|
+
);
|
|
81
|
+
#endif
|
|
170
82
|
|
|
83
|
+
// Direct multiscatter is owned by forgeax_pbr::brdf. Keep directional
|
|
84
|
+
// lighting as a consumer of that shared function so its LUT and energy
|
|
85
|
+
// compensation cannot diverge from punctual and cluster lighting.
|
|
171
86
|
// Pick the cascade layer for a positive view-space depth -- walks
|
|
172
87
|
// splitPlanes in order, returns the first split the depth falls below. Last
|
|
173
88
|
// layer (count - 1) catches everything beyond splits[count-2]. cascadeCount=1
|
|
@@ -226,8 +141,128 @@ fn _atlasTileOrigin(layer : u32, count : u32) -> vec2<f32> {
|
|
|
226
141
|
return vec2<f32>(tile) / vec2<f32>(grid);
|
|
227
142
|
}
|
|
228
143
|
|
|
144
|
+
#ifdef DIRECTIONAL_PCSS_AVAILABLE
|
|
145
|
+
fn _pcssDiskRotation(texel : vec2<i32>, layer : u32) -> f32 {
|
|
146
|
+
let hash = u32(texel.x) * 1664525u + u32(texel.y) * 1013904223u + (layer + 1u) * 374761393u;
|
|
147
|
+
return f32(hash % 6283u) * 0.001;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fn _pcssDiskPoint(index : u32, angle : f32, radius : f32) -> vec2<f32> {
|
|
151
|
+
let point = PCSS_DISK_OFFSETS[index];
|
|
152
|
+
let cs = cos(angle);
|
|
153
|
+
let sn = sin(angle);
|
|
154
|
+
return vec2<f32>(point.x * cs - point.y * sn, point.x * sn + point.y * cs) * radius;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
fn _pcssProjectedSample(
|
|
158
|
+
shadowMapSize : vec2<u32>,
|
|
159
|
+
tileOrigin : vec2<u32>,
|
|
160
|
+
tileSize : vec2<u32>,
|
|
161
|
+
baseTexel : vec2<i32>,
|
|
162
|
+
offset : vec2<f32>,
|
|
163
|
+
) -> vec2<f32> {
|
|
164
|
+
let texel = shadow_clamp_texel_to_tile(
|
|
165
|
+
baseTexel + vec2<i32>(round(offset)),
|
|
166
|
+
vec2<i32>(tileOrigin),
|
|
167
|
+
vec2<i32>(tileSize),
|
|
168
|
+
1,
|
|
169
|
+
);
|
|
170
|
+
return (vec2<f32>(texel) + vec2<f32>(0.5)) / vec2<f32>(shadowMapSize);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
fn _samplePcssForCascade(
|
|
174
|
+
worldPos : vec3<f32>,
|
|
175
|
+
layer : u32,
|
|
176
|
+
count : u32,
|
|
177
|
+
normal : vec3<f32>,
|
|
178
|
+
l : vec3<f32>,
|
|
179
|
+
profile : u32,
|
|
180
|
+
) -> f32 {
|
|
181
|
+
let lightClip = _cascadeLightViewProj(layer) * vec4<f32>(worldPos, 1.0);
|
|
182
|
+
if (!(lightClip.w > 0.0 || lightClip.w < 0.0)) {
|
|
183
|
+
return 1.0;
|
|
184
|
+
}
|
|
185
|
+
let projCoords = lightClip.xyz / lightClip.w;
|
|
186
|
+
let tileUv = vec2<f32>(projCoords.x * 0.5 + 0.5, -projCoords.y * 0.5 + 0.5);
|
|
187
|
+
if (!(tileUv.x >= 0.0 && tileUv.x <= 1.0 && tileUv.y >= 0.0 && tileUv.y <= 1.0 && projCoords.z >= 0.0 && projCoords.z <= 1.0)) {
|
|
188
|
+
return 1.0;
|
|
189
|
+
}
|
|
190
|
+
let nDotL = dot(normal, l);
|
|
191
|
+
if (!(nDotL >= -1.0 && nDotL <= 1.0)) {
|
|
192
|
+
return 1.0;
|
|
193
|
+
}
|
|
194
|
+
let shadowMapSize = textureDimensions(shadowMap, 0);
|
|
195
|
+
let grid = _atlasTileGrid(count);
|
|
196
|
+
let tileSize = shadowMapSize / grid;
|
|
197
|
+
let tileOrigin = vec2<u32>(layer % grid.x, layer / grid.x) * tileSize;
|
|
198
|
+
let baseTexel = vec2<i32>(tileOrigin) + vec2<i32>(floor(tileUv * vec2<f32>(tileSize)));
|
|
199
|
+
let angle = _pcssDiskRotation(baseTexel, layer);
|
|
200
|
+
let biasedDepth = shadow_biased_receiver_depth(
|
|
201
|
+
projCoords.z,
|
|
202
|
+
view.normalBias,
|
|
203
|
+
view.depthBias,
|
|
204
|
+
nDotL,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
let rawRadius = select(2.0, 3.0, profile == 5u);
|
|
208
|
+
var blockerDepth = 0.0;
|
|
209
|
+
var blockerCount = 0u;
|
|
210
|
+
if (profile == 4u) {
|
|
211
|
+
for (var i = 0u; i < PCSS_MEDIUM_RAW_TAPS; i = i + 1u) {
|
|
212
|
+
let rawUv = _pcssProjectedSample(shadowMapSize, tileOrigin, tileSize, baseTexel, _pcssDiskPoint(i, angle, rawRadius));
|
|
213
|
+
let rawTexel = vec2<i32>(rawUv * vec2<f32>(shadowMapSize) - vec2<f32>(0.5));
|
|
214
|
+
let rawDepth = shadow_load_raw_depth(shadowMap, rawTexel);
|
|
215
|
+
if (rawDepth >= 0.0 && rawDepth < biasedDepth) {
|
|
216
|
+
blockerDepth = blockerDepth + rawDepth;
|
|
217
|
+
blockerCount = blockerCount + 1u;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
for (var i = 0u; i < PCSS_HIGH_RAW_TAPS; i = i + 1u) {
|
|
222
|
+
let rawUv = _pcssProjectedSample(shadowMapSize, tileOrigin, tileSize, baseTexel, _pcssDiskPoint(i, angle, rawRadius));
|
|
223
|
+
let rawTexel = vec2<i32>(rawUv * vec2<f32>(shadowMapSize) - vec2<f32>(0.5));
|
|
224
|
+
let rawDepth = shadow_load_raw_depth(shadowMap, rawTexel);
|
|
225
|
+
if (rawDepth >= 0.0 && rawDepth < biasedDepth) {
|
|
226
|
+
blockerDepth = blockerDepth + rawDepth;
|
|
227
|
+
blockerCount = blockerCount + 1u;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (blockerCount == 0u) {
|
|
232
|
+
return 1.0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let averageBlockerDepth = blockerDepth / f32(blockerCount);
|
|
236
|
+
let lightDepthWorldSpan = max(view.splitPlanes[layer].z, 0.0);
|
|
237
|
+
let worldUnitsPerTexel = max(view.splitPlanes[layer].y, 0.0);
|
|
238
|
+
if (!(lightDepthWorldSpan > 0.0 && worldUnitsPerTexel > 0.0 && view.directionalShadowFilter.y >= 0.0 && view.directionalShadowFilter.z >= 0.0)) {
|
|
239
|
+
return 1.0;
|
|
240
|
+
}
|
|
241
|
+
let worldDistance = max(0.0, biasedDepth - averageBlockerDepth) * lightDepthWorldSpan;
|
|
242
|
+
let penumbraTexels = clamp(
|
|
243
|
+
worldDistance * tan(view.directionalShadowFilter.y) / worldUnitsPerTexel,
|
|
244
|
+
0.0,
|
|
245
|
+
view.directionalShadowFilter.z,
|
|
246
|
+
);
|
|
247
|
+
let compareRadius = max(0.5, penumbraTexels);
|
|
248
|
+
var litSum = 0.0;
|
|
249
|
+
if (profile == 4u) {
|
|
250
|
+
for (var i = 0u; i < PCSS_MEDIUM_COMPARE_TAPS; i = i + 1u) {
|
|
251
|
+
let compareUv = _pcssProjectedSample(shadowMapSize, tileOrigin, tileSize, baseTexel, _pcssDiskPoint(i, angle, compareRadius));
|
|
252
|
+
litSum = litSum + shadow_sample_compare(shadowMap, shadowSampler, compareUv, biasedDepth);
|
|
253
|
+
}
|
|
254
|
+
return litSum / f32(PCSS_MEDIUM_COMPARE_TAPS);
|
|
255
|
+
}
|
|
256
|
+
for (var i = 0u; i < PCSS_HIGH_COMPARE_TAPS; i = i + 1u) {
|
|
257
|
+
let compareUv = _pcssProjectedSample(shadowMapSize, tileOrigin, tileSize, baseTexel, _pcssDiskPoint(i, angle, compareRadius));
|
|
258
|
+
litSum = litSum + shadow_sample_compare(shadowMap, shadowSampler, compareUv, biasedDepth);
|
|
259
|
+
}
|
|
260
|
+
return litSum / f32(PCSS_HIGH_COMPARE_TAPS);
|
|
261
|
+
}
|
|
262
|
+
#endif
|
|
263
|
+
|
|
229
264
|
// Sample the shadow atlas with the LO 3.1.3 slope-scaled bias + dynamic PCF
|
|
230
|
-
// kernel (driven by
|
|
265
|
+
// kernel (driven by the directional filter profile, MAX_PCF_HALF=2),
|
|
231
266
|
// against the lightViewProj for the chosen cascade. The shader maps NDC
|
|
232
267
|
// xy to that cascade's atlas tile in fragment space (matrix carries
|
|
233
268
|
// clip-space; tile placement happens here so shadow_caster.gl_Position
|
|
@@ -275,21 +310,16 @@ fn _sampleShadowForCascade(
|
|
|
275
310
|
// [tileOrigin, tileOrigin+tileScale) (one texel inset) so taps stay in-tile.
|
|
276
311
|
let tileLo = tileOrigin + texel;
|
|
277
312
|
let tileHi = tileOrigin + tileScale - texel;
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
//
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
let
|
|
288
|
-
// Preserve the previous radius mapping for malformed even values:
|
|
289
|
-
// 1 -> 1x1, 2/3/4 -> 3x3, 5 -> 5x5. The authored component accepts only
|
|
290
|
-
// {1,3,5}, but keeping this normalization makes the refactor output-stable
|
|
291
|
-
// for raw UBO callers too.
|
|
292
|
-
let kernel = select(select(5u, 3u, requestedKernel <= 4u), 1u, requestedKernel == 1u);
|
|
313
|
+
// PCF1/3/5 profiles 1/2/3 retain their existing receiver. PCSS profiles 4/5
|
|
314
|
+
// use the bounded three-stage receiver below without a material or variant
|
|
315
|
+
// axis; the carrier y/z lanes provide angular radius and penumbra limit.
|
|
316
|
+
let filterProfile = clamp(u32(round(view.directionalShadowFilter.x)), 1u, 5u);
|
|
317
|
+
#ifdef DIRECTIONAL_PCSS_AVAILABLE
|
|
318
|
+
if (filterProfile >= 4u) {
|
|
319
|
+
return _samplePcssForCascade(worldPos, layer, count, normal, l, filterProfile);
|
|
320
|
+
}
|
|
321
|
+
#endif
|
|
322
|
+
let kernel = select(select(3u, 5u, filterProfile == 3u), 1u, filterProfile == 1u);
|
|
293
323
|
if (kernel == 1u) {
|
|
294
324
|
let lit = textureSampleCompareLevel(shadowMap, shadowSampler, clamp(uv, tileLo, tileHi), adjustedDepth);
|
|
295
325
|
return lit;
|
|
@@ -383,10 +413,9 @@ fn evalDirectionalNoShadow(
|
|
|
383
413
|
let nDotV = max(dot(normal, viewDir), 1e-5);
|
|
384
414
|
let nDotH = max(dot(normal, h), 0.0);
|
|
385
415
|
let vDotH = max(dot(viewDir, h), 0.0);
|
|
386
|
-
let
|
|
387
|
-
let f = F0 * (vec3<f32>(1.0) - fresnel) + vec3<f32>(fresnel);
|
|
416
|
+
let f = f_schlick(vDotH, F0);
|
|
388
417
|
let roughness = sqrt(max(alphaSq, 0.0));
|
|
389
|
-
let multiScatter =
|
|
418
|
+
let multiScatter = threeR184DirectMultiScatter(roughness, nDotV, nDotL, F0);
|
|
390
419
|
let specular = d_ggx(nDotH, alphaSq) * v_smith(nDotV, nDotL, alphaSq) * f + multiScatter;
|
|
391
420
|
let diffuse = (1.0 - metallic) * baseColor / 3.14159265;
|
|
392
421
|
return (diffuse + specular) * view.lightColor * nDotL;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @forgeax/engine-shader - lighting-probe.wgsl
|
|
2
|
+
// Local diffuse LightProbe composition. The record is supplied by the
|
|
3
|
+
// renderer's per-object retained projection; Skylight remains the sole Sky
|
|
4
|
+
// and specular owner.
|
|
5
|
+
|
|
6
|
+
#define_import_path forgeax_pbr::lighting_probe
|
|
7
|
+
|
|
8
|
+
const PROBE_INV_PI : f32 = 0.3183098861837907;
|
|
9
|
+
|
|
10
|
+
fn probe_sh9(shPreblend : array<vec4<f32>, 9>, normal : vec3<f32>) -> vec3<f32> {
|
|
11
|
+
let x = normal.x;
|
|
12
|
+
let y = normal.y;
|
|
13
|
+
let z = normal.z;
|
|
14
|
+
let basis = array<f32, 9>(
|
|
15
|
+
0.2820947918,
|
|
16
|
+
0.4886025119 * y,
|
|
17
|
+
0.4886025119 * z,
|
|
18
|
+
0.4886025119 * x,
|
|
19
|
+
1.0925484306 * x * y,
|
|
20
|
+
1.0925484306 * y * z,
|
|
21
|
+
0.3153915653 * (3.0 * z * z - 1.0),
|
|
22
|
+
1.0925484306 * x * z,
|
|
23
|
+
0.5462742153 * (x * x - y * y),
|
|
24
|
+
);
|
|
25
|
+
var result = vec3<f32>(0.0);
|
|
26
|
+
for (var band = 0u; band < 9u; band = band + 1u) {
|
|
27
|
+
result += shPreblend[band].xyz * basis[band];
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// One SH9 evaluation, then the real Skylight residual. No Sky q, probe loop,
|
|
33
|
+
// hidden gain, smoothstep, or specular probe path is present here.
|
|
34
|
+
fn evaluateProbeDiffuse(
|
|
35
|
+
shPreblend : array<vec4<f32>, 9>,
|
|
36
|
+
localBlendFraction : f32,
|
|
37
|
+
normal : vec3<f32>,
|
|
38
|
+
e_sky : vec3<f32>,
|
|
39
|
+
k_d : vec3<f32>,
|
|
40
|
+
albedo : vec3<f32>,
|
|
41
|
+
metallic : f32,
|
|
42
|
+
) -> vec3<f32> {
|
|
43
|
+
// `shPreblend` stores cosine-convolved irradiance. Match the existing
|
|
44
|
+
// Standard-PBR Skylight path and Three's BRDF_Lambert: irradiance becomes
|
|
45
|
+
// reflected diffuse radiance only after the single 1/pi factor. The Sky
|
|
46
|
+
// argument is already the Skylight path's E/pi * color * intensity value,
|
|
47
|
+
// so it must not be divided a second time below.
|
|
48
|
+
let local = max(probe_sh9(shPreblend, normal), vec3<f32>(0.0)) * PROBE_INV_PI;
|
|
49
|
+
let skyResidualFraction = 1.0 - localBlendFraction;
|
|
50
|
+
return (local + skyResidualFraction * e_sky) * k_d * albedo * (1.0 - metallic);
|
|
51
|
+
}
|