@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
package/src/common.wgsl
CHANGED
|
@@ -142,13 +142,10 @@ fn ditherUnorm8(value : vec3<f32>, pixelPosition : vec2<f32>) -> vec3<f32> {
|
|
|
142
142
|
// the per-spot perspective `spotLightViewProj` matrices (4 lanes, fragment-read)
|
|
143
143
|
// fold into the View UBO tail instead of a standalone @group(0) binding 9
|
|
144
144
|
// uniform buffer. The standalone binding pushed the fragment-stage uniform
|
|
145
|
-
// buffer count to 12
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
// pipeline-layout creation. Folding into the View UBO costs zero new bindings
|
|
150
|
-
// (the count drops back to 11). D-1 rejected the View UBO for the CASTER vertex
|
|
151
|
-
// channel (binding 7) because directional + spot casters both need a light-view
|
|
145
|
+
// buffer count to 12 before the local-light arrays were removed. The current
|
|
146
|
+
// view declares no point/spot light arrays; the spot matrices remain folded
|
|
147
|
+
// into the View UBO with no standalone binding. D-1 rejected the View UBO for
|
|
148
|
+
// the CASTER vertex channel (binding 7) because directional + spot casters both need a light-view
|
|
152
149
|
// matrix in the same frame (same-frame write contention); the FRAGMENT read
|
|
153
150
|
// channel has no such contention — the host writes all <=4 spot matrices once
|
|
154
151
|
// per frame before the forward pass, so the fold is safe. mat4 array align=16:
|
|
@@ -207,12 +204,22 @@ struct Mesh {
|
|
|
207
204
|
#endif
|
|
208
205
|
};
|
|
209
206
|
|
|
207
|
+
// Retained CPU ProbeBlendRecord ABI: 4 scalar lanes plus 9 vec4 lanes = 160 B.
|
|
208
|
+
// The last lane carries padding for the 27 f32 SH coefficients. Sky residual
|
|
209
|
+
// is derived in lighting-probe.wgsl, never stored as a second fraction.
|
|
210
|
+
struct ProbeBlendRecord {
|
|
211
|
+
objectKey : f32,
|
|
212
|
+
generation : f32,
|
|
213
|
+
localBlendFraction : f32,
|
|
214
|
+
flags : f32,
|
|
215
|
+
shPreblend : array<vec4<f32>, 9>,
|
|
216
|
+
};
|
|
217
|
+
|
|
210
218
|
// feat-20260519-light-casters-point-spot-pbr M4 / w21 (D-S1 + D-S2 +
|
|
211
219
|
// AC-04 b/c + AC-05 binding declaration). Punctual-light std430 storage
|
|
212
|
-
// types
|
|
213
|
-
// `packages/runtime/src/light-buffer-layout.ts`:
|
|
220
|
+
// types use the shared five-row host ABI in `light-buffer-layout.ts`:
|
|
214
221
|
//
|
|
215
|
-
//
|
|
222
|
+
// Point/Spot/Rect direct slot (80 B / 20 u32-or-float lanes):
|
|
216
223
|
// [ 0..2 ] position vec3<f32>
|
|
217
224
|
// [ 3 ] invRangeSquared f32 (Bevy color_inverse_square_range.w; 0
|
|
218
225
|
// collapses range falloff to a pure 1/d^2 inverse-square law)
|
|
@@ -220,7 +227,7 @@ struct Mesh {
|
|
|
220
227
|
// color * intensity so the shader avoids the per-fragment mul)
|
|
221
228
|
// [ 7 ] pad f32 = 0
|
|
222
229
|
//
|
|
223
|
-
//
|
|
230
|
+
// The metadata row carries kind, shadow, IES, and Cookie identities.
|
|
224
231
|
// [ 0..2 ] position vec3<f32>
|
|
225
232
|
// [ 3 ] invRangeSquared f32
|
|
226
233
|
// [ 4..6 ] colorTimesIntensity vec3<f32>
|
|
@@ -229,81 +236,31 @@ struct Mesh {
|
|
|
229
236
|
// [ 8..10] direction vec3<f32> (raw outgoing vector; shader reads
|
|
230
237
|
// via dot(L, -direction) for cone angle test)
|
|
231
238
|
// [ 11 ] cosOuter f32
|
|
232
|
-
// [12] depthBias
|
|
233
|
-
// [
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
//
|
|
239
|
+
// Spot row 3: [12] depthBias, [13] normalBias, [14] shadowIntensity,
|
|
240
|
+
// [15] rollDeg. The unified slot has no separate pcf lane; the current
|
|
241
|
+
// surface and volume receivers use the stable PCF3 profile.
|
|
242
|
+
// Rect row 1/2/3: halfWidth, axisY + halfHeight, axisX + zero pad. The
|
|
243
|
+
// final metadata row carries the kind,
|
|
244
|
+
// shadow, IES, and Cookie identities.
|
|
237
245
|
//
|
|
238
246
|
// WGSL std430 alignment audit: vec3<f32> alignof=16 / sizeof=12. The
|
|
239
247
|
// f32 lane wedged immediately after each vec3 fills the 4 B remainder
|
|
240
248
|
// (WGSL struct member rule: next.offset = roundUp(prev.offset +
|
|
241
249
|
// prev.size, this.alignof) - for f32 alignof=4 the round-up is a
|
|
242
250
|
// no-op, so position[3] / color[3] / direction[3] sit at byte
|
|
243
|
-
// offsets 12 / 28 / 44 with zero internal padding).
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
// parity-only `shadowIntensity` lane at byte 64. These struct sizes match the
|
|
247
|
-
// host packers (packPointLight 32 B / packSpotLight 80 B) exactly.
|
|
251
|
+
// offsets 12 / 28 / 44 with zero internal padding). Point, Spot, and Rect all
|
|
252
|
+
// use the unified 80 B host packer; this shared slot is the sole local-light
|
|
253
|
+
// carrier.
|
|
248
254
|
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
struct PointLight {
|
|
256
|
-
position : vec3<f32>,
|
|
257
|
-
invRangeSquared : f32,
|
|
258
|
-
colorTimesIntensity : vec3<f32>,
|
|
259
|
-
// feat-20260612-point-light-shadows-urp-hdrp M1 / T-M1-8 (plan-strategy §D-2):
|
|
260
|
-
// Repurposes the prior `pointPadW` (f32 zero-pad) lane as `shadowAtlasLayer`
|
|
261
|
-
// (i32 sentinel, -1 = no shadow, 0..3 = cube_array atlas layer index for
|
|
262
|
-
// shadow-casting point lights). Cap = 4 enforced by the PointLightShadow
|
|
263
|
-
// ECS component cardinality. The shader path samples the cube_array atlas
|
|
264
|
-
// (binding 5) only when `shadowAtlasLayer >= 0`. Field name is unique to
|
|
265
|
-
// this struct (no `pad0`/`pad1` collision with the pbr Material struct
|
|
266
|
-
// under naga_oil writeback substitution).
|
|
267
|
-
shadowAtlasLayer : i32,
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
struct SpotLight {
|
|
271
|
-
position : vec3<f32>,
|
|
272
|
-
invRangeSquared : f32,
|
|
273
|
-
colorTimesIntensity : vec3<f32>,
|
|
274
|
-
cosInner : f32,
|
|
275
|
-
direction : vec3<f32>,
|
|
276
|
-
cosOuter : f32,
|
|
277
|
-
// feat-20260625-spot-light-shadow-mapping M3 / w13 (plan-strategy D-4):
|
|
278
|
-
// The trailing vec4 transports receiver controls and the tile identity.
|
|
279
|
-
// Host packSpotLight writes slots 12..14 from the same snapshot; slot 15 is
|
|
280
|
-
// the i32 shadow tile sentinel and slot 16 carries shadowIntensity.
|
|
281
|
-
depthBias : f32,
|
|
282
|
-
normalBias : f32,
|
|
283
|
-
pcfKernelSize : f32,
|
|
284
|
-
shadowAtlasTile : i32,
|
|
285
|
-
shadowIntensity : f32,
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
struct PointLightsArray {
|
|
289
|
-
count : u32,
|
|
290
|
-
slots : array<PointLight, 4>,
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
struct SpotLightsArray {
|
|
294
|
-
count : u32,
|
|
295
|
-
slots : array<SpotLight, 4>,
|
|
255
|
+
struct DirectLightSlot {
|
|
256
|
+
position : vec4<f32>, // row0: position + inverse range
|
|
257
|
+
colorTimesIntensity : vec4<f32>, // row1: color + first angular fact
|
|
258
|
+
direction : vec4<f32>, // row2: primary axis + second angular fact
|
|
259
|
+
auxiliary : vec4<f32>, // row3: auxiliary Rect axis
|
|
260
|
+
metadata : vec4<u32>,
|
|
296
261
|
};
|
|
297
262
|
|
|
298
263
|
@group(0) @binding(0) var<uniform> view : View;
|
|
299
|
-
|
|
300
|
-
#if STORAGE_BUFFER_AVAILABLE == true
|
|
301
|
-
@group(0) @binding(1) var<storage, read> pointLightsBuffer : PointLightsArray;
|
|
302
|
-
@group(0) @binding(2) var<storage, read> spotLightsBuffer : SpotLightsArray;
|
|
303
|
-
#else
|
|
304
|
-
@group(0) @binding(1) var<uniform> pointLightsBuffer : PointLightsArray;
|
|
305
|
-
@group(0) @binding(2) var<uniform> spotLightsBuffer : SpotLightsArray;
|
|
306
|
-
#endif
|
|
307
264
|
// feat-20260520-directional-light-shadow-mapping M3 / w16 (D-1 / plan-strategy §8.1):
|
|
308
265
|
// shadowMap + shadowSampler consume @group(0) bindings 3/4 (smallest unused
|
|
309
266
|
// slots adjacent to view UBO at 0). M3 uses 3x3 PCF with textureLoad on
|
|
@@ -314,7 +271,7 @@ struct SpotLightsArray {
|
|
|
314
271
|
// layers=4, depth32float; one cube per shadow-casting point light, cap=4).
|
|
315
272
|
// Binding 6 declares the per-light shadow params buffer (URP only — proj
|
|
316
273
|
// constants for cube depth-ref reconstruction); HDRP rides the same constants
|
|
317
|
-
// on
|
|
274
|
+
// on direct-light metadata so binding 6 stays unbound on
|
|
318
275
|
// the HDRP path. Sample-time gating by PointLight.shadowAtlasLayer >= 0.
|
|
319
276
|
@group(0) @binding(3) var shadowMap : texture_depth_2d;
|
|
320
277
|
@group(0) @binding(4) var shadowSampler : sampler_comparison;
|
|
@@ -337,7 +294,7 @@ struct SpotLightsArray {
|
|
|
337
294
|
// depth-ref reconstruction (research L0.5 + L1.13). Each lane stores the
|
|
338
295
|
// shader-side reconstruction constants for one shadow-casting point light;
|
|
339
296
|
// slot N matches `PointLight.shadowAtlasLayer = N`. HDRP rides the same
|
|
340
|
-
// constants on
|
|
297
|
+
// constants on direct-light metadata so binding 6 stays unbound on
|
|
341
298
|
// the HDRP path.
|
|
342
299
|
#ifdef POINT_SHADOW_AVAILABLE
|
|
343
300
|
@group(0) @binding(5) var shadowAtlas : texture_depth_cube_array;
|
|
@@ -410,6 +367,23 @@ struct ShadowCasterCascade {
|
|
|
410
367
|
// — folded there in feat-20260625 w25 (scope-amend) to keep the WebGL2 fallback
|
|
411
368
|
// fragment uniform-buffer count <= 11; binding 8 is the last view-BG binding.
|
|
412
369
|
@group(0) @binding(8) var spotShadowMap : texture_depth_2d;
|
|
370
|
+
// Extended-lighting resources are a real optional view topology. The
|
|
371
|
+
// renderer selects the matching material variant and BGL together; keeping
|
|
372
|
+
// these declarations behind the same axis prevents a no-extension variant
|
|
373
|
+
// from consuming texture budget or requiring absent bindings.
|
|
374
|
+
#ifdef EXTENDED_LIGHTING_AVAILABLE
|
|
375
|
+
@group(0) @binding(9) var spotModifierSampler : sampler;
|
|
376
|
+
@group(0) @binding(11) var iesProfileTexture : texture_2d_array<f32>;
|
|
377
|
+
@group(0) @binding(12) var cookieTexture : texture_2d_array<f32>;
|
|
378
|
+
@group(0) @binding(13) var ltcLambertTexture : texture_2d<f32>;
|
|
379
|
+
@group(0) @binding(14) var ltcGgxTexture : texture_2d<f32>;
|
|
380
|
+
// One aspect-correction matrix per Cookie array slice. The matrix is kept in
|
|
381
|
+
// the shared view group so the same projected Cookie semantics are available
|
|
382
|
+
// to both the ordinary and clustered Standard PBR consumers.
|
|
383
|
+
@group(0) @binding(15) var<uniform> cookieMatrices : array<mat4x4<f32>, 32>;
|
|
384
|
+
#endif
|
|
385
|
+
#ifdef PROJECTOR_AVAILABLE
|
|
386
|
+
#ifndef EXTENDED_LIGHTING_AVAILABLE
|
|
413
387
|
// Optional authored SpotLight projector. Surface and volume bind the same
|
|
414
388
|
// accepted TextureAsset view and linear-clamp sampler; an unprojected spot
|
|
415
389
|
// receives the renderer-owned white fallback. The declaration is capability
|
|
@@ -417,10 +391,10 @@ struct ShadowCasterCascade {
|
|
|
417
391
|
// minimum of 16 sampled textures without this optional cookie. Devices that
|
|
418
392
|
// cannot expose the 17th sampled texture select the matching white-projector
|
|
419
393
|
// shader variant and omit these resources from the view BGL.
|
|
420
|
-
#ifdef PROJECTOR_AVAILABLE
|
|
421
394
|
@group(0) @binding(11) var projectorTexture : texture_2d<f32>;
|
|
422
395
|
@group(0) @binding(12) var projectorSampler : sampler;
|
|
423
396
|
#endif
|
|
397
|
+
#endif
|
|
424
398
|
#if STORAGE_BUFFER_AVAILABLE == true
|
|
425
399
|
@group(2) @binding(0) var<storage, read> meshes : array<Mesh>;
|
|
426
400
|
#else
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
#import forgeax_view::common::{View, Mesh, InstanceData, view, meshes, instances, sampleMaterialTexture}
|
|
1
|
+
#import forgeax_view::common::{View, Mesh, InstanceData, view, meshes, instances, shadowMap, shadowSampler, sampleMaterialTexture}
|
|
2
2
|
#import forgeax_scene_temporal::{sceneViewZ}
|
|
3
3
|
#import forgeax_pbr::temporal::{projectPbrSceneTemporal}
|
|
4
4
|
#import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx}
|
|
5
5
|
#import forgeax_pbr::ibl_sampling::{sampleIblDiffuse, sampleIblSpecular}
|
|
6
|
+
#import forgeax_pbr::lighting_probe::{evaluateProbeDiffuse}
|
|
6
7
|
#import forgeax_pbr::tbn::{decodeTangentSpaceNormalRg, scaleTangentSpaceNormal, applyTBN}
|
|
7
8
|
#import forgeax_pbr::lighting_directional::{evalDirectionalNoShadow, evalDirectionalShadowFactor}
|
|
8
9
|
#ifdef CLUSTER_FORWARD_AVAILABLE
|
|
@@ -13,6 +14,9 @@
|
|
|
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
|
|
19
|
+
|
|
16
20
|
#pragma variant_axis DIRECTIONAL_PCSS_AVAILABLE
|
|
17
21
|
|
|
18
22
|
// @forgeax/engine-shader - default-standard-pbr-skin.wgsl
|
|
@@ -171,14 +175,36 @@ struct SkylightUniforms {
|
|
|
171
175
|
@group(1) @binding(22) var brdfLutSampler : sampler;
|
|
172
176
|
@group(1) @binding(23) var<uniform> skylight : SkylightUniforms;
|
|
173
177
|
|
|
174
|
-
#
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
179
|
+
// Optional consumer lane. The host must provide the retained 160B record
|
|
180
|
+
// buffer and matching BGL before enabling this capability.
|
|
181
|
+
@group(3) @binding(1) var<storage, read> probeBlendRecords : array<vec4<f32>>;
|
|
182
|
+
#endif
|
|
183
|
+
|
|
184
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
185
|
+
@group(2) @binding(1) var<storage, read> paletteStorage : array<mat4x4<f32>>;
|
|
186
|
+
@group(2) @binding(2) var<storage, read> previousPaletteStorage : array<mat4x4<f32>>;
|
|
177
187
|
#else
|
|
178
|
-
@group(2) @binding(1) var<uniform>
|
|
179
|
-
@group(2) @binding(2) var<uniform>
|
|
188
|
+
@group(2) @binding(1) var<uniform> paletteUniform : array<mat4x4<f32>, 255>;
|
|
189
|
+
@group(2) @binding(2) var<uniform> previousPaletteUniform : array<mat4x4<f32>, 255>;
|
|
180
190
|
#endif
|
|
181
191
|
|
|
192
|
+
fn skinPalette(index : u32) -> mat4x4<f32> {
|
|
193
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
194
|
+
return paletteStorage[index];
|
|
195
|
+
#else
|
|
196
|
+
return paletteUniform[index];
|
|
197
|
+
#endif
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
fn previousSkinPalette(index : u32) -> mat4x4<f32> {
|
|
201
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
202
|
+
return previousPaletteStorage[index];
|
|
203
|
+
#else
|
|
204
|
+
return previousPaletteUniform[index];
|
|
205
|
+
#endif
|
|
206
|
+
}
|
|
207
|
+
|
|
182
208
|
struct VsIn {
|
|
183
209
|
@location(0) pos : vec3<f32>,
|
|
184
210
|
@location(1) normal : vec3<f32>,
|
|
@@ -232,8 +258,7 @@ fn pick_channel(rgba : vec4<f32>, channelIndex : u32) -> f32 {
|
|
|
232
258
|
}
|
|
233
259
|
}
|
|
234
260
|
|
|
235
|
-
|
|
236
|
-
fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
261
|
+
fn vs_main_impl(in : VsIn, idx : u32) -> VsOut {
|
|
237
262
|
// 4-bone weighted skinning (plan-strategy D-3 / D-3a).
|
|
238
263
|
// The host pre-computes each joint matrix as worldFromJoint * inverseBindMatrix
|
|
239
264
|
// (CPU-side pre-multiplication, per D-4) and writes them into the palette
|
|
@@ -245,10 +270,10 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
245
270
|
// The host sets the BindGroup dynamic offset to (byteOffset / 64) so the
|
|
246
271
|
// first palette entry visible to this draw is palette[0]. The shader
|
|
247
272
|
// indexes into palette directly using the per-vertex skinIndex values.
|
|
248
|
-
let skinMatrix =
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
273
|
+
let skinMatrix = skinPalette(in.skinIndex.x) * in.skinWeight.x +
|
|
274
|
+
skinPalette(in.skinIndex.y) * in.skinWeight.y +
|
|
275
|
+
skinPalette(in.skinIndex.z) * in.skinWeight.z +
|
|
276
|
+
skinPalette(in.skinIndex.w) * in.skinWeight.w;
|
|
252
277
|
|
|
253
278
|
// glTF 2.0 sec.Skins Implementation Note: when a mesh node has a skin
|
|
254
279
|
// property, the joint matrices already encode the global transform of each
|
|
@@ -260,7 +285,7 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
260
285
|
// skinnedLocal IS the world position -- no additional left-multiply by
|
|
261
286
|
// meshes[0].worldFromLocal or instanceLocal is needed.
|
|
262
287
|
//
|
|
263
|
-
// This removes the implicit contract "Skin entity
|
|
288
|
+
// This removes the implicit contract "Skin entity GlobalTransform.world must be
|
|
264
289
|
// identity" -- a skin entity can be parented under any Transform chain and
|
|
265
290
|
// the skinned mesh will rigidly follow via joint propagation alone.
|
|
266
291
|
let skinnedLocal = skinMatrix * vec4<f32>(in.pos, 1.0);
|
|
@@ -312,6 +337,16 @@ fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
|
312
337
|
return out;
|
|
313
338
|
}
|
|
314
339
|
|
|
340
|
+
@vertex
|
|
341
|
+
fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
342
|
+
return vs_main_impl(in, idx);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
@vertex
|
|
346
|
+
fn vs_scene_index(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
|
|
347
|
+
return vs_main_impl(in, idx);
|
|
348
|
+
}
|
|
349
|
+
|
|
315
350
|
fn transformedMaterialUv(transform : vec4<f32>, metadata : vec4<f32>, in : VsOut) -> vec2<f32> {
|
|
316
351
|
var source = in.uv;
|
|
317
352
|
if (metadata.x >= 1.0) { source = in.uv1; }
|
|
@@ -383,16 +418,34 @@ fn fs_main(in : VsOut) -> @location(0) vec4<f32> {
|
|
|
383
418
|
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
384
419
|
);
|
|
385
420
|
let skyColor = vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB);
|
|
421
|
+
let skyFactor = skyColor * skylight.intensity;
|
|
386
422
|
var ambient = (kD * irradiance * albedo + specularIbl) * (vec3<f32>(1.0) - coatF);
|
|
423
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
424
|
+
// group(3) is the per-object bind group; record zero is the object selected
|
|
425
|
+
// by this draw, independent of instance count.
|
|
426
|
+
let probeShPreblend = array<vec4<f32>, 9>(
|
|
427
|
+
probeBlendRecords[1], probeBlendRecords[2], probeBlendRecords[3],
|
|
428
|
+
probeBlendRecords[4], probeBlendRecords[5], probeBlendRecords[6],
|
|
429
|
+
probeBlendRecords[7], probeBlendRecords[8], probeBlendRecords[9],
|
|
430
|
+
);
|
|
431
|
+
let probeLocalBlendFraction = probeBlendRecords[0].z;
|
|
432
|
+
let probeDiffuseK = kD / max(vec3<f32>(1.0 - metallic), vec3<f32>(0.0001));
|
|
433
|
+
let probeDiffuse = evaluateProbeDiffuse(probeShPreblend, probeLocalBlendFraction, n, irradiance * skyFactor, probeDiffuseK, albedo, metallic);
|
|
434
|
+
ambient = (probeDiffuse + specularIbl * skyFactor) * (vec3<f32>(1.0) - coatF);
|
|
435
|
+
#endif
|
|
387
436
|
if (material.clearcoat != 0.0) {
|
|
388
437
|
let clearcoatIbl = sampleIblSpecular(
|
|
389
438
|
n, v, coatRoughness, vec3<f32>(0.04),
|
|
390
439
|
skylight.rotation,
|
|
391
440
|
prefilterMap, prefilterSampler, brdfLut, brdfLutSampler,
|
|
392
441
|
);
|
|
393
|
-
ambient = ambient + clearcoatIbl * material.clearcoat;
|
|
442
|
+
ambient = ambient + clearcoatIbl * material.clearcoat * skyFactor;
|
|
394
443
|
}
|
|
395
|
-
|
|
444
|
+
#ifdef PROBE_BLEND_AVAILABLE
|
|
445
|
+
ambient = ambient;
|
|
446
|
+
#else
|
|
447
|
+
ambient = ambient * skyFactor;
|
|
448
|
+
#endif
|
|
396
449
|
var color = ambient;
|
|
397
450
|
let directionalShadow = evalDirectionalShadowFactor(n, in.worldPos, in.viewZ);
|
|
398
451
|
let directionalBase = evalDirectionalNoShadow(n, v, albedo, metallic, a, f0);
|
|
@@ -437,14 +490,14 @@ struct TemporalVsOut {
|
|
|
437
490
|
|
|
438
491
|
@vertex
|
|
439
492
|
fn vs_temporal(in : VsIn, @builtin(instance_index) idx : u32) -> TemporalVsOut {
|
|
440
|
-
let currentSkin =
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
let previousSkin =
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
493
|
+
let currentSkin = skinPalette(in.skinIndex.x) * in.skinWeight.x +
|
|
494
|
+
skinPalette(in.skinIndex.y) * in.skinWeight.y +
|
|
495
|
+
skinPalette(in.skinIndex.z) * in.skinWeight.z +
|
|
496
|
+
skinPalette(in.skinIndex.w) * in.skinWeight.w;
|
|
497
|
+
let previousSkin = previousSkinPalette(in.skinIndex.x) * in.skinWeight.x +
|
|
498
|
+
previousSkinPalette(in.skinIndex.y) * in.skinWeight.y +
|
|
499
|
+
previousSkinPalette(in.skinIndex.z) * in.skinWeight.z +
|
|
500
|
+
previousSkinPalette(in.skinIndex.w) * in.skinWeight.w;
|
|
448
501
|
let currentWorld = currentSkin * vec4<f32>(in.pos, 1.0);
|
|
449
502
|
let previousWorld = previousSkin * vec4<f32>(in.pos, 1.0);
|
|
450
503
|
var out : TemporalVsOut;
|
|
@@ -481,6 +534,10 @@ fn temporalVertexAlpha(in : TemporalVsOut) -> f32 {
|
|
|
481
534
|
|
|
482
535
|
@fragment
|
|
483
536
|
fn fs_temporal(in : TemporalVsOut) -> @location(0) vec4<f32> {
|
|
537
|
+
var reactive = 0.0;
|
|
538
|
+
#ifdef STORAGE_BUFFER_AVAILABLE
|
|
539
|
+
reactive = meshes[0].temporal.x;
|
|
540
|
+
#endif
|
|
484
541
|
return projectPbrSceneTemporal(
|
|
485
542
|
material.baseColor.a * temporalVertexAlpha(in),
|
|
486
543
|
material.alphaCutoff,
|