@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
|
@@ -1,20 +1,56 @@
|
|
|
1
|
-
#
|
|
1
|
+
#pragma material_slot surface
|
|
2
|
+
#import forgeax_material::slot::surface::{evaluate_surface}
|
|
3
|
+
#import forgeax_material::surface_v1::{SurfaceInput, SurfaceData}
|
|
4
|
+
#import forgeax_view::common::{View, Mesh, InstanceData, view, meshes, instances, shadowMap, shadowSampler, sampleMaterialTexture}
|
|
2
5
|
#import forgeax_scene_temporal::{sceneViewZ}
|
|
6
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
7
|
+
#import forgeax_view::common::{spotModifierSampler, iesProfileTexture, cookieTexture, cookieMatrices}
|
|
8
|
+
#endif
|
|
3
9
|
#import forgeax_pbr::temporal::{projectPbrSceneTemporal}
|
|
4
10
|
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx}
|
|
5
|
-
#import forgeax_pbr::ibl_sampling::{sampleIblDiffuse, sampleIblSpecular}
|
|
11
|
+
#import forgeax_pbr::ibl_sampling::{sampleIblDiffuse, sampleIblSpecular, sampleReflectionProbeSpecular}
|
|
12
|
+
#import forgeax_pbr::lighting_probe::{evaluateProbeDiffuse}
|
|
6
13
|
#import forgeax_pbr::tbn::{decodeTangentSpaceNormalRg, scaleTangentSpaceNormal, applyTBN}
|
|
14
|
+
#ifdef CLEARCOAT_AVAILABLE
|
|
15
|
+
#import forgeax_pbr::clearcoat::{evaluateClearcoatLayer}
|
|
16
|
+
#endif
|
|
17
|
+
#ifdef ANISOTROPY_AVAILABLE
|
|
18
|
+
#import forgeax_pbr::anisotropy::{evaluateAnisotropicNormal}
|
|
19
|
+
#endif
|
|
20
|
+
#ifdef SHEEN_AVAILABLE
|
|
21
|
+
#import forgeax_pbr::sheen::{evaluateSheenLayer}
|
|
22
|
+
#endif
|
|
23
|
+
#ifdef IRIDESCENCE_AVAILABLE
|
|
24
|
+
#import forgeax_pbr::iridescence::{evaluateIridescenceFresnel}
|
|
25
|
+
#endif
|
|
7
26
|
#import forgeax_pbr::lighting_directional::{evalDirectionalNoShadow, evalDirectionalShadowFactor}
|
|
8
27
|
#ifdef CLUSTER_FORWARD_AVAILABLE
|
|
9
|
-
#import forgeax_standard::cluster::{evaluateStandardClusterLights}
|
|
28
|
+
#import forgeax_standard::cluster::{evaluateStandardClusterLights, get_ssao_intensity}
|
|
10
29
|
#endif
|
|
11
30
|
|
|
12
31
|
#define_import_path forgeax_material::pbr-skin
|
|
13
32
|
#pragma variant_axis STORAGE_BUFFER_AVAILABLE
|
|
14
33
|
#pragma variant_axis CLUSTER_FORWARD_AVAILABLE
|
|
15
34
|
#pragma variant_axis VERTEX_COLOR_AVAILABLE
|
|
35
|
+
#pragma variant_axis PROBE_BLEND_AVAILABLE
|
|
36
|
+
#pragma variant_axis EXTENDED_LIGHTING_AVAILABLE
|
|
37
|
+
#pragma variant_axis TRANSMISSION_AVAILABLE
|
|
16
38
|
#pragma variant_axis DIRECTIONAL_PCSS_AVAILABLE
|
|
17
39
|
|
|
40
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
41
|
+
fn composeProbeDiffuse(
|
|
42
|
+
shPreblend : array<vec4<f32>, 9>,
|
|
43
|
+
localBlendFraction : f32,
|
|
44
|
+
normal : vec3<f32>,
|
|
45
|
+
skyIrradiance : vec3<f32>,
|
|
46
|
+
kD : vec3<f32>,
|
|
47
|
+
albedo : vec3<f32>,
|
|
48
|
+
metallic : f32,
|
|
49
|
+
) -> vec3<f32> {
|
|
50
|
+
return evaluateProbeDiffuse(shPreblend, localBlendFraction, normal, skyIrradiance, kD, albedo, metallic);
|
|
51
|
+
}
|
|
52
|
+
#endif
|
|
53
|
+
|
|
18
54
|
// @forgeax/engine-shader - default-standard-pbr-skin.wgsl
|
|
19
55
|
// (feat-20260523-skin-skeleton-animation M3 / T-29).
|
|
20
56
|
//
|
|
@@ -37,7 +73,6 @@
|
|
|
37
73
|
// @group(1) @binding(4) metallicRoughnessTexture texture_2d<f32>
|
|
38
74
|
// @group(1) @binding(5) normalSampler sampler
|
|
39
75
|
// @group(1) @binding(6) normalTexture texture_2d<f32>
|
|
40
|
-
// @group(1) @binding(7) specularTintSampler + @binding(8) specularTintTexture
|
|
41
76
|
// @group(1) @binding(9..15) Skylight (irradiance / prefilter / brdfLut +
|
|
42
77
|
// samplers) + skylight uniform (intensity)
|
|
43
78
|
// @group(2) @binding(0) meshes storage (worldFromLocal mat4
|
|
@@ -67,86 +102,128 @@
|
|
|
67
102
|
// 4 joints max; weighted sum of skinned positions from the palette buffer
|
|
68
103
|
// indexed by the per-vertex skinIndex vector.
|
|
69
104
|
|
|
70
|
-
struct
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// Channel selectors (D-8): 4 independent f32 entries split out of the
|
|
75
|
-
// legacy `channelMap : vec4<u32>`. See default-standard-pbr.wgsl for
|
|
76
|
-
// the full rationale; the skin shader shares the same merged UBO shape.
|
|
77
|
-
metallicChannel : f32,
|
|
78
|
-
roughnessChannel : f32,
|
|
79
|
-
aoChannel : f32,
|
|
80
|
-
extraChannel : f32,
|
|
81
|
-
// vec3 align=16 inserts implicit padding so emissive lands at offset 48;
|
|
82
|
-
// the authored schema rounds to 112 B (matches default-standard-pbr SSOT).
|
|
83
|
-
emissive : vec3<f32>,
|
|
84
|
-
emissiveIntensity : f32,
|
|
85
|
-
occlusionStrength : f32,
|
|
86
|
-
alphaCutoff : f32,
|
|
87
|
-
clearcoat : f32,
|
|
88
|
-
clearcoatRoughness : f32,
|
|
89
|
-
specularTint : vec3<f32>,
|
|
90
|
-
normalScale : f32,
|
|
91
|
-
transmission : f32,
|
|
92
|
-
ior : f32,
|
|
93
|
-
thickness : f32,
|
|
94
|
-
attenuationColor : vec3<f32>,
|
|
95
|
-
attenuationDistance : f32,
|
|
96
|
-
baseColorTextureCoordinatesTransform : vec4<f32>,
|
|
97
|
-
baseColorTextureCoordinatesMetadata : vec4<f32>,
|
|
98
|
-
metallicRoughnessTextureCoordinatesTransform : vec4<f32>,
|
|
99
|
-
metallicRoughnessTextureCoordinatesMetadata : vec4<f32>,
|
|
100
|
-
normalTextureCoordinatesTransform : vec4<f32>,
|
|
101
|
-
normalTextureCoordinatesMetadata : vec4<f32>,
|
|
102
|
-
specularTintTextureCoordinatesTransform : vec4<f32>,
|
|
103
|
-
specularTintTextureCoordinatesMetadata : vec4<f32>,
|
|
104
|
-
emissiveTextureCoordinatesTransform : vec4<f32>,
|
|
105
|
-
emissiveTextureCoordinatesMetadata : vec4<f32>,
|
|
106
|
-
occlusionTextureCoordinatesTransform : vec4<f32>,
|
|
107
|
-
occlusionTextureCoordinatesMetadata : vec4<f32>,
|
|
108
|
-
transmissionTextureCoordinatesTransform : vec4<f32>,
|
|
109
|
-
transmissionTextureCoordinatesMetadata : vec4<f32>,
|
|
110
|
-
thicknessTextureCoordinatesTransform : vec4<f32>,
|
|
111
|
-
thicknessTextureCoordinatesMetadata : vec4<f32>,
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
@group(1) @binding(0) var<uniform> material : Material;
|
|
105
|
+
// The MaterialParameters struct and its binding-0 declaration are generated
|
|
106
|
+
// from the root ParamSchema during material composition. Keeping the ABI out
|
|
107
|
+
// of this template prevents a second handwritten interface from drifting from
|
|
108
|
+
// the runtime UBO writer.
|
|
115
109
|
@group(1) @binding(1) var baseColorSampler : sampler;
|
|
116
110
|
@group(1) @binding(2) var baseColorTexture : texture_2d<f32>;
|
|
117
111
|
@group(1) @binding(3) var metallicRoughnessSampler : sampler;
|
|
118
112
|
@group(1) @binding(4) var metallicRoughnessTexture : texture_2d<f32>;
|
|
119
113
|
@group(1) @binding(5) var normalSampler : sampler;
|
|
120
114
|
@group(1) @binding(6) var normalTexture : texture_2d<f32>;
|
|
121
|
-
@group(1) @binding(7) var specularTintSampler : sampler;
|
|
122
|
-
@group(1) @binding(8) var specularTintTexture : texture_2d<f32>;
|
|
123
115
|
@group(1) @binding(9) var emissiveSampler : sampler;
|
|
124
116
|
@group(1) @binding(10) var emissiveTexture : texture_2d<f32>;
|
|
125
117
|
@group(1) @binding(11) var occlusionSampler : sampler;
|
|
126
118
|
@group(1) @binding(12) var occlusionTexture : texture_2d<f32>;
|
|
119
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
127
120
|
@group(1) @binding(13) var transmissionSampler : sampler;
|
|
128
121
|
@group(1) @binding(14) var transmissionTexture : texture_2d<f32>;
|
|
129
122
|
@group(1) @binding(15) var thicknessSampler : sampler;
|
|
130
123
|
@group(1) @binding(16) var thicknessTexture : texture_2d<f32>;
|
|
124
|
+
@group(1) @binding(24) var transmissionBackdropSampler : sampler;
|
|
125
|
+
@group(1) @binding(25) var transmissionBackdropTexture : texture_2d<f32>;
|
|
126
|
+
#endif
|
|
127
|
+
#ifdef CLEARCOAT_TEXTURE_AVAILABLE
|
|
128
|
+
@group(1) @binding(26) var clearcoatSampler : sampler;
|
|
129
|
+
@group(1) @binding(27) var clearcoatTexture : texture_2d<f32>;
|
|
130
|
+
#endif
|
|
131
|
+
#ifdef CLEARCOAT_ROUGHNESS_TEXTURE_AVAILABLE
|
|
132
|
+
@group(1) @binding(28) var clearcoatRoughnessSampler : sampler;
|
|
133
|
+
@group(1) @binding(29) var clearcoatRoughnessTexture : texture_2d<f32>;
|
|
134
|
+
#endif
|
|
135
|
+
#ifdef CLEARCOAT_NORMAL_TEXTURE_AVAILABLE
|
|
136
|
+
@group(1) @binding(30) var clearcoatNormalSampler : sampler;
|
|
137
|
+
@group(1) @binding(31) var clearcoatNormalTexture : texture_2d<f32>;
|
|
138
|
+
#endif
|
|
139
|
+
#ifdef ANISOTROPY_TEXTURE_AVAILABLE
|
|
140
|
+
@group(1) @binding(32) var anisotropySampler : sampler;
|
|
141
|
+
@group(1) @binding(33) var anisotropyTexture : texture_2d<f32>;
|
|
142
|
+
#endif
|
|
143
|
+
#ifdef SHEEN_COLOR_TEXTURE_AVAILABLE
|
|
144
|
+
@group(1) @binding(34) var sheenColorSampler : sampler;
|
|
145
|
+
@group(1) @binding(35) var sheenColorTexture : texture_2d<f32>;
|
|
146
|
+
#endif
|
|
147
|
+
#ifdef SHEEN_ROUGHNESS_TEXTURE_AVAILABLE
|
|
148
|
+
@group(1) @binding(36) var sheenRoughnessSampler : sampler;
|
|
149
|
+
@group(1) @binding(37) var sheenRoughnessTexture : texture_2d<f32>;
|
|
150
|
+
#endif
|
|
151
|
+
#ifdef IRIDESCENCE_TEXTURE_AVAILABLE
|
|
152
|
+
@group(1) @binding(38) var iridescenceSampler : sampler;
|
|
153
|
+
@group(1) @binding(39) var iridescenceTexture : texture_2d<f32>;
|
|
154
|
+
#endif
|
|
155
|
+
#ifdef IRIDESCENCE_THICKNESS_TEXTURE_AVAILABLE
|
|
156
|
+
@group(1) @binding(40) var iridescenceThicknessSampler : sampler;
|
|
157
|
+
@group(1) @binding(41) var iridescenceThicknessTexture : texture_2d<f32>;
|
|
158
|
+
#endif
|
|
159
|
+
#ifdef SPECULAR_TEXTURE_AVAILABLE
|
|
160
|
+
@group(1) @binding(42) var specularTextureSampler : sampler;
|
|
161
|
+
@group(1) @binding(43) var specularTexture : texture_2d<f32>;
|
|
162
|
+
#endif
|
|
163
|
+
#ifdef SPECULAR_COLOR_TEXTURE_AVAILABLE
|
|
164
|
+
@group(1) @binding(44) var specularColorTextureSampler : sampler;
|
|
165
|
+
@group(1) @binding(45) var specularColorTexture : texture_2d<f32>;
|
|
166
|
+
#endif
|
|
131
167
|
|
|
132
168
|
// Preserve filtering reflection for resources passed to the shared sampler.
|
|
133
169
|
fn materialTextureFilteringWitness() {
|
|
134
170
|
let base = baseColorTexture;
|
|
135
171
|
let metallicRoughness = metallicRoughnessTexture;
|
|
136
172
|
let normal = normalTexture;
|
|
137
|
-
let specularTint = specularTintTexture;
|
|
138
173
|
let emissive = emissiveTexture;
|
|
139
174
|
let occlusion = occlusionTexture;
|
|
175
|
+
#ifdef CLEARCOAT_TEXTURE_AVAILABLE
|
|
176
|
+
let clearcoat = clearcoatTexture;
|
|
177
|
+
#endif
|
|
178
|
+
#ifdef CLEARCOAT_ROUGHNESS_TEXTURE_AVAILABLE
|
|
179
|
+
let clearcoatRoughness = clearcoatRoughnessTexture;
|
|
180
|
+
#endif
|
|
181
|
+
#ifdef CLEARCOAT_NORMAL_TEXTURE_AVAILABLE
|
|
182
|
+
let clearcoatNormal = clearcoatNormalTexture;
|
|
183
|
+
#endif
|
|
184
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
140
185
|
let transmission = transmissionTexture;
|
|
141
186
|
let thickness = thicknessTexture;
|
|
187
|
+
#endif
|
|
142
188
|
let baseWitness = textureSample(base, baseColorSampler, vec2<f32>(0.0));
|
|
143
189
|
let metallicRoughnessWitness = textureSample(metallicRoughness, metallicRoughnessSampler, vec2<f32>(0.0));
|
|
144
190
|
let normalWitness = textureSample(normal, normalSampler, vec2<f32>(0.0));
|
|
145
|
-
let specularTintWitness = textureSample(specularTint, specularTintSampler, vec2<f32>(0.0));
|
|
146
191
|
let emissiveWitness = textureSample(emissive, emissiveSampler, vec2<f32>(0.0));
|
|
147
192
|
let occlusionWitness = textureSample(occlusion, occlusionSampler, vec2<f32>(0.0));
|
|
193
|
+
#ifdef CLEARCOAT_TEXTURE_AVAILABLE
|
|
194
|
+
let clearcoatWitness = textureSample(clearcoat, clearcoatSampler, vec2<f32>(0.0));
|
|
195
|
+
#endif
|
|
196
|
+
#ifdef CLEARCOAT_ROUGHNESS_TEXTURE_AVAILABLE
|
|
197
|
+
let clearcoatRoughnessWitness = textureSample(clearcoatRoughness, clearcoatRoughnessSampler, vec2<f32>(0.0));
|
|
198
|
+
#endif
|
|
199
|
+
#ifdef CLEARCOAT_NORMAL_TEXTURE_AVAILABLE
|
|
200
|
+
let clearcoatNormalWitness = textureSample(clearcoatNormal, clearcoatNormalSampler, vec2<f32>(0.0));
|
|
201
|
+
#endif
|
|
202
|
+
#ifdef ANISOTROPY_TEXTURE_AVAILABLE
|
|
203
|
+
let anisotropyWitness = textureSample(anisotropyTexture, anisotropySampler, vec2<f32>(0.0));
|
|
204
|
+
#endif
|
|
205
|
+
#ifdef SHEEN_COLOR_TEXTURE_AVAILABLE
|
|
206
|
+
let sheenColorWitness = textureSample(sheenColorTexture, sheenColorSampler, vec2<f32>(0.0));
|
|
207
|
+
#endif
|
|
208
|
+
#ifdef SHEEN_ROUGHNESS_TEXTURE_AVAILABLE
|
|
209
|
+
let sheenRoughnessWitness = textureSample(sheenRoughnessTexture, sheenRoughnessSampler, vec2<f32>(0.0));
|
|
210
|
+
#endif
|
|
211
|
+
#ifdef IRIDESCENCE_TEXTURE_AVAILABLE
|
|
212
|
+
let iridescenceWitness = textureSample(iridescenceTexture, iridescenceSampler, vec2<f32>(0.0));
|
|
213
|
+
#endif
|
|
214
|
+
#ifdef IRIDESCENCE_THICKNESS_TEXTURE_AVAILABLE
|
|
215
|
+
let iridescenceThicknessWitness = textureSample(iridescenceThicknessTexture, iridescenceThicknessSampler, vec2<f32>(0.0));
|
|
216
|
+
#endif
|
|
217
|
+
#ifdef SPECULAR_TEXTURE_AVAILABLE
|
|
218
|
+
let specularWeightWitness = textureSample(specularTexture, specularTextureSampler, vec2<f32>(0.0));
|
|
219
|
+
#endif
|
|
220
|
+
#ifdef SPECULAR_COLOR_TEXTURE_AVAILABLE
|
|
221
|
+
let specularColorWitness = textureSample(specularColorTexture, specularColorTextureSampler, vec2<f32>(0.0));
|
|
222
|
+
#endif
|
|
223
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
148
224
|
let transmissionWitness = textureSample(transmission, transmissionSampler, vec2<f32>(0.0));
|
|
149
225
|
let thicknessWitness = textureSample(thickness, thicknessSampler, vec2<f32>(0.0));
|
|
226
|
+
#endif
|
|
150
227
|
}
|
|
151
228
|
|
|
152
229
|
struct SkylightUniforms {
|
|
@@ -171,6 +248,10 @@ struct SkylightUniforms {
|
|
|
171
248
|
@group(1) @binding(22) var brdfLutSampler : sampler;
|
|
172
249
|
@group(1) @binding(23) var<uniform> skylight : SkylightUniforms;
|
|
173
250
|
|
|
251
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
252
|
+
@group(3) @binding(1) var<storage, read> probeBlendRecords : array<vec4<f32>>;
|
|
253
|
+
#endif
|
|
254
|
+
|
|
174
255
|
#if STORAGE_BUFFER_AVAILABLE == true
|
|
175
256
|
@group(2) @binding(1) var<storage, read> palette : array<mat4x4<f32>>;
|
|
176
257
|
@group(2) @binding(2) var<storage, read> previousPalette : array<mat4x4<f32>>;
|
|
@@ -201,6 +282,13 @@ struct VsIn {
|
|
|
201
282
|
};
|
|
202
283
|
struct VsOut {
|
|
203
284
|
@builtin(position) clip : vec4<f32>,
|
|
285
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
286
|
+
@location(4) @interpolate(flat) transmissionBasis0 : vec4<f32>,
|
|
287
|
+
#else
|
|
288
|
+
// WebGL2 exposes only inter-stage locations 0..14. Pack the object-space
|
|
289
|
+
// Surface position with its cluster/CSM depth in one varying.
|
|
290
|
+
@location(7) positionOSAndViewZ : vec4<f32>,
|
|
291
|
+
#endif
|
|
204
292
|
@location(0) worldPos : vec3<f32>,
|
|
205
293
|
@location(1) worldNormal : vec3<f32>,
|
|
206
294
|
@location(2) uv : vec2<f32>,
|
|
@@ -212,28 +300,20 @@ struct VsOut {
|
|
|
212
300
|
@location(9) uv3 : vec2<f32>,
|
|
213
301
|
@location(10) uv4 : vec2<f32>,
|
|
214
302
|
@location(11) uv5 : vec2<f32>,
|
|
215
|
-
|
|
216
|
-
|
|
303
|
+
// UV6/UV7 share one vec4 slot so the transmission basis tail can stay
|
|
304
|
+
// inside WebGL2's 14 user varying locations.
|
|
305
|
+
@location(12) uv6And7 : vec4<f32>,
|
|
217
306
|
#ifdef VERTEX_COLOR_AVAILABLE
|
|
218
307
|
@location(14) color : vec4<f32>,
|
|
219
308
|
#endif
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
@location(6) ndc : vec3<f32>,
|
|
309
|
+
@location(6) ndc : vec4<f32>,
|
|
310
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
223
311
|
@location(7) viewZ : f32,
|
|
312
|
+
@location(13) @interpolate(flat) transmissionBasis1 : vec4<f32>,
|
|
313
|
+
#endif
|
|
224
314
|
};
|
|
225
315
|
|
|
226
|
-
fn
|
|
227
|
-
switch (channelIndex) {
|
|
228
|
-
case 0u: { return rgba.r; }
|
|
229
|
-
case 1u: { return rgba.g; }
|
|
230
|
-
case 2u: { return rgba.b; }
|
|
231
|
-
default: { return rgba.a; }
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
@vertex
|
|
236
|
-
fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
316
|
+
fn vs_main_impl(in : VsIn, meshIndex : u32, instanceIndex : u32) -> VsOut {
|
|
237
317
|
// 4-bone weighted skinning (plan-strategy D-3 / D-3a).
|
|
238
318
|
// The host pre-computes each joint matrix as worldFromJoint * inverseBindMatrix
|
|
239
319
|
// (CPU-side pre-multiplication, per D-4) and writes them into the palette
|
|
@@ -282,10 +362,13 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
282
362
|
// globals. The host-side BGL shape must remain compatible with non-skin
|
|
283
363
|
// PBR pipeline layout (buildPbrSkinLayouts declares 2-entry mesh-array
|
|
284
364
|
// slot + separate instances slot). Without these keep-alive references,
|
|
285
|
-
// createRenderPipeline would fail
|
|
286
|
-
_ = meshes[
|
|
287
|
-
_ = instances[
|
|
365
|
+
// createRenderPipeline would fail at binding-count validation.
|
|
366
|
+
_ = meshes[meshIndex].worldFromLocal;
|
|
367
|
+
_ = instances[instanceIndex].localFromInstance;
|
|
288
368
|
out.clip = view.worldViewProj * skinnedLocal;
|
|
369
|
+
#ifndef TRANSMISSION_AVAILABLE
|
|
370
|
+
out.positionOSAndViewZ = vec4<f32>(in.pos, sceneViewZ(out.clip, view.temporalProjection));
|
|
371
|
+
#endif
|
|
289
372
|
out.worldPos = skinnedLocal.xyz;
|
|
290
373
|
out.worldNormal = normalize(skinNormal3x3 * in.normal);
|
|
291
374
|
let worldTangentXyz = normalize(skinNormal3x3 * in.tangent.xyz);
|
|
@@ -296,22 +379,48 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
296
379
|
out.uv3 = in.uv3;
|
|
297
380
|
out.uv4 = in.uv4;
|
|
298
381
|
out.uv5 = in.uv5;
|
|
299
|
-
out.
|
|
300
|
-
out.uv7 = in.uv7;
|
|
382
|
+
out.uv6And7 = vec4<f32>(in.uv6, in.uv7);
|
|
301
383
|
#ifdef VERTEX_COLOR_AVAILABLE
|
|
302
384
|
out.color = in.color;
|
|
303
385
|
#endif
|
|
386
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
387
|
+
// Skin palette already contains the world-space transform. Forward its
|
|
388
|
+
// affine basis so transmission does not reread Mesh/Instance storage in
|
|
389
|
+
// the fragment stage.
|
|
390
|
+
out.transmissionBasis0 = vec4<f32>(skinMatrix[0].xyz, skinMatrix[1].x);
|
|
391
|
+
out.transmissionBasis1 = vec4<f32>(skinMatrix[1].y, skinMatrix[1].z, skinMatrix[2].x, skinMatrix[2].y);
|
|
392
|
+
#endif
|
|
393
|
+
let clipPos = out.clip;
|
|
394
|
+
out.ndc = vec4(clipPos.xy / clipPos.w, clipPos.z / clipPos.w, skinMatrix[2].z);
|
|
304
395
|
// feat-20260613-csm-cascaded-shadow-maps M5 / w19: viewZ replaces the
|
|
305
396
|
// prior light-space-position varying; evalDirectional picks the cascade
|
|
306
397
|
// matrix per fragment from viewZ + worldPos.
|
|
307
|
-
let clipPos = out.clip;
|
|
308
|
-
out.ndc = vec3(clipPos.xy / clipPos.w, clipPos.z / clipPos.w);
|
|
309
398
|
// Keep the cluster depth exactly aligned with the CPU binner for both
|
|
310
399
|
// perspective and off-axis orthographic projections.
|
|
311
|
-
|
|
400
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
401
|
+
out.viewZ = sceneViewZ(clipPos, view.temporalProjection);
|
|
402
|
+
#endif
|
|
312
403
|
return out;
|
|
313
404
|
}
|
|
314
405
|
|
|
406
|
+
fn standardViewZ(in : VsOut) -> f32 {
|
|
407
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
408
|
+
return in.viewZ;
|
|
409
|
+
#else
|
|
410
|
+
return in.positionOSAndViewZ.w;
|
|
411
|
+
#endif
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@vertex
|
|
415
|
+
fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
416
|
+
return vs_main_impl(in, 0u, idx);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
@vertex
|
|
420
|
+
fn vs_scene_index(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
421
|
+
return vs_main_impl(in, idx, 0u);
|
|
422
|
+
}
|
|
423
|
+
|
|
315
424
|
fn transformedMaterialUv(transform : vec4<f32>, metadata : vec4<f32>, in : VsOut) -> vec2<f32> {
|
|
316
425
|
var source = in.uv;
|
|
317
426
|
if (metadata.x >= 1.0) { source = in.uv1; }
|
|
@@ -319,8 +428,8 @@ fn transformedMaterialUv(transform : vec4<f32>, metadata : vec4<f32>, in : VsOut
|
|
|
319
428
|
if (metadata.x >= 3.0) { source = in.uv3; }
|
|
320
429
|
if (metadata.x >= 4.0) { source = in.uv4; }
|
|
321
430
|
if (metadata.x >= 5.0) { source = in.uv5; }
|
|
322
|
-
if (metadata.x >= 6.0) { source = in.
|
|
323
|
-
if (metadata.x >= 7.0) { source = in.
|
|
431
|
+
if (metadata.x >= 6.0) { source = in.uv6And7.xy; }
|
|
432
|
+
if (metadata.x >= 7.0) { source = in.uv6And7.zw; }
|
|
324
433
|
let scaled = source * transform.zw;
|
|
325
434
|
let angle = metadata.y;
|
|
326
435
|
let c = cos(angle);
|
|
@@ -336,83 +445,518 @@ fn materialVertexColor(in : VsOut) -> vec4<f32> {
|
|
|
336
445
|
#endif
|
|
337
446
|
}
|
|
338
447
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
448
|
+
// Keep the cooked skinned artifact content-addressable per declared
|
|
449
|
+
// capability set, including axes whose imported helper/resource surface is
|
|
450
|
+
// otherwise identical after lowering.
|
|
451
|
+
fn standardSkinVariantIdentity() -> f32 {
|
|
452
|
+
var identity = 0.0;
|
|
453
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
454
|
+
identity = identity + 1.0;
|
|
455
|
+
#endif
|
|
456
|
+
#ifdef CLUSTER_FORWARD_AVAILABLE
|
|
457
|
+
identity = identity + 2.0;
|
|
458
|
+
#endif
|
|
459
|
+
#ifdef VERTEX_COLOR_AVAILABLE
|
|
460
|
+
identity = identity + 4.0;
|
|
461
|
+
#endif
|
|
462
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
463
|
+
identity = identity + 8.0;
|
|
464
|
+
#endif
|
|
465
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
466
|
+
identity = identity + 16.0;
|
|
467
|
+
#endif
|
|
468
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
469
|
+
identity = identity + 32.0;
|
|
470
|
+
#endif
|
|
471
|
+
#ifdef DIRECTIONAL_PCSS_AVAILABLE
|
|
472
|
+
identity = identity + 64.0;
|
|
473
|
+
#endif
|
|
474
|
+
return identity;
|
|
475
|
+
}
|
|
349
476
|
|
|
350
|
-
|
|
351
|
-
let
|
|
352
|
-
|
|
353
|
-
let
|
|
477
|
+
fn evaluateStandardSurface(in : VsOut, frontFacing : bool) -> SurfaceData {
|
|
478
|
+
let viewDirectionWS = normalize(view.cameraPos - in.worldPos);
|
|
479
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
480
|
+
let positionOS = in.worldPos;
|
|
481
|
+
#else
|
|
482
|
+
let positionOS = in.positionOSAndViewZ.xyz;
|
|
483
|
+
#endif
|
|
484
|
+
return evaluate_surface(SurfaceInput(
|
|
485
|
+
positionOS,
|
|
486
|
+
in.worldPos,
|
|
487
|
+
in.worldNormal,
|
|
488
|
+
in.worldTangent,
|
|
489
|
+
viewDirectionWS,
|
|
490
|
+
in.uv,
|
|
491
|
+
in.uv1,
|
|
492
|
+
materialVertexColor(in),
|
|
493
|
+
frontFacing,
|
|
494
|
+
));
|
|
495
|
+
}
|
|
354
496
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
497
|
+
fn finiteScalar(value : f32, fallback : f32) -> f32 {
|
|
498
|
+
let bounded = clamp(value, -65504.0, 65504.0);
|
|
499
|
+
return select(fallback, bounded, value == value);
|
|
500
|
+
}
|
|
358
501
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
502
|
+
fn finiteColor(value : vec3<f32>, fallback : vec3<f32>) -> vec3<f32> {
|
|
503
|
+
return vec3<f32>(
|
|
504
|
+
finiteScalar(value.x, fallback.x),
|
|
505
|
+
finiteScalar(value.y, fallback.y),
|
|
506
|
+
finiteScalar(value.z, fallback.z),
|
|
363
507
|
);
|
|
364
|
-
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
fn alphaTestSurface(surface : SurfaceData) {
|
|
511
|
+
if (surface.alphaClipThreshold > 0.0 && surface.opacity <= surface.alphaClipThreshold) {
|
|
512
|
+
discard;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
@fragment
|
|
517
|
+
fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0) vec4<f32> {
|
|
518
|
+
let _variantIdentity = standardSkinVariantIdentity();
|
|
519
|
+
let surface = evaluateStandardSurface(in, frontFacing);
|
|
520
|
+
alphaTestSurface(surface);
|
|
521
|
+
let alpha = surface.opacity;
|
|
522
|
+
let albedo = surface.baseColor;
|
|
523
|
+
let metallic = clamp(finiteScalar(surface.metallic, 0.0), 0.0, 1.0);
|
|
524
|
+
let iblRoughness = clamp(finiteScalar(surface.roughness, 0.5), 0.04, 1.0);
|
|
525
|
+
let a = iblRoughness * iblRoughness;
|
|
526
|
+
let n = normalize(surface.normalWS);
|
|
365
527
|
|
|
366
528
|
let v = normalize(view.cameraPos - in.worldPos);
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
529
|
+
var specularColor = material.specularColor;
|
|
530
|
+
#ifdef SPECULAR_COLOR_TEXTURE_AVAILABLE
|
|
531
|
+
specularColor = specularColor * sampleMaterialTexture(
|
|
532
|
+
specularColorTexture,
|
|
533
|
+
specularColorTextureSampler,
|
|
534
|
+
transformedMaterialUv(
|
|
535
|
+
material.specularColorTextureCoordinatesTransform,
|
|
536
|
+
material.specularColorTextureCoordinatesMetadata,
|
|
537
|
+
in,
|
|
538
|
+
),
|
|
539
|
+
material.specularColorTextureCoordinatesMetadata.zw,
|
|
371
540
|
).rgb;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
let
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
let irradiance = sampleIblDiffuse(n, skylight.rotation, irradianceMap, irradianceSampler);
|
|
380
|
-
let specularIbl = sampleIblSpecular(
|
|
381
|
-
n, v, iblRoughness, f0,
|
|
382
|
-
skylight.rotation,
|
|
383
|
-
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
541
|
+
#endif
|
|
542
|
+
var specularWeight = clamp(finiteScalar(material.specular, 1.0), 0.0, 1.0);
|
|
543
|
+
#ifdef SPECULAR_TEXTURE_AVAILABLE
|
|
544
|
+
let specularWeightUv = transformedMaterialUv(
|
|
545
|
+
material.specularTextureCoordinatesTransform,
|
|
546
|
+
material.specularTextureCoordinatesMetadata,
|
|
547
|
+
in,
|
|
384
548
|
);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
549
|
+
specularWeight = specularWeight * sampleMaterialTexture(
|
|
550
|
+
specularTexture,
|
|
551
|
+
specularTextureSampler,
|
|
552
|
+
specularWeightUv,
|
|
553
|
+
material.specularTextureCoordinatesMetadata.zw,
|
|
554
|
+
).a;
|
|
555
|
+
#endif
|
|
556
|
+
let safeIor = max(finiteScalar(material.ior, 1.5), 1.0);
|
|
557
|
+
let dielectricF0 = pow((safeIor - 1.0) / (safeIor + 1.0), 2.0);
|
|
558
|
+
var f0 = mix(vec3<f32>(dielectricF0) * specularColor * specularWeight, albedo, metallic);
|
|
559
|
+
var physicalNormal = n;
|
|
560
|
+
#ifdef ANISOTROPY_AVAILABLE
|
|
561
|
+
var anisotropyStrength = finiteScalar(material.anisotropyStrength, 0.0);
|
|
562
|
+
var anisotropyRotation = finiteScalar(material.anisotropyRotation, 0.0);
|
|
563
|
+
var anisotropyDirection = vec2<f32>(1.0, 0.0);
|
|
564
|
+
#ifdef ANISOTROPY_TEXTURE_AVAILABLE
|
|
565
|
+
let anisotropyUv = transformedMaterialUv(
|
|
566
|
+
material.anisotropyTextureCoordinatesTransform,
|
|
567
|
+
material.anisotropyTextureCoordinatesMetadata,
|
|
568
|
+
in,
|
|
569
|
+
);
|
|
570
|
+
let anisotropySample = sampleMaterialTexture(
|
|
571
|
+
anisotropyTexture,
|
|
572
|
+
anisotropySampler,
|
|
573
|
+
anisotropyUv,
|
|
574
|
+
material.anisotropyTextureCoordinatesMetadata.zw,
|
|
575
|
+
);
|
|
576
|
+
let encodedAnisotropyDirection = 2.0 * anisotropySample.rg - vec2<f32>(1.0, 1.0);
|
|
577
|
+
if (dot(encodedAnisotropyDirection, encodedAnisotropyDirection) >= 1e-6) {
|
|
578
|
+
anisotropyDirection = normalize(encodedAnisotropyDirection);
|
|
579
|
+
}
|
|
580
|
+
anisotropyStrength = anisotropyStrength * anisotropySample.b;
|
|
581
|
+
#endif
|
|
582
|
+
physicalNormal = evaluateAnisotropicNormal(
|
|
583
|
+
n,
|
|
584
|
+
in.worldTangent,
|
|
585
|
+
anisotropyStrength,
|
|
586
|
+
anisotropyRotation,
|
|
587
|
+
anisotropyDirection,
|
|
588
|
+
);
|
|
589
|
+
#endif
|
|
590
|
+
#ifdef IRIDESCENCE_AVAILABLE
|
|
591
|
+
var iridescenceStrength = finiteScalar(material.iridescence, 0.0);
|
|
592
|
+
var iridescenceThicknessFactor = 1.0;
|
|
593
|
+
#ifdef IRIDESCENCE_TEXTURE_AVAILABLE
|
|
594
|
+
let iridescenceUv = transformedMaterialUv(
|
|
595
|
+
material.iridescenceTextureCoordinatesTransform,
|
|
596
|
+
material.iridescenceTextureCoordinatesMetadata,
|
|
597
|
+
in,
|
|
598
|
+
);
|
|
599
|
+
let iridescenceSample = sampleMaterialTexture(
|
|
600
|
+
iridescenceTexture,
|
|
601
|
+
iridescenceSampler,
|
|
602
|
+
iridescenceUv,
|
|
603
|
+
material.iridescenceTextureCoordinatesMetadata.zw,
|
|
604
|
+
);
|
|
605
|
+
iridescenceStrength = iridescenceStrength * iridescenceSample.r;
|
|
606
|
+
#endif
|
|
607
|
+
#ifdef IRIDESCENCE_THICKNESS_TEXTURE_AVAILABLE
|
|
608
|
+
let iridescenceThicknessUv = transformedMaterialUv(
|
|
609
|
+
material.iridescenceThicknessTextureCoordinatesTransform,
|
|
610
|
+
material.iridescenceThicknessTextureCoordinatesMetadata,
|
|
611
|
+
in,
|
|
612
|
+
);
|
|
613
|
+
let iridescenceThicknessSample = sampleMaterialTexture(
|
|
614
|
+
iridescenceThicknessTexture,
|
|
615
|
+
iridescenceThicknessSampler,
|
|
616
|
+
iridescenceThicknessUv,
|
|
617
|
+
material.iridescenceThicknessTextureCoordinatesMetadata.zw,
|
|
618
|
+
);
|
|
619
|
+
iridescenceThicknessFactor = clamp(iridescenceThicknessSample.g, 0.0, 1.0);
|
|
620
|
+
#endif
|
|
621
|
+
let filmThickness = mix(
|
|
622
|
+
finiteScalar(material.iridescenceThicknessMinimum, 100.0),
|
|
623
|
+
finiteScalar(material.iridescenceThicknessMaximum, 400.0),
|
|
624
|
+
iridescenceThicknessFactor,
|
|
625
|
+
);
|
|
626
|
+
f0 = evaluateIridescenceFresnel(
|
|
627
|
+
f0,
|
|
628
|
+
iridescenceStrength,
|
|
629
|
+
finiteScalar(material.iridescenceIor, 1.3),
|
|
630
|
+
filmThickness,
|
|
631
|
+
);
|
|
632
|
+
#endif
|
|
633
|
+
var diffuseAlbedo = albedo;
|
|
634
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
635
|
+
let transmissionUv = transformedMaterialUv(
|
|
636
|
+
material.transmissionTextureCoordinatesTransform,
|
|
637
|
+
material.transmissionTextureCoordinatesMetadata,
|
|
638
|
+
in,
|
|
639
|
+
);
|
|
640
|
+
let thicknessUv = transformedMaterialUv(
|
|
641
|
+
material.thicknessTextureCoordinatesTransform,
|
|
642
|
+
material.thicknessTextureCoordinatesMetadata,
|
|
643
|
+
in,
|
|
644
|
+
);
|
|
645
|
+
let transmissionSample = sampleMaterialTexture(
|
|
646
|
+
transmissionTexture,
|
|
647
|
+
transmissionSampler,
|
|
648
|
+
transmissionUv,
|
|
649
|
+
material.transmissionTextureCoordinatesMetadata.zw,
|
|
650
|
+
).r;
|
|
651
|
+
let thicknessSample = sampleMaterialTexture(
|
|
652
|
+
thicknessTexture,
|
|
653
|
+
thicknessSampler,
|
|
654
|
+
thicknessUv,
|
|
655
|
+
material.thicknessTextureCoordinatesMetadata.zw,
|
|
656
|
+
).g;
|
|
657
|
+
let transmissionFactor = clamp(
|
|
658
|
+
finiteScalar(material.transmission, 0.0) * finiteScalar(transmissionSample, 1.0),
|
|
659
|
+
0.0,
|
|
660
|
+
1.0,
|
|
661
|
+
);
|
|
662
|
+
let viewDot = finiteScalar(dot(n, v), 0.0);
|
|
663
|
+
let refractionFromInside = viewDot < 0.0;
|
|
664
|
+
let refractionNormal = select(n, -n, refractionFromInside);
|
|
665
|
+
let refractionEta = select(1.0 / safeIor, safeIor, refractionFromInside);
|
|
666
|
+
let incident = -v;
|
|
667
|
+
let refracted = refract(incident, refractionNormal, refractionEta);
|
|
668
|
+
let refractedLengthSquared = dot(refracted, refracted);
|
|
669
|
+
let viewCos = clamp(abs(viewDot), 0.0, 1.0);
|
|
670
|
+
let fresnel = clamp(f_schlick(viewCos, vec3<f32>(dielectricF0)).x, 0.0, 1.0);
|
|
671
|
+
let transmittedEnergy = select(
|
|
672
|
+
0.0,
|
|
673
|
+
transmissionFactor * (1.0 - metallic) * (1.0 - fresnel),
|
|
674
|
+
refractedLengthSquared > 1e-6,
|
|
675
|
+
);
|
|
676
|
+
diffuseAlbedo = albedo * (1.0 - transmittedEnergy);
|
|
677
|
+
#endif
|
|
678
|
+
let kD = (vec3<f32>(1.0) - f_schlick(max(dot(physicalNormal, v), 0.0), f0)) * (1.0 - metallic);
|
|
679
|
+
var coatRoughness = 0.04;
|
|
680
|
+
var coatAlpha = coatRoughness * coatRoughness;
|
|
681
|
+
var coatF = vec3<f32>(0.0);
|
|
682
|
+
#ifdef CLEARCOAT_AVAILABLE
|
|
683
|
+
coatRoughness = max(finiteScalar(material.clearcoatRoughness, 0.04), 0.04);
|
|
684
|
+
coatAlpha = coatRoughness * coatRoughness;
|
|
685
|
+
coatF = f_schlick(max(dot(physicalNormal, v), 0.0), vec3<f32>(0.04)) *
|
|
686
|
+
clamp(finiteScalar(material.clearcoat, 0.0), 0.0, 1.0);
|
|
687
|
+
#endif
|
|
688
|
+
var irradiance = vec3<f32>(0.0);
|
|
689
|
+
var specularIbl = vec3<f32>(0.0);
|
|
690
|
+
if (skylight.intensity < 0.0) {
|
|
691
|
+
specularIbl = sampleReflectionProbeSpecular(
|
|
692
|
+
physicalNormal, v, iblRoughness, f0, in.worldPos,
|
|
693
|
+
vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB),
|
|
694
|
+
skylight.rotation.xyz, vec4<f32>(0.0, 0.0, 0.0, 1.0),
|
|
695
|
+
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
696
|
+
);
|
|
697
|
+
} else {
|
|
698
|
+
irradiance = sampleIblDiffuse(physicalNormal, skylight.rotation, irradianceMap, irradianceSampler);
|
|
699
|
+
specularIbl = sampleIblSpecular(
|
|
700
|
+
physicalNormal, v, iblRoughness, f0,
|
|
390
701
|
skylight.rotation,
|
|
391
702
|
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
392
703
|
);
|
|
393
|
-
ambient = ambient + clearcoatIbl * material.clearcoat;
|
|
394
704
|
}
|
|
395
|
-
|
|
705
|
+
let ao = surface.occlusion;
|
|
706
|
+
let skyColor = vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB);
|
|
707
|
+
let skyFactor = skyColor * skylight.intensity;
|
|
708
|
+
var ambient = (kD * irradiance * diffuseAlbedo + specularIbl) *
|
|
709
|
+
(vec3<f32>(1.0) - coatF);
|
|
710
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
711
|
+
let probeShPreblend = array<vec4<f32>, 9>(
|
|
712
|
+
probeBlendRecords[1], probeBlendRecords[2], probeBlendRecords[3],
|
|
713
|
+
probeBlendRecords[4], probeBlendRecords[5], probeBlendRecords[6],
|
|
714
|
+
probeBlendRecords[7], probeBlendRecords[8], probeBlendRecords[9],
|
|
715
|
+
);
|
|
716
|
+
let probeLocalBlendFraction = probeBlendRecords[0].z;
|
|
717
|
+
let probeDiffuseK = kD / max(vec3<f32>(1.0 - metallic), vec3<f32>(0.0001));
|
|
718
|
+
let probeDiffuse = composeProbeDiffuse(probeShPreblend,
|
|
719
|
+
probeLocalBlendFraction,
|
|
720
|
+
physicalNormal,
|
|
721
|
+
irradiance * skyFactor,
|
|
722
|
+
probeDiffuseK,
|
|
723
|
+
diffuseAlbedo,
|
|
724
|
+
metallic,
|
|
725
|
+
);
|
|
726
|
+
ambient = (probeDiffuse + specularIbl * skyFactor) *
|
|
727
|
+
(vec3<f32>(1.0) - coatF);
|
|
728
|
+
#endif
|
|
729
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
730
|
+
ambient = ambient * ao;
|
|
731
|
+
#else
|
|
732
|
+
if (skylight.intensity < 0.0) {
|
|
733
|
+
let environmentScale = max(-skylight.intensity - 1.0, 0.0) * ao;
|
|
734
|
+
ambient = ambient * environmentScale;
|
|
735
|
+
} else {
|
|
736
|
+
let environmentScale = skyColor * skylight.intensity * ao;
|
|
737
|
+
ambient = ambient * environmentScale;
|
|
738
|
+
}
|
|
739
|
+
#endif
|
|
396
740
|
var color = ambient;
|
|
397
|
-
|
|
398
|
-
let
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
741
|
+
#ifdef TRANSMISSION_AVAILABLE
|
|
742
|
+
let screenUv = in.ndc.xy * vec2<f32>(0.5, -0.5) + vec2<f32>(0.5);
|
|
743
|
+
let localToWorld0 = in.transmissionBasis0.xyz;
|
|
744
|
+
let localToWorld1 = vec3<f32>(
|
|
745
|
+
in.transmissionBasis0.w,
|
|
746
|
+
in.transmissionBasis1.x,
|
|
747
|
+
in.transmissionBasis1.y,
|
|
748
|
+
);
|
|
749
|
+
let localToWorld2 = vec3<f32>(
|
|
750
|
+
in.transmissionBasis1.z,
|
|
751
|
+
in.transmissionBasis1.w,
|
|
752
|
+
in.ndc.w,
|
|
753
|
+
);
|
|
754
|
+
let inverseCofactor0 = cross(localToWorld1, localToWorld2);
|
|
755
|
+
let inverseCofactor1 = cross(localToWorld2, localToWorld0);
|
|
756
|
+
let inverseCofactor2 = cross(localToWorld0, localToWorld1);
|
|
757
|
+
let localToWorldDet = dot(localToWorld0, inverseCofactor0);
|
|
758
|
+
let safeLocalToWorldDet = select(1.0, localToWorldDet, abs(localToWorldDet) >= 1e-6);
|
|
759
|
+
let worldToLocal0 = vec3<f32>(
|
|
760
|
+
inverseCofactor0.x,
|
|
761
|
+
inverseCofactor1.x,
|
|
762
|
+
inverseCofactor2.x,
|
|
763
|
+
) / safeLocalToWorldDet;
|
|
764
|
+
let worldToLocal1 = vec3<f32>(
|
|
765
|
+
inverseCofactor0.y,
|
|
766
|
+
inverseCofactor1.y,
|
|
767
|
+
inverseCofactor2.y,
|
|
768
|
+
) / safeLocalToWorldDet;
|
|
769
|
+
let worldToLocal2 = vec3<f32>(
|
|
770
|
+
inverseCofactor0.z,
|
|
771
|
+
inverseCofactor1.z,
|
|
772
|
+
inverseCofactor2.z,
|
|
773
|
+
) / safeLocalToWorldDet;
|
|
774
|
+
let refractedLocal = normalize(
|
|
775
|
+
worldToLocal0 * refracted.x +
|
|
776
|
+
worldToLocal1 * refracted.y +
|
|
777
|
+
worldToLocal2 * refracted.z,
|
|
778
|
+
);
|
|
779
|
+
let worldRefractedDirection =
|
|
780
|
+
localToWorld0 * refractedLocal.x +
|
|
781
|
+
localToWorld1 * refractedLocal.y +
|
|
782
|
+
localToWorld2 * refractedLocal.z;
|
|
783
|
+
let worldThickness = max(
|
|
784
|
+
finiteScalar(material.thickness, 0.0) * length(worldRefractedDirection) *
|
|
785
|
+
finiteScalar(thicknessSample, 1.0),
|
|
786
|
+
0.0,
|
|
787
|
+
);
|
|
788
|
+
let refractedUv = screenUv + (refracted.xy - incident.xy) * worldThickness * 0.25;
|
|
789
|
+
let guardBand = 0.02;
|
|
790
|
+
let insideGuardBand = all(refractedUv >= vec2<f32>(guardBand)) &&
|
|
791
|
+
all(refractedUv <= vec2<f32>(1.0 - guardBand));
|
|
792
|
+
let backdropMipCount = textureNumLevels(transmissionBackdropTexture);
|
|
793
|
+
let backdropMaxLod = max(f32(backdropMipCount) - 1.0, 0.0);
|
|
794
|
+
let backdropLod = clamp(iblRoughness * iblRoughness * backdropMaxLod, 0.0, backdropMaxLod);
|
|
795
|
+
let unrefractedBackdrop = textureSampleLevel(
|
|
796
|
+
transmissionBackdropTexture,
|
|
797
|
+
transmissionBackdropSampler,
|
|
798
|
+
clamp(screenUv, vec2<f32>(0.0), vec2<f32>(1.0)),
|
|
799
|
+
backdropLod,
|
|
800
|
+
).rgb;
|
|
801
|
+
var transmittedBackdrop = unrefractedBackdrop;
|
|
802
|
+
if (refractedLengthSquared > 1e-6 && insideGuardBand) {
|
|
803
|
+
transmittedBackdrop = textureSampleLevel(
|
|
804
|
+
transmissionBackdropTexture,
|
|
805
|
+
transmissionBackdropSampler,
|
|
806
|
+
clamp(refractedUv, vec2<f32>(0.0), vec2<f32>(1.0)),
|
|
807
|
+
backdropLod,
|
|
808
|
+
).rgb;
|
|
405
809
|
}
|
|
810
|
+
let safeAttenuationColor = clamp(
|
|
811
|
+
finiteColor(material.attenuationColor, vec3<f32>(1.0)),
|
|
812
|
+
vec3<f32>(0.0),
|
|
813
|
+
vec3<f32>(1.0),
|
|
814
|
+
);
|
|
815
|
+
let safeAttenuationDistance = max(finiteScalar(material.attenuationDistance, 0.0), 0.0);
|
|
816
|
+
let attenuationExponent = worldThickness / max(safeAttenuationDistance, 1e-6);
|
|
817
|
+
let beerAttenuation = select(
|
|
818
|
+
vec3<f32>(1.0),
|
|
819
|
+
pow(safeAttenuationColor, vec3<f32>(attenuationExponent)),
|
|
820
|
+
safeAttenuationDistance > 1e-6 && worldThickness > 0.0,
|
|
821
|
+
);
|
|
822
|
+
color = color + finiteColor(transmittedBackdrop, vec3<f32>(0.0)) *
|
|
823
|
+
transmittedEnergy * beerAttenuation;
|
|
824
|
+
#endif
|
|
825
|
+
color = color + surface.emissive;
|
|
826
|
+
let directionalShadow = evalDirectionalShadowFactor(
|
|
827
|
+
physicalNormal,
|
|
828
|
+
in.worldPos,
|
|
829
|
+
standardViewZ(in),
|
|
830
|
+
);
|
|
831
|
+
let directionalBase = evalDirectionalNoShadow(physicalNormal, v, diffuseAlbedo, metallic, a, f0);
|
|
832
|
+
color = color + directionalShadow * directionalBase;
|
|
406
833
|
#ifdef CLUSTER_FORWARD_AVAILABLE
|
|
407
834
|
color = color + evaluateStandardClusterLights(
|
|
408
|
-
in.ndc, in
|
|
835
|
+
in.ndc.xyz, standardViewZ(in), in.worldPos, physicalNormal, v,
|
|
836
|
+
diffuseAlbedo, metallic, a, f0, false,
|
|
409
837
|
);
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
838
|
+
#endif // CLUSTER_FORWARD_AVAILABLE
|
|
839
|
+
#ifdef SHEEN_AVAILABLE
|
|
840
|
+
var sheenColor = material.sheenColor;
|
|
841
|
+
var sheenRoughnessFactor = 1.0;
|
|
842
|
+
#ifdef SHEEN_COLOR_TEXTURE_AVAILABLE
|
|
843
|
+
sheenColor = sheenColor * sampleMaterialTexture(
|
|
844
|
+
sheenColorTexture,
|
|
845
|
+
sheenColorSampler,
|
|
846
|
+
transformedMaterialUv(material.sheenColorTextureCoordinatesTransform, material.sheenColorTextureCoordinatesMetadata, in),
|
|
847
|
+
material.sheenColorTextureCoordinatesMetadata.zw,
|
|
848
|
+
).rgb;
|
|
849
|
+
#endif
|
|
850
|
+
#ifdef SHEEN_ROUGHNESS_TEXTURE_AVAILABLE
|
|
851
|
+
sheenRoughnessFactor = sampleMaterialTexture(
|
|
852
|
+
sheenRoughnessTexture,
|
|
853
|
+
sheenRoughnessSampler,
|
|
854
|
+
transformedMaterialUv(material.sheenRoughnessTextureCoordinatesTransform, material.sheenRoughnessTextureCoordinatesMetadata, in),
|
|
855
|
+
material.sheenRoughnessTextureCoordinatesMetadata.zw,
|
|
856
|
+
).a;
|
|
857
|
+
#endif
|
|
858
|
+
let sheenRoughness = clamp(
|
|
859
|
+
material.sheenRoughness * sheenRoughnessFactor,
|
|
860
|
+
0.0,
|
|
861
|
+
1.0,
|
|
862
|
+
);
|
|
863
|
+
color = evaluateSheenLayer(color, sheenColor, sheenRoughness, dot(n, v));
|
|
864
|
+
#endif
|
|
865
|
+
#ifdef CLEARCOAT_AVAILABLE
|
|
866
|
+
var clearcoatFactor = clamp(material.clearcoat, 0.0, 1.0);
|
|
867
|
+
#ifdef CLEARCOAT_TEXTURE_AVAILABLE
|
|
868
|
+
let clearcoatUv = transformedMaterialUv(material.clearcoatTextureCoordinatesTransform, material.clearcoatTextureCoordinatesMetadata, in);
|
|
869
|
+
clearcoatFactor = clamp(
|
|
870
|
+
material.clearcoat * sampleMaterialTexture(
|
|
871
|
+
clearcoatTexture,
|
|
872
|
+
clearcoatSampler,
|
|
873
|
+
clearcoatUv,
|
|
874
|
+
material.clearcoatTextureCoordinatesMetadata.zw,
|
|
875
|
+
).r,
|
|
876
|
+
0.0,
|
|
877
|
+
1.0,
|
|
878
|
+
);
|
|
879
|
+
#endif
|
|
880
|
+
var clearcoatRoughnessValue = clamp(max(material.clearcoatRoughness, 0.04), 0.04, 1.0);
|
|
881
|
+
#ifdef CLEARCOAT_ROUGHNESS_TEXTURE_AVAILABLE
|
|
882
|
+
let clearcoatRoughnessUv = transformedMaterialUv(material.clearcoatRoughnessTextureCoordinatesTransform, material.clearcoatRoughnessTextureCoordinatesMetadata, in);
|
|
883
|
+
clearcoatRoughnessValue = clamp(
|
|
884
|
+
max(material.clearcoatRoughness, 0.04) * sampleMaterialTexture(
|
|
885
|
+
clearcoatRoughnessTexture,
|
|
886
|
+
clearcoatRoughnessSampler,
|
|
887
|
+
clearcoatRoughnessUv,
|
|
888
|
+
material.clearcoatRoughnessTextureCoordinatesMetadata.zw,
|
|
889
|
+
).g,
|
|
890
|
+
0.04,
|
|
891
|
+
1.0,
|
|
892
|
+
);
|
|
893
|
+
#endif
|
|
894
|
+
var clearcoatNormalValue = in.worldNormal;
|
|
895
|
+
#ifdef CLEARCOAT_NORMAL_TEXTURE_AVAILABLE
|
|
896
|
+
let clearcoatNormalUv = transformedMaterialUv(material.clearcoatNormalTextureCoordinatesTransform, material.clearcoatNormalTextureCoordinatesMetadata, in);
|
|
897
|
+
clearcoatNormalValue = applyTBN(
|
|
898
|
+
in.worldNormal,
|
|
899
|
+
in.worldTangent,
|
|
900
|
+
scaleTangentSpaceNormal(
|
|
901
|
+
decodeTangentSpaceNormalRg(sampleMaterialTexture(
|
|
902
|
+
clearcoatNormalTexture,
|
|
903
|
+
clearcoatNormalSampler,
|
|
904
|
+
clearcoatNormalUv,
|
|
905
|
+
material.clearcoatNormalTextureCoordinatesMetadata.zw,
|
|
906
|
+
).rg),
|
|
907
|
+
material.clearcoatNormalScale,
|
|
908
|
+
),
|
|
909
|
+
);
|
|
910
|
+
#endif
|
|
911
|
+
var clearcoatIbl = vec3<f32>(0.0);
|
|
912
|
+
if (skylight.intensity < 0.0) {
|
|
913
|
+
clearcoatIbl = sampleReflectionProbeSpecular(
|
|
914
|
+
clearcoatNormalValue,
|
|
915
|
+
v,
|
|
916
|
+
clearcoatRoughnessValue,
|
|
917
|
+
vec3<f32>(0.04),
|
|
918
|
+
in.worldPos,
|
|
919
|
+
vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB),
|
|
920
|
+
skylight.rotation.xyz,
|
|
921
|
+
vec4<f32>(0.0, 0.0, 0.0, 1.0),
|
|
922
|
+
prefilterMap,
|
|
923
|
+
prefilterSampler,
|
|
924
|
+
brdfLut,
|
|
925
|
+
brdfLutSampler,
|
|
926
|
+
);
|
|
927
|
+
} else {
|
|
928
|
+
clearcoatIbl = sampleIblSpecular(
|
|
929
|
+
clearcoatNormalValue,
|
|
930
|
+
v,
|
|
931
|
+
clearcoatRoughnessValue,
|
|
932
|
+
vec3<f32>(0.04),
|
|
933
|
+
skylight.rotation,
|
|
934
|
+
prefilterMap,
|
|
935
|
+
prefilterSampler,
|
|
936
|
+
brdfLut,
|
|
937
|
+
brdfLutSampler,
|
|
414
938
|
);
|
|
415
939
|
}
|
|
940
|
+
let clearcoatAlpha = clearcoatRoughnessValue * clearcoatRoughnessValue;
|
|
941
|
+
let clearcoatDirect = directionalShadow * evalDirectionalNoShadow(
|
|
942
|
+
clearcoatNormalValue,
|
|
943
|
+
v,
|
|
944
|
+
vec3<f32>(0.0),
|
|
945
|
+
1.0,
|
|
946
|
+
clearcoatAlpha,
|
|
947
|
+
vec3<f32>(0.04),
|
|
948
|
+
);
|
|
949
|
+
let directionalClearcoat = clearcoatDirect;
|
|
950
|
+
var clearcoatEnvironment = clearcoatIbl * skyColor * skylight.intensity;
|
|
951
|
+
if (skylight.intensity < 0.0) {
|
|
952
|
+
clearcoatEnvironment = clearcoatIbl;
|
|
953
|
+
}
|
|
954
|
+
color = evaluateClearcoatLayer(
|
|
955
|
+
color,
|
|
956
|
+
clearcoatEnvironment + directionalClearcoat,
|
|
957
|
+
dot(clearcoatNormalValue, v),
|
|
958
|
+
clearcoatFactor,
|
|
959
|
+
);
|
|
416
960
|
#endif
|
|
417
961
|
return vec4<f32>(color, alpha);
|
|
418
962
|
}
|
|
@@ -429,7 +973,6 @@ struct TemporalVsOut {
|
|
|
429
973
|
@location(7) uv7 : vec2<f32>,
|
|
430
974
|
@location(8) @interpolate(perspective) currentClip : vec4<f32>,
|
|
431
975
|
@location(9) @interpolate(perspective) previousClip : vec4<f32>,
|
|
432
|
-
@location(10) @interpolate(flat) reactive : f32,
|
|
433
976
|
#ifdef VERTEX_COLOR_AVAILABLE
|
|
434
977
|
@location(14) color : vec4<f32>,
|
|
435
978
|
#endif
|
|
@@ -451,11 +994,6 @@ fn vs_temporal(in : VsIn, @builtin(instance_index) idx : u32) -> TemporalVsOut {
|
|
|
451
994
|
out.currentClip = view.temporalCurrentViewProj * currentWorld;
|
|
452
995
|
out.clip = out.currentClip;
|
|
453
996
|
out.previousClip = view.temporalPreviousViewProj * previousWorld;
|
|
454
|
-
#if STORAGE_BUFFER_AVAILABLE == true
|
|
455
|
-
out.reactive = meshes[0].temporal.x;
|
|
456
|
-
#else
|
|
457
|
-
out.reactive = 1.0;
|
|
458
|
-
#endif
|
|
459
997
|
out.uv = in.uv;
|
|
460
998
|
out.uv1 = in.uv1;
|
|
461
999
|
out.uv2 = in.uv2;
|
|
@@ -481,6 +1019,11 @@ fn temporalVertexAlpha(in : TemporalVsOut) -> f32 {
|
|
|
481
1019
|
|
|
482
1020
|
@fragment
|
|
483
1021
|
fn fs_temporal(in : TemporalVsOut) -> @location(0) vec4<f32> {
|
|
1022
|
+
#if STORAGE_BUFFER_AVAILABLE == true
|
|
1023
|
+
let reactive = meshes[0].temporal.x;
|
|
1024
|
+
#else
|
|
1025
|
+
let reactive = 1.0;
|
|
1026
|
+
#endif
|
|
484
1027
|
return projectPbrSceneTemporal(
|
|
485
1028
|
material.baseColor.a * temporalVertexAlpha(in),
|
|
486
1029
|
material.alphaCutoff,
|
|
@@ -491,7 +1034,7 @@ fn fs_temporal(in : TemporalVsOut) -> @location(0) vec4<f32> {
|
|
|
491
1034
|
in.currentClip,
|
|
492
1035
|
in.previousClip,
|
|
493
1036
|
view.temporalProjection,
|
|
494
|
-
|
|
1037
|
+
reactive,
|
|
495
1038
|
in.uv, in.uv1, in.uv2, in.uv3,
|
|
496
1039
|
in.uv4, in.uv5, in.uv6, in.uv7,
|
|
497
1040
|
);
|