@forgeax/engine-shader 0.1.21 → 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 +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +33019 -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/__tests__/default-standard-pbr-transmission.unit.test.ts +121 -58
- 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 +8 -2
- package/src/__tests__/lighting-punctual.unit.test.ts +29 -2
- 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__/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 +24 -2
- package/src/__tests__/shader.unit.test.ts +6 -2
- 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-variants.unit.test.ts +4 -1
- package/src/brdf.wgsl +115 -1
- package/src/common.wgsl +53 -79
- package/src/default-standard-pbr-skin.wgsl +80 -23
- package/src/default-standard-pbr.wgsl +119 -50
- package/src/ibl-irradiance.wgsl +4 -1
- package/src/ibl-sampling.wgsl +2 -2
- package/src/index.ts +17 -0
- package/src/lighting-directional.wgsl +6 -116
- 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 +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/sprite-lit.wgsl +3 -3
- package/src/sprite.wgsl +1 -1
- package/src/standard-cluster.wgsl +94 -57
- 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
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#define_import_path forgeax_material::standard
|
|
2
|
-
#import forgeax_view::common::{View, Mesh, InstanceData, view, meshes, instances, sampleMaterialTexture}
|
|
2
|
+
#import forgeax_view::common::{View, Mesh, InstanceData, view, meshes, instances, shadowMap, shadowSampler, sampleMaterialTexture}
|
|
3
3
|
#import forgeax_scene_temporal::{sceneViewZ}
|
|
4
4
|
#import forgeax_pbr::temporal::{projectPbrSceneTemporal}
|
|
5
5
|
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx}
|
|
6
|
-
#import forgeax_pbr::ibl_sampling::{
|
|
6
|
+
#import forgeax_pbr::ibl_sampling::{sampleIblDiffuse, sampleIblSpecular, sampleReflectionProbeSpecular}
|
|
7
|
+
#import forgeax_pbr::lighting_probe::{evaluateProbeDiffuse}
|
|
7
8
|
#import forgeax_pbr::tbn::{decodeTangentSpaceNormalRg, scaleTangentSpaceNormal, applyTBN}
|
|
8
9
|
#import forgeax_pbr::lighting_directional::{evalDirectionalNoShadow, evalDirectionalShadowFactor}
|
|
9
10
|
#ifdef CLUSTER_FORWARD_AVAILABLE
|
|
@@ -13,21 +14,12 @@
|
|
|
13
14
|
#pragma variant_axis STORAGE_BUFFER_AVAILABLE
|
|
14
15
|
#pragma variant_axis CLUSTER_FORWARD_AVAILABLE
|
|
15
16
|
#pragma variant_axis VERTEX_COLOR_AVAILABLE
|
|
17
|
+
#pragma variant_axis PROBE_BLEND_AVAILABLE
|
|
18
|
+
#pragma variant_axis EXTENDED_LIGHTING_AVAILABLE
|
|
16
19
|
#pragma variant_axis TRANSMISSION_AVAILABLE
|
|
17
20
|
#pragma variant_axis DIRECTIONAL_PCSS_AVAILABLE
|
|
18
21
|
#pragma variant_axis PROJECTOR_AVAILABLE
|
|
19
|
-
|
|
20
|
-
// Reflection probes remain a bounded scene-projected sampling lane. Their
|
|
21
|
-
// optional texture resources are the same Skylight inputs; when no probe is
|
|
22
|
-
// admitted, the explicit Skylight path below remains authoritative.
|
|
23
|
-
fn reflection_probe_sampling_contract(
|
|
24
|
-
worldPosition: vec3<f32>,
|
|
25
|
-
direction: vec3<f32>,
|
|
26
|
-
boxCenter: vec3<f32>,
|
|
27
|
-
boxExtents: vec3<f32>,
|
|
28
|
-
) -> vec3<f32> {
|
|
29
|
-
return box_project(worldPosition, direction, boxCenter, boxExtents);
|
|
30
|
-
}
|
|
22
|
+
#pragma variant_axis REFLECTION_FALLBACK_AVAILABLE
|
|
31
23
|
|
|
32
24
|
// @forgeax/engine-shader - default-standard-pbr.wgsl
|
|
33
25
|
// (feat-20260523-shader-template-instance-split M5 / T04).
|
|
@@ -223,6 +215,12 @@ struct SkylightUniforms {
|
|
|
223
215
|
@group(1) @binding(22) var brdfLutSampler : sampler;
|
|
224
216
|
@group(1) @binding(23) var<uniform> skylight : SkylightUniforms;
|
|
225
217
|
|
|
218
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
219
|
+
// Optional consumer lane. The host must provide the retained 160B record
|
|
220
|
+
// buffer and matching BGL before enabling this capability.
|
|
221
|
+
@group(3) @binding(1) var<storage, read> probeBlendRecords : array<vec4<f32>>;
|
|
222
|
+
#endif
|
|
223
|
+
|
|
226
224
|
// feat-20260612-hdrp-ssao M7 (round 2) D-B + D-C, scope-amend-webgl2-ubo:
|
|
227
225
|
// SSAO sampling lives on the HDRP unified BGL @group(2) alongside the
|
|
228
226
|
// cluster bindings (binding 7 = ssao texture, binding 8 = sampler). The
|
|
@@ -305,18 +303,12 @@ fn pick_channel(rgba : vec4<f32>, channelIndex : u32) -> f32 {
|
|
|
305
303
|
}
|
|
306
304
|
}
|
|
307
305
|
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
// / evalSpot share evalPunctualBody (GGX specular + Lambertian diffuse +
|
|
313
|
-
// KHR_lights_punctual quartic range attenuation;
|
|
314
|
-
// feat-20260519-light-casters-point-spot-pbr M4 / w22 byte-equivalent).
|
|
315
|
-
// Charter P4: spot light is a thin cone-multiplier on top of the punctual
|
|
316
|
-
// body, point light is the body unchanged -- no magic-value collapse.
|
|
306
|
+
// Directional lighting lives in forgeax_pbr::lighting_directional. Point,
|
|
307
|
+
// Spot, and Rect local lights are evaluated by the Standard Cluster module
|
|
308
|
+
// below from one indexed light_data corpus; no per-kind fixed-slot loop is
|
|
309
|
+
// present in this material shader.
|
|
317
310
|
|
|
318
|
-
|
|
319
|
-
fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
311
|
+
fn vs_main_impl(in : VsIn, meshIndex : u32, instanceIndex : u32) -> VsOut {
|
|
320
312
|
// feat-20260604-instances-per-instance-transform-shader-group3-bin M1 / w4:
|
|
321
313
|
// Entity world from meshes[0] — the @group(2) dynamic-offset window has
|
|
322
314
|
// already been aimed at this entity's slot (render-system-record.ts:2996
|
|
@@ -324,8 +316,8 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
324
316
|
// local from instances[idx] — @group(3) is a flat per-instance buffer indexed
|
|
325
317
|
// directly by instance_index (firstInstance=0, render-system-record.ts:2898).
|
|
326
318
|
// Combine: entity_world * per_instance_local.
|
|
327
|
-
let instanceLocal = instances[
|
|
328
|
-
let entityWorld = meshes[
|
|
319
|
+
let instanceLocal = instances[instanceIndex].localFromInstance;
|
|
320
|
+
let entityWorld = meshes[meshIndex].worldFromLocal;
|
|
329
321
|
let localToWorld = entityWorld * instanceLocal;
|
|
330
322
|
let world = localToWorld * vec4<f32>(in.pos, 1.0);
|
|
331
323
|
var out : VsOut;
|
|
@@ -396,6 +388,19 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
396
388
|
return out;
|
|
397
389
|
}
|
|
398
390
|
|
|
391
|
+
@vertex
|
|
392
|
+
fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
393
|
+
return vs_main_impl(in, 0u, idx);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
@vertex
|
|
397
|
+
fn vs_scene_index(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
398
|
+
// GPU-driven scene projection packs one Mesh row per visible candidate and
|
|
399
|
+
// uses the identity instance row. The scene index therefore selects the
|
|
400
|
+
// projected Mesh directly while retaining the Standard PBR varyings.
|
|
401
|
+
return vs_main_impl(in, idx, 0u);
|
|
402
|
+
}
|
|
403
|
+
|
|
399
404
|
fn transformedMaterialUv(transform : vec4<f32>, metadata : vec4<f32>, in : VsOut) -> vec2<f32> {
|
|
400
405
|
var source = in.uv;
|
|
401
406
|
if (metadata.x >= 1.0) { source = in.uv1; }
|
|
@@ -457,8 +462,17 @@ fn alphaTest(alpha : f32) {
|
|
|
457
462
|
}
|
|
458
463
|
}
|
|
459
464
|
|
|
465
|
+
struct StandardPbrOutput {
|
|
466
|
+
@location(0) color : vec4<f32>,
|
|
467
|
+
#ifdef REFLECTION_FALLBACK_AVAILABLE
|
|
468
|
+
// Linear HDR environment contribution from this same Standard BRDF callsite.
|
|
469
|
+
// The detached producer names this second target S_fallback.
|
|
470
|
+
@location(1) reflectionFallback : vec4<f32>,
|
|
471
|
+
#endif
|
|
472
|
+
};
|
|
473
|
+
|
|
460
474
|
@fragment
|
|
461
|
-
fn fs_main(in : VsOut) ->
|
|
475
|
+
fn fs_main(in : VsOut) -> StandardPbrOutput {
|
|
462
476
|
let baseUv = transformedMaterialUv(material.baseColorTextureCoordinatesTransform, material.baseColorTextureCoordinatesMetadata, in);
|
|
463
477
|
let baseSample = sampleMaterialTexture(baseColorTexture, baseColorSampler, baseUv, material.baseColorTextureCoordinatesMetadata.zw);
|
|
464
478
|
let vertexColor = materialVertexColor(in);
|
|
@@ -571,7 +585,7 @@ fn fs_main(in : VsOut) -> @location(0) vec4<f32> {
|
|
|
571
585
|
// feat-20260520-directional-light-shadow-mapping +
|
|
572
586
|
// feat-20260518-pbr-direct-lighting-mvp Finding 4):
|
|
573
587
|
//
|
|
574
|
-
// color = ambient(IBL) + directional(shadowed) +
|
|
588
|
+
// color = ambient(IBL) + directional(shadowed) + clustered local lights
|
|
575
589
|
//
|
|
576
590
|
// When the host Skylight bind group provides default-zero resources the IBL
|
|
577
591
|
// helpers sample to vec3(0) and ambient = 0, so the shader falls through to
|
|
@@ -587,22 +601,19 @@ fn fs_main(in : VsOut) -> @location(0) vec4<f32> {
|
|
|
587
601
|
// split-sum mip lookup, so we re-derive the post-shader-clamp roughness
|
|
588
602
|
// here (matches sampleIblSpecular's `mip = roughness * 4.0` expectation).
|
|
589
603
|
//
|
|
590
|
-
//
|
|
591
|
-
//
|
|
592
|
-
//
|
|
593
|
-
// forgeax_pbr::brdf) run inside each evalDirectional / evalPoint / evalSpot
|
|
594
|
-
// so all three light types share the same microfacet specular + Lambertian
|
|
595
|
-
// diffuse form. The directional path additionally projects worldPos
|
|
596
|
-
// through the per-cascade light-space matrix in the fragment stage for
|
|
597
|
-
// shadow-map PCF lookup (CSM, feat-20260613).
|
|
604
|
+
// Directional lighting is evaluated here. All local lights (Point, Spot,
|
|
605
|
+
// Rect) are evaluated by the Standard Cluster module below, which reads
|
|
606
|
+
// one indexed light_data corpus and never performs a fixed-slot loop.
|
|
598
607
|
let kD = (vec3<f32>(1.0) - f_schlick(max(dot(n, v), 0.0), f0)) * (1.0 - metallic);
|
|
599
608
|
let iblRoughness = clamp(max(finiteScalar(material.roughness, 0.5), 0.04) * roughnessTex, 0.04, 1.0);
|
|
600
609
|
var irradiance = vec3<f32>(0.0);
|
|
601
610
|
var specularIbl = vec3<f32>(0.0);
|
|
602
611
|
if (skylight.intensity < 0.0) {
|
|
603
|
-
// A negative intensity is the renderer-owned probe sentinel. The
|
|
604
|
-
//
|
|
605
|
-
//
|
|
612
|
+
// A negative intensity is the renderer-owned probe sentinel. The producer
|
|
613
|
+
// stores -(probeIntensity + 1), so intensity=0 remains distinguishable
|
|
614
|
+
// from the ordinary Skylight zero payload. The four color/rotation lanes
|
|
615
|
+
// carry probe center and half extents in this mode; Skylight resources
|
|
616
|
+
// remain unchanged and therefore preserve the ABI.
|
|
606
617
|
specularIbl = sampleReflectionProbeSpecular(
|
|
607
618
|
n, v, iblRoughness, f0, in.worldPos,
|
|
608
619
|
vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB),
|
|
@@ -624,20 +635,67 @@ fn fs_main(in : VsOut) -> @location(0) vec4<f32> {
|
|
|
624
635
|
// CLUSTER_FORWARD_AVAILABLE branch below can `ambient *=` the SSAO
|
|
625
636
|
// factor. The non-HDRP path leaves ambient untouched.
|
|
626
637
|
let skyColor = vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB);
|
|
638
|
+
let skyFactor = skyColor * skylight.intensity;
|
|
639
|
+
var reflectionFallback = specularIbl * (vec3<f32>(1.0) - coatF);
|
|
627
640
|
var ambient = (kD * irradiance * diffuseAlbedo + specularIbl) * (vec3<f32>(1.0) - coatF);
|
|
641
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
642
|
+
// group(3) is the per-object bind group; record zero is the object selected
|
|
643
|
+
// by this draw, independent of instance count.
|
|
644
|
+
let probeShPreblend = array<vec4<f32>, 9>(
|
|
645
|
+
probeBlendRecords[1], probeBlendRecords[2], probeBlendRecords[3],
|
|
646
|
+
probeBlendRecords[4], probeBlendRecords[5], probeBlendRecords[6],
|
|
647
|
+
probeBlendRecords[7], probeBlendRecords[8], probeBlendRecords[9],
|
|
648
|
+
);
|
|
649
|
+
let probeLocalBlendFraction = probeBlendRecords[0].z;
|
|
650
|
+
let probeDiffuseK = kD / max(vec3<f32>(1.0 - metallic), vec3<f32>(0.0001));
|
|
651
|
+
let probeDiffuse = evaluateProbeDiffuse(probeShPreblend, probeLocalBlendFraction, n, irradiance * skyFactor, probeDiffuseK, albedo, metallic);
|
|
652
|
+
ambient = (probeDiffuse + specularIbl * skyFactor) * (vec3<f32>(1.0) - coatF);
|
|
653
|
+
#endif
|
|
628
654
|
if (material.clearcoat != 0.0) {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
);
|
|
634
|
-
|
|
655
|
+
// Keep the clearcoat lobe on the same selected environment as the base
|
|
656
|
+
// specular lobe. Probe mode reuses the packed center/extents lanes in the
|
|
657
|
+
// per-probe uniform; routing it through global Skylight IBL would make the
|
|
658
|
+
// fallback a mixed-source projection and break c=1 source equivalence.
|
|
659
|
+
var clearcoatIbl = vec3<f32>(0.0);
|
|
660
|
+
if (skylight.intensity < 0.0) {
|
|
661
|
+
clearcoatIbl = sampleReflectionProbeSpecular(
|
|
662
|
+
n, v, coatRoughness, vec3<f32>(0.04), in.worldPos,
|
|
663
|
+
vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB),
|
|
664
|
+
skylight.rotation.xyz, vec4<f32>(0.0, 0.0, 0.0, 1.0),
|
|
665
|
+
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
666
|
+
);
|
|
667
|
+
} else {
|
|
668
|
+
clearcoatIbl = sampleIblSpecular(
|
|
669
|
+
n, v, coatRoughness, vec3<f32>(0.04),
|
|
670
|
+
skylight.rotation,
|
|
671
|
+
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
let clearcoatContribution = clearcoatIbl * material.clearcoat;
|
|
675
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
676
|
+
if (skylight.intensity < 0.0) {
|
|
677
|
+
ambient = ambient + clearcoatContribution;
|
|
678
|
+
} else {
|
|
679
|
+
ambient = ambient + clearcoatIbl * material.clearcoat * skyFactor;
|
|
680
|
+
}
|
|
681
|
+
#else
|
|
682
|
+
ambient = ambient + clearcoatContribution;
|
|
683
|
+
#endif
|
|
684
|
+
reflectionFallback = reflectionFallback + clearcoatContribution;
|
|
635
685
|
}
|
|
686
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
687
|
+
ambient = ambient * ao;
|
|
688
|
+
#else
|
|
636
689
|
if (skylight.intensity < 0.0) {
|
|
637
|
-
|
|
690
|
+
let environmentScale = max(-skylight.intensity - 1.0, 0.0) * ao;
|
|
691
|
+
ambient = ambient * environmentScale;
|
|
692
|
+
reflectionFallback = reflectionFallback * environmentScale;
|
|
638
693
|
} else {
|
|
639
|
-
|
|
694
|
+
let environmentScale = skyColor * skylight.intensity * ao;
|
|
695
|
+
ambient = ambient * environmentScale;
|
|
696
|
+
reflectionFallback = reflectionFallback * environmentScale;
|
|
640
697
|
}
|
|
698
|
+
#endif
|
|
641
699
|
#ifdef CLUSTER_FORWARD_AVAILABLE
|
|
642
700
|
// feat-20260612-hdrp-ssao M2 round-1 + M7 round-2 (plan-strategy D-7 + D-B + D-C):
|
|
643
701
|
// SSAO ambient synthesis. Reads the half-res R8 `ssaoBlurredTexture` from
|
|
@@ -653,7 +711,9 @@ fn fs_main(in : VsOut) -> @location(0) vec4<f32> {
|
|
|
653
711
|
let ssaoFactor = textureSample(ssaoBlurredTexture, ssaoBlurredSampler, ssaoUv).r;
|
|
654
712
|
// scope-amend-webgl2-ubo: intensity packed into cluster_uniform.near_far_log.w.
|
|
655
713
|
let ssaoIntensity = get_ssao_intensity();
|
|
714
|
+
let ssaoScale = mix(1.0, ssaoFactor * ao, ssaoIntensity);
|
|
656
715
|
ambient *= mix(1.0, ssaoFactor * ao, ssaoIntensity);
|
|
716
|
+
reflectionFallback *= ssaoScale;
|
|
657
717
|
#endif
|
|
658
718
|
var color = ambient;
|
|
659
719
|
#ifdef TRANSMISSION_AVAILABLE
|
|
@@ -770,7 +830,12 @@ fn fs_main(in : VsOut) -> @location(0) vec4<f32> {
|
|
|
770
830
|
let emissiveUv = transformedMaterialUv(material.emissiveTextureCoordinatesTransform, material.emissiveTextureCoordinatesMetadata, in);
|
|
771
831
|
let emissiveSample = sampleMaterialTexture(emissiveTexture, emissiveSampler, emissiveUv, material.emissiveTextureCoordinatesMetadata.zw).rgb;
|
|
772
832
|
color = color + material.emissive * material.emissiveIntensity * emissiveSample;
|
|
773
|
-
|
|
833
|
+
var output : StandardPbrOutput;
|
|
834
|
+
output.color = vec4<f32>(color, alpha);
|
|
835
|
+
#ifdef REFLECTION_FALLBACK_AVAILABLE
|
|
836
|
+
output.reflectionFallback = vec4<f32>(reflectionFallback, 1.0);
|
|
837
|
+
#endif
|
|
838
|
+
return output;
|
|
774
839
|
}
|
|
775
840
|
|
|
776
841
|
// ── G-buffer output struct (feat-20260612-hdrp-deferred-shading M2 / w12) ──
|
|
@@ -869,7 +934,7 @@ fn vs_temporal(in : VsIn, @builtin(instance_index) idx : u32) -> TemporalVsOut {
|
|
|
869
934
|
let currentWorld = meshes[0].worldFromLocal *
|
|
870
935
|
instances[idx].localFromInstance * vec4<f32>(in.pos, 1.0);
|
|
871
936
|
var previousWorld = currentWorld;
|
|
872
|
-
#
|
|
937
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
873
938
|
previousWorld = meshes[0].previousWorldFromLocal *
|
|
874
939
|
instances[idx].previousLocalFromInstance * vec4<f32>(in.pos, 1.0);
|
|
875
940
|
#endif
|
|
@@ -906,6 +971,10 @@ fn temporalVertexAlpha(in : TemporalVsOut) -> f32 {
|
|
|
906
971
|
|
|
907
972
|
@fragment
|
|
908
973
|
fn fs_temporal(in : TemporalVsOut) -> @location(0) vec4<f32> {
|
|
974
|
+
var reactive = 0.0;
|
|
975
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
976
|
+
reactive = meshes[0].temporal.x;
|
|
977
|
+
#endif
|
|
909
978
|
return projectPbrSceneTemporal(
|
|
910
979
|
material.baseColor.a * temporalVertexAlpha(in),
|
|
911
980
|
material.alphaCutoff,
|
package/src/ibl-irradiance.wgsl
CHANGED
|
@@ -83,7 +83,10 @@ fn irradianceConvolve_fs(in0: CubemapVsOut) -> @location(0) vec4<f32> {
|
|
|
83
83
|
phi += IRRADIANCE_SAMPLE_DELTA;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
//
|
|
86
|
+
// IRRADIANCE_PAYLOAD_E_OVER_PI: PI * the uniform theta/phi sample average
|
|
87
|
+
// produces the Lambert-normalized diffuse radiance E / PI. Runtime sampling
|
|
88
|
+
// consumes this payload directly; applying another Lambert divide would
|
|
89
|
+
// darken diffuse IBL by PI.
|
|
87
90
|
irradiance = PI * irradiance / max(nrSamples, 1.0);
|
|
88
91
|
return vec4<f32>(irradiance, 1.0);
|
|
89
92
|
}
|
package/src/ibl-sampling.wgsl
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// - box_project(worldPosition, direction, boxCenter, boxExtents)
|
|
20
20
|
// - sampleReflectionProbeSpecular(..., probeMap, probeSampler, ...)
|
|
21
21
|
|
|
22
|
-
#import forgeax_pbr::ibl_shared::{
|
|
22
|
+
#import forgeax_pbr::ibl_shared::{fresnelSchlickRoughness, inverseRotateEnvironment}
|
|
23
23
|
|
|
24
24
|
// Sample pre-convolved irradiance from the irradiance cubemap.
|
|
25
25
|
// Y is negated to compensate for WebGPU's top-left texture origin vs the
|
|
@@ -33,7 +33,7 @@ fn sampleIblDiffuse(
|
|
|
33
33
|
let rotated = inverseRotateEnvironment(normal, rotation);
|
|
34
34
|
let dir = vec3<f32>(rotated.x, -rotated.y, rotated.z);
|
|
35
35
|
let irradianceEOverPi = textureSample(irradianceMap, irradianceSampler, dir).rgb;
|
|
36
|
-
return irradianceEOverPi
|
|
36
|
+
return irradianceEOverPi;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Split-sum specular IBL: prefiltered env * (F0 * scale + bias).
|
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,
|
|
@@ -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
|
|
@@ -522,10 +413,9 @@ fn evalDirectionalNoShadow(
|
|
|
522
413
|
let nDotV = max(dot(normal, viewDir), 1e-5);
|
|
523
414
|
let nDotH = max(dot(normal, h), 0.0);
|
|
524
415
|
let vDotH = max(dot(viewDir, h), 0.0);
|
|
525
|
-
let
|
|
526
|
-
let f = F0 * (vec3<f32>(1.0) - fresnel) + vec3<f32>(fresnel);
|
|
416
|
+
let f = f_schlick(vDotH, F0);
|
|
527
417
|
let roughness = sqrt(max(alphaSq, 0.0));
|
|
528
|
-
let multiScatter =
|
|
418
|
+
let multiScatter = threeR184DirectMultiScatter(roughness, nDotV, nDotL, F0);
|
|
529
419
|
let specular = d_ggx(nDotH, alphaSq) * v_smith(nDotV, nDotL, alphaSq) * f + multiScatter;
|
|
530
420
|
let diffuse = (1.0 - metallic) * baseColor / 3.14159265;
|
|
531
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
|
+
}
|
|
@@ -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 +
|