reze-engine 0.62.1 → 0.64.0
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 +95 -57
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +466 -162
- package/dist/graph/compile.d.ts.map +1 -1
- package/dist/graph/compile.js +4 -1
- package/dist/graph/registry.d.ts +3 -0
- package/dist/graph/registry.d.ts.map +1 -1
- package/dist/graph/registry.js +133 -0
- package/dist/graph/schema.d.ts +12 -0
- package/dist/graph/schema.d.ts.map +1 -1
- package/dist/graph/slots.d.ts.map +1 -1
- package/dist/graph/slots.js +11 -20
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/shaders/lights.d.ts +3 -2
- package/dist/shaders/lights.d.ts.map +1 -1
- package/dist/shaders/lights.js +16 -3
- package/dist/shaders/materials/common.d.ts.map +1 -1
- package/dist/shaders/materials/common.js +63 -56
- 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 +210 -0
- package/dist/shaders/passes/composite.d.ts.map +1 -1
- package/dist/shaders/passes/composite.js +13 -1
- package/dist/shaders/passes/cull.d.ts +1 -1
- package/dist/shaders/passes/cull.d.ts.map +1 -1
- package/dist/shaders/passes/cull.js +7 -3
- package/dist/shaders/passes/ground.d.ts.map +1 -1
- package/dist/shaders/passes/ground.js +32 -55
- package/dist/shaders/passes/particles.d.ts +11 -1
- package/dist/shaders/passes/particles.d.ts.map +1 -1
- package/dist/shaders/passes/particles.js +9 -4
- package/dist/shaders/scene-light-api.d.ts +18 -10
- package/dist/shaders/scene-light-api.d.ts.map +1 -1
- package/dist/shaders/scene-light-api.js +58 -46
- package/dist/shadow-cascades.d.ts +47 -20
- package/dist/shadow-cascades.d.ts.map +1 -1
- package/dist/shadow-cascades.js +36 -13
- package/dist/unity/character.d.ts +59 -0
- package/dist/unity/character.d.ts.map +1 -0
- package/dist/unity/character.js +120 -0
- package/dist/unity/globals.d.ts +93 -0
- package/dist/unity/globals.d.ts.map +1 -0
- package/dist/unity/globals.js +340 -0
- package/dist/unity/host.d.ts +137 -0
- package/dist/unity/host.d.ts.map +1 -0
- package/dist/unity/host.js +489 -0
- package/dist/unity/looks.d.ts +88 -0
- package/dist/unity/looks.d.ts.map +1 -0
- package/dist/unity/looks.js +295 -0
- package/dist/unity/skin.d.ts +9 -0
- package/dist/unity/skin.d.ts.map +1 -0
- package/dist/unity/skin.js +117 -0
- package/dist/unity/stage.d.ts +148 -0
- package/dist/unity/stage.d.ts.map +1 -0
- package/dist/unity/stage.js +375 -0
- package/dist/unity/state.d.ts +22 -0
- package/dist/unity/state.d.ts.map +1 -0
- package/dist/unity/state.js +170 -0
- package/package.json +1 -1
- package/src/engine.ts +504 -176
- package/src/graph/compile.ts +3 -1
- package/src/graph/registry.ts +142 -0
- package/src/graph/schema.ts +9 -0
- package/src/graph/slots.ts +11 -20
- package/src/index.ts +11 -0
- package/src/shaders/lights.ts +16 -3
- package/src/shaders/materials/common.ts +63 -57
- package/src/shaders/materials/nodes.ts +210 -0
- package/src/shaders/passes/composite.ts +13 -1
- package/src/shaders/passes/cull.ts +7 -3
- package/src/shaders/passes/ground.ts +32 -55
- package/src/shaders/passes/particles.ts +19 -5
- package/src/shaders/scene-light-api.ts +59 -46
- package/src/shadow-cascades.ts +61 -32
- package/src/unity/character.ts +169 -0
- package/src/unity/globals.ts +443 -0
- package/src/unity/host.ts +587 -0
- package/src/unity/looks.ts +372 -0
- package/src/unity/skin.ts +128 -0
- package/src/unity/stage.ts +568 -0
- package/src/unity/state.ts +172 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// The game pipeline's per-frame globals, computed from the engine's scene.
|
|
2
|
+
//
|
|
3
|
+
// The game's shaders read what its render pipeline (UnityEngine.Rendering.
|
|
4
|
+
// Replica / ReplicaExt, decompiled from GameAssembly.dll) sets before a camera
|
|
5
|
+
// renders: the camera, the main light, the Forward+ light table and its bins,
|
|
6
|
+
// the cascades, the ambient SH, fog, time. ag-rip's AGSimPipeline.cs and
|
|
7
|
+
// AGSimShadows.cs reproduce those calls in Unity, method by method, and the
|
|
8
|
+
// compare page proved them against the game's frames; this is that code again,
|
|
9
|
+
// fed by the engine instead of by a Unity scene.
|
|
10
|
+
//
|
|
11
|
+
// SPACE. The game's shaders work in the game's world, and the engine's scene
|
|
12
|
+
// is that world as ag-rip exports it to MMD: `scale` PMX units per game unit
|
|
13
|
+
// (8: the one-scene-scale rule) and turned half round Y — game (x, y, z) is
|
|
14
|
+
// PMX (-x, y, -z), the convention its camera and motion VMDs and its stages
|
|
15
|
+
// share. Everything positional is handed over through that map (gameToEngine
|
|
16
|
+
// and back) — the camera, the lights and their reach, the cascades — so a
|
|
17
|
+
// shader's distances (outline widths, light ranges, fog) and directions mean
|
|
18
|
+
// what they meant in the game. A half turn keeps handedness: both are
|
|
19
|
+
// left-handed and Y-up.
|
|
20
|
+
//
|
|
21
|
+
// CLIP SPACE. naga negates y on the way out of every vertex shader (Vulkan to
|
|
22
|
+
// WebGPU), so the projection handed to the shaders is the engine's with y
|
|
23
|
+
// flipped: the two flips cancel and a native draw lands exactly where the
|
|
24
|
+
// engine's own draw of the same triangle would, on the same depth.
|
|
25
|
+
const PLUS_MAX = 255;
|
|
26
|
+
/** Column-major 4x4 multiply. */
|
|
27
|
+
export function mul4(a, b) {
|
|
28
|
+
const o = new Float32Array(16);
|
|
29
|
+
for (let c = 0; c < 4; c++)
|
|
30
|
+
for (let r = 0; r < 4; r++) {
|
|
31
|
+
let s = 0;
|
|
32
|
+
for (let k = 0; k < 4; k++)
|
|
33
|
+
s += a[k * 4 + r] * b[c * 4 + k];
|
|
34
|
+
o[c * 4 + r] = s;
|
|
35
|
+
}
|
|
36
|
+
return o;
|
|
37
|
+
}
|
|
38
|
+
export function invert4(m) {
|
|
39
|
+
const a = m;
|
|
40
|
+
const o = new Float32Array(16);
|
|
41
|
+
const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
|
|
42
|
+
const a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
|
43
|
+
const b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10;
|
|
44
|
+
const b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12;
|
|
45
|
+
const b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30;
|
|
46
|
+
const b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32;
|
|
47
|
+
let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
48
|
+
if (!det)
|
|
49
|
+
return Float32Array.from([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
|
50
|
+
det = 1 / det;
|
|
51
|
+
o[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
|
52
|
+
o[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
|
53
|
+
o[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
|
54
|
+
o[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
|
|
55
|
+
o[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
|
56
|
+
o[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
|
57
|
+
o[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
|
58
|
+
o[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
|
|
59
|
+
o[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
|
60
|
+
o[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
|
61
|
+
o[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
|
62
|
+
o[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
|
|
63
|
+
o[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
|
|
64
|
+
o[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
|
|
65
|
+
o[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
|
|
66
|
+
o[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
|
|
67
|
+
return o;
|
|
68
|
+
}
|
|
69
|
+
/** Game world -> engine world: `s` PMX per unit, half a turn about Y. */
|
|
70
|
+
export function gameToEngine(s) {
|
|
71
|
+
return Float32Array.from([-s, 0, 0, 0, 0, s, 0, 0, 0, 0, -s, 0, 0, 0, 0, 1]);
|
|
72
|
+
}
|
|
73
|
+
/** Engine world -> game world. */
|
|
74
|
+
export function engineToGame(s) {
|
|
75
|
+
return Float32Array.from([-1 / s, 0, 0, 0, 0, 1 / s, 0, 0, 0, 0, -1 / s, 0, 0, 0, 0, 1]);
|
|
76
|
+
}
|
|
77
|
+
/** An engine point in the game's world. */
|
|
78
|
+
export function gamePoint(p, s) {
|
|
79
|
+
return [-p[0] / s, p[1] / s, -p[2] / s];
|
|
80
|
+
}
|
|
81
|
+
/** An engine direction in the game's world. */
|
|
82
|
+
export function gameDir(d) {
|
|
83
|
+
return [-d[0], d[1], -d[2]];
|
|
84
|
+
}
|
|
85
|
+
/** Uniform scale, as a column-major matrix. */
|
|
86
|
+
export function scale4(s) {
|
|
87
|
+
return Float32Array.from([s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1]);
|
|
88
|
+
}
|
|
89
|
+
/** The projection with clip y negated — undone by naga's own negation. */
|
|
90
|
+
export function flipY(p) {
|
|
91
|
+
const o = Float32Array.from(p);
|
|
92
|
+
for (let c = 0; c < 4; c++)
|
|
93
|
+
o[c * 4 + 1] = -p[c * 4 + 1];
|
|
94
|
+
return o;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The engine's folded SH9 (ibl.ts: c0 + c1·y + c2·z + c3·x + c4·xy + c5·yz +
|
|
98
|
+
* c6·(3z²−1) + c7·xz + c8·(x²−y²)) as Unity's seven shader constants —
|
|
99
|
+
* SHA = (x, y, z, constant), SHB = (xy, yz, z², zx), SHC = (x²−y²) — the same
|
|
100
|
+
* polynomial, regrouped.
|
|
101
|
+
*/
|
|
102
|
+
export function unitySH(sh, flat) {
|
|
103
|
+
const out = {};
|
|
104
|
+
const ch = ["r", "g", "b"];
|
|
105
|
+
const c = (i, k) => (sh ? sh[i * 3 + k] : i === 0 ? flat[k] : 0);
|
|
106
|
+
for (let k = 0; k < 3; k++) {
|
|
107
|
+
out[`_Replica_SHA${ch[k]}`] = [c(3, k), c(1, k), c(2, k), c(0, k) - c(6, k)];
|
|
108
|
+
out[`_Replica_SHB${ch[k]}`] = [c(4, k), c(5, k), 3 * c(6, k), c(7, k)];
|
|
109
|
+
}
|
|
110
|
+
out._Replica_SHC = [c(8, 0), c(8, 1), c(8, 2), 1];
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
/** Everything the frame sets, by name. */
|
|
114
|
+
export function unityFrameGlobals(f) {
|
|
115
|
+
const s = f.scale;
|
|
116
|
+
const g = {};
|
|
117
|
+
// ---- the camera (UnityPerFrame), in game units
|
|
118
|
+
// Unity's own pair, so what a shader rebuilds from them means what it did
|
|
119
|
+
// in the game: the view in game units, right-handed and looking down -Z;
|
|
120
|
+
// the projection on game-unit depths (the engine's, conjugated by the scale
|
|
121
|
+
// and the z flip, and divided through by s, which leaves the same NDC). Their
|
|
122
|
+
// product puts every vertex exactly where the engine's own draw of it lands.
|
|
123
|
+
const zFlip = Float32Array.from([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1]);
|
|
124
|
+
const view = mul4(zFlip, mul4(scale4(1 / s), mul4(f.view, gameToEngine(s))));
|
|
125
|
+
const toEngineView = mul4(scale4(s), zFlip);
|
|
126
|
+
const proj = flipY(mul4(f.proj, toEngineView));
|
|
127
|
+
for (let i = 0; i < 16; i++)
|
|
128
|
+
proj[i] /= s;
|
|
129
|
+
const vp = mul4(proj, view);
|
|
130
|
+
const w = Math.max(1, f.width);
|
|
131
|
+
const h = Math.max(1, f.height);
|
|
132
|
+
const near = f.near / s;
|
|
133
|
+
const far = f.far / s;
|
|
134
|
+
g._WorldSpaceCameraPos = [...gamePoint(f.eye, s), 1];
|
|
135
|
+
g.unity_MatrixV = view;
|
|
136
|
+
g.unity_MatrixInvV = invert4(view);
|
|
137
|
+
g.unity_MatrixP = proj;
|
|
138
|
+
g.glstate_matrix_projection = proj;
|
|
139
|
+
g.unity_MatrixVP = vp;
|
|
140
|
+
g._NonJitteredViewProjMatrix = vp;
|
|
141
|
+
// x = -1: a flipped projection, as Unity's into a texture.
|
|
142
|
+
g._ProjectionParams = [-1, near, far, 1 / far];
|
|
143
|
+
g._ScreenParams = [w, h, 1 + 1 / w, 1 + 1 / h];
|
|
144
|
+
g._ScaledScreenParams = [w, h, 1 + 1 / w, 1 + 1 / h];
|
|
145
|
+
g._ZBufferParams = [-1 + far / near, 1, (-1 + far / near) / far, 1 / far];
|
|
146
|
+
g.unity_OrthoParams = [0, 0, 0, 0];
|
|
147
|
+
const t = f.time;
|
|
148
|
+
g._Time = [t / 20, t, t * 2, t * 3];
|
|
149
|
+
g._SinTime = [Math.sin(t / 8), Math.sin(t / 4), Math.sin(t / 2), Math.sin(t)];
|
|
150
|
+
g._CosTime = [Math.cos(t / 8), Math.cos(t / 4), Math.cos(t / 2), Math.cos(t)];
|
|
151
|
+
const dt = Math.max(f.dt, 1e-4);
|
|
152
|
+
g.unity_DeltaTime = [dt, 1 / dt, dt, 1 / dt];
|
|
153
|
+
// UpdateRenderSettings: sim_Time = (t - floor t, floor t)
|
|
154
|
+
g.sim_Time = [t - Math.floor(t), Math.floor(t), 0, 0];
|
|
155
|
+
g.identity_matrix = scale4(1);
|
|
156
|
+
// ---- LightingFeatures.SetupLightings / PlusLighting SetupMainLightConstants
|
|
157
|
+
if (f.sunDirection) {
|
|
158
|
+
const d = gameDir(f.sunDirection);
|
|
159
|
+
g.SimMainLightDir = [-d[0], -d[1], -d[2], 0];
|
|
160
|
+
g.SimMainLightColor = [...f.sunColor, 1];
|
|
161
|
+
g.SimMainLightColorNoInt = [...f.sunColor, 1];
|
|
162
|
+
// As the game's pipeline leaves it (recorded): the way the light travels.
|
|
163
|
+
g._MainLightPosition = [d[0], d[1], d[2], 0];
|
|
164
|
+
g.sim_ShadowLightDirection = [-d[0], -d[1], -d[2], 0];
|
|
165
|
+
g._MainLightColor = [...f.sunColor, 1];
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
g.SimMainLightDir = [0, 0, 0, 0];
|
|
169
|
+
g.SimMainLightColor = [0, 0, 0, 0];
|
|
170
|
+
g.SimMainLightColorNoInt = [0, 0, 0, 0];
|
|
171
|
+
g._MainLightPosition = [0, 1, 0, 0];
|
|
172
|
+
g._MainLightColor = [0, 0, 0, 0];
|
|
173
|
+
}
|
|
174
|
+
// ---- ForwardFeature.SetupRenderFeature, UpdateRenderSettings: a scene
|
|
175
|
+
// with no stage of the game's has no settings of its own — the defaults the
|
|
176
|
+
// game's SceneSetting starts from.
|
|
177
|
+
g.SimSceneTint = [1, 1, 1, 1];
|
|
178
|
+
g._ReceiveSceneShadow = 1;
|
|
179
|
+
g.sim_FogRotation = 0;
|
|
180
|
+
g.sim_FogInverseRootRotationMatrix = scale4(1);
|
|
181
|
+
g.sim_FogColor = [0, 0, 0, 0];
|
|
182
|
+
g.sim_FogColor2 = [0, 0, 0, 0];
|
|
183
|
+
g.sim_FogParams = [0, 1, 0, 1];
|
|
184
|
+
g.sim_FogDirectionalColor = [0, 0, 0, 0];
|
|
185
|
+
g.sim_FogDirectionalDir = [0, 0, 1, 0];
|
|
186
|
+
g.sim_FogDirectionalFalloff = 0;
|
|
187
|
+
g.sim_DYN_FOG_LINEAR_Variable = 0;
|
|
188
|
+
g.sim_DynFogColor = [0, 0, 0, 0];
|
|
189
|
+
g.sim_DynFogParams = [0, 1, 0, 1];
|
|
190
|
+
g._ProbeLightingBase = [1, 1, 1, 1];
|
|
191
|
+
g._ProbeLightingScale = 0;
|
|
192
|
+
g._AcceptLightProbe = 0;
|
|
193
|
+
g.sim_VertexAmbientScale = 1;
|
|
194
|
+
g._EnableShadowScatter = 0;
|
|
195
|
+
g._ShadowScatterColor = [0, 0, 0, 0];
|
|
196
|
+
g._ShadowScatterRange = 0;
|
|
197
|
+
// realtimeShadowColor's default grey, made linear (ConvertSRGBToActiveColorSpace)
|
|
198
|
+
g._SubtractiveShadowColor = [0.2158605, 0.2158605, 0.2158605, 1];
|
|
199
|
+
g._AmbientOcclusionParam = [0, 0, 0, 0];
|
|
200
|
+
g.sim_EnvCubeScale = 0;
|
|
201
|
+
g.sim_EnvCube_BoxMin = [0, 0, 0, 0];
|
|
202
|
+
g.sim_EnvCube_BoxMax = [0, 0, 0, 0];
|
|
203
|
+
g.sim_EnvCube_ProbePosition = [0, 0, 0, 0];
|
|
204
|
+
// ---- SetupEnvironmentLighting: the scene's ambient SH
|
|
205
|
+
// The half turn negates x and z: the terms odd in either (z, x, xy, yz) flip.
|
|
206
|
+
const sh = f.ambientSH ? Array.from(f.ambientSH) : null;
|
|
207
|
+
if (sh)
|
|
208
|
+
for (const i of [2, 3, 4, 5])
|
|
209
|
+
for (let k = 0; k < 3; k++)
|
|
210
|
+
sh[i * 3 + k] = -sh[i * 3 + k];
|
|
211
|
+
Object.assign(g, unitySH(sh, f.ambientFlat));
|
|
212
|
+
// ---- a game stage's own settings over all of the above
|
|
213
|
+
if (f.settings)
|
|
214
|
+
Object.assign(g, f.settings);
|
|
215
|
+
// ---- PlusLightingFeature: the light table, one tile and one depth bin
|
|
216
|
+
// holding every light (binning only culls; the shader applies each range)
|
|
217
|
+
const n = Math.min(f.lights.length, PLUS_MAX);
|
|
218
|
+
const pos = [], col = [], att = [], dir = [];
|
|
219
|
+
const extra = [], w2l = [];
|
|
220
|
+
const simDir = [], simColorW = [];
|
|
221
|
+
const types = new Float32Array(PLUS_MAX);
|
|
222
|
+
const masks = new Uint32Array(PLUS_MAX);
|
|
223
|
+
const ident = scale4(1);
|
|
224
|
+
for (let i = 0; i < PLUS_MAX; i++) {
|
|
225
|
+
const l = f.lights[i];
|
|
226
|
+
if (i >= n || !l) {
|
|
227
|
+
pos.push([0, 0, 0, 0]);
|
|
228
|
+
col.push([0, 0, 0, 0]);
|
|
229
|
+
att.push([0, 1, 0, 1]);
|
|
230
|
+
dir.push([0, 0, 0, 0]);
|
|
231
|
+
extra.push([0, 0, 0, 0]);
|
|
232
|
+
w2l.push(ident);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const spot = l.aim[0] !== 0 || l.aim[1] !== 0 || l.aim[2] !== 0;
|
|
236
|
+
const r = l.radius / s;
|
|
237
|
+
const r2 = r * r;
|
|
238
|
+
// LightInfo.GetPunctualLightDistanceAttenuation / GetSpotAngleAttenuation
|
|
239
|
+
let z = 0;
|
|
240
|
+
let ww = 1;
|
|
241
|
+
if (spot) {
|
|
242
|
+
const inv = 1 / Math.max(l.cosInner - l.cosOuter, 0.001);
|
|
243
|
+
z = inv;
|
|
244
|
+
ww = -l.cosOuter * inv;
|
|
245
|
+
}
|
|
246
|
+
pos.push([...gamePoint(l.position, s), 1]);
|
|
247
|
+
// The engine's lamp brightness is per its own unit; the inverse square in
|
|
248
|
+
// game units is s² larger at the same place, so the colour carries 1/s².
|
|
249
|
+
col.push([l.color[0] / (s * s), l.color[1] / (s * s), l.color[2] / (s * s), 1]);
|
|
250
|
+
att.push([1 / Math.max(r2, 1e-4), -r2 / (r2 * 0.64 - r2), z, ww]);
|
|
251
|
+
const u = l.unity;
|
|
252
|
+
if (u) {
|
|
253
|
+
col[col.length - 1][3] = u.colorW;
|
|
254
|
+
dir.push(u.spotDir.slice(0, 4));
|
|
255
|
+
extra.push(u.extra.slice(0, 4));
|
|
256
|
+
w2l.push(u.worldToLight ? Float32Array.from(u.worldToLight) : ident);
|
|
257
|
+
simDir.push((u.simSpotDir ?? u.spotDir).slice(0, 4));
|
|
258
|
+
simColorW.push(u.simColorW ?? 1);
|
|
259
|
+
types[i] = u.lightType;
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
// The pipeline's own defaults for a light it did not author: forward
|
|
263
|
+
// along the aim, w = 1 / the 0.1 sphere every game lamp of these stages has.
|
|
264
|
+
const a = gameDir(l.aim);
|
|
265
|
+
dir.push(spot ? [...a, 10] : [0, 0, 1, 10]);
|
|
266
|
+
extra.push([0, 0, 0, 0]);
|
|
267
|
+
w2l.push(ident);
|
|
268
|
+
simDir.push(spot ? [...a, 10] : [0, 0, 1, 10]);
|
|
269
|
+
simColorW.push(1);
|
|
270
|
+
types[i] = spot ? 0 : 2;
|
|
271
|
+
}
|
|
272
|
+
masks[i] = l.layers >>> 0;
|
|
273
|
+
}
|
|
274
|
+
g._AdditionalLightsPosition = pos;
|
|
275
|
+
g._AdditionalLightsColor = col;
|
|
276
|
+
g._AdditionalLightsAttenuation = att;
|
|
277
|
+
g._AdditionalLightsSpotDir = dir;
|
|
278
|
+
g._AdditionalLightsExtra = extra;
|
|
279
|
+
g._AdditionalLightsWorldToLights = w2l;
|
|
280
|
+
g._AdditionalLightsLightTypes = types;
|
|
281
|
+
g._AdditionalLightsLayerMasks = masks;
|
|
282
|
+
g._AdditionalLightsCookieEnableBits = new Float32Array(8);
|
|
283
|
+
const words = Math.max(1, Math.ceil(n / 32));
|
|
284
|
+
const zb = new Uint32Array(4096);
|
|
285
|
+
const tiles = new Uint32Array(16384);
|
|
286
|
+
zb[0] = n > 0 ? ((n - 1) << 16) >>> 0 : 0xffff;
|
|
287
|
+
for (let k = 0; k < words; k++) {
|
|
288
|
+
const bits = Math.min(Math.max(n - k * 32, 0), 32);
|
|
289
|
+
const m = bits >= 32 ? 0xffffffff : ((1 << bits) >>> 0) - 1;
|
|
290
|
+
zb[1 + k] = m >>> 0;
|
|
291
|
+
tiles[k] = m >>> 0;
|
|
292
|
+
}
|
|
293
|
+
// LightingFeatures' own copy for the per-vertex lights: the first 16, colour
|
|
294
|
+
// without the intensity in w.
|
|
295
|
+
g.SimAdditionalLightPosition = pos.slice(0, 16);
|
|
296
|
+
g.SimAdditionalLightColor = col
|
|
297
|
+
.slice(0, 16)
|
|
298
|
+
.map((c, i) => (c[0] || c[1] || c[2] ? [c[0], c[1], c[2], simColorW[i] ?? 1] : [0, 0, 0, 0]));
|
|
299
|
+
g.SimAdditionalLightAttenuation = att.slice(0, 16);
|
|
300
|
+
g.SimAdditionalLightSpotDir = simDir.slice(0, 16).concat(dir.slice(simDir.length, 16));
|
|
301
|
+
g._PlusLighting_ZBins = zb;
|
|
302
|
+
g._PlusLighting_Tiles = tiles;
|
|
303
|
+
g._PlusLightingParams0 = [0, 0, 1, words];
|
|
304
|
+
g._PlusLightingParams1 = [1000, 0, 0, 0];
|
|
305
|
+
// ---- the main light's cascades, sampled from the engine's atlas
|
|
306
|
+
if (f.shadow) {
|
|
307
|
+
const sh = f.shadow;
|
|
308
|
+
const unit = sh.tileSize / sh.atlasSize;
|
|
309
|
+
const w2s = [];
|
|
310
|
+
for (let i = 0; i < 4; i++) {
|
|
311
|
+
const vpe = sh.viewProj[i];
|
|
312
|
+
const tile = sh.tiles[i];
|
|
313
|
+
if (!vpe || !tile) {
|
|
314
|
+
w2s.push(scale4(0));
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
// ndc -> the tile's uv (y down, as the atlas is addressed), depth as drawn
|
|
318
|
+
const tx = tile[0] / sh.atlasSize;
|
|
319
|
+
const ty = tile[1] / sh.atlasSize;
|
|
320
|
+
const toTile = Float32Array.from([0.5 * unit, 0, 0, 0, 0, -0.5 * unit, 0, 0, 0, 0, 1, 0, 0.5 * unit + tx, 0.5 * unit + ty, 0, 1]);
|
|
321
|
+
w2s.push(mul4(toTile, mul4(vpe, gameToEngine(s))));
|
|
322
|
+
}
|
|
323
|
+
g._MainLightWorldToShadow = w2s;
|
|
324
|
+
for (let i = 0; i < 4; i++) {
|
|
325
|
+
const sp = sh.spheres[i];
|
|
326
|
+
g[`_CascadeShadowSplitSpheres${i}`] = sp ? [...gamePoint(sp.center, s), sp.radius / s] : [0, 0, 0, 0];
|
|
327
|
+
}
|
|
328
|
+
const r = (i) => (sh.spheres[i] ? (sh.spheres[i].radius / s) ** 2 : 0);
|
|
329
|
+
g._CascadeShadowSplitSphereRadii = [r(0), r(1), r(2), r(3)];
|
|
330
|
+
const half = 0.5 / sh.atlasSize;
|
|
331
|
+
g._MainLightShadowOffset0 = [-half, -half, half, -half];
|
|
332
|
+
g._MainLightShadowOffset1 = [-half, half, half, half];
|
|
333
|
+
g._MainLightShadowmapSize = [1 / sh.atlasSize, 1 / sh.atlasSize, sh.atlasSize, sh.atlasSize];
|
|
334
|
+
g._MainLightShadowParams = [f.sunShadow, 1, 0, 0];
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
g._MainLightShadowParams = [0, 0, 0, 0];
|
|
338
|
+
}
|
|
339
|
+
return g;
|
|
340
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { type PassState } from "./state";
|
|
2
|
+
export type NativeBinding = {
|
|
3
|
+
group: number;
|
|
4
|
+
binding: number;
|
|
5
|
+
space: string;
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
stages: string[];
|
|
9
|
+
};
|
|
10
|
+
export type NativeMember = {
|
|
11
|
+
name: string;
|
|
12
|
+
offset: number;
|
|
13
|
+
size: number;
|
|
14
|
+
type: string;
|
|
15
|
+
};
|
|
16
|
+
export type NativeStruct = {
|
|
17
|
+
size: number;
|
|
18
|
+
members: NativeMember[];
|
|
19
|
+
};
|
|
20
|
+
export type NativeShaderInfo = {
|
|
21
|
+
bindings: Record<string, NativeBinding>;
|
|
22
|
+
structs: Record<string, NativeStruct>;
|
|
23
|
+
vertexInputs: {
|
|
24
|
+
location: number;
|
|
25
|
+
name: string;
|
|
26
|
+
type: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
/** One translated shader variant: what shader_wgsl.py writes for a pass. */
|
|
30
|
+
export type NativeShader = {
|
|
31
|
+
name: string;
|
|
32
|
+
vert: string;
|
|
33
|
+
frag: string;
|
|
34
|
+
info: NativeShaderInfo;
|
|
35
|
+
};
|
|
36
|
+
/** A value a uniform member takes: a scalar, a flat vector or matrix, an array of
|
|
37
|
+
* those, or raw integer bits (Uint32Array — never passed through a float). */
|
|
38
|
+
export type NativeValue = number | ArrayLike<number> | ArrayLike<ArrayLike<number>>;
|
|
39
|
+
/** Name -> value; the first source that has a name wins. */
|
|
40
|
+
export type ValueSource = Record<string, NativeValue | undefined>;
|
|
41
|
+
/** One vertex stream a draw binds, by the semantic a shader input names. */
|
|
42
|
+
export type NativeStream = {
|
|
43
|
+
buffer: GPUBuffer;
|
|
44
|
+
offset: number;
|
|
45
|
+
stride: number;
|
|
46
|
+
format: GPUVertexFormat;
|
|
47
|
+
};
|
|
48
|
+
/** "in_u002e_var_u002e_TEXCOORD2_" -> "TEXCOORD2"; TEXCOORD alone is 0. */
|
|
49
|
+
export declare function semantic(inputName: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* The fragment module, returning the engine's attachments.
|
|
52
|
+
*
|
|
53
|
+
* naga writes the entry point last: it copies its inputs to private globals,
|
|
54
|
+
* calls the translated body, and returns the one SV_Target. That return is
|
|
55
|
+
* rewritten to the engine's output struct — the colour as the game computed
|
|
56
|
+
* it, the aux mask (bloom on, canvas alpha from the colour's alpha) and, when
|
|
57
|
+
* the device has an id attachment, a zero id. Anything else about the module
|
|
58
|
+
* is left exactly as translated.
|
|
59
|
+
*/
|
|
60
|
+
export declare function wrapFragment(frag: string, ids: boolean): string;
|
|
61
|
+
export type NativeHostTargets = {
|
|
62
|
+
/** The scene pass's colour formats, in attachment order: hdr, aux[, id]. */
|
|
63
|
+
colorFormats: GPUTextureFormat[];
|
|
64
|
+
depthFormat: GPUTextureFormat;
|
|
65
|
+
sampleCount: number;
|
|
66
|
+
reversedZ: boolean;
|
|
67
|
+
};
|
|
68
|
+
export type NativeDraw = {
|
|
69
|
+
shader: string;
|
|
70
|
+
state: PassState;
|
|
71
|
+
streams: NativeStream[];
|
|
72
|
+
index: {
|
|
73
|
+
buffer: GPUBuffer;
|
|
74
|
+
format: GPUIndexFormat;
|
|
75
|
+
offset: number;
|
|
76
|
+
count: number;
|
|
77
|
+
};
|
|
78
|
+
/** Name -> value, first match wins. */
|
|
79
|
+
sources: ValueSource[];
|
|
80
|
+
/** Texture name -> view (material slots, globals, render targets). */
|
|
81
|
+
textures: Record<string, GPUTextureView | undefined>;
|
|
82
|
+
/** Texture name -> its sampler (wrap and filter as the game imported it);
|
|
83
|
+
* a texture without one samples repeating, trilinear. */
|
|
84
|
+
samplers?: Record<string, GPUSampler | undefined>;
|
|
85
|
+
/** Separates draws' uniform buffers: one renderer's pass, one slot. */
|
|
86
|
+
key: string;
|
|
87
|
+
/** The pass the frame's globals belong to (main, a shadow cascade): a block
|
|
88
|
+
* filled from the globals alone is one buffer per shader and pass, shared by
|
|
89
|
+
* every draw in it. */
|
|
90
|
+
pass?: string;
|
|
91
|
+
};
|
|
92
|
+
export declare class NativeHost {
|
|
93
|
+
private device;
|
|
94
|
+
private targets;
|
|
95
|
+
private fallback;
|
|
96
|
+
private prepared;
|
|
97
|
+
private pipelines;
|
|
98
|
+
private draws;
|
|
99
|
+
private shared;
|
|
100
|
+
private frame;
|
|
101
|
+
private sampler;
|
|
102
|
+
/** Names no source supplied, with how often — the audit the compare page showed. */
|
|
103
|
+
readonly missing: Map<string, number>;
|
|
104
|
+
readonly errors: string[];
|
|
105
|
+
constructor(device: GPUDevice, targets: NativeHostTargets, fallback: {
|
|
106
|
+
white: GPUTextureView;
|
|
107
|
+
black: GPUTextureView;
|
|
108
|
+
blackCube: GPUTextureView;
|
|
109
|
+
depth: GPUTextureView;
|
|
110
|
+
comparison: GPUSampler;
|
|
111
|
+
});
|
|
112
|
+
has(name: string): boolean;
|
|
113
|
+
/** Register a translated shader. Idempotent by name. */
|
|
114
|
+
register(shader: NativeShader): void;
|
|
115
|
+
/** The vertex inputs a shader reads, by Unity semantic, in location order. */
|
|
116
|
+
inputs(name: string): {
|
|
117
|
+
location: number;
|
|
118
|
+
semantic: string;
|
|
119
|
+
}[];
|
|
120
|
+
private pipeline;
|
|
121
|
+
private lookup;
|
|
122
|
+
/** A new frame: shared blocks are brought up to date once in it. */
|
|
123
|
+
beginFrame(): void;
|
|
124
|
+
private lookupFrom;
|
|
125
|
+
private newBlock;
|
|
126
|
+
/** Bring a block up to date with its sources; upload what changed. */
|
|
127
|
+
private fill;
|
|
128
|
+
/** Encode one draw into the scene pass. */
|
|
129
|
+
draw(pass: GPURenderPassEncoder, d: NativeDraw): void;
|
|
130
|
+
/** sampler_AlbedoTex / samplerAlbedoTex -> the sampler of the texture it pairs with. */
|
|
131
|
+
private samplerFor;
|
|
132
|
+
private textureView;
|
|
133
|
+
/** Forget a draw's buffers (its model left). */
|
|
134
|
+
release(prefix: string): void;
|
|
135
|
+
}
|
|
136
|
+
export declare function sameBytes(a: Uint8Array, b: Uint8Array): boolean;
|
|
137
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/unity/host.ts"],"names":[],"mappings":"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"}
|