reze-engine 0.61.4 → 0.61.6
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/dist/engine.d.ts +69 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +310 -36
- package/dist/graph/presets/pool_floor.d.ts +3 -0
- package/dist/graph/presets/pool_floor.d.ts.map +1 -0
- package/dist/graph/presets/pool_floor.js +42 -0
- package/dist/graph/presets/water.d.ts +3 -0
- package/dist/graph/presets/water.d.ts.map +1 -0
- package/dist/graph/presets/water.js +31 -0
- package/dist/graph/registry.d.ts.map +1 -1
- package/dist/graph/registry.js +11 -0
- package/dist/graph/slots.js +2 -2
- package/dist/physics/autofit.d.ts +147 -0
- package/dist/physics/autofit.d.ts.map +1 -0
- package/dist/physics/autofit.js +501 -0
- package/dist/shaders/directives.d.ts +9 -0
- package/dist/shaders/directives.d.ts.map +1 -1
- package/dist/shaders/directives.js +5 -0
- package/dist/shaders/materials/common.js +5 -5
- package/dist/shaders/materials/nodes.d.ts +1 -1
- package/dist/shaders/materials/nodes.d.ts.map +1 -1
- package/dist/shaders/materials/nodes.js +12 -0
- package/dist/shaders/passes/field-blit.d.ts +26 -0
- package/dist/shaders/passes/field-blit.d.ts.map +1 -0
- package/dist/shaders/passes/field-blit.js +65 -0
- package/dist/shaders/passes/ghosts.d.ts +22 -0
- package/dist/shaders/passes/ghosts.d.ts.map +1 -0
- package/dist/shaders/passes/ghosts.js +75 -0
- package/dist/shaders/passes/ground-noise.d.ts +7 -0
- package/dist/shaders/passes/ground-noise.d.ts.map +1 -0
- package/dist/shaders/passes/ground-noise.js +88 -0
- package/dist/shaders/passes/particles.js +6 -6
- package/dist/shaders/passes/scene-contract.js +1 -1
- package/dist/shaders/passes/sim.d.ts +34 -0
- package/dist/shaders/passes/sim.d.ts.map +1 -0
- package/dist/shaders/passes/sim.js +169 -0
- package/dist/shaders/passes/subsurface.d.ts +34 -0
- package/dist/shaders/passes/subsurface.d.ts.map +1 -0
- package/dist/shaders/passes/subsurface.js +134 -0
- package/dist/shaders/score-api.d.ts +10 -0
- package/dist/shaders/score-api.d.ts.map +1 -0
- package/dist/shaders/score-api.js +114 -0
- package/dist/shaders/shadow-api.d.ts +29 -0
- package/dist/shaders/shadow-api.d.ts.map +1 -0
- package/dist/shaders/shadow-api.js +112 -0
- package/package.json +1 -1
- package/src/engine.ts +309 -26
- package/src/graph/registry.ts +11 -0
- package/src/graph/slots.ts +2 -2
- package/src/shaders/directives.ts +14 -0
- package/src/shaders/materials/common.ts +5 -5
- package/src/shaders/materials/nodes.ts +12 -0
- package/src/shaders/passes/particles.ts +6 -6
- package/src/shaders/passes/scene-contract.ts +1 -1
- package/src/shaders/passes/subsurface.ts +136 -0
- package/dist/_dbg-loader.mjs +0 -1100
- package/dist/physics-debug.d.ts +0 -30
- package/dist/physics-debug.d.ts.map +0 -1
- package/dist/physics-debug.js +0 -526
- package/dist/shaders/materials/body.d.ts +0 -2
- package/dist/shaders/materials/body.d.ts.map +0 -1
- package/dist/shaders/materials/body.js +0 -95
- package/dist/shaders/materials/cloth_rough.d.ts +0 -2
- package/dist/shaders/materials/cloth_rough.d.ts.map +0 -1
- package/dist/shaders/materials/cloth_rough.js +0 -69
- package/dist/shaders/materials/cloth_smooth.d.ts +0 -2
- package/dist/shaders/materials/cloth_smooth.d.ts.map +0 -1
- package/dist/shaders/materials/cloth_smooth.js +0 -61
- package/dist/shaders/materials/default.d.ts +0 -2
- package/dist/shaders/materials/default.d.ts.map +0 -1
- package/dist/shaders/materials/default.js +0 -43
- package/dist/shaders/materials/eye.d.ts +0 -2
- package/dist/shaders/materials/eye.d.ts.map +0 -1
- package/dist/shaders/materials/eye.js +0 -60
- package/dist/shaders/materials/face.d.ts +0 -2
- package/dist/shaders/materials/face.d.ts.map +0 -1
- package/dist/shaders/materials/face.js +0 -95
- package/dist/shaders/materials/hair.d.ts +0 -2
- package/dist/shaders/materials/hair.d.ts.map +0 -1
- package/dist/shaders/materials/hair.js +0 -90
- package/dist/shaders/materials/metal.d.ts +0 -2
- package/dist/shaders/materials/metal.d.ts.map +0 -1
- package/dist/shaders/materials/metal.js +0 -77
- package/dist/shaders/materials/mmd_classic.d.ts +0 -2
- package/dist/shaders/materials/mmd_classic.d.ts.map +0 -1
- package/dist/shaders/materials/mmd_classic.js +0 -66
- package/dist/shaders/materials/stockings.d.ts +0 -2
- package/dist/shaders/materials/stockings.d.ts.map +0 -1
- package/dist/shaders/materials/stockings.js +0 -122
- package/dist/shaders/passes/physics-debug.d.ts +0 -2
- package/dist/shaders/passes/physics-debug.d.ts.map +0 -1
- package/dist/shaders/passes/physics-debug.js +0 -69
|
@@ -391,13 +391,13 @@ struct FSOut {
|
|
|
391
391
|
// writes it; a blended one writes all four, which is what not declaring it
|
|
392
392
|
// would have meant.
|
|
393
393
|
@builtin(sample_mask) samples: u32,
|
|
394
|
-
// The scene's aux target: (bloom mask, coverage). Materials write
|
|
395
|
-
// particle that skipped it would punch a hole in the mask of whatever
|
|
396
|
-
// over.
|
|
394
|
+
// The scene's aux target: (bloom mask, coverage, subsurface). Materials write
|
|
395
|
+
// it, so a particle that skipped it would punch a hole in the mask of whatever
|
|
396
|
+
// it drew over. A particle is never skin, so its .b is 0.
|
|
397
397
|
//
|
|
398
|
-
// vec4f
|
|
399
|
-
//
|
|
400
|
-
//
|
|
398
|
+
// vec4f because that target's blend factors reference SrcAlpha, and a fragment
|
|
399
|
+
// with no alpha channel is rejected outright — "reading alpha but it is
|
|
400
|
+
// missing from fragment output".
|
|
401
401
|
// The material shaders declare vec4f here for the same reason.
|
|
402
402
|
@location(1) mask: vec4f,
|
|
403
403
|
// Declared whenever the pass carries the attachment, and padded rather than
|
|
@@ -127,7 +127,7 @@ const ADD_KEEP_ALPHA: GPUBlendState = {
|
|
|
127
127
|
alpha: { srcFactor: "zero", dstFactor: "one", operation: "add" },
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
/** Both channels sum.
|
|
130
|
+
/** Both channels sum. rgba8unorm clamps at 1, which is the saturation alpha-over
|
|
131
131
|
* would have reached anyway. */
|
|
132
132
|
const ADD_BOTH: GPUBlendState = {
|
|
133
133
|
color: { srcFactor: "one", dstFactor: "one", operation: "add" },
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screen-space subsurface scattering — ray-mmd's skin pass (PostProcessScattering.fxsub,
|
|
3
|
+
* SSSGaussBlurPS), ported constant for constant.
|
|
4
|
+
*
|
|
5
|
+
* A skin surface is not shaded by the light at its own pixel alone: light that
|
|
6
|
+
* enters a little way off comes back out here, red furthest. ray-mmd models that
|
|
7
|
+
* as a separable blur of the lit skin in screen space, one axis per pass, with a
|
|
8
|
+
* per-channel Gaussian (red widest) and a depth reject so light never crosses from
|
|
9
|
+
* a forearm onto the body behind it. The width is a length ON THE SURFACE, so it
|
|
10
|
+
* is divided by depth, and it narrows where the surface turns away from the view.
|
|
11
|
+
* Then a share of the unblurred picture is laid back over it — the "spike" that
|
|
12
|
+
* keeps pores, painted lines and the terminator from dissolving.
|
|
13
|
+
*
|
|
14
|
+
* What marks a pixel as skin is the scene pass's aux .b, written by the graph's
|
|
15
|
+
* `subsurface` node (0 everywhere else), as a quarter of its strength. The strength
|
|
16
|
+
* scales the radius, as ray-mmd's sssStrength does; 1 is ray-mmd's skin, 4 the most.
|
|
17
|
+
*
|
|
18
|
+
* One departure, and it is a routing one: ray-mmd blurs the lit colour BEFORE the
|
|
19
|
+
* albedo multiply and adds specular after. This engine resolves one HDR colour per
|
|
20
|
+
* pixel, so the blur runs over the finished colour. At this radius — a few pixels,
|
|
21
|
+
* with the spike keeping 14–20% of the original — the texture is not visibly
|
|
22
|
+
* softened; the lighting is.
|
|
23
|
+
*
|
|
24
|
+
* Two entry points share the module: X reads the HDR resolve and writes the
|
|
25
|
+
* scratch target, Y reads the scratch and writes back INTO the HDR resolve. The
|
|
26
|
+
* spike mix (lerp toward the original) is done by the Y pipeline's blend state,
|
|
27
|
+
* with the blend constant holding ray-mmd's per-channel spike: the destination IS
|
|
28
|
+
* the original, so no third copy of the frame is needed.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** ray-mmd, skin profile (index 1): profileSpikeRadArr[1].xyz × (1 − sssAmount),
|
|
32
|
+
* with sssAmount = customA = 0.6 in Materials/Skin/material_skin.fx. */
|
|
33
|
+
export const SSS_SPIKE: [number, number, number] = [0.35 * 0.4, 0.4 * 0.4, 0.5 * 0.4]
|
|
34
|
+
|
|
35
|
+
export const SUBSURFACE_WGSL = /* wgsl */ `
|
|
36
|
+
@group(0) @binding(0) var srcTex: texture_2d<f32>;
|
|
37
|
+
@group(0) @binding(1) var maskTex: texture_2d<f32>;
|
|
38
|
+
@group(0) @binding(2) var depthTex: texture_depth_multisampled_2d;
|
|
39
|
+
// dofU[2] = (projA, projB): the same z-buffer inversion the composite uses.
|
|
40
|
+
@group(0) @binding(3) var<uniform> dofU: array<vec4f, 3>;
|
|
41
|
+
// sssU[0] = (direction.xy, radius, _); sssU[1] = (tanHalfFov·aspect, tanHalfFov, width, height).
|
|
42
|
+
@group(0) @binding(4) var<uniform> sssU: array<vec4f, 2>;
|
|
43
|
+
|
|
44
|
+
struct VsOut { @builtin(position) pos: vec4f };
|
|
45
|
+
|
|
46
|
+
@vertex fn vs(@builtin(vertex_index) i: u32) -> VsOut {
|
|
47
|
+
let p = vec2f(f32((i << 1u) & 2u), f32(i & 2u));
|
|
48
|
+
var o: VsOut;
|
|
49
|
+
o.pos = vec4f(p * 2.0 - 1.0, 0.0, 1.0);
|
|
50
|
+
return o;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fn size() -> vec2i { return vec2i(sssU[1].zw); }
|
|
54
|
+
|
|
55
|
+
fn texel(uv: vec2f) -> vec2i {
|
|
56
|
+
return clamp(vec2i(floor(uv * sssU[1].zw)), vec2i(0), size() - 1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn linearDepth(c: vec2i) -> f32 {
|
|
60
|
+
let z = textureLoad(depthTex, c, 0);
|
|
61
|
+
return clamp(dofU[2].y / (z - dofU[2].x), 0.05, 100000.0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// View-space position of a texel centre — ray-mmd's GetViewPosition, with y up.
|
|
65
|
+
fn viewPos(c: vec2i, d: f32) -> vec3f {
|
|
66
|
+
let uv = (vec2f(c) + 0.5) / sssU[1].zw;
|
|
67
|
+
let ndc = vec2f(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0);
|
|
68
|
+
return vec3f(ndc * sssU[1].xy * d, d);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
fn skin(c: vec2i) -> f32 { return textureLoad(maskTex, c, 0).b; }
|
|
72
|
+
|
|
73
|
+
fn blur(fragPos: vec4f) -> vec4f {
|
|
74
|
+
let c = vec2i(fragPos.xy);
|
|
75
|
+
let amount = skin(c) * 4.0;
|
|
76
|
+
let dir = sssU[0].xy;
|
|
77
|
+
let uv = (vec2f(c) + 0.5) / sssU[1].zw;
|
|
78
|
+
let centre = textureLoad(srcTex, c, 0);
|
|
79
|
+
|
|
80
|
+
// ray-mmd, verbatim: six offsets, and the skin variances per channel.
|
|
81
|
+
// A var, not a const: a const array cannot be indexed by the loop counter.
|
|
82
|
+
var offsets = array<f32, 6>(0.352, 0.719, 1.117, 1.579, 2.177, 3.213);
|
|
83
|
+
const profileVar = vec3f(9.6, 2.8, 2.2);
|
|
84
|
+
// mSSSSScale at the controller's default; it sets both the width and how hard
|
|
85
|
+
// a depth step rejects.
|
|
86
|
+
const SSSS_SCALE: f32 = 0.04;
|
|
87
|
+
|
|
88
|
+
let d = linearDepth(c);
|
|
89
|
+
|
|
90
|
+
// The surface's normal, rebuilt from depth (ray-mmd reads it from its G-buffer;
|
|
91
|
+
// this engine keeps none). Only its angle to the view matters: the blur narrows
|
|
92
|
+
// along an axis the surface is turning away on.
|
|
93
|
+
let s = size();
|
|
94
|
+
let cx = min(c + vec2i(1, 0), s - 1);
|
|
95
|
+
let cy = min(c + vec2i(0, 1), s - 1);
|
|
96
|
+
let P = viewPos(c, d);
|
|
97
|
+
let N = cross(viewPos(cx, linearDepth(cx)) - P, viewPos(cy, linearDepth(cy)) - P);
|
|
98
|
+
let nxz = select(vec2f(0.0, 1.0), normalize(N.xz), dot(N.xz, N.xz) > 1e-12);
|
|
99
|
+
let nyz = select(vec2f(0.0, 1.0), normalize(N.yz), dot(N.yz, N.yz) > 1e-12);
|
|
100
|
+
let scaleX = abs(dot(nxz, normalize(P.xz)));
|
|
101
|
+
let scaleY = abs(dot(nyz, normalize(P.yz)));
|
|
102
|
+
let perspectiveScale = max(dot(dir, vec2f(scaleX, scaleY)), 0.3);
|
|
103
|
+
|
|
104
|
+
let radius = 0.0055 * amount * perspectiveScale / SSSS_SCALE;
|
|
105
|
+
let step = dir * radius / d;
|
|
106
|
+
|
|
107
|
+
var weightSum = vec3f(1.0);
|
|
108
|
+
var colour = centre.rgb;
|
|
109
|
+
for (var i = 0; i < 6; i++) {
|
|
110
|
+
let o = offsets[i] / 5.5 * step;
|
|
111
|
+
for (var side = 0; side < 2; side++) {
|
|
112
|
+
let tc = texel(select(uv - o, uv + o, side == 0));
|
|
113
|
+
// Skin only: ray-mmd zeroes a non-skin pixel's depth so the depth term
|
|
114
|
+
// rejects it; the mask says the same thing directly.
|
|
115
|
+
let isSkin = select(0.0, 1.0, skin(tc) > 0.004);
|
|
116
|
+
let dd = (linearDepth(tc) - d) * 1000.0 * SSSS_SCALE;
|
|
117
|
+
let w = exp(-(offsets[i] * offsets[i] + dd * dd) / profileVar) * isSkin;
|
|
118
|
+
weightSum += w;
|
|
119
|
+
colour += w * textureLoad(srcTex, tc, 0).rgb;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return vec4f(colour / weightSum, centre.a);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@fragment fn fsX(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
126
|
+
// Nothing reads the scratch target off skin: the Y pass rejects those taps.
|
|
127
|
+
if (skin(vec2i(pos.xy)) <= 0.004) { return vec4f(0.0); }
|
|
128
|
+
return blur(pos);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@fragment fn fsY(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
132
|
+
// Off skin the HDR resolve must stay exactly as the scene left it.
|
|
133
|
+
if (skin(vec2i(pos.xy)) <= 0.004) { discard; }
|
|
134
|
+
return blur(pos);
|
|
135
|
+
}
|
|
136
|
+
`
|