@forgeax/engine-shader 0.1.21 → 0.1.24
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 +14 -5
- package/dist/ShaderRegistry.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +33042 -55
- 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 +36 -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 +0 -17
- package/src/__tests__/default-standard-pbr-alpha.unit.test.ts +9 -3
- package/src/__tests__/default-standard-pbr-transmission.unit.test.ts +67 -122
- package/src/__tests__/deferred-lighting-ssao.test.ts +3 -3
- package/src/__tests__/direct-light-layout.unit.test.ts +40 -0
- package/src/__tests__/ibl-irradiance.unit.test.ts +16 -4
- package/src/__tests__/ibl-sampling.unit.test.ts +3 -4
- package/src/__tests__/lighting-directional.unit.test.ts +36 -0
- package/src/__tests__/lighting-point-spot-volume.unit.test.ts +8 -2
- package/src/__tests__/lighting-punctual.unit.test.ts +40 -5
- 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-builtins.unit.test.ts +21 -3
- package/src/__tests__/material-contract.unit.test.ts +188 -14
- package/src/__tests__/physical-clearcoat.unit.test.ts +65 -0
- package/src/__tests__/probe-lighting-composition.unit.test.ts +39 -0
- package/src/__tests__/rect-area-brdf.unit.test.ts +36 -0
- package/src/__tests__/reflection-probe-sampling.unit.test.ts +24 -2
- package/src/__tests__/shader-manifest-transmission.unit.test.ts +8 -10
- package/src/__tests__/shader.unit.test.ts +54 -85
- package/src/__tests__/spot-cookie-composition.unit.test.ts +58 -0
- package/src/__tests__/spot-modifier-composition.unit.test.ts +19 -0
- package/src/__tests__/sprite-variants.unit.test.ts +4 -1
- package/src/__tests__/standard-webgl2-varying-budget.unit.test.ts +17 -0
- package/src/__tests__/surface-v1-negative.unit.test.ts +37 -0
- package/src/__tests__/surface-v1.unit.test.ts +83 -0
- package/src/__tests__/transmission-thickness-scale.unit.test.ts +2 -6
- package/src/__tests__/vertex-color-variant.unit.test.ts +16 -5
- package/src/brdf.wgsl +115 -1
- package/src/common.wgsl +53 -79
- package/src/default-standard-pbr-skin.wgsl +687 -144
- package/src/default-standard-pbr.wgsl +600 -247
- package/src/default_standard_surface.wgsl +88 -0
- package/src/hdrp-cluster-forward.wgsl +225 -0
- package/src/ibl-irradiance.wgsl +47 -9
- package/src/ibl-prefilter.wgsl +13 -3
- package/src/ibl-sampling.wgsl +2 -2
- package/src/ibl-shared.wgsl +9 -2
- package/src/index.ts +23 -0
- package/src/lighting-directional.wgsl +9 -117
- package/src/lighting-probe.wgsl +51 -0
- package/src/lighting-punctual.wgsl +21 -11
- package/src/lighting-rect-area.wgsl +162 -0
- package/src/lighting-spot-modifiers.wgsl +100 -0
- package/src/lighting-spot-projector.wgsl +31 -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/physical/anisotropy.wgsl +26 -0
- package/src/material/physical/clearcoat.wgsl +24 -0
- package/src/material/physical/iridescence.wgsl +23 -0
- package/src/material/physical/sheen.wgsl +17 -0
- package/src/material-schemas.ts +77 -30
- package/src/register-default-sprite-lit.ts +3 -6
- package/src/register-default-standard-pbr-skin.ts +2 -2
- package/src/sprite-lit.wgsl +3 -3
- package/src/sprite.wgsl +1 -1
- package/src/standard-cluster.wgsl +80 -78
- package/src/surface_v1.wgsl +26 -0
- package/src/types.ts +2 -1
- package/src/volume/volume-inject.wgsl +34 -36
- package/src/volume/volume-integrate.wgsl +48 -38
- package/dist/.tsbuildinfo +0 -1
|
@@ -46,7 +46,7 @@
|
|
|
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
51
|
#ifdef DIRECTIONAL_PCSS_AVAILABLE
|
|
52
52
|
#import forgeax_pbr::shadow_pcf::{shadow_biased_receiver_depth, shadow_clamp_texel_to_tile, shadow_load_raw_depth, shadow_sample_compare}
|
|
@@ -80,118 +80,9 @@ const PCSS_DISK_OFFSETS : array<vec2<f32>, 32> = array<vec2<f32>, 32>(
|
|
|
80
80
|
);
|
|
81
81
|
#endif
|
|
82
82
|
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
// adding a host binding or coupling direct light to the engine IBL LUT.
|
|
87
|
-
const THREE_R184_DFG_LUT_SIZE : u32 = 16u;
|
|
88
|
-
const THREE_R184_DFG_LUT : array<vec2<f32>, 256> = array<vec2<f32>, 256>(
|
|
89
|
-
vec2<f32>(0.1470947265625, 0.85205078125), vec2<f32>(0.16552734375, 0.78759765625), vec2<f32>(0.244384765625, 0.638671875), vec2<f32>(0.370849609375, 0.51953125),
|
|
90
|
-
vec2<f32>(0.496826171875, 0.41552734375), vec2<f32>(0.60205078125, 0.326416015625), vec2<f32>(0.68408203125, 0.25390625), vec2<f32>(0.74609375, 0.197509765625),
|
|
91
|
-
vec2<f32>(0.79052734375, 0.154296875), vec2<f32>(0.822265625, 0.12164306640625), vec2<f32>(0.84326171875, 0.09698486328125), vec2<f32>(0.8564453125, 0.07843017578125),
|
|
92
|
-
vec2<f32>(0.86328125, 0.06439208984375), vec2<f32>(0.86572265625, 0.0537109375), vec2<f32>(0.8642578125, 0.045440673828125), vec2<f32>(0.85986328125, 0.039031982421875),
|
|
93
|
-
vec2<f32>(0.388671875, 0.611328125), vec2<f32>(0.39306640625, 0.6005859375), vec2<f32>(0.412353515625, 0.5458984375), vec2<f32>(0.45654296875, 0.4482421875),
|
|
94
|
-
vec2<f32>(0.52783203125, 0.3525390625), vec2<f32>(0.607421875, 0.27392578125), vec2<f32>(0.6787109375, 0.21142578125), vec2<f32>(0.7333984375, 0.16259765625),
|
|
95
|
-
vec2<f32>(0.77099609375, 0.1253662109375), vec2<f32>(0.79345703125, 0.0972900390625), vec2<f32>(0.80322265625, 0.07623291015625), vec2<f32>(0.8037109375, 0.06036376953125),
|
|
96
|
-
vec2<f32>(0.79638671875, 0.048431396484375), vec2<f32>(0.78564453125, 0.03936767578125), vec2<f32>(0.77197265625, 0.03240966796875), vec2<f32>(0.7548828125, 0.0269775390625),
|
|
97
|
-
vec2<f32>(0.572265625, 0.427490234375), vec2<f32>(0.57373046875, 0.424072265625), vec2<f32>(0.57958984375, 0.403564453125), vec2<f32>(0.591796875, 0.3544921875),
|
|
98
|
-
vec2<f32>(0.6162109375, 0.2880859375), vec2<f32>(0.6552734375, 0.224853515625), vec2<f32>(0.69873046875, 0.172607421875), vec2<f32>(0.7353515625, 0.1318359375),
|
|
99
|
-
vec2<f32>(0.75927734375, 0.10089111328125), vec2<f32>(0.77001953125, 0.07745361328125), vec2<f32>(0.77197265625, 0.0599365234375), vec2<f32>(0.76611328125, 0.046844482421875),
|
|
100
|
-
vec2<f32>(0.751953125, 0.0369873046875), vec2<f32>(0.732421875, 0.029541015625), vec2<f32>(0.70947265625, 0.023834228515625), vec2<f32>(0.68359375, 0.019439697265625),
|
|
101
|
-
vec2<f32>(0.708984375, 0.291015625), vec2<f32>(0.708984375, 0.289794921875), vec2<f32>(0.7099609375, 0.28125), vec2<f32>(0.7099609375, 0.258544921875),
|
|
102
|
-
vec2<f32>(0.71142578125, 0.220458984375), vec2<f32>(0.7197265625, 0.1768798828125), vec2<f32>(0.734375, 0.1370849609375), vec2<f32>(0.748046875, 0.10479736328125),
|
|
103
|
-
vec2<f32>(0.755859375, 0.07989501953125), vec2<f32>(0.759765625, 0.061004638671875), vec2<f32>(0.75341796875, 0.046844482421875), vec2<f32>(0.73876953125, 0.036224365234375),
|
|
104
|
-
vec2<f32>(0.7177734375, 0.02825927734375), vec2<f32>(0.69189453125, 0.0222625732421875), vec2<f32>(0.6611328125, 0.0177001953125), vec2<f32>(0.62841796875, 0.01419830322265625),
|
|
105
|
-
vec2<f32>(0.80810546875, 0.1917724609375), vec2<f32>(0.8076171875, 0.1912841796875), vec2<f32>(0.80615234375, 0.18798828125), vec2<f32>(0.8017578125, 0.1781005859375),
|
|
106
|
-
vec2<f32>(0.79296875, 0.15869140625), vec2<f32>(0.78369140625, 0.1322021484375), vec2<f32>(0.775390625, 0.1048583984375), vec2<f32>(0.7685546875, 0.08111572265625),
|
|
107
|
-
vec2<f32>(0.7646484375, 0.061981201171875), vec2<f32>(0.75537109375, 0.047271728515625), vec2<f32>(0.740234375, 0.036163330078125), vec2<f32>(0.71875, 0.0277557373046875),
|
|
108
|
-
vec2<f32>(0.69091796875, 0.021484375), vec2<f32>(0.658203125, 0.0167388916015625), vec2<f32>(0.6220703125, 0.01316070556640625), vec2<f32>(0.583984375, 0.01041412353515625),
|
|
109
|
-
vec2<f32>(0.87841796875, 0.1217041015625), vec2<f32>(0.8779296875, 0.1217041015625), vec2<f32>(0.875, 0.12060546875), vec2<f32>(0.869140625, 0.116943359375),
|
|
110
|
-
vec2<f32>(0.85693359375, 0.1080322265625), vec2<f32>(0.837890625, 0.09375), vec2<f32>(0.81494140625, 0.076904296875), vec2<f32>(0.7958984375, 0.060699462890625),
|
|
111
|
-
vec2<f32>(0.7763671875, 0.046875), vec2<f32>(0.75634765625, 0.035919189453125), vec2<f32>(0.732421875, 0.0274505615234375), vec2<f32>(0.703125, 0.021026611328125),
|
|
112
|
-
vec2<f32>(0.6689453125, 0.01617431640625), vec2<f32>(0.63037109375, 0.01251220703125), vec2<f32>(0.58935546875, 0.00974273681640625), vec2<f32>(0.54638671875, 0.007633209228515625),
|
|
113
|
-
vec2<f32>(0.92626953125, 0.07379150390625), vec2<f32>(0.92578125, 0.07391357421875), vec2<f32>(0.9228515625, 0.07391357421875), vec2<f32>(0.9169921875, 0.0731201171875),
|
|
114
|
-
vec2<f32>(0.90380859375, 0.06982421875), vec2<f32>(0.88134765625, 0.0631103515625), vec2<f32>(0.85107421875, 0.053802490234375), vec2<f32>(0.8212890625, 0.043701171875),
|
|
115
|
-
vec2<f32>(0.791015625, 0.034393310546875), vec2<f32>(0.76123046875, 0.026611328125), vec2<f32>(0.72802734375, 0.02044677734375), vec2<f32>(0.69189453125, 0.015655517578125),
|
|
116
|
-
vec2<f32>(0.65087890625, 0.0120086669921875), vec2<f32>(0.607421875, 0.00925445556640625), vec2<f32>(0.56103515625, 0.0071563720703125), vec2<f32>(0.51416015625, 0.005565643310546875),
|
|
117
|
-
vec2<f32>(0.95751953125, 0.042327880859375), vec2<f32>(0.95703125, 0.042449951171875), vec2<f32>(0.95458984375, 0.042816162109375), vec2<f32>(0.94921875, 0.043182373046875),
|
|
118
|
-
vec2<f32>(0.93701171875, 0.04266357421875), vec2<f32>(0.9130859375, 0.040252685546875), vec2<f32>(0.8818359375, 0.035797119140625), vec2<f32>(0.8447265625, 0.0301361083984375),
|
|
119
|
-
vec2<f32>(0.80615234375, 0.0243377685546875), vec2<f32>(0.76708984375, 0.0191497802734375), vec2<f32>(0.7265625, 0.01485443115234375), vec2<f32>(0.6826171875, 0.01142120361328125),
|
|
120
|
-
vec2<f32>(0.63623046875, 0.0087738037109375), vec2<f32>(0.5869140625, 0.006740570068359375), vec2<f32>(0.53662109375, 0.005199432373046875), vec2<f32>(0.486083984375, 0.00402069091796875),
|
|
121
|
-
vec2<f32>(0.9775390625, 0.0226287841796875), vec2<f32>(0.97705078125, 0.0227508544921875), vec2<f32>(0.97509765625, 0.023193359375), vec2<f32>(0.9697265625, 0.0239105224609375),
|
|
122
|
-
vec2<f32>(0.95947265625, 0.0244903564453125), vec2<f32>(0.93603515625, 0.0241241455078125), vec2<f32>(0.9052734375, 0.02252197265625), vec2<f32>(0.865234375, 0.0197601318359375),
|
|
123
|
-
vec2<f32>(0.82177734375, 0.016510009765625), vec2<f32>(0.7744140625, 0.0132904052734375), vec2<f32>(0.7265625, 0.01045989990234375), vec2<f32>(0.67626953125, 0.0081329345703125),
|
|
124
|
-
vec2<f32>(0.6240234375, 0.00627899169921875), vec2<f32>(0.56982421875, 0.004825592041015625), vec2<f32>(0.51513671875, 0.0037136077880859375), vec2<f32>(0.46142578125, 0.0028629302978515625),
|
|
125
|
-
vec2<f32>(0.98876953125, 0.01107025146484375), vec2<f32>(0.98876953125, 0.01116180419921875), vec2<f32>(0.98681640625, 0.01151275634765625), vec2<f32>(0.98291015625, 0.01221466064453125),
|
|
126
|
-
vec2<f32>(0.97314453125, 0.01299285888671875), vec2<f32>(0.953125, 0.013519287109375), vec2<f32>(0.9228515625, 0.01328277587890625), vec2<f32>(0.88232421875, 0.01226043701171875),
|
|
127
|
-
vec2<f32>(0.8349609375, 0.01065826416015625), vec2<f32>(0.783203125, 0.00885009765625), vec2<f32>(0.728515625, 0.007114410400390625), vec2<f32>(0.671875, 0.00560760498046875),
|
|
128
|
-
vec2<f32>(0.61376953125, 0.004360198974609375), vec2<f32>(0.5546875, 0.0033721923828125), vec2<f32>(0.496337890625, 0.0025997161865234375), vec2<f32>(0.439453125, 0.0020046234130859375),
|
|
129
|
-
vec2<f32>(0.9951171875, 0.00479888916015625), vec2<f32>(0.9951171875, 0.004863739013671875), vec2<f32>(0.99365234375, 0.005096435546875), vec2<f32>(0.990234375, 0.005603790283203125),
|
|
130
|
-
vec2<f32>(0.9814453125, 0.0063323974609375), vec2<f32>(0.96435546875, 0.006977081298828125), vec2<f32>(0.93603515625, 0.007297515869140625), vec2<f32>(0.896484375, 0.0071258544921875),
|
|
131
|
-
vec2<f32>(0.8466796875, 0.00649261474609375), vec2<f32>(0.79150390625, 0.005596160888671875), vec2<f32>(0.7314453125, 0.004627227783203125), vec2<f32>(0.6689453125, 0.0037174224853515625),
|
|
132
|
-
vec2<f32>(0.60546875, 0.0029296875), vec2<f32>(0.54150390625, 0.00228118896484375), vec2<f32>(0.479248046875, 0.001766204833984375), vec2<f32>(0.419677734375, 0.00136566162109375),
|
|
133
|
-
vec2<f32>(0.998046875, 0.0017604827880859375), vec2<f32>(0.998046875, 0.0017938613891601562), vec2<f32>(0.99658203125, 0.0019292831420898438), vec2<f32>(0.994140625, 0.002239227294921875),
|
|
134
|
-
vec2<f32>(0.986328125, 0.0027294158935546875), vec2<f32>(0.9716796875, 0.0032501220703125), vec2<f32>(0.94580078125, 0.00366973876953125), vec2<f32>(0.90771484375, 0.003818511962890625),
|
|
135
|
-
vec2<f32>(0.8583984375, 0.003681182861328125), vec2<f32>(0.79931640625, 0.0033206939697265625), vec2<f32>(0.7353515625, 0.0028438568115234375), vec2<f32>(0.66748046875, 0.0023441314697265625),
|
|
136
|
-
vec2<f32>(0.5986328125, 0.0018796920776367188), vec2<f32>(0.5302734375, 0.0014829635620117188), vec2<f32>(0.464111328125, 0.0011587142944335938), vec2<f32>(0.402099609375, 0.0008993148803710938),
|
|
137
|
-
vec2<f32>(0.99951171875, 0.0005011558532714844), vec2<f32>(0.99951171875, 0.0005154609680175781), vec2<f32>(0.998046875, 0.000583648681640625), vec2<f32>(0.99658203125, 0.0007505416870117188),
|
|
138
|
-
vec2<f32>(0.9892578125, 0.00101470947265625), vec2<f32>(0.97607421875, 0.001346588134765625), vec2<f32>(0.95263671875, 0.0016527175903320312), vec2<f32>(0.916015625, 0.0018558502197265625),
|
|
139
|
-
vec2<f32>(0.8671875, 0.0019054412841796875), vec2<f32>(0.8076171875, 0.0018167495727539062), vec2<f32>(0.7392578125, 0.001621246337890625), vec2<f32>(0.6669921875, 0.0013799667358398438),
|
|
140
|
-
vec2<f32>(0.59326171875, 0.0011358261108398438), vec2<f32>(0.52001953125, 0.0009121894836425781), vec2<f32>(0.450439453125, 0.0007219314575195312), vec2<f32>(0.385986328125, 0.0005650520324707031),
|
|
141
|
-
vec2<f32>(1.0, 0.00009316205978393555), vec2<f32>(1.0, 0.0000978708267211914), vec2<f32>(0.9990234375, 0.00012540817260742188), vec2<f32>(0.9970703125, 0.00019216537475585938),
|
|
142
|
-
vec2<f32>(0.99072265625, 0.0003104209899902344), vec2<f32>(0.97900390625, 0.0004699230194091797), vec2<f32>(0.95751953125, 0.0006470680236816406), vec2<f32>(0.92333984375, 0.0007915496826171875),
|
|
143
|
-
vec2<f32>(0.87548828125, 0.0008769035339355469), vec2<f32>(0.81494140625, 0.0008869171142578125), vec2<f32>(0.744140625, 0.0008325576782226562), vec2<f32>(0.66748046875, 0.0007386207580566406),
|
|
144
|
-
vec2<f32>(0.58837890625, 0.0006265640258789062), vec2<f32>(0.51123046875, 0.0005168914794921875), vec2<f32>(0.438232421875, 0.0004165172576904297), vec2<f32>(0.37109375, 0.0003311634063720703),
|
|
145
|
-
vec2<f32>(1.0, 0.000007271766662597656), vec2<f32>(1.0, 0.000008165836334228516), vec2<f32>(0.9990234375, 0.000016987323760986328), vec2<f32>(0.99755859375, 0.00003790855407714844),
|
|
146
|
-
vec2<f32>(0.9921875, 0.00007593631744384766), vec2<f32>(0.9814453125, 0.00013744831085205078), vec2<f32>(0.96142578125, 0.00020754337310791016), vec2<f32>(0.92919921875, 0.00028014183044433594),
|
|
147
|
-
vec2<f32>(0.8828125, 0.0003345012664794922), vec2<f32>(0.82177734375, 0.00036263465881347656), vec2<f32>(0.7490234375, 0.00036215782165527344), vec2<f32>(0.66845703125, 0.0003380775451660156),
|
|
148
|
-
vec2<f32>(0.58544921875, 0.00029969215393066406), vec2<f32>(0.50390625, 0.00025582313537597656), vec2<f32>(0.427001953125, 0.0002117156982421875), vec2<f32>(0.357666015625, 0.00017201900482177734),
|
|
149
|
-
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),
|
|
150
|
-
vec2<f32>(0.9931640625, 0.000015079975128173828), vec2<f32>(0.98291015625, 0.00002855062484741211), vec2<f32>(0.96435546875, 0.00004744529724121094), vec2<f32>(0.93408203125, 0.00006842613220214844),
|
|
151
|
-
vec2<f32>(0.88916015625, 0.00008893013000488281), vec2<f32>(0.828125, 0.0001042485237121582), vec2<f32>(0.75390625, 0.00011217594146728516), vec2<f32>(0.67041015625, 0.00011241436004638672),
|
|
152
|
-
vec2<f32>(0.5830078125, 0.00010627508163452148), vec2<f32>(0.4970703125, 0.00009584426879882812), vec2<f32>(0.4169921875, 0.0000833272933959961), vec2<f32>(0.34521484375, 0.00007051229476928711),
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
fn _sampleThreeR184DfgLut(roughness : f32, dotNV : f32) -> vec2<f32> {
|
|
156
|
-
let uv = clamp(vec2<f32>(roughness, dotNV), vec2<f32>(0.0), vec2<f32>(1.0));
|
|
157
|
-
let samplePosition = uv * f32(THREE_R184_DFG_LUT_SIZE) - vec2<f32>(0.5);
|
|
158
|
-
let base = vec2<i32>(floor(samplePosition));
|
|
159
|
-
let weight = fract(samplePosition);
|
|
160
|
-
let last = i32(THREE_R184_DFG_LUT_SIZE - 1u);
|
|
161
|
-
let lo = clamp(base, vec2<i32>(0), vec2<i32>(last));
|
|
162
|
-
let hi = clamp(base + vec2<i32>(1), vec2<i32>(0), vec2<i32>(last));
|
|
163
|
-
let rowLo = mix(
|
|
164
|
-
THREE_R184_DFG_LUT[u32(lo.y) * THREE_R184_DFG_LUT_SIZE + u32(lo.x)],
|
|
165
|
-
THREE_R184_DFG_LUT[u32(lo.y) * THREE_R184_DFG_LUT_SIZE + u32(hi.x)],
|
|
166
|
-
weight.x,
|
|
167
|
-
);
|
|
168
|
-
let rowHi = mix(
|
|
169
|
-
THREE_R184_DFG_LUT[u32(hi.y) * THREE_R184_DFG_LUT_SIZE + u32(lo.x)],
|
|
170
|
-
THREE_R184_DFG_LUT[u32(hi.y) * THREE_R184_DFG_LUT_SIZE + u32(hi.x)],
|
|
171
|
-
weight.x,
|
|
172
|
-
);
|
|
173
|
-
return mix(rowLo, rowHi, weight.y);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
fn _threeR184DirectMultiScatter(
|
|
177
|
-
roughness : f32,
|
|
178
|
-
nDotV : f32,
|
|
179
|
-
nDotL : f32,
|
|
180
|
-
F0 : vec3<f32>,
|
|
181
|
-
) -> vec3<f32> {
|
|
182
|
-
let dfgV = _sampleThreeR184DfgLut(roughness, nDotV);
|
|
183
|
-
let dfgL = _sampleThreeR184DfgLut(roughness, nDotL);
|
|
184
|
-
let fssEssV = F0 * dfgV.x + vec3<f32>(dfgV.y);
|
|
185
|
-
let fssEssL = F0 * dfgL.x + vec3<f32>(dfgL.y);
|
|
186
|
-
let emsV = 1.0 - dfgV.x - dfgV.y;
|
|
187
|
-
let emsL = 1.0 - dfgL.x - dfgL.y;
|
|
188
|
-
let favg = F0 + (vec3<f32>(1.0) - F0) * 0.047619;
|
|
189
|
-
let energyLoss = emsV * emsL;
|
|
190
|
-
let fms = fssEssV * fssEssL * favg
|
|
191
|
-
/ (vec3<f32>(1.0) - energyLoss * favg * favg + vec3<f32>(1e-6));
|
|
192
|
-
return fms * energyLoss;
|
|
193
|
-
}
|
|
194
|
-
|
|
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.
|
|
195
86
|
// Pick the cascade layer for a positive view-space depth -- walks
|
|
196
87
|
// splitPlanes in order, returns the first split the depth falls below. Last
|
|
197
88
|
// layer (count - 1) catches everything beyond splits[count-2]. cascadeCount=1
|
|
@@ -517,15 +408,16 @@ fn evalDirectionalNoShadow(
|
|
|
517
408
|
F0 : vec3<f32>,
|
|
518
409
|
) -> vec3<f32> {
|
|
519
410
|
let l = normalize(-view.lightDir);
|
|
520
|
-
let
|
|
411
|
+
let halfVector = viewDir + l;
|
|
412
|
+
let halfVectorLengthSquared = max(dot(halfVector, halfVector), 1e-8);
|
|
413
|
+
let h = halfVector * inverseSqrt(halfVectorLengthSquared);
|
|
521
414
|
let nDotL = max(dot(normal, l), 0.0);
|
|
522
415
|
let nDotV = max(dot(normal, viewDir), 1e-5);
|
|
523
416
|
let nDotH = max(dot(normal, h), 0.0);
|
|
524
417
|
let vDotH = max(dot(viewDir, h), 0.0);
|
|
525
|
-
let
|
|
526
|
-
let f = F0 * (vec3<f32>(1.0) - fresnel) + vec3<f32>(fresnel);
|
|
418
|
+
let f = f_schlick(vDotH, F0);
|
|
527
419
|
let roughness = sqrt(max(alphaSq, 0.0));
|
|
528
|
-
let multiScatter =
|
|
420
|
+
let multiScatter = threeR184DirectMultiScatter(roughness, nDotV, nDotL, F0);
|
|
529
421
|
let specular = d_ggx(nDotH, alphaSq) * v_smith(nDotV, nDotL, alphaSq) * f + multiScatter;
|
|
530
422
|
let diffuse = (1.0 - metallic) * baseColor / 3.14159265;
|
|
531
423
|
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
|
+
}
|
|
@@ -31,7 +31,11 @@
|
|
|
31
31
|
// - evalSpot(lightPos, lightDir, colorTimesIntensity, cosInner, cosOuter,
|
|
32
32
|
// invRangeSquared, ...) -> vec3<f32>
|
|
33
33
|
|
|
34
|
-
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx}
|
|
34
|
+
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx, threeR184DirectMultiScatter}
|
|
35
|
+
#import forgeax_pbr::lighting_spot_modifiers::{spotModifierProduct}
|
|
36
|
+
|
|
37
|
+
// extendedLighting is one closed resource topology for IES, Cookie, and
|
|
38
|
+
// probe factors. The ordinary path supplies identity factors.
|
|
35
39
|
#import forgeax_pbr::lighting_attenuation::{evalDistanceAttenuation, evalSpotAttenuation, projectSpotUv}
|
|
36
40
|
// feat-20260625-spot-light-shadow-mapping M3 / w15 (plan-strategy D-3 + D-5):
|
|
37
41
|
// spot shadow sampling reuses the shared 2D 9-tap PCF core (sample_shadow_2d)
|
|
@@ -102,9 +106,13 @@ fn evalPunctualBody(
|
|
|
102
106
|
let nDotH = max(dot(normal, h), 0.0);
|
|
103
107
|
let vDotH = max(dot(viewDir, h), 0.0);
|
|
104
108
|
let f = f_schlick(vDotH, F0);
|
|
105
|
-
let
|
|
106
|
-
let
|
|
107
|
-
let
|
|
109
|
+
let roughness = sqrt(max(alphaSq, 0.0));
|
|
110
|
+
let multiScatter = threeR184DirectMultiScatter(roughness, nDotV, nDotL, F0);
|
|
111
|
+
let specular = d_ggx(nDotH, alphaSq) * v_smith(nDotV, nDotL, alphaSq) * f + multiScatter;
|
|
112
|
+
// Three r184 direct-light parity keeps diffuse independent of the
|
|
113
|
+
// view-dependent Schlick term; the metallic factor is the only diffuse
|
|
114
|
+
// energy gate in this punctual path.
|
|
115
|
+
let diffuse = (1.0 - metallic) * baseColor / 3.14159265;
|
|
108
116
|
let attenuation = evalDistanceAttenuation(dSquared, invRangeSquared);
|
|
109
117
|
return (diffuse + specular) * colorTimesIntensity * nDotL * attenuation;
|
|
110
118
|
}
|
|
@@ -128,14 +136,14 @@ fn evalPoint(
|
|
|
128
136
|
);
|
|
129
137
|
}
|
|
130
138
|
|
|
131
|
-
// Flat 2D punctual evaluators share the range/cone math with the
|
|
132
|
-
// path
|
|
139
|
+
// Flat 2D punctual evaluators share the range/cone math with the clustered
|
|
140
|
+
// path, but intentionally skip the 3D BRDF normal term.
|
|
133
141
|
// Sprite-lit treats every quad as an omnidirectional receiver; keeping this
|
|
134
142
|
// owner here prevents URP and Cluster from drifting when the light lies in the
|
|
135
143
|
// sprite plane (the common 2D flashlight setup).
|
|
136
144
|
fn evalFlatRangeAttenuation(dSquared : f32, invRangeSquared : f32) -> f32 {
|
|
137
145
|
let factor = max(min(1.0 - (dSquared * invRangeSquared) * (dSquared * invRangeSquared), 1.0), 0.0);
|
|
138
|
-
return factor / dSquared;
|
|
146
|
+
return factor * factor / dSquared;
|
|
139
147
|
}
|
|
140
148
|
|
|
141
149
|
fn evalPointFlat(
|
|
@@ -182,7 +190,8 @@ fn evalSpotFlat(
|
|
|
182
190
|
// projection (research L0.5 Bevy pattern); the caller passes `near` / `far`
|
|
183
191
|
// directly so both pipelines route the same constants without owning the
|
|
184
192
|
// upstream binding (URP reads them from `shadowParams[layer]` at @group(0)
|
|
185
|
-
// binding 6;
|
|
193
|
+
// binding 6; the shared DirectLightSlot metadata remains the identity owner
|
|
194
|
+
// while this shadow-parameter buffer carries the reconstruction constants per
|
|
186
195
|
// plan-strategy §D-8).
|
|
187
196
|
//
|
|
188
197
|
// Caller responsibility: gate this on `shadowAtlasLayer >= 0` so the
|
|
@@ -258,9 +267,10 @@ fn evalSpot(
|
|
|
258
267
|
lightPos, colorTimesIntensity, invRangeSquared,
|
|
259
268
|
worldPos, normal, viewDir, baseColor, metallic, alphaSq, F0,
|
|
260
269
|
);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
270
|
+
let toLight = lightPos - worldPos;
|
|
271
|
+
let l = normalize(toLight);
|
|
272
|
+
let cone = smoothstep(cosOuter, cosInner, dot(l, -lightDir));
|
|
273
|
+
return body * spotModifierProduct(1.0, 1.0, cone, 1.0, 1.0, 1.0);
|
|
264
274
|
}
|
|
265
275
|
|
|
266
276
|
// feat-20260625-spot-light-shadow-mapping M3 / w15 (plan-strategy D-3 + D-4 +
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#define_import_path forgeax_pbr::lighting_rect_area
|
|
2
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
3
|
+
#import forgeax_view::common::{ltcLambertTexture, ltcGgxTexture, spotModifierSampler}
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
// One-sided finite-area direct lighting using the same Heitz LTC formulation
|
|
7
|
+
// and tracked 64x64 tables as Three.js r184. The rectangle corners, rather
|
|
8
|
+
// than a punctual center direction, are transformed into the fitted cosine
|
|
9
|
+
// space before the spherical edge integral is evaluated.
|
|
10
|
+
|
|
11
|
+
fn ltcUv(n : vec3<f32>, v : vec3<f32>, roughness : f32) -> vec2<f32> {
|
|
12
|
+
let lutScale = 63.0 / 64.0;
|
|
13
|
+
let lutBias = 0.5 / 64.0;
|
|
14
|
+
let nDotV = clamp(dot(n, v), 0.0, 1.0);
|
|
15
|
+
return vec2<f32>(clamp(roughness, 0.0, 1.0), sqrt(1.0 - nDotV)) * lutScale + lutBias;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fn ltcClippedSphereFormFactor(f : vec3<f32>) -> f32 {
|
|
19
|
+
let magnitude = length(f);
|
|
20
|
+
return max((magnitude * magnitude + f.z) / (magnitude + 1.0), 0.0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fn ltcEdgeVectorFormFactor(v1 : vec3<f32>, v2 : vec3<f32>) -> vec3<f32> {
|
|
24
|
+
let x = clamp(dot(v1, v2), -1.0, 1.0);
|
|
25
|
+
let y = abs(x);
|
|
26
|
+
let a = 0.8543985 + (0.4965155 + 0.0145206 * y) * y;
|
|
27
|
+
let b = 3.4175940 + (4.1616724 + y) * y;
|
|
28
|
+
let rational = a / b;
|
|
29
|
+
let thetaOverSinTheta = select(
|
|
30
|
+
0.5 * inverseSqrt(max(1.0 - x * x, 1e-7)) - rational,
|
|
31
|
+
rational,
|
|
32
|
+
x > 0.0,
|
|
33
|
+
);
|
|
34
|
+
return cross(v1, v2) * thetaOverSinTheta;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fn ltcEvaluate(
|
|
38
|
+
n : vec3<f32>,
|
|
39
|
+
v : vec3<f32>,
|
|
40
|
+
worldPos : vec3<f32>,
|
|
41
|
+
mInv : mat3x3<f32>,
|
|
42
|
+
lightPos : vec3<f32>,
|
|
43
|
+
axisX : vec3<f32>,
|
|
44
|
+
axisY : vec3<f32>,
|
|
45
|
+
halfWidth : f32,
|
|
46
|
+
halfHeight : f32,
|
|
47
|
+
) -> f32 {
|
|
48
|
+
let halfX = axisX * halfWidth;
|
|
49
|
+
let halfY = axisY * halfHeight;
|
|
50
|
+
// Counter-clockwise from the authored front (+cross(axisX, axisY)).
|
|
51
|
+
let rect0 = lightPos - halfX - halfY;
|
|
52
|
+
let rect1 = lightPos + halfX - halfY;
|
|
53
|
+
let rect2 = lightPos + halfX + halfY;
|
|
54
|
+
let rect3 = lightPos - halfX + halfY;
|
|
55
|
+
let lightNormal = cross(rect1 - rect0, rect3 - rect0);
|
|
56
|
+
if (dot(lightNormal, worldPos - rect0) <= 0.0) {
|
|
57
|
+
return 0.0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let tangentCandidate = v - n * dot(v, n);
|
|
61
|
+
let tangentLengthSquared = dot(tangentCandidate, tangentCandidate);
|
|
62
|
+
var tangent = vec3<f32>(1.0, 0.0, 0.0);
|
|
63
|
+
if (tangentLengthSquared > 1e-7) {
|
|
64
|
+
tangent = tangentCandidate * inverseSqrt(tangentLengthSquared);
|
|
65
|
+
} else {
|
|
66
|
+
let fallback = select(vec3<f32>(0.0, 1.0, 0.0), vec3<f32>(1.0, 0.0, 0.0), abs(n.x) < 0.9);
|
|
67
|
+
tangent = normalize(cross(fallback, n));
|
|
68
|
+
}
|
|
69
|
+
let bitangent = -cross(n, tangent);
|
|
70
|
+
let transform = mInv * transpose(mat3x3<f32>(tangent, bitangent, n));
|
|
71
|
+
|
|
72
|
+
let c0 = normalize(transform * (rect0 - worldPos));
|
|
73
|
+
let c1 = normalize(transform * (rect1 - worldPos));
|
|
74
|
+
let c2 = normalize(transform * (rect2 - worldPos));
|
|
75
|
+
let c3 = normalize(transform * (rect3 - worldPos));
|
|
76
|
+
let vectorFormFactor =
|
|
77
|
+
ltcEdgeVectorFormFactor(c0, c1) +
|
|
78
|
+
ltcEdgeVectorFormFactor(c1, c2) +
|
|
79
|
+
ltcEdgeVectorFormFactor(c2, c3) +
|
|
80
|
+
ltcEdgeVectorFormFactor(c3, c0);
|
|
81
|
+
return ltcClippedSphereFormFactor(vectorFormFactor);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fn rectAreaRangeFactor(lightPos : vec3<f32>, worldPos : vec3<f32>, invRangeSquared : f32) -> f32 {
|
|
85
|
+
let toLight = lightPos - worldPos;
|
|
86
|
+
let distanceSquared = dot(toLight, toLight);
|
|
87
|
+
let rangeTerm = distanceSquared * invRangeSquared;
|
|
88
|
+
let factor = clamp(1.0 - rangeTerm * rangeTerm, 0.0, 1.0);
|
|
89
|
+
return factor * factor;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fn evalRectAreaLtcDiffuse(
|
|
93
|
+
lightPos : vec3<f32>, lightColor : vec3<f32>, axisX : vec3<f32>, axisY : vec3<f32>,
|
|
94
|
+
halfWidth : f32, halfHeight : f32, invRangeSquared : f32, worldPos : vec3<f32>,
|
|
95
|
+
n : vec3<f32>, v : vec3<f32>, baseColor : vec3<f32>, metallic : f32, alphaSq : f32, F0 : vec3<f32>,
|
|
96
|
+
) -> vec3<f32> {
|
|
97
|
+
let identity = mat3x3<f32>(
|
|
98
|
+
vec3<f32>(1.0, 0.0, 0.0),
|
|
99
|
+
vec3<f32>(0.0, 1.0, 0.0),
|
|
100
|
+
vec3<f32>(0.0, 0.0, 1.0),
|
|
101
|
+
);
|
|
102
|
+
let formFactor = ltcEvaluate(
|
|
103
|
+
n, v, worldPos, identity, lightPos, axisX, axisY, halfWidth, halfHeight,
|
|
104
|
+
);
|
|
105
|
+
// The LTC edge fit is already normalized by 1/(2*pi); unlike punctual
|
|
106
|
+
// irradiance this form factor must not receive another Lambert 1/pi.
|
|
107
|
+
let diffuse = baseColor * (1.0 - metallic);
|
|
108
|
+
return lightColor * diffuse * formFactor * rectAreaRangeFactor(lightPos, worldPos, invRangeSquared);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fn evalRectAreaLtcStandard(
|
|
112
|
+
lightPos : vec3<f32>, lightColor : vec3<f32>, axisX : vec3<f32>, axisY : vec3<f32>,
|
|
113
|
+
halfWidth : f32, halfHeight : f32, invRangeSquared : f32, worldPos : vec3<f32>,
|
|
114
|
+
n : vec3<f32>, v : vec3<f32>, baseColor : vec3<f32>, metallic : f32, alphaSq : f32, F0 : vec3<f32>,
|
|
115
|
+
) -> vec3<f32> {
|
|
116
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
117
|
+
let uv = ltcUv(n, v, sqrt(max(alphaSq, 0.0)));
|
|
118
|
+
let matrixSample = textureSampleLevel(ltcLambertTexture, spotModifierSampler, uv, 0.0);
|
|
119
|
+
let fresnelSample = textureSampleLevel(ltcGgxTexture, spotModifierSampler, uv, 0.0);
|
|
120
|
+
let mInv = mat3x3<f32>(
|
|
121
|
+
vec3<f32>(matrixSample.x, 0.0, matrixSample.y),
|
|
122
|
+
vec3<f32>(0.0, 1.0, 0.0),
|
|
123
|
+
vec3<f32>(matrixSample.z, 0.0, matrixSample.w),
|
|
124
|
+
);
|
|
125
|
+
let fresnel = F0 * fresnelSample.x + (vec3<f32>(1.0) - F0) * fresnelSample.y;
|
|
126
|
+
let specularFormFactor = ltcEvaluate(
|
|
127
|
+
n, v, worldPos, mInv, lightPos, axisX, axisY, halfWidth, halfHeight,
|
|
128
|
+
);
|
|
129
|
+
let diffuse = evalRectAreaLtcDiffuse(
|
|
130
|
+
lightPos, lightColor, axisX, axisY, halfWidth, halfHeight, invRangeSquared,
|
|
131
|
+
worldPos, n, v, baseColor, metallic, alphaSq, F0,
|
|
132
|
+
);
|
|
133
|
+
return diffuse + lightColor * fresnel * specularFormFactor * rectAreaRangeFactor(lightPos, worldPos, invRangeSquared);
|
|
134
|
+
#else
|
|
135
|
+
return vec3<f32>(0.0);
|
|
136
|
+
#endif
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Both renderer routes consume one complete Standard-PBR Rect contribution.
|
|
140
|
+
// The public names retain the direct/cluster shader import contract while the
|
|
141
|
+
// Lambert and fitted-GGX terms stay inseparable in one owner implementation.
|
|
142
|
+
fn evalRectAreaLtcLambert(
|
|
143
|
+
lightPos : vec3<f32>, lightColor : vec3<f32>, axisX : vec3<f32>, axisY : vec3<f32>,
|
|
144
|
+
halfWidth : f32, halfHeight : f32, invRangeSquared : f32, worldPos : vec3<f32>,
|
|
145
|
+
n : vec3<f32>, v : vec3<f32>, baseColor : vec3<f32>, metallic : f32, alphaSq : f32, F0 : vec3<f32>,
|
|
146
|
+
) -> vec3<f32> {
|
|
147
|
+
return evalRectAreaLtcStandard(
|
|
148
|
+
lightPos, lightColor, axisX, axisY, halfWidth, halfHeight, invRangeSquared,
|
|
149
|
+
worldPos, n, v, baseColor, metallic, alphaSq, F0,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
fn evalRectAreaLtcGgx(
|
|
154
|
+
lightPos : vec3<f32>, lightColor : vec3<f32>, axisX : vec3<f32>, axisY : vec3<f32>,
|
|
155
|
+
halfWidth : f32, halfHeight : f32, invRangeSquared : f32, worldPos : vec3<f32>,
|
|
156
|
+
n : vec3<f32>, v : vec3<f32>, baseColor : vec3<f32>, metallic : f32, alphaSq : f32, F0 : vec3<f32>,
|
|
157
|
+
) -> vec3<f32> {
|
|
158
|
+
return evalRectAreaLtcStandard(
|
|
159
|
+
lightPos, lightColor, axisX, axisY, halfWidth, halfHeight, invRangeSquared,
|
|
160
|
+
worldPos, n, v, baseColor, metallic, alphaSq, F0,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#define_import_path forgeax_pbr::lighting_spot_modifiers
|
|
2
|
+
|
|
3
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
4
|
+
#import forgeax_view::common::{spotModifierSampler, iesProfileTexture, cookieTexture, cookieMatrices}
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
// DirectLightSlot.metadata.y carries this marker for the SpotLight projector
|
|
8
|
+
// path. A marked spot samples the shared array with its lightViewProj in the
|
|
9
|
+
// punctual owner, so the Cookie projection
|
|
10
|
+
// below must not modulate it a second time.
|
|
11
|
+
const PROJECTOR_FLAG: u32 = 0x40000000u;
|
|
12
|
+
|
|
13
|
+
// Shared Spot modifier composition. Identity defaults preserve the ordinary
|
|
14
|
+
// punctual path when an extension resource is absent.
|
|
15
|
+
fn spotModifierProduct(
|
|
16
|
+
brdf : f32,
|
|
17
|
+
range : f32,
|
|
18
|
+
cone : f32,
|
|
19
|
+
ies : f32,
|
|
20
|
+
cookie : f32,
|
|
21
|
+
shadow : f32,
|
|
22
|
+
) -> f32 {
|
|
23
|
+
return brdf * range * cone * ies * cookie * shadow;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Shared IES/Cookie projection owner. The light direction is the authored
|
|
27
|
+
// outgoing axis (light -> scene), matching evalSpot's `dot(L, -lightDir)`.
|
|
28
|
+
// Cookie matrices carry only source-texture aspect correction; keeping the
|
|
29
|
+
// cone term here allows a Cookie slice to be shared by Spots with different
|
|
30
|
+
// outer cones.
|
|
31
|
+
fn spotModifierFactors(
|
|
32
|
+
lightPos : vec3<f32>,
|
|
33
|
+
lightDir : vec3<f32>,
|
|
34
|
+
cosOuter : f32,
|
|
35
|
+
worldPos : vec3<f32>,
|
|
36
|
+
rollDeg : f32,
|
|
37
|
+
metadata : vec4<u32>,
|
|
38
|
+
) -> vec4<f32> {
|
|
39
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
40
|
+
let toSurface = worldPos - lightPos;
|
|
41
|
+
let distanceToSurface = length(toSurface);
|
|
42
|
+
var ies = 1.0;
|
|
43
|
+
var cookie = vec3<f32>(1.0);
|
|
44
|
+
if (distanceToSurface <= 0.000001) {
|
|
45
|
+
return vec4<f32>(ies, cookie);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let outgoing = toSurface / distanceToSurface;
|
|
49
|
+
let forward = normalize(lightDir);
|
|
50
|
+
var referenceUp = vec3<f32>(0.0, 1.0, 0.0);
|
|
51
|
+
if (abs(forward.y) > 0.999) {
|
|
52
|
+
referenceUp = vec3<f32>(0.0, 0.0, 1.0);
|
|
53
|
+
}
|
|
54
|
+
let right = normalize(cross(forward, referenceUp));
|
|
55
|
+
let up = normalize(cross(right, forward));
|
|
56
|
+
let localX = dot(outgoing, right);
|
|
57
|
+
let localY = dot(outgoing, up);
|
|
58
|
+
let depth = dot(outgoing, forward);
|
|
59
|
+
let roll = rollDeg * 0.01745329252;
|
|
60
|
+
let rolledX = localX * cos(roll) - localY * sin(roll);
|
|
61
|
+
let rolledY = localX * sin(roll) + localY * cos(roll);
|
|
62
|
+
|
|
63
|
+
if (metadata.z != 0xffffffffu) {
|
|
64
|
+
let azimuth = (atan2(rolledY, rolledX) + 6.283185307) % 6.283185307;
|
|
65
|
+
let elevation = acos(clamp(depth, -1.0, 1.0)) / 3.14159265;
|
|
66
|
+
let iesUv = vec2<f32>(azimuth / 6.283185307, elevation);
|
|
67
|
+
ies = max(textureSampleLevel(iesProfileTexture, spotModifierSampler, iesUv, metadata.z, 0.0).r, 0.0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// The shadow lane uses 0xffffffff as its no-shadow sentinel. That value
|
|
71
|
+
// contains PROJECTOR_FLAG bits, so test the sentinel before interpreting
|
|
72
|
+
// the lane as a projector marker; otherwise every non-shadow Cookie spot
|
|
73
|
+
// silently takes the projector exclusion path.
|
|
74
|
+
if (
|
|
75
|
+
metadata.w != 0xffffffffu &&
|
|
76
|
+
(metadata.y == 0xffffffffu || (metadata.y & PROJECTOR_FLAG) == 0u)
|
|
77
|
+
) {
|
|
78
|
+
if (depth <= 0.0) {
|
|
79
|
+
cookie = vec3<f32>(0.0);
|
|
80
|
+
} else {
|
|
81
|
+
let sinOuter = sqrt(max(1.0 - cosOuter * cosOuter, 0.0));
|
|
82
|
+
let tanOuter = sinOuter / max(cosOuter, 0.0001);
|
|
83
|
+
let matrixPlane = cookieMatrices[metadata.w] * vec4<f32>(rolledX / depth, rolledY / depth, 0.0, 1.0);
|
|
84
|
+
let cookieUv = vec2<f32>(0.5) + matrixPlane.xy / tanOuter * 0.5;
|
|
85
|
+
if (
|
|
86
|
+
cookieUv.x < 0.0 || cookieUv.x > 1.0 ||
|
|
87
|
+
cookieUv.y < 0.0 || cookieUv.y > 1.0
|
|
88
|
+
) {
|
|
89
|
+
cookie = vec3<f32>(0.0);
|
|
90
|
+
} else {
|
|
91
|
+
let cookieSample = textureSampleLevel(cookieTexture, spotModifierSampler, cookieUv, metadata.w, 0.0);
|
|
92
|
+
cookie = max(cookieSample.rgb * cookieSample.a, vec3<f32>(0.0));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return vec4<f32>(ies, cookie);
|
|
97
|
+
#else
|
|
98
|
+
return vec4<f32>(1.0);
|
|
99
|
+
#endif
|
|
100
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#define_import_path forgeax_pbr::lighting_spot_projector
|
|
2
|
+
|
|
3
|
+
// Clustered Standard owns the light membership/decode, while this helper
|
|
4
|
+
// keeps projector projection and resource sampling in one module. Keeping the
|
|
5
|
+
// projection/sample pair out of standard-cluster avoids a naga-oil scope edge
|
|
6
|
+
// when the low-resource projector path is composed with the shared cluster.
|
|
7
|
+
#import forgeax_pbr::lighting_attenuation::{projectSpotUv}
|
|
8
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
9
|
+
#import forgeax_view::common::{spotModifierSampler, cookieTexture}
|
|
10
|
+
#else
|
|
11
|
+
#import forgeax_view::common::{projectorTexture, projectorSampler}
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
fn sampleStandardSpotProjector(
|
|
15
|
+
lightViewProj : mat4x4<f32>,
|
|
16
|
+
world_pos : vec3<f32>,
|
|
17
|
+
metadata : vec4<u32>,
|
|
18
|
+
) -> vec3<f32> {
|
|
19
|
+
let uv = projectSpotUv(lightViewProj, world_pos);
|
|
20
|
+
if (!(uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0)) {
|
|
21
|
+
return vec3<f32>(1.0);
|
|
22
|
+
}
|
|
23
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
24
|
+
if (metadata.w == 0xffffffffu) {
|
|
25
|
+
return vec3<f32>(1.0);
|
|
26
|
+
}
|
|
27
|
+
return textureSampleLevel(cookieTexture, spotModifierSampler, uv, metadata.w, 0.0).rgb;
|
|
28
|
+
#else
|
|
29
|
+
return textureSampleLevel(projectorTexture, projectorSampler, uv, 0.0).rgb;
|
|
30
|
+
#endif
|
|
31
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @forgeax/engine-shader - provenance for the tracked RectArea LTC tables.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The table source is the Three.js r184 RectAreaLight implementation. The
|
|
5
|
+
* source arrays are converted to IEEE-754 binary16 offline and checked into
|
|
6
|
+
* `tables.ts`; the runtime never fetches or parses a source file.
|
|
7
|
+
*/
|
|
8
|
+
export const LTC_SOURCE_PROVENANCE = {
|
|
9
|
+
source: 'Three.js',
|
|
10
|
+
revision: 'r184',
|
|
11
|
+
sourceUrl:
|
|
12
|
+
'https://github.com/mrdoob/three.js/blob/r184/examples/jsm/lights/RectAreaLightTexturesLib.js',
|
|
13
|
+
upstreamData: 'selfshadow/ltc_code fit/results/ltc.js',
|
|
14
|
+
generator: 'deterministic Three.js source-array to rgba16float conversion',
|
|
15
|
+
inputSha256: {
|
|
16
|
+
lambert: 'cf5cf21e5c112d2095c7e2418cb0a1ac54636e275d73e42f3453646c67f26814',
|
|
17
|
+
ggx: '3b1b09080b26104498db277c14fc1733786465c6958e7a8403d688b1e24c2ff5',
|
|
18
|
+
},
|
|
19
|
+
} as const;
|