@forgeax/engine-shader 0.1.2
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/LICENSE +202 -0
- package/README.md +99 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/ShaderRegistry.d.ts +208 -0
- package/dist/ShaderRegistry.d.ts.map +1 -0
- package/dist/__tests__/atmosphere-background.test.d.ts +2 -0
- package/dist/__tests__/atmosphere-background.test.d.ts.map +1 -0
- package/dist/__tests__/atmosphere-cubemap-orientation.test.d.ts +2 -0
- package/dist/__tests__/atmosphere-cubemap-orientation.test.d.ts.map +1 -0
- package/dist/__tests__/atmosphere-preetham-numeric.test.d.ts +2 -0
- package/dist/__tests__/atmosphere-preetham-numeric.test.d.ts.map +1 -0
- package/dist/__tests__/atmosphere-preetham-red.test.d.ts +2 -0
- package/dist/__tests__/atmosphere-preetham-red.test.d.ts.map +1 -0
- package/dist/__tests__/atmosphere-preetham.test.d.ts +2 -0
- package/dist/__tests__/atmosphere-preetham.test.d.ts.map +1 -0
- package/dist/__tests__/atmosphere-three-r184-reference.test.d.ts +2 -0
- package/dist/__tests__/atmosphere-three-r184-reference.test.d.ts.map +1 -0
- package/dist/__tests__/bloom-fxaa-tonemap.unit.test.d.ts +2 -0
- package/dist/__tests__/bloom-fxaa-tonemap.unit.test.d.ts.map +1 -0
- package/dist/__tests__/builtin-texture-sampling-contract.test.d.ts +2 -0
- package/dist/__tests__/builtin-texture-sampling-contract.test.d.ts.map +1 -0
- package/dist/__tests__/default-standard-pbr-alpha.unit.test.d.ts +2 -0
- package/dist/__tests__/default-standard-pbr-alpha.unit.test.d.ts.map +1 -0
- package/dist/__tests__/deferred-lighting-ssao.test.d.ts +2 -0
- package/dist/__tests__/deferred-lighting-ssao.test.d.ts.map +1 -0
- package/dist/__tests__/fog-oracle.unit.test.d.ts +2 -0
- package/dist/__tests__/fog-oracle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fog-orthographic-ray.unit.test.d.ts +2 -0
- package/dist/__tests__/fog-orthographic-ray.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fog-producer-matrix.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-producer-matrix.integration.test.d.ts.map +1 -0
- package/dist/__tests__/hdrp-ssao-compile.test.d.ts +2 -0
- package/dist/__tests__/hdrp-ssao-compile.test.d.ts.map +1 -0
- package/dist/__tests__/ibl-irradiance.unit.test.d.ts +2 -0
- package/dist/__tests__/ibl-irradiance.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ibl-sampling.unit.test.d.ts +2 -0
- package/dist/__tests__/ibl-sampling.unit.test.d.ts.map +1 -0
- package/dist/__tests__/lighting-punctual.unit.test.d.ts +2 -0
- package/dist/__tests__/lighting-punctual.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-artifact-dedup.unit.test.d.ts +2 -0
- package/dist/__tests__/material-artifact-dedup.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-builtins.unit.test.d.ts +2 -0
- package/dist/__tests__/material-builtins.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/material-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-derived-builtins.integration.test.d.ts +2 -0
- package/dist/__tests__/material-derived-builtins.integration.test.d.ts.map +1 -0
- package/dist/__tests__/public-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/public-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scene-temporal.unit.test.d.ts +2 -0
- package/dist/__tests__/scene-temporal.unit.test.d.ts.map +1 -0
- package/dist/__tests__/shader-registry-transaction.unit.test.d.ts +2 -0
- package/dist/__tests__/shader-registry-transaction.unit.test.d.ts.map +1 -0
- package/dist/__tests__/shader.unit.test.d.ts +2 -0
- package/dist/__tests__/shader.unit.test.d.ts.map +1 -0
- package/dist/__tests__/sprite-lit-shader.test.d.ts +2 -0
- package/dist/__tests__/sprite-lit-shader.test.d.ts.map +1 -0
- package/dist/__tests__/sprite-variants.unit.test.d.ts +2 -0
- package/dist/__tests__/sprite-variants.unit.test.d.ts.map +1 -0
- package/dist/__tests__/taa-resolve.unit.test.d.ts +2 -0
- package/dist/__tests__/taa-resolve.unit.test.d.ts.map +1 -0
- package/dist/__tests__/transparent-pbr.unit.test.d.ts +2 -0
- package/dist/__tests__/transparent-pbr.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vertex-color-variant.unit.test.d.ts +2 -0
- package/dist/__tests__/vertex-color-variant.unit.test.d.ts.map +1 -0
- package/dist/errors.d.ts +96 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +560 -0
- package/dist/index.mjs.map +1 -0
- package/dist/material/artifact-registry.d.ts +31 -0
- package/dist/material/artifact-registry.d.ts.map +1 -0
- package/dist/material/artifact-types.d.ts +13 -0
- package/dist/material/artifact-types.d.ts.map +1 -0
- package/dist/material-schemas.d.ts +8 -0
- package/dist/material-schemas.d.ts.map +1 -0
- package/dist/register-default-sprite-lit.d.ts +40 -0
- package/dist/register-default-sprite-lit.d.ts.map +1 -0
- package/dist/register-default-standard-pbr-skin.d.ts +34 -0
- package/dist/register-default-standard-pbr-skin.d.ts.map +1 -0
- package/dist/tonemap.d.ts +13 -0
- package/dist/tonemap.d.ts.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +58 -0
- package/src/ShaderRegistry.ts +519 -0
- package/src/__tests__/atmosphere-background.test.ts +33 -0
- package/src/__tests__/atmosphere-cubemap-orientation.test.ts +68 -0
- package/src/__tests__/atmosphere-preetham-numeric.test.ts +122 -0
- package/src/__tests__/atmosphere-preetham-red.test.ts +52 -0
- package/src/__tests__/atmosphere-preetham.test.ts +132 -0
- package/src/__tests__/atmosphere-three-r184-reference.test.ts +122 -0
- package/src/__tests__/bloom-fxaa-tonemap.unit.test.ts +31 -0
- package/src/__tests__/builtin-texture-sampling-contract.test.ts +56 -0
- package/src/__tests__/default-standard-pbr-alpha.unit.test.ts +19 -0
- package/src/__tests__/deferred-lighting-ssao.test.ts +114 -0
- package/src/__tests__/fog-oracle.unit.test.ts +132 -0
- package/src/__tests__/fog-orthographic-ray.unit.test.ts +62 -0
- package/src/__tests__/fog-producer-matrix.integration.test.ts +77 -0
- package/src/__tests__/hdrp-ssao-compile.test.ts +185 -0
- package/src/__tests__/ibl-irradiance.unit.test.ts +43 -0
- package/src/__tests__/ibl-sampling.unit.test.ts +40 -0
- package/src/__tests__/lighting-punctual.unit.test.ts +66 -0
- package/src/__tests__/manifest.fixture.json +22 -0
- package/src/__tests__/material-artifact-dedup.unit.test.ts +21 -0
- package/src/__tests__/material-builtins.unit.test.ts +111 -0
- package/src/__tests__/material-contract.unit.test.ts +79 -0
- package/src/__tests__/material-derived-builtins.integration.test.ts +30 -0
- package/src/__tests__/public-surface.unit.test.ts +9 -0
- package/src/__tests__/scene-temporal.unit.test.ts +32 -0
- package/src/__tests__/shader-registry-transaction.unit.test.ts +116 -0
- package/src/__tests__/shader.unit.test.ts +1909 -0
- package/src/__tests__/sprite-lit-shader.test.ts +240 -0
- package/src/__tests__/sprite-variants.unit.test.ts +209 -0
- package/src/__tests__/taa-resolve.unit.test.ts +32 -0
- package/src/__tests__/transparent-pbr.unit.test.ts +21 -0
- package/src/__tests__/vertex-color-variant.unit.test.ts +52 -0
- package/src/atmosphere-background.wgsl +80 -0
- package/src/atmosphere-cubemap.wgsl +72 -0
- package/src/atmosphere-ibl.wgsl +127 -0
- package/src/atmosphere-preetham.wgsl +214 -0
- package/src/bloom-blur.wgsl +89 -0
- package/src/bloom-bright.wgsl +50 -0
- package/src/bloom-composite.wgsl +54 -0
- package/src/brdf.wgsl +25 -0
- package/src/common.wgsl +523 -0
- package/src/default-standard-pbr-skin.wgsl +538 -0
- package/src/default-standard-pbr.wgsl +794 -0
- package/src/errors.ts +169 -0
- package/src/fog.wgsl +27 -0
- package/src/fxaa.wgsl +259 -0
- package/src/hdrp-cluster-forward.wgsl +186 -0
- package/src/hdrp-deferred-lighting.wgsl +69 -0
- package/src/hdrp-ssao.wgsl +174 -0
- package/src/ibl-brdf-lut.wgsl +92 -0
- package/src/ibl-equirect-to-cube.wgsl +56 -0
- package/src/ibl-irradiance.wgsl +89 -0
- package/src/ibl-prefilter.wgsl +101 -0
- package/src/ibl-sampling.wgsl +58 -0
- package/src/ibl-shared.wgsl +118 -0
- package/src/index.ts +166 -0
- package/src/lighting-directional.wgsl +471 -0
- package/src/lighting-punctual.wgsl +274 -0
- package/src/material/artifact-registry.ts +78 -0
- package/src/material/artifact-types.ts +26 -0
- package/src/material-schemas.ts +48 -0
- package/src/msdf-text.wgsl +208 -0
- package/src/pbr-temporal.wgsl +73 -0
- package/src/register-default-sprite-lit.ts +87 -0
- package/src/register-default-standard-pbr-skin.ts +74 -0
- package/src/shadow-pcf.wgsl +120 -0
- package/src/shadow_caster.wgsl +54 -0
- package/src/skybox.wgsl +75 -0
- package/src/sprite-lit.wgsl +307 -0
- package/src/sprite.wgsl +365 -0
- package/src/taa-resolve.wgsl +129 -0
- package/src/tbn.wgsl +54 -0
- package/src/tonemap.ts +13 -0
- package/src/tonemap.wgsl +177 -0
- package/src/types.ts +59 -0
- package/src/unlit.wgsl +186 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#define_import_path forgeax_pbr::ibl_shared
|
|
2
|
+
|
|
3
|
+
// @forgeax/engine-shader - ibl-shared.wgsl (feat-20260520-skylight-ibl-cubemap M3 / t42).
|
|
4
|
+
//
|
|
5
|
+
// Pure-function math shared across the 6-module ibl-* family. Zero binding
|
|
6
|
+
// declarations -- this module never touches @group/@binding so it composes
|
|
7
|
+
// cleanly with any host that has its own @group(0)/@group(1) layout.
|
|
8
|
+
//
|
|
9
|
+
// Origin: round-1's monolithic ibl.wgsl collided @group(1) @binding(0)
|
|
10
|
+
// across texture_2d (equirect) and texture_cube (irradiance, prefilter),
|
|
11
|
+
// which the WGSL spec forbids inside a single module. round-2 splits the
|
|
12
|
+
// math out into this file so the 4 precompute modules + 2 sampling helpers
|
|
13
|
+
// can each declare their own (group, binding) namespace without overlap.
|
|
14
|
+
//
|
|
15
|
+
// Exports (no entry points):
|
|
16
|
+
// - PI, INV_ATAN constants
|
|
17
|
+
// - sampleSphericalMap(v)
|
|
18
|
+
// - radicalInverseVdC(bits)
|
|
19
|
+
// - hammersley(i, N)
|
|
20
|
+
// - iblDGGX(nDotH, roughness)
|
|
21
|
+
// - iblGeometrySchlickGGX(NdotV, roughness) (IBL k = roughness^2 / 2)
|
|
22
|
+
// - iblGeometrySmith(NdotV, NdotL, roughness)
|
|
23
|
+
// - importanceSampleGGX(Xi, N, roughness)
|
|
24
|
+
// - fresnelSchlickRoughness(cosTheta, F0, roughness)
|
|
25
|
+
//
|
|
26
|
+
// References: LearnOpenGL §6.2 IBL pipeline; Karis 2013 split-sum.
|
|
27
|
+
|
|
28
|
+
const INV_ATAN: vec2<f32> = vec2<f32>(0.1591, 0.3183);
|
|
29
|
+
const PI: f32 = 3.14159265;
|
|
30
|
+
|
|
31
|
+
// Map a direction vector to equirectangular UV.
|
|
32
|
+
fn sampleSphericalMap(v: vec3<f32>) -> vec2<f32> {
|
|
33
|
+
let uv = vec2<f32>(atan2(v.z, v.x), asin(v.y));
|
|
34
|
+
return uv * INV_ATAN + 0.5;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Rotate a sampling direction by the inverse of an environment quaternion.
|
|
38
|
+
// This keeps the baked cubemap reusable while rotating the source map in
|
|
39
|
+
// world space at the final sampling boundary.
|
|
40
|
+
fn inverseRotateEnvironment(direction: vec3<f32>, rotation: vec4<f32>) -> vec3<f32> {
|
|
41
|
+
let q = normalize(rotation);
|
|
42
|
+
let t = 2.0 * cross(q.xyz, direction);
|
|
43
|
+
return direction - q.w * t + cross(q.xyz, t);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Van der Corput radical inverse in base 2.
|
|
47
|
+
fn radicalInverseVdC(bits: u32) -> f32 {
|
|
48
|
+
var b: u32 = bits;
|
|
49
|
+
b = (b << 16u) | (b >> 16u);
|
|
50
|
+
b = ((b & 0x55555555u) << 1u) | ((b & 0xAAAAAAAAu) >> 1u);
|
|
51
|
+
b = ((b & 0x33333333u) << 2u) | ((b & 0xCCCCCCCCu) >> 2u);
|
|
52
|
+
b = ((b & 0x0F0F0F0Fu) << 4u) | ((b & 0xF0F0F0F0u) >> 4u);
|
|
53
|
+
b = ((b & 0x00FF00FFu) << 8u) | ((b & 0xFF00FF00u) >> 8u);
|
|
54
|
+
return f32(b) * 2.3283064365386963e-10;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Hammersley low-discrepancy 2D sequence: (i/N, radicalInverseVdC(i)).
|
|
58
|
+
fn hammersley(i: u32, N: u32) -> vec2<f32> {
|
|
59
|
+
return vec2<f32>(f32(i) / f32(N), radicalInverseVdC(i));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// GGX NDF.
|
|
63
|
+
fn iblDGGX(nDotH: f32, roughness: f32) -> f32 {
|
|
64
|
+
let a = roughness * roughness;
|
|
65
|
+
let a2 = a * a;
|
|
66
|
+
let f = (nDotH * a2 - nDotH) * nDotH + 1.0;
|
|
67
|
+
return a2 / (max(PI * f * f, 1e-7));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Smith-GGX G1 for IBL: k = roughness^2 / 2.
|
|
71
|
+
// DIFFERENT from direct-light's k = ((roughness+1)^2)/8 (in brdf.wgsl).
|
|
72
|
+
fn iblGeometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 {
|
|
73
|
+
let k = (roughness * roughness) / 2.0;
|
|
74
|
+
return NdotV / max(NdotV * (1.0 - k) + k, 1e-5);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Smith-GGX height-correlated geometry for IBL.
|
|
78
|
+
fn iblGeometrySmith(NdotV: f32, NdotL: f32, roughness: f32) -> f32 {
|
|
79
|
+
let ggxV = iblGeometrySchlickGGX(NdotV, roughness);
|
|
80
|
+
let ggxL = iblGeometrySchlickGGX(NdotL, roughness);
|
|
81
|
+
return ggxV * ggxL;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// GGX importance sampling: maps uniform 2D sample Xi to a half-vector H
|
|
85
|
+
// in the local frame around N.
|
|
86
|
+
fn importanceSampleGGX(Xi: vec2<f32>, N: vec3<f32>, roughness: f32) -> vec3<f32> {
|
|
87
|
+
let a = roughness * roughness;
|
|
88
|
+
|
|
89
|
+
let phi = 2.0 * PI * Xi.x;
|
|
90
|
+
let cosTheta = sqrt(max((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y), 0.0));
|
|
91
|
+
let sinTheta = sqrt(max(1.0 - cosTheta * cosTheta, 0.0));
|
|
92
|
+
|
|
93
|
+
// GGX half-vector in tangent space.
|
|
94
|
+
let Ht = vec3<f32>(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
|
95
|
+
|
|
96
|
+
// Tangent frame construction (avoids singularity at N parallel to z).
|
|
97
|
+
// WGSL `select(falseVal, trueVal, cond)` returns trueVal when cond is
|
|
98
|
+
// true; the LearnOpenGL reference is `cond ? vec3(0,0,1) : vec3(1,0,0)`.
|
|
99
|
+
// When N is (near-)parallel to z (e.g. the BRDF-LUT canonical frame
|
|
100
|
+
// N = (0,0,1)) we need up = (1,0,0); otherwise up = (0,0,1). Swapping the
|
|
101
|
+
// operands here fixes the brdf-lut bake silently producing all-zero output
|
|
102
|
+
// (cross(up, N) = 0 when up == N, normalize(0) = NaN, GPU flushes to 0).
|
|
103
|
+
let up = select(
|
|
104
|
+
vec3<f32>(1.0, 0.0, 0.0),
|
|
105
|
+
vec3<f32>(0.0, 0.0, 1.0),
|
|
106
|
+
abs(N.z) < 0.999,
|
|
107
|
+
);
|
|
108
|
+
let tangent = normalize(cross(up, N));
|
|
109
|
+
let bitangent = cross(N, tangent);
|
|
110
|
+
|
|
111
|
+
return normalize(tangent * Ht.x + bitangent * Ht.y + N * Ht.z);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Fresnel-Schlick with roughness dampening for IBL specular.
|
|
115
|
+
fn fresnelSchlickRoughness(cosTheta: f32, F0: vec3<f32>, roughness: f32) -> vec3<f32> {
|
|
116
|
+
let oneMinusRough = max(vec3<f32>(1.0 - roughness), F0);
|
|
117
|
+
return F0 + (oneMinusRough - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
|
118
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// @forgeax/engine-shader — runtime shader registry public surface.
|
|
2
|
+
//
|
|
3
|
+
// Shape rules (plan-strategy §S-10 / D-R10 / OQ-5 close):
|
|
4
|
+
// - instance-per-engine — exposed through the lazy `engine.shader:
|
|
5
|
+
// ShaderRegistry` property; module-level singletons / static methods are
|
|
6
|
+
// forbidden (aligned with `Engine.create({ rhi })`'s instance-based style).
|
|
7
|
+
// - Physical isolation — this package's deps only contain `@forgeax/engine-rhi` +
|
|
8
|
+
// `@forgeax/engine-types`; importing `@forgeax/engine-shader-compiler` / `@forgeax/engine-naga`
|
|
9
|
+
// / `@forgeax/engine-wgpu-wasm` directly or transitively is **forbidden**
|
|
10
|
+
// (guarded by the AC-06 triple-grep gate; feat-20260511-naga-rhi-wgpu-merge
|
|
11
|
+
// M4 replaced the legacy single-shim ban with the merged ban triple above).
|
|
12
|
+
// - Result model — expected failures go through
|
|
13
|
+
// `Result.err(RhiError | ShaderError)` and **never throw** (AGENTS.md
|
|
14
|
+
// "Errors are structured" / charter proposition 4: explicit failure).
|
|
15
|
+
//
|
|
16
|
+
// Top-level surface (charter proposition 1: progressive disclosure):
|
|
17
|
+
// - ShaderRegistry / ShaderRegistryOptions / ShaderRegistryDevice — main class
|
|
18
|
+
// + injection interface
|
|
19
|
+
// - ShaderError / ShaderErrorCode / 2 factories — runtime error types
|
|
20
|
+
// - Result<T, E> + ok / err — binary result type and constructors
|
|
21
|
+
// - ManifestEntry — re-exported from `@forgeax/engine-types` (manifest schema SSOT)
|
|
22
|
+
|
|
23
|
+
export type { ManifestEntry, ParamSchemaEntry } from '@forgeax/engine-types';
|
|
24
|
+
|
|
25
|
+
import type { MaterialAsset, MaterialParameter, MaterialValue } from '@forgeax/engine-types';
|
|
26
|
+
import { STANDARD_PBR_ALPHA_CUTOFF_DEFAULT } from './material-schemas.js';
|
|
27
|
+
|
|
28
|
+
export { MATERIAL_PARAM_TYPES } from '@forgeax/engine-types';
|
|
29
|
+
export {
|
|
30
|
+
err,
|
|
31
|
+
manifestMalformed,
|
|
32
|
+
materialShaderNotFound,
|
|
33
|
+
ok,
|
|
34
|
+
type Result,
|
|
35
|
+
type ResultErr,
|
|
36
|
+
type ResultOk,
|
|
37
|
+
ShaderError,
|
|
38
|
+
type ShaderErrorCode,
|
|
39
|
+
type ShaderErrorDetail,
|
|
40
|
+
shaderNotFound,
|
|
41
|
+
} from './errors.js';
|
|
42
|
+
export {
|
|
43
|
+
type MaterialArtifactConflictError,
|
|
44
|
+
type MaterialArtifactInspection,
|
|
45
|
+
MaterialArtifactRegistry,
|
|
46
|
+
type MaterialRuntimeArtifact,
|
|
47
|
+
registerMaterialArtifact,
|
|
48
|
+
} from './material/artifact-registry.js';
|
|
49
|
+
export {
|
|
50
|
+
isMaterialShaderArtifact,
|
|
51
|
+
type MaterialShaderArtifact,
|
|
52
|
+
} from './material/artifact-types.js';
|
|
53
|
+
export {
|
|
54
|
+
DEFAULT_MSDF_TEXT_PARAM_SCHEMA,
|
|
55
|
+
DEFAULT_SPRITE_PARAM_SCHEMA,
|
|
56
|
+
DEFAULT_STANDARD_PBR_PARAM_SCHEMA,
|
|
57
|
+
DEFAULT_UNLIT_PARAM_SCHEMA,
|
|
58
|
+
STANDARD_PBR_ALPHA_CUTOFF_DEFAULT,
|
|
59
|
+
} from './material-schemas.js';
|
|
60
|
+
export {
|
|
61
|
+
registerDefaultSpriteLit,
|
|
62
|
+
type SpriteLitCaps,
|
|
63
|
+
} from './register-default-sprite-lit.js';
|
|
64
|
+
export { registerDefaultStandardPbrSkin } from './register-default-standard-pbr-skin.js';
|
|
65
|
+
export {
|
|
66
|
+
FORGEAX_RESERVED_PATH_PREFIX,
|
|
67
|
+
type MaterialShaderEntry,
|
|
68
|
+
type RegisteredMaterialShaderEntry,
|
|
69
|
+
ShaderRegistry,
|
|
70
|
+
type ShaderRegistryDevice,
|
|
71
|
+
type ShaderRegistryOptions,
|
|
72
|
+
} from './ShaderRegistry.js';
|
|
73
|
+
export {
|
|
74
|
+
findVariantByKey,
|
|
75
|
+
type MaterialShaderManifestEntry,
|
|
76
|
+
type MaterialShaderManifestVariant,
|
|
77
|
+
} from './types.js';
|
|
78
|
+
|
|
79
|
+
export const BUILTIN_MATERIAL_MODULES = {
|
|
80
|
+
standard: 'forgeax_material::standard',
|
|
81
|
+
unlit: 'forgeax_material::unlit',
|
|
82
|
+
sprite: 'forgeax_material::sprite',
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Material modules whose shader source and parameter contract are owned by
|
|
87
|
+
* the Engine. They live in the runtime ShaderRegistry, so a Pack containing
|
|
88
|
+
* one of these materials carries authored values only and does not require a
|
|
89
|
+
* project material-cook artifact.
|
|
90
|
+
*/
|
|
91
|
+
export const ENGINE_MATERIAL_MODULES = [
|
|
92
|
+
'forgeax::default-standard-pbr',
|
|
93
|
+
'forgeax::pbr-skin',
|
|
94
|
+
'forgeax::default-standard-pbr-skin',
|
|
95
|
+
'forgeax::default-unlit',
|
|
96
|
+
'forgeax::default-shadow-caster',
|
|
97
|
+
'forgeax::sprite',
|
|
98
|
+
'forgeax::sprite-lit',
|
|
99
|
+
'forgeax::msdf-text',
|
|
100
|
+
BUILTIN_MATERIAL_MODULES.standard,
|
|
101
|
+
BUILTIN_MATERIAL_MODULES.unlit,
|
|
102
|
+
BUILTIN_MATERIAL_MODULES.sprite,
|
|
103
|
+
'forgeax_material::sprite-lit',
|
|
104
|
+
] as const;
|
|
105
|
+
|
|
106
|
+
export function isEngineMaterialModule(module: string): boolean {
|
|
107
|
+
return (ENGINE_MATERIAL_MODULES as readonly string[]).includes(module);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function isEngineMaterial(material: Pick<MaterialAsset, 'passes'>): boolean {
|
|
111
|
+
const passes = material.passes ?? [];
|
|
112
|
+
return passes.length > 0 && passes.every((pass) => isEngineMaterialModule(pass.program.module));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type BuiltinMaterialKind = keyof typeof BUILTIN_MATERIAL_MODULES;
|
|
116
|
+
|
|
117
|
+
const BUILTIN_PARAMETERS: Readonly<Record<BuiltinMaterialKind, readonly MaterialParameter[]>> = {
|
|
118
|
+
standard: [
|
|
119
|
+
{ name: 'baseColor', type: 'color' },
|
|
120
|
+
{ name: 'metallic', type: 'f32' },
|
|
121
|
+
{ name: 'roughness', type: 'f32' },
|
|
122
|
+
{ name: 'alphaCutoff', type: 'f32', optional: true },
|
|
123
|
+
],
|
|
124
|
+
unlit: [{ name: 'baseColor', type: 'color' }],
|
|
125
|
+
sprite: [{ name: 'colorTint', type: 'vec4', colorSpace: 'srgb' }],
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const BUILTIN_VALUES: Readonly<
|
|
129
|
+
Record<BuiltinMaterialKind, Readonly<Record<string, MaterialValue>>>
|
|
130
|
+
> = {
|
|
131
|
+
standard: {
|
|
132
|
+
baseColor: [1, 1, 1, 1],
|
|
133
|
+
metallic: 0,
|
|
134
|
+
roughness: 0.5,
|
|
135
|
+
alphaCutoff: STANDARD_PBR_ALPHA_CUTOFF_DEFAULT,
|
|
136
|
+
},
|
|
137
|
+
unlit: { baseColor: [1, 1, 1, 1] },
|
|
138
|
+
sprite: { colorTint: [1, 1, 1, 1] },
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export function createBuiltinMaterialAsset(kind: BuiltinMaterialKind): MaterialAsset {
|
|
142
|
+
return {
|
|
143
|
+
kind: 'material',
|
|
144
|
+
passes: [{ name: 'forward', program: { module: BUILTIN_MATERIAL_MODULES[kind] } }],
|
|
145
|
+
parameters: BUILTIN_PARAMETERS[kind],
|
|
146
|
+
values: BUILTIN_VALUES[kind],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Shared luminance epsilon floor for the extended Reinhard tone-map
|
|
152
|
+
* (feat-20260519-tonemap-reinhard-mvp / D-O3).
|
|
153
|
+
*
|
|
154
|
+
* Both the TS port at `packages/runtime/src/systems/tonemap.ts` and the WGSL
|
|
155
|
+
* fragment stage in `packages/shader/src/tonemap.wgsl` apply
|
|
156
|
+
* `max(Y, TONEMAP_LUMINANCE_EPSILON)` before dividing the luminance ratio.
|
|
157
|
+
* The floor keeps the divisor finite at degenerate inputs (`Y = 0` from black
|
|
158
|
+
* pixels, `Y < 0` from rare numerical artefacts). Single SSOT here so a
|
|
159
|
+
* single `import { TONEMAP_LUMINANCE_EPSILON } from '@forgeax/engine-shader'`
|
|
160
|
+
* keeps TS / WGSL byte-equivalent.
|
|
161
|
+
*
|
|
162
|
+
* Value: `1e-5` — small enough to not perturb any plausible HDR luminance.
|
|
163
|
+
*/
|
|
164
|
+
export const TONEMAP_LUMINANCE_EPSILON = 1e-5;
|
|
165
|
+
|
|
166
|
+
export { TONEMAP_SHADER_MODE, type TonemapShaderMode } from './tonemap.js';
|