reze-engine 0.66.5 → 0.67.1
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/camera.d.ts +1 -0
- package/dist/camera.d.ts.map +1 -1
- package/dist/camera.js +9 -5
- package/dist/engine.d.ts +20 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +91 -28
- package/dist/graph/presets/body.js +1 -1
- package/dist/graph/presets/cloth_rough.js +1 -1
- package/dist/graph/presets/cloth_smooth.js +1 -1
- package/dist/graph/presets/face.js +1 -1
- package/dist/graph/presets/metal.js +1 -1
- 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 +84 -6
- package/dist/graph/schema.d.ts +14 -0
- package/dist/graph/schema.d.ts.map +1 -1
- 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/agx-lut.d.ts +11 -0
- package/dist/shaders/agx-lut.d.ts.map +1 -0
- package/dist/shaders/agx-lut.js +29 -0
- package/dist/shaders/dfg_lut.d.ts +3 -0
- package/dist/shaders/dfg_lut.d.ts.map +1 -0
- package/dist/shaders/dfg_lut.js +129 -0
- package/dist/shaders/ltc_mag_lut.d.ts +3 -0
- package/dist/shaders/ltc_mag_lut.d.ts.map +1 -0
- package/dist/shaders/ltc_mag_lut.js +1033 -0
- 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 +176 -7
- package/dist/shaders/passes/composite.d.ts.map +1 -1
- package/dist/shaders/passes/composite.js +4 -2
- 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/outline.d.ts +7 -0
- package/dist/shaders/passes/outline.d.ts.map +1 -1
- package/dist/shaders/passes/outline.js +67 -16
- 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/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/camera.ts +9 -5
- package/src/engine.ts +109 -30
- package/src/graph/presets/body.ts +1 -1
- package/src/graph/presets/cloth_rough.ts +1 -1
- package/src/graph/presets/cloth_smooth.ts +1 -1
- package/src/graph/presets/face.ts +1 -1
- package/src/graph/presets/metal.ts +1 -1
- package/src/graph/registry.ts +85 -6
- package/src/graph/schema.ts +14 -0
- package/src/shaders/materials/nodes.ts +176 -7
- package/src/shaders/passes/composite.ts +4 -2
- package/src/shaders/passes/outline.ts +67 -16
- package/dist/_dbg-loader.mjs +0 -1100
package/dist/engine.js
CHANGED
|
@@ -36,7 +36,7 @@ import { sceneTargets as sceneTargetsFor, sceneColorFormats, setMrtIds, mrtIdsEn
|
|
|
36
36
|
import { LIGHT_GRID_BASE, LIGHT_HEADER, LIGHT_STRIDE, LIGHTS_FLOATS, MAX_LIGHTS, buildLightEmitShader, hasLightEmit, } from "./shaders/lights";
|
|
37
37
|
import { buildLightGrid } from "./light-grid";
|
|
38
38
|
import { groundShaderWgsl, GROUND_NOISE_BAKE_WGSL, GROUND_NOISE_SIZE } from "./shaders/passes/ground";
|
|
39
|
-
import { outlineShaderWgsl, RZ_OUTLINE_COLOR_OFFSET, RZ_OUTLINE_DISSOLVE_OFFSET, RZ_OUTLINE_WIDTH_OFFSET } from "./shaders/passes/outline";
|
|
39
|
+
import { outlineShaderWgsl, RZ_OUTLINE_COLOR_OFFSET, RZ_OUTLINE_DISSOLVE_OFFSET, RZ_OUTLINE_SHADOW_OFFSET, RZ_OUTLINE_TEXTURED_OFFSET, RZ_OUTLINE_WIDTH_OFFSET, } from "./shaders/passes/outline";
|
|
40
40
|
import { transparentDepthPrepassWgsl } from "./shaders/passes/depth-prepass";
|
|
41
41
|
import { SELECTION_MASK_SHADER_WGSL, SELECTION_EDGE_SHADER_WGSL } from "./shaders/passes/selection";
|
|
42
42
|
import { GIZMO_SHADER_WGSL } from "./shaders/passes/gizmo";
|
|
@@ -101,7 +101,7 @@ const PRESET_NAME_HINTS = [
|
|
|
101
101
|
"hair", "ahoge", "bang",
|
|
102
102
|
],
|
|
103
103
|
],
|
|
104
|
-
["body", ["肌", "皮肤", "skin"]],
|
|
104
|
+
["body", ["肌", "皮肤", "skin", "指甲", "nail"]],
|
|
105
105
|
["metal", ["金属", "メタル", "metal", "earring", "耳环", "耳環"]],
|
|
106
106
|
[
|
|
107
107
|
"cloth_smooth",
|
|
@@ -146,6 +146,10 @@ const PRESET_NAME_HINTS = [
|
|
|
146
146
|
],
|
|
147
147
|
],
|
|
148
148
|
];
|
|
149
|
+
// Whole names that are body parts — skin by another name. Whole, never
|
|
150
|
+
// substrings: 手 alone is a hand, inside 手套 (gloves) or 手镯 (a bracelet) it is
|
|
151
|
+
// what the hand wears; 足 is a leg, 足袋 a sock.
|
|
152
|
+
const BODY_PART_NAMES = new Set(["手", "手部", "腕", "足", "脚", "腿", "爪", "hand", "hands", "arm", "arms", "leg", "legs", "body"]);
|
|
149
153
|
// Resolve a material name to a style category (override map first, then name hints), or
|
|
150
154
|
// null if nothing matches — a null-resolving material stays ungrouped (neutral default).
|
|
151
155
|
function resolvePreset(materialName, map) {
|
|
@@ -156,6 +160,8 @@ function resolvePreset(materialName, map) {
|
|
|
156
160
|
}
|
|
157
161
|
}
|
|
158
162
|
const lower = materialName.toLowerCase();
|
|
163
|
+
if (BODY_PART_NAMES.has(lower.replace(/[\s_.\-0-9]+$/, "")))
|
|
164
|
+
return "body";
|
|
159
165
|
for (const [preset, hints] of PRESET_NAME_HINTS) {
|
|
160
166
|
for (const hint of hints) {
|
|
161
167
|
if (lower.includes(hint))
|
|
@@ -245,6 +251,7 @@ export const DEFAULT_DEPTH_OF_FIELD_OPTIONS = {
|
|
|
245
251
|
export const DEFAULT_VIEW_TRANSFORM = {
|
|
246
252
|
exposure: 0,
|
|
247
253
|
gamma: 1.0,
|
|
254
|
+
contrast: 1.4,
|
|
248
255
|
transform: "soft",
|
|
249
256
|
};
|
|
250
257
|
const NEUTRAL_GRADE_CHANNEL = 0.5;
|
|
@@ -1071,7 +1078,7 @@ export class Engine {
|
|
|
1071
1078
|
// 15 × vec4f — see the viewU comment in composite.ts. The last one is the
|
|
1072
1079
|
// camera's world position, which is what lets a foreground effect turn the
|
|
1073
1080
|
// depth it is handed into a PLACE (bgWorldPos) rather than a distance.
|
|
1074
|
-
this.compositeUniformData = new Float32Array(
|
|
1081
|
+
this.compositeUniformData = new Float32Array(64);
|
|
1075
1082
|
/** Composite background (display-space sRGB 0–1) — null = transparent canvas. */
|
|
1076
1083
|
this.backgroundColor = null;
|
|
1077
1084
|
// 360 backdrop (equirectangular skybox, sampled by view ray in composite).
|
|
@@ -1765,6 +1772,7 @@ export class Engine {
|
|
|
1765
1772
|
return {
|
|
1766
1773
|
exposure: partial?.exposure ?? d.exposure,
|
|
1767
1774
|
gamma: partial?.gamma ?? d.gamma,
|
|
1775
|
+
contrast: partial?.contrast ?? d.contrast,
|
|
1768
1776
|
transform: partial?.transform ?? d.transform,
|
|
1769
1777
|
};
|
|
1770
1778
|
}
|
|
@@ -1781,7 +1789,7 @@ export class Engine {
|
|
|
1781
1789
|
}
|
|
1782
1790
|
getViewTransformOptions() {
|
|
1783
1791
|
const v = this.viewTransform;
|
|
1784
|
-
return { exposure: v.exposure, gamma: v.gamma, transform: v.transform };
|
|
1792
|
+
return { exposure: v.exposure, gamma: v.gamma, contrast: v.contrast, transform: v.transform };
|
|
1785
1793
|
}
|
|
1786
1794
|
/**
|
|
1787
1795
|
* Color-grade the tonemapped scene (ASC CDL slope/offset/power + saturation).
|
|
@@ -1891,6 +1899,8 @@ export class Engine {
|
|
|
1891
1899
|
v.exposure = patch.exposure;
|
|
1892
1900
|
if (patch.gamma !== undefined)
|
|
1893
1901
|
v.gamma = patch.gamma;
|
|
1902
|
+
if (patch.contrast !== undefined)
|
|
1903
|
+
v.contrast = patch.contrast;
|
|
1894
1904
|
if (patch.transform !== undefined)
|
|
1895
1905
|
v.transform = patch.transform;
|
|
1896
1906
|
if (this.device && this.compositeUniformBuffer) {
|
|
@@ -1960,6 +1970,9 @@ export class Engine {
|
|
|
1960
1970
|
u[25] = Engine.VIEW_TRANSFORM_ID[v.transform] ?? 0;
|
|
1961
1971
|
u[26] = this.canvas.width;
|
|
1962
1972
|
u[27] = this.canvas.height;
|
|
1973
|
+
// The soft curve's power (viewU[15].x), the scene's own (SceneSetting._contrast).
|
|
1974
|
+
// Its own vec4: viewU[11..14] are the cast's positions whenever an effect runs.
|
|
1975
|
+
u[60] = v.contrast;
|
|
1963
1976
|
// ── Grade (viewU[7..9]) ── The UI's three tonal COLORS map to ASC CDL here,
|
|
1964
1977
|
// on the CPU, so the shader only ever sees slope/offset/power. Mid-gray is
|
|
1965
1978
|
// neutral in all three; the signed distance from it is the amount.
|
|
@@ -6832,6 +6845,8 @@ export class Engine {
|
|
|
6832
6845
|
entries: [
|
|
6833
6846
|
{ binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
|
|
6834
6847
|
{ binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } },
|
|
6848
|
+
// the key light, for a style graph's outline colour (see outline.ts)
|
|
6849
|
+
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
|
|
6835
6850
|
],
|
|
6836
6851
|
});
|
|
6837
6852
|
// Outline per-instance reuses mainPerInstanceBindGroupLayout (same skinMats binding)
|
|
@@ -6840,6 +6855,7 @@ export class Engine {
|
|
|
6840
6855
|
entries: [
|
|
6841
6856
|
{ binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
|
|
6842
6857
|
{ binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float" } },
|
|
6858
|
+
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float" } },
|
|
6843
6859
|
],
|
|
6844
6860
|
});
|
|
6845
6861
|
const outlinePipelineLayout = this.device.createPipelineLayout({
|
|
@@ -6856,6 +6872,7 @@ export class Engine {
|
|
|
6856
6872
|
entries: [
|
|
6857
6873
|
{ binding: 0, resource: { buffer: this.cameraUniformBuffer } },
|
|
6858
6874
|
{ binding: 1, resource: this.materialSampler },
|
|
6875
|
+
{ binding: 2, resource: { buffer: this.lightUniformBuffer } },
|
|
6859
6876
|
],
|
|
6860
6877
|
});
|
|
6861
6878
|
// The same group on the MIRROR camera. An outline is geometry expanded
|
|
@@ -6868,6 +6885,7 @@ export class Engine {
|
|
|
6868
6885
|
entries: [
|
|
6869
6886
|
{ binding: 0, resource: { buffer: this.mirrorCameraBuffer } },
|
|
6870
6887
|
{ binding: 1, resource: this.materialSampler },
|
|
6888
|
+
{ binding: 2, resource: { buffer: this.lightUniformBuffer } },
|
|
6871
6889
|
],
|
|
6872
6890
|
});
|
|
6873
6891
|
const outlineShaderModule = this.device.createShaderModule({
|
|
@@ -7037,13 +7055,14 @@ export class Engine {
|
|
|
7037
7055
|
// strength belong to the combine step.
|
|
7038
7056
|
this.compositeUniformBuffer = this.device.createBuffer({
|
|
7039
7057
|
label: "composite view uniforms",
|
|
7040
|
-
//
|
|
7058
|
+
// 16 × vec4f: (exposure, invGamma, _, _) · (bloom tint, intensity) ·
|
|
7041
7059
|
// (bg rgb, mode) · camera right/up/forward basis for the 360 skybox ray ·
|
|
7042
7060
|
// (time, _, canvas width, canvas height) for user effects · three grade
|
|
7043
7061
|
// vectors (CDL offset+contrast, power+saturation, slope+flag) · camera
|
|
7044
7062
|
// world position, for an effect placing itself in the scene · four
|
|
7045
|
-
// character positions, for one that wants to respond to the cast
|
|
7046
|
-
|
|
7063
|
+
// character positions, for one that wants to respond to the cast · the
|
|
7064
|
+
// soft curve's contrast. Shaders that stop at the cast declare 15.
|
|
7065
|
+
size: 256,
|
|
7047
7066
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
7048
7067
|
});
|
|
7049
7068
|
this.dofUniformBuffer = this.device.createBuffer({
|
|
@@ -12784,6 +12803,7 @@ export class Engine {
|
|
|
12784
12803
|
dissolve: 1,
|
|
12785
12804
|
materialUniformBuffers: [],
|
|
12786
12805
|
outlineUniformBuffers: [],
|
|
12806
|
+
outlineByMaterial: new Map(),
|
|
12787
12807
|
cullModelIndex: 0,
|
|
12788
12808
|
// Seeded false: the first skin-matrix upload decides it, and until then the
|
|
12789
12809
|
// sphere path is the safe answer (it never culls something it should not).
|
|
@@ -13321,8 +13341,12 @@ export class Engine {
|
|
|
13321
13341
|
// every material — on the heaviest mesh in the scene that doubles the
|
|
13322
13342
|
// geometry submitted per frame to draw cartoon outlines around
|
|
13323
13343
|
// architecture, which is not the look anyone is after.
|
|
13344
|
+
// Every character material gets its hull: the PMX edge flag draws it as
|
|
13345
|
+
// MMD does, and a style group whose look carries an outline draws it on
|
|
13346
|
+
// any material (assignDrawCallGroups sets `drawn`).
|
|
13324
13347
|
let outline;
|
|
13325
|
-
|
|
13348
|
+
const pmxEdge = (mat.edgeFlag & 0x10) !== 0 && mat.edgeSize > 0;
|
|
13349
|
+
if (!inst.isStage) {
|
|
13326
13350
|
const materialUniformData = new Float32Array([
|
|
13327
13351
|
mat.edgeColor[0],
|
|
13328
13352
|
mat.edgeColor[1],
|
|
@@ -13337,25 +13361,29 @@ export class Engine {
|
|
|
13337
13361
|
1,
|
|
13338
13362
|
// The scene's width multiplier, at RZ_OUTLINE_WIDTH_OFFSET.
|
|
13339
13363
|
this.outlineWidth,
|
|
13364
|
+
// A style graph's outline, at RZ_OUTLINE_TEXTURED_OFFSET: none yet.
|
|
13340
13365
|
0,
|
|
13341
13366
|
// The scene's colour override, at RZ_OUTLINE_COLOR_OFFSET.
|
|
13342
13367
|
this.outlineColor[0],
|
|
13343
13368
|
this.outlineColor[1],
|
|
13344
13369
|
this.outlineColor[2],
|
|
13345
13370
|
this.outlineColor[3],
|
|
13371
|
+
// The graph outline's shadow colour, at RZ_OUTLINE_SHADOW_OFFSET.
|
|
13372
|
+
0,
|
|
13373
|
+
0,
|
|
13374
|
+
0,
|
|
13375
|
+
0,
|
|
13346
13376
|
]);
|
|
13347
13377
|
const outlineUniformBuffer = this.createUniformBuffer(`${prefix}outline: ${mat.name}`, materialUniformData);
|
|
13348
13378
|
inst.gpuBuffers.push(outlineUniformBuffer);
|
|
13349
13379
|
inst.outlineUniformBuffers.push(outlineUniformBuffer);
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
{ binding: 0, resource: { buffer: outlineUniformBuffer } },
|
|
13355
|
-
{ binding: 1, resource: textureView },
|
|
13356
|
-
],
|
|
13380
|
+
inst.outlineByMaterial.set(mat.name, {
|
|
13381
|
+
buffer: outlineUniformBuffer,
|
|
13382
|
+
edge: materialUniformData.slice(0, 5),
|
|
13383
|
+
picture: textureView,
|
|
13357
13384
|
});
|
|
13358
|
-
|
|
13385
|
+
const outlineBindGroup = this.outlineBindGroup(`${prefix}outline: ${mat.name}`, outlineUniformBuffer, textureView, null);
|
|
13386
|
+
outline = { bindGroup: outlineBindGroup, pmx: pmxEdge, drawn: pmxEdge };
|
|
13359
13387
|
if (!inst.outlineVertexBuffer) {
|
|
13360
13388
|
const data = inst.model.getOutlineVertices();
|
|
13361
13389
|
const buf = this.device.createBuffer({
|
|
@@ -14595,29 +14623,26 @@ export class Engine {
|
|
|
14595
14623
|
py += pos.y;
|
|
14596
14624
|
pz += pos.z;
|
|
14597
14625
|
}
|
|
14598
|
-
px += this.cameraTargetOffset.x;
|
|
14599
|
-
py += this.cameraTargetOffset.y;
|
|
14600
|
-
pz += this.cameraTargetOffset.z;
|
|
14601
14626
|
const tau = this.cameraFollowSmoothing;
|
|
14627
|
+
const f = this.cameraFollowPos;
|
|
14602
14628
|
if (tau > 0 && this.cameraFollowSeeded) {
|
|
14603
14629
|
// Exponential lag toward the bone: the handheld-camera feel. The
|
|
14604
14630
|
// orbit pivot trails the target and eases in, never snapping.
|
|
14605
14631
|
const k = 1 - Math.exp(-deltaTime / tau);
|
|
14606
|
-
const f = this.cameraFollowPos;
|
|
14607
14632
|
f.x += (px - f.x) * k;
|
|
14608
14633
|
f.y += (py - f.y) * k;
|
|
14609
14634
|
f.z += (pz - f.z) * k;
|
|
14610
|
-
this.camera.target.x = f.x;
|
|
14611
|
-
this.camera.target.y = f.y;
|
|
14612
|
-
this.camera.target.z = f.z;
|
|
14613
14635
|
}
|
|
14614
14636
|
else {
|
|
14615
|
-
|
|
14637
|
+
f.setXYZ(px, py, pz);
|
|
14616
14638
|
this.cameraFollowSeeded = true;
|
|
14617
|
-
this.camera.target.x = px;
|
|
14618
|
-
this.camera.target.y = py;
|
|
14619
|
-
this.camera.target.z = pz;
|
|
14620
14639
|
}
|
|
14640
|
+
// The offset goes on AFTER the lag. A pan writes the offset (panSink),
|
|
14641
|
+
// and the lag is for the bone's motion: eased with it, a pan glided
|
|
14642
|
+
// on after the hand let go while an orbit stopped dead.
|
|
14643
|
+
this.camera.target.x = f.x + this.cameraTargetOffset.x;
|
|
14644
|
+
this.camera.target.y = f.y + this.cameraTargetOffset.y;
|
|
14645
|
+
this.camera.target.z = f.z + this.cameraTargetOffset.z;
|
|
14621
14646
|
}
|
|
14622
14647
|
}
|
|
14623
14648
|
// Who holds the shot this frame. An external pose is a statement about
|
|
@@ -15578,8 +15603,46 @@ export class Engine {
|
|
|
15578
15603
|
}
|
|
15579
15604
|
// Rebind each material draw call to its (successfully-installed) group's uniform buffer,
|
|
15580
15605
|
// or the zero buffer when ungrouped, then re-sort by render-class draw order.
|
|
15606
|
+
/** A hull's per-material group: its block, the picture, the look's tint. */
|
|
15607
|
+
outlineBindGroup(label, buffer, picture, tint) {
|
|
15608
|
+
return this.device.createBindGroup({
|
|
15609
|
+
label,
|
|
15610
|
+
layout: this.outlinePerMaterialBindGroupLayout,
|
|
15611
|
+
entries: [
|
|
15612
|
+
{ binding: 0, resource: { buffer } },
|
|
15613
|
+
{ binding: 1, resource: picture },
|
|
15614
|
+
{ binding: 2, resource: (tint ?? this.fallbackMaterialTexture).createView() },
|
|
15615
|
+
],
|
|
15616
|
+
});
|
|
15617
|
+
}
|
|
15581
15618
|
assignDrawCallGroups(inst, claimed) {
|
|
15582
15619
|
inst.materialToGroup.clear();
|
|
15620
|
+
// The hulls: a group whose look carries an outline (ShaderGraph.outline)
|
|
15621
|
+
// draws it in place of the PMX edge; the rest keep, or get back, their own.
|
|
15622
|
+
for (const [name, hull] of inst.outlineByMaterial) {
|
|
15623
|
+
const id = claimed.get(name);
|
|
15624
|
+
const install = id ? inst.styleGroups.get(id) : undefined;
|
|
15625
|
+
const o = install?.group.graph.outline;
|
|
15626
|
+
const block = o
|
|
15627
|
+
? new Float32Array([o.color[0], o.color[1], o.color[2], 1, o.width])
|
|
15628
|
+
: hull.edge;
|
|
15629
|
+
this.device.queue.writeBuffer(hull.buffer, 0, block);
|
|
15630
|
+
this.device.queue.writeBuffer(hull.buffer, RZ_OUTLINE_TEXTURED_OFFSET, new Float32Array([o ? 1 : 0]));
|
|
15631
|
+
if (o)
|
|
15632
|
+
this.device.queue.writeBuffer(hull.buffer, RZ_OUTLINE_SHADOW_OFFSET, new Float32Array([...o.shadowColor, 1]));
|
|
15633
|
+
const tint = o?.tint != null ? (install?.imagesByMaterial?.[name] ?? install?.images)?.[o.tint] ?? null : null;
|
|
15634
|
+
for (const dc of inst.drawCalls) {
|
|
15635
|
+
if (dc.materialName !== name || !dc.outline)
|
|
15636
|
+
continue;
|
|
15637
|
+
dc.outline.bindGroup = this.outlineBindGroup(`outline: ${name}`, hull.buffer, hull.picture, tint);
|
|
15638
|
+
this.bundlesDirty = true;
|
|
15639
|
+
const drawn = o ? o.width > 0 : dc.outline.pmx;
|
|
15640
|
+
if (dc.outline.drawn !== drawn) {
|
|
15641
|
+
dc.outline.drawn = drawn;
|
|
15642
|
+
this.bundlesDirty = true;
|
|
15643
|
+
}
|
|
15644
|
+
}
|
|
15645
|
+
}
|
|
15583
15646
|
for (const dc of inst.drawCalls) {
|
|
15584
15647
|
if (!dc.baseBindGroupEntries)
|
|
15585
15648
|
continue; // outlines/ground are never grouped
|
|
@@ -16030,7 +16093,7 @@ export class Engine {
|
|
|
16030
16093
|
}
|
|
16031
16094
|
pass.setBindGroup(2, draw.bindGroup);
|
|
16032
16095
|
this.issueDraw(pass, draw, view.args);
|
|
16033
|
-
if (draw.outline && this.outlineEnabled && view.outlines)
|
|
16096
|
+
if (draw.outline?.drawn && this.outlineEnabled && view.outlines)
|
|
16034
16097
|
outlined.push(draw);
|
|
16035
16098
|
}
|
|
16036
16099
|
// THE HULLS AFTER THE SURFACES, as MMD draws a model's edges. A hull held
|
|
@@ -21,7 +21,7 @@ export const BODY_GRAPH = {
|
|
|
21
21
|
{ id: "lit_tint", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.5, value: 1.0, fac: 1.0 } },
|
|
22
22
|
{ id: "toon_color", type: "mix/blend" },
|
|
23
23
|
{ id: "bc", type: "bright_contrast", inputs: { bright: 0.1, contrast: 0.2 } },
|
|
24
|
-
{ id: "emission3", type: "vector_math/scale", inputs: { scale:
|
|
24
|
+
{ id: "emission3", type: "vector_math/scale", inputs: { scale: 3.2 } },
|
|
25
25
|
{ id: "warm_add", type: "math/add", inputs: { b: 0.5 } },
|
|
26
26
|
{ id: "warm_clamp", type: "math/clamp01" },
|
|
27
27
|
{
|
|
@@ -27,7 +27,7 @@ export const CLOTH_ROUGH_GRAPH = {
|
|
|
27
27
|
{ id: "mix_003", type: "mix/blend" },
|
|
28
28
|
{ id: "hue_004", type: "hue_sat", inputs: { hue: 0.5, saturation: 0.800000011920929, value: 2.0, fac: 1.0 } },
|
|
29
29
|
{ id: "npr_overlay", type: "mix/overlay", inputs: { fac: 1.0 } },
|
|
30
|
-
{ id: "npr_emit", type: "vector_math/scale", inputs: { scale:
|
|
30
|
+
{ id: "npr_emit", type: "vector_math/scale", inputs: { scale: 14.56 } },
|
|
31
31
|
{ id: "noise", type: "tex_noise", inputs: { scale: 17.7 } },
|
|
32
32
|
{ id: "noise_ramp", type: "ramp_linear", inputs: { pos0: 0.0, pos1: 1.0 } },
|
|
33
33
|
{ id: "bump", type: "bump", inputs: { strength: 1.0 } },
|
|
@@ -25,7 +25,7 @@ export const CLOTH_SMOOTH_GRAPH = {
|
|
|
25
25
|
{ id: "mix_003", type: "mix/blend" },
|
|
26
26
|
{ id: "hue_004", type: "hue_sat", inputs: { hue: 0.5, saturation: 0.800000011920929, value: 2.0, fac: 1.0 } },
|
|
27
27
|
{ id: "npr_overlay", type: "mix/overlay", inputs: { fac: 1.0 } },
|
|
28
|
-
{ id: "npr_emit", type: "vector_math/scale", inputs: { scale:
|
|
28
|
+
{ id: "npr_emit", type: "vector_math/scale", inputs: { scale: 14.56 } },
|
|
29
29
|
{ id: "principled_base", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.0, value: 0.800000011920929, fac: 1.0 } },
|
|
30
30
|
{
|
|
31
31
|
id: "principled",
|
|
@@ -25,7 +25,7 @@ export const FACE_GRAPH = {
|
|
|
25
25
|
{ id: "lit_tint", type: "hue_sat", inputs: { hue: 0.46000000834465027, saturation: 1.600000023841858, value: 1.5, fac: 1.0 } },
|
|
26
26
|
{ id: "toon_color", type: "mix/blend" },
|
|
27
27
|
{ id: "bc", type: "bright_contrast", inputs: { bright: 0.1, contrast: 0.2 } },
|
|
28
|
-
{ id: "emission3", type: "vector_math/scale", inputs: { scale: 2.
|
|
28
|
+
{ id: "emission3", type: "vector_math/scale", inputs: { scale: 2.0 } },
|
|
29
29
|
// ── warm rim (toon*0.5+0.5 → cardinal ramp) ──
|
|
30
30
|
{ id: "warm_mul", type: "math/multiply", inputs: { b: 0.5 } },
|
|
31
31
|
{ id: "warm_add", type: "math/add", inputs: { b: 0.5 } },
|
|
@@ -24,7 +24,7 @@ export const METAL_GRAPH = {
|
|
|
24
24
|
{ id: "mix_004", type: "mix/blend" },
|
|
25
25
|
{ id: "hue_004", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.0, value: 2.0, fac: 1.0 } },
|
|
26
26
|
{ id: "npr_overlay", type: "mix/overlay", inputs: { fac: 1.0 } },
|
|
27
|
-
{ id: "npr_emit", type: "vector_math/scale", inputs: { scale:
|
|
27
|
+
{ id: "npr_emit", type: "vector_math/scale", inputs: { scale: 6.48 } },
|
|
28
28
|
{ id: "voro_cross", type: "vect_cross", inputs: { b: [0, 1, 0] } },
|
|
29
29
|
{ id: "voro", type: "tex_voronoi/color", inputs: { scale: 4.3 } },
|
|
30
30
|
{ id: "voro_ramp", type: "ramp_linear", inputs: { pos0: 0.0, pos1: 1.0 } },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool_floor.d.ts","sourceRoot":"","sources":["../../../src/graph/presets/pool_floor.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,eAAO,MAAM,gBAAgB,EAAE,WA6B9B,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Pool floor — the tiled bottom seen through water, with caustics on it.
|
|
2
|
+
//
|
|
3
|
+
// The other half of a pool, and the half that does most of the work. A water
|
|
4
|
+
// surface can be tuned for a long time without the shot reading as a pool;
|
|
5
|
+
// putting the focused-light web on the FLOOR is what settles it, because that
|
|
6
|
+
// is the cue a photograph actually carries. It is a floor material, so it is
|
|
7
|
+
// applied to the tile under the water rather than to the water itself.
|
|
8
|
+
//
|
|
9
|
+
// Caustics land between the albedo and the shading deliberately: they are
|
|
10
|
+
// light, so they should still be dimmed by the floor's own shadow rather than
|
|
11
|
+
// glowing through it. That is the difference between water-focused sun and a
|
|
12
|
+
// decal.
|
|
13
|
+
export const POOL_FLOOR_GRAPH = {
|
|
14
|
+
version: 1,
|
|
15
|
+
name: "Pool floor",
|
|
16
|
+
tags: ["stage", "water", "pool"],
|
|
17
|
+
nodes: [
|
|
18
|
+
{ id: "tex", type: "texture" },
|
|
19
|
+
{ id: "mat", type: "material_diffuse" },
|
|
20
|
+
{ id: "base", type: "mix/multiply", inputs: { fac: 1.0 } },
|
|
21
|
+
{ id: "caust", type: "caustics" },
|
|
22
|
+
{
|
|
23
|
+
id: "principled",
|
|
24
|
+
type: "principled",
|
|
25
|
+
inputs: { metallic: 0.0, specular_ior_level: 0.4, roughness: 0.45, spec_clamp: 10.0, sheen_weight: 0.0, sheen_tint: 0.0 },
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
links: [
|
|
29
|
+
{ from: { node: "tex", socket: "color" }, to: { node: "base", socket: "a" } },
|
|
30
|
+
{ from: { node: "mat", socket: "color" }, to: { node: "base", socket: "b" } },
|
|
31
|
+
{ from: { node: "base", socket: "color" }, to: { node: "caust", socket: "color" } },
|
|
32
|
+
{ from: { node: "caust", socket: "color" }, to: { node: "principled", socket: "base_color" } },
|
|
33
|
+
],
|
|
34
|
+
output: { node: "principled", socket: "color" },
|
|
35
|
+
params: [
|
|
36
|
+
{ id: "tint", label: "Light tint", target: { node: "caust", socket: "tint" }, kind: "color", default: [1.0, 1.0, 1.0] },
|
|
37
|
+
{ id: "scale", label: "Caustic scale", target: { node: "caust", socket: "scale" }, kind: "float", min: 0.01, max: 1, default: 0.12 },
|
|
38
|
+
{ id: "speed", label: "Caustic speed", target: { node: "caust", socket: "speed" }, kind: "float", min: 0, max: 1, default: 0.15 },
|
|
39
|
+
{ id: "strength", label: "Caustic strength", target: { node: "caust", socket: "strength" }, kind: "float", min: 0, max: 3, default: 0.6 },
|
|
40
|
+
{ id: "fade", label: "Depth fade", target: { node: "caust", socket: "fade" }, kind: "float", min: 1, max: 200, default: 30 },
|
|
41
|
+
],
|
|
42
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"water.d.ts","sourceRoot":"","sources":["../../../src/graph/presets/water.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,eAAO,MAAM,WAAW,EAAE,WAgBzB,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Water — a planar reflection, rippled, seen through Fresnel.
|
|
2
|
+
//
|
|
3
|
+
// Put a stage's water materials in a style group carrying this graph and the
|
|
4
|
+
// pool starts reflecting. The reflection itself is the engine's mirror pass,
|
|
5
|
+
// which this is the only graph to read; everything else here is the shaping
|
|
6
|
+
// that keeps it from reading as a mirror laid flat in the floor.
|
|
7
|
+
//
|
|
8
|
+
// The exposed params are the ones worth a slider while judging a shot. Scale
|
|
9
|
+
// and speed are the ripple; a real pool's surface is slow and broad, so both
|
|
10
|
+
// defaults sit low. Tint is the water's own colour — a game rip carries that
|
|
11
|
+
// in its material, and the converter hands it straight over.
|
|
12
|
+
//
|
|
13
|
+
// How see-through the water is belongs to the MATERIAL's alpha, not to this
|
|
14
|
+
// graph, which is where every other group's coverage comes from too.
|
|
15
|
+
export const WATER_GRAPH = {
|
|
16
|
+
version: 1,
|
|
17
|
+
name: "Water",
|
|
18
|
+
tags: ["water", "stage"],
|
|
19
|
+
nodes: [{ id: "water", type: "water" }],
|
|
20
|
+
links: [],
|
|
21
|
+
output: { node: "water", socket: "color" },
|
|
22
|
+
params: [
|
|
23
|
+
{ id: "tint", label: "Tint", target: { node: "water", socket: "tint" }, kind: "color", default: [0.04, 0.62, 0.66] },
|
|
24
|
+
{ id: "scale", label: "Ripple scale", target: { node: "water", socket: "scale" }, kind: "float", min: 0.01, max: 1, default: 0.18 },
|
|
25
|
+
{ id: "speed", label: "Ripple speed", target: { node: "water", socket: "speed" }, kind: "float", min: 0, max: 1, default: 0.12 },
|
|
26
|
+
{ id: "strength", label: "Ripple depth", target: { node: "water", socket: "strength" }, kind: "float", min: 0, max: 2, default: 0.7 },
|
|
27
|
+
{ id: "blur", label: "Reflection blur", target: { node: "water", socket: "blur" }, kind: "float", min: 0, max: 1, default: 0.25 },
|
|
28
|
+
{ id: "mirroring", label: "Mirroring", target: { node: "water", socket: "mirroring" }, kind: "float", min: 0, max: 1, default: 0.20 },
|
|
29
|
+
{ id: "sparkle", label: "Sparkle", target: { node: "water", socket: "sparkle" }, kind: "float", min: 0, max: 4, default: 1.0 },
|
|
30
|
+
],
|
|
31
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/graph/registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEzD,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,KAAK,CAAA;IACX,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,yFAAyF;IACzF,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC9B,2FAA2F;IAC3F,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAA;IAC/C,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC;sEACkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAYD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,CAoBhE;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO,CAIpE;AAMD,wBAAgB,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAM1D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpE;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/graph/registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEzD,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,KAAK,CAAA;IACX,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,yFAAyF;IACzF,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC9B,2FAA2F;IAC3F,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAA;IAC/C,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC;sEACkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAYD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,GAAG,MAAM,CAoBhE;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO,CAIpE;AAMD,wBAAgB,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAM1D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpE;AAsLD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAozBlD,CAAA"}
|
package/dist/graph/registry.js
CHANGED
|
@@ -101,7 +101,11 @@ const uberNode = (slot) => ({
|
|
|
101
101
|
roughness: F(0.6),
|
|
102
102
|
occlusion: F(1),
|
|
103
103
|
normal: { type: "vector", contextDefault: "n" },
|
|
104
|
-
|
|
104
|
+
// The key light: this draw's, by default — the sun, or the light on the
|
|
105
|
+
// character's own layer — its way and its colour (the game's _LocalLightDir,
|
|
106
|
+
// _LocalLightColor). Linked, a look supplies its own (ag_key_light).
|
|
107
|
+
direction: { type: "vector", contextDefault: "l" },
|
|
108
|
+
light_color: { type: "color", contextDefault: "sun" },
|
|
105
109
|
// Unity's v into the ramp: the property map's alpha, which picks a
|
|
106
110
|
// surface's band (skin 0.702, hair and pale cloth 0.506).
|
|
107
111
|
row: F(0.702),
|
|
@@ -115,23 +119,44 @@ const uberNode = (slot) => ({
|
|
|
115
119
|
rim_in_light: F(1),
|
|
116
120
|
emission: C([0, 0, 0]),
|
|
117
121
|
reflection: F(1),
|
|
122
|
+
// THE STUDIO AMBIENT (_GlobalIlluminationOverride): the game blends a
|
|
123
|
+
// character's ambient from its own reflection cube's smallest mip — near
|
|
124
|
+
// neutral, 0.4–0.9 across the newer skins — over the scene's light, by the
|
|
125
|
+
// material's blend (bodies 0.8, hair 1, faces 0.5). It is what keeps a
|
|
126
|
+
// character clean on a coloured stage.
|
|
127
|
+
studio: C([0.6, 0.6, 0.6]),
|
|
128
|
+
studio_blend: F(0),
|
|
118
129
|
// A face's SDF shade (ag_face_sdf); left at -1, the material reads N·L.
|
|
119
130
|
shade: F(-1),
|
|
120
131
|
// 1: the game's FACE_MODE — no GGX, the environment at a flat 0.0157.
|
|
121
132
|
face: F(0),
|
|
133
|
+
// A face's SDF highlight (ag_face_spec), in place of GGX.
|
|
134
|
+
face_spec: F(0),
|
|
135
|
+
// 1: hair (_ANISOTROPIC_SPECULAR) — its ring (ag_hair_ring) in place of GGX,
|
|
136
|
+
// the environment at a flat 0.0157.
|
|
137
|
+
hair: F(0),
|
|
138
|
+
hair_spec: C([0, 0, 0]),
|
|
122
139
|
},
|
|
123
140
|
outputs: { color: "color" },
|
|
124
|
-
emit: (a) => `ag_uber(${slot}u, ${a.base}, ${a.metallic}, ${a.roughness}, ${a.occlusion}, ${a.normal}, ${a.direction}, ${a.row}, ${a.receive_shadow}, ` +
|
|
125
|
-
`${a.rim_mask}, ${a.rim_mid}, ${a.rim_width}, ${a.rim_tint}, ${a.rim_intensity}, ${a.rim_albedo}, ${a.rim_in_light}, ${a.emission}, ${a.reflection}, ${a.shade}, ${a.face}, input.worldPos, v)`,
|
|
141
|
+
emit: (a) => `ag_uber(${slot}u, ${a.base}, ${a.metallic}, ${a.roughness}, ${a.occlusion}, ${a.normal}, ${a.direction}, ${a.light_color}, ${a.row}, ${a.receive_shadow}, ` +
|
|
142
|
+
`${a.rim_mask}, ${a.rim_mid}, ${a.rim_width}, ${a.rim_tint}, ${a.rim_intensity}, ${a.rim_albedo}, ${a.rim_in_light}, ${a.emission}, ${a.reflection}, ${a.studio}, ${a.studio_blend}, ${a.shade}, ${a.face}, ${a.face_spec}, ${a.hair}, ${a.hair_spec}, input.worldPos, v)`,
|
|
126
143
|
takesLight: true,
|
|
127
144
|
});
|
|
128
145
|
const UBER_NODES = Object.fromEntries([0, 1, 2, 3].map((s) => [`ag_uber/${s}`, uberNode(s)]));
|
|
129
|
-
//
|
|
130
|
-
//
|
|
146
|
+
// How much a colour reads as skin (ag_skin): what picks a surface's ramp row in
|
|
147
|
+
// a general look, where the game would read its property mask.
|
|
148
|
+
const AG_SKIN = {
|
|
149
|
+
inputs: { color: C([1, 1, 1], true) },
|
|
150
|
+
outputs: { value: "float" },
|
|
151
|
+
emit: (a) => `ag_skin(${a.color})`,
|
|
152
|
+
};
|
|
153
|
+
// The face's SDF shade, the image on the slot the type names. An empty slot
|
|
154
|
+
// reads white: the whole face takes one shade from where the key light stands
|
|
155
|
+
// to the head, the game's flat face for a model without its SDF.
|
|
131
156
|
const faceSdfNode = (slot) => ({
|
|
132
157
|
inputs: {
|
|
133
158
|
uv: { type: "vector", contextDefault: "vec3f(input.uv, 0.0)" },
|
|
134
|
-
direction: { type: "vector",
|
|
159
|
+
direction: { type: "vector", contextDefault: "l" },
|
|
135
160
|
normal: { type: "vector", contextDefault: "n" },
|
|
136
161
|
smoothness: F(0.1),
|
|
137
162
|
invert: F(0),
|
|
@@ -140,6 +165,54 @@ const faceSdfNode = (slot) => ({
|
|
|
140
165
|
emit: (a) => `ag_face_sdf(${slot}u, ${a.uv}.xy, ${a.direction}, ${a.normal}, ${a.smoothness}, ${a.invert})`,
|
|
141
166
|
});
|
|
142
167
|
const FACE_SDF_NODES = Object.fromEntries([0, 1, 2, 3].map((s) => [`ag_face_sdf/${s}`, faceSdfNode(s)]));
|
|
168
|
+
// The newer SDF (_SDFType 1): a painted face normal, not a threshold field.
|
|
169
|
+
const faceSdfNewNode = (slot) => ({
|
|
170
|
+
...faceSdfNode(slot),
|
|
171
|
+
emit: (a) => `ag_face_sdf_new(${slot}u, ${a.uv}.xy, ${a.direction}, ${a.normal}, ${a.smoothness}, ${a.invert})`,
|
|
172
|
+
});
|
|
173
|
+
const FACE_SDF_NEW_NODES = Object.fromEntries([0, 1, 2, 3].map((s) => [`ag_face_sdf_new/${s}`, faceSdfNewNode(s)]));
|
|
174
|
+
// The face's highlight from the newer SDF's green and blue.
|
|
175
|
+
const faceSpecNode = (slot) => ({
|
|
176
|
+
inputs: {
|
|
177
|
+
uv: { type: "vector", contextDefault: "vec3f(input.uv, 0.0)" },
|
|
178
|
+
direction: { type: "vector", contextDefault: "l" },
|
|
179
|
+
normal: { type: "vector", contextDefault: "n" },
|
|
180
|
+
anisotropy: F(1),
|
|
181
|
+
shift: F(0),
|
|
182
|
+
},
|
|
183
|
+
outputs: { value: "float" },
|
|
184
|
+
emit: (a) => `ag_face_spec(${slot}u, ${a.uv}.xy, ${a.direction}, ${a.normal}, v, ${a.anisotropy}, ${a.shift})`,
|
|
185
|
+
});
|
|
186
|
+
// The hair's angel ring, the band on the slot's image.
|
|
187
|
+
const hairRingNode = (slot) => ({
|
|
188
|
+
inputs: {
|
|
189
|
+
uv: { type: "vector", contextDefault: "vec3f(input.uv, 0.0)" },
|
|
190
|
+
normal: { type: "vector", contextDefault: "n" },
|
|
191
|
+
color: C([1, 1, 1]),
|
|
192
|
+
anisotropy: F(1),
|
|
193
|
+
shift: F(0),
|
|
194
|
+
},
|
|
195
|
+
outputs: { color: "color" },
|
|
196
|
+
emit: (a) => `ag_hair_ring(${slot}u, ${a.uv}.xy, ${a.normal}, v, ${a.color}, ${a.anisotropy}, ${a.shift})`,
|
|
197
|
+
});
|
|
198
|
+
const HAIR_RING_NODES = Object.fromEntries([0, 1, 2, 3].map((s) => [`ag_hair_ring/${s}`, hairRingNode(s)]));
|
|
199
|
+
// The game's pupil (SimPipeline/Character/Eye): unlit relief, matcap and
|
|
200
|
+
// glints — slots: 0 depth, 1 normal, 2 matcap, 3 glint mask.
|
|
201
|
+
const AG_EYE = {
|
|
202
|
+
inputs: {
|
|
203
|
+
height_scale: F(0.2), min_layer: F(8), max_layer: F(32), intensity: F(0.9),
|
|
204
|
+
main_color: C([1, 1, 1]), matcap_color: C([1, 1, 1]), matcap_pow: F(1),
|
|
205
|
+
mask_scale: F(0.15), mask_soft: F(0.014),
|
|
206
|
+
mask2: F(0), mask2_color: C([1, 1, 1]), mask3: F(0), mask3_color: C([1, 1, 1]),
|
|
207
|
+
blink: F(0), blink_scale: F(10), scale_speed: F(0.1), rotate_speed: F(0.6), blink_angle: F(5),
|
|
208
|
+
level: F(1),
|
|
209
|
+
},
|
|
210
|
+
outputs: { color: "color" },
|
|
211
|
+
emit: (a) => `ag_eye(input.uv, n, v, input.worldPos, ${a.height_scale}, ${a.min_layer}, ${a.max_layer}, ${a.intensity}, ${a.main_color}, ` +
|
|
212
|
+
`${a.matcap_color}, ${a.matcap_pow}, ${a.mask_scale}, ${a.mask_soft}, ${a.mask2}, ${a.mask2_color}, ${a.mask3}, ${a.mask3_color}, ` +
|
|
213
|
+
`${a.blink}, ${a.blink_scale}, ${a.scale_speed}, ${a.rotate_speed}, ${a.blink_angle}, ${a.level})`,
|
|
214
|
+
};
|
|
215
|
+
const FACE_SPEC_NODES = Object.fromEntries([0, 1, 2, 3].map((s) => [`ag_face_spec/${s}`, faceSpecNode(s)]));
|
|
143
216
|
// A packed property map on the slot the type names — the game's material
|
|
144
217
|
// contract: R metal, G perceptual roughness (answered as smoothness, Unity's
|
|
145
218
|
// word for 1 − r), B occlusion, A emission mask, each remapped through the
|
|
@@ -586,7 +659,12 @@ export const NODE_REGISTRY = {
|
|
|
586
659
|
// Principled is one: the ramp image on the group slot named by the type.
|
|
587
660
|
// Defaults are 104903's skin.
|
|
588
661
|
...UBER_NODES,
|
|
662
|
+
ag_skin: AG_SKIN,
|
|
589
663
|
...FACE_SDF_NODES,
|
|
664
|
+
...FACE_SDF_NEW_NODES,
|
|
665
|
+
...FACE_SPEC_NODES,
|
|
666
|
+
ag_eye: AG_EYE,
|
|
667
|
+
...HAIR_RING_NODES,
|
|
590
668
|
...PROPERTY_MAP_NODES,
|
|
591
669
|
/**
|
|
592
670
|
* Lit — Unity's Lit (URP's PBR), term for term: what a stage, a prop or
|
package/dist/graph/schema.d.ts
CHANGED
|
@@ -89,6 +89,20 @@ export type ShaderGraph = {
|
|
|
89
89
|
url: string;
|
|
90
90
|
srgb?: boolean;
|
|
91
91
|
} | null)[];
|
|
92
|
+
/**
|
|
93
|
+
* The look's outline, the anime game's in place of MMD's flat edge: the
|
|
94
|
+
* material's picture × colour, toward shadowColor where the key light leaves
|
|
95
|
+
* it, `width` world units wide (held 1.2–3 px of a 1920-wide frame) — an Aether
|
|
96
|
+
* Gazer _OutlineWidth w is w·1.3/1920·8 here. Unset, the PMX edge stands.
|
|
97
|
+
*/
|
|
98
|
+
outline?: {
|
|
99
|
+
color: [number, number, number];
|
|
100
|
+
shadowColor: [number, number, number];
|
|
101
|
+
width: number;
|
|
102
|
+
/** One of `images` (its index) whose colour multiplies the outline at the
|
|
103
|
+
* mesh's uvs — the game's per-texel outline mask. */
|
|
104
|
+
tint?: number;
|
|
105
|
+
};
|
|
92
106
|
};
|
|
93
107
|
export type Diagnostic = {
|
|
94
108
|
severity: "error" | "warning";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/graph/schema.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAE9F,MAAM,MAAM,SAAS,GAAG;IACtB,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAA;IACV,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpC;mFAC+E;IAC/E,EAAE,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CACrC,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,YAAY,GAAG;IACzB,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,WAAW,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,CAAC,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,uEAAuE;IACvE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;IACvB;;uFAEmF;IACnF,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/graph/schema.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAE9F,MAAM,MAAM,SAAS,GAAG;IACtB,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAA;IACV,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpC;mFAC+E;IAC/E,EAAE,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CACrC,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,YAAY,GAAG;IACzB,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,WAAW,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,CAAC,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,uEAAuE;IACvE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;IACvB;;uFAEmF;IACnF,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,EAAE,CAAA;IACnD;;;;;OAKG;IACH,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QACrC,KAAK,EAAE,MAAM,CAAA;QACb;8DACsD;QACtD,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,eAAO,MAAM,SAAS,MAAM,CAAA;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAA"}
|