reze-engine 0.21.0 → 0.21.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/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Reze Engine
2
2
 
3
- [npm](https://www.npmjs.com/package/reze-engine)
3
+ [![npm](https://img.shields.io/npm/v/reze-engine)](https://www.npmjs.com/package/reze-engine)
4
4
 
5
5
  **Zero-runtime-dependency** WebGPU engine for real-time MMD/PMX rendering — renderer, animation, IK, and physics, all in TypeScript.
6
6
 
7
- screenshot
7
+ ![screenshot](./screenshot.png)
8
8
 
9
9
  ```bash
10
10
  npm install reze-engine
@@ -67,8 +67,7 @@ engine/src/
67
67
 
68
68
  shaders/
69
69
  materials/ nodes.ts (Blender-node WGSL library the graph compiler emits into) +
70
- common.ts (bindings, skinning VS); the per-material .ts files are the
71
- original hand shaders, kept as the graph-port reference
70
+ common.ts (bindings, skinning VS, fs() shell)
72
71
  passes/ shadow, morph (GPU vertex-morph compute), bloom, composite (Filmic),
73
72
  outline, selection, gizmo, pick, ground, mipmap
74
73
  ```
@@ -243,6 +242,14 @@ engine.removeStyleGroup("reze", "hair") // its materials drop to the neutral def
243
242
  const { ok, wgsl, diagnostics } = compileGraph(HAIR_GRAPH, { renderClass: "hair" })
244
243
  ```
245
244
 
245
+ **How `autoStyleGroups(model, overrides?)` resolves** — it assigns each material a *style category*, then buckets materials by category into one group each:
246
+
247
+ 1. **`overrides` first** — an explicit `{ category: [materialNames] }` map (the arg). Use it for the names the built-in hints can't read.
248
+ 2. **Then built-in name hints** — a case-insensitive **substring** match of the material name against per-category JP/CN/EN keyword lists, ordered **most-specific-first** so families don't collide (`靴下`/`stocking` resolves to `stockings` before `靴`/`shoes` would hit `cloth_smooth`). This covers standard-named models with no overrides at all.
249
+ 3. **No match → ungrouped** — the material renders the neutral default. "Unmatched" is a real, intended outcome, not a catch-all bucket.
250
+
251
+ Each category carries its shipped graph **and** pass-integration: `eye` → `EYE_GRAPH` + `renderClass: "eye"`, `hair` → `HAIR_GRAPH` + `"hair"`, `stockings` → `STOCKINGS_GRAPH` + `alphaMode: "hashed"`, the rest → their graph + `auto`/`opaque`. The group `id` is the category name (`hair`, `eye`, …), so re-running is idempotent. The returned promise resolves after grouping **and** every graph compiles, so `getStyleGroups(model)` is populated the moment it resolves — seed your own store from it and edit with `applyStyleGroups` afterward.
252
+
246
253
  Validation catches material conflicts, type mismatches, cycles, and bad links with node-level diagnostics; a failed compile keeps the previous pipeline rendering (fallback-on-error).
247
254
 
248
255
  ## Physics
package/dist/engine.d.ts CHANGED
@@ -4,7 +4,6 @@ import { type AssetReader } from "./asset-reader";
4
4
  import { type CompileOptions } from "./graph/compile";
5
5
  import type { ApplyStyleGroupResult, ApplyStyleGroupsResult, StyleGroup } from "./graph/style-group";
6
6
  export type MaterialPreset = "default" | "face" | "hair" | "body" | "eye" | "stockings" | "metal" | "cloth_smooth" | "cloth_rough";
7
- export type ResolvedMaterialPreset = MaterialPreset | "mmd_classic";
8
7
  export type MaterialPresetMap = Partial<Record<MaterialPreset, string[]>>;
9
8
  export type RaycastCallback = (modelName: string, material: string | null, bone: string | null, screenX: number, screenY: number) => void;
10
9
  /** Select a folder (webkitdirectory) and pass FileList or File[]; pmxFile picks which .pmx when several exist. */
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -26,11 +26,10 @@ import { STOCKINGS_GRAPH } from "./graph/presets/stockings";
26
26
  import { METAL_GRAPH } from "./graph/presets/metal";
27
27
  import { CLOTH_SMOOTH_GRAPH } from "./graph/presets/cloth_smooth";
28
28
  import { CLOTH_ROUGH_GRAPH } from "./graph/presets/cloth_rough";
29
- // Substring hints mapping common PMX material names (JP/CN/EN) to presets,
30
- // tried when a material isn't in the model's explicit MaterialPresetMap.
31
- // Ordered: more specific families first (靴下 must hit stockings before 靴
32
- // hits cloth). Anything unmatched falls through to mmd_classic, which renders
33
- // the author-tuned PMX material data faithfully.
29
+ // Substring hints mapping common PMX material names (JP/CN/EN) to a style category,
30
+ // tried when a material isn't in the caller's explicit override map. Ordered: more
31
+ // specific families first (靴下 must hit stockings before 靴 hits cloth). A material
32
+ // matching nothing resolves to null it stays ungrouped (neutral default).
34
33
  const PRESET_NAME_HINTS = [
35
34
  ["stockings", ["靴下", "ソックス", "タイツ", "ニーソ", "袜", "stocking", "socks", "tights"]],
36
35
  [
@@ -71,6 +70,8 @@ const PRESET_NAME_HINTS = [
71
70
  ],
72
71
  ],
73
72
  ];
73
+ // Resolve a material name to a style category (override map first, then name hints), or
74
+ // null if nothing matches — a null-resolving material stays ungrouped (neutral default).
74
75
  function resolvePreset(materialName, map) {
75
76
  if (map) {
76
77
  for (const [preset, names] of Object.entries(map)) {
@@ -85,12 +86,11 @@ function resolvePreset(materialName, map) {
85
86
  return preset;
86
87
  }
87
88
  }
88
- return "mmd_classic";
89
+ return null;
89
90
  }
90
- // Default-group recipe per preset label: the shipped graph + its natural pass-integration
91
- // (renderClass, alphaMode). This is the auto-default-groups mapping (docs §8) — the same
92
- // label→integration knowledge the old fixed slots encoded, now producing editable groups.
93
- // mmd_classic has no entry — those materials stay ungrouped (hand-shader path).
91
+ // Default-group recipe per style category: the shipped graph + its natural pass-integration
92
+ // (renderClass, alphaMode). This is the auto-default-groups mapping — the same
93
+ // category→integration knowledge the old fixed slots encoded, now producing editable groups.
94
94
  const PRESET_GROUP_INFO = {
95
95
  default: { graph: DEFAULT_GRAPH, renderClass: "auto", alphaMode: "opaque" },
96
96
  face: { graph: FACE_GRAPH, renderClass: "auto", alphaMode: "opaque" },
@@ -3230,8 +3230,8 @@ export class Engine {
3230
3230
  if (!dc.baseBindGroupEntries)
3231
3231
  continue; // material draw calls only (skip outlines)
3232
3232
  const preset = resolvePreset(dc.materialName, overrides);
3233
- if (preset === "mmd_classic")
3234
- continue; // unmatched → ungrouped
3233
+ if (!preset)
3234
+ continue; // unmatched → stays ungrouped (neutral default)
3235
3235
  const arr = buckets.get(preset) ?? [];
3236
3236
  if (!arr.includes(dc.materialName))
3237
3237
  arr.push(dc.materialName);
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { Engine, DEFAULT_BLOOM_OPTIONS, DEFAULT_VIEW_TRANSFORM, type EngineStats, type EngineOptions, type BloomOptions, type ViewTransformOptions, type LoadModelFromFilesOptions, type MaterialPreset, type ResolvedMaterialPreset, type MaterialPresetMap, type GizmoDragEvent, type GizmoDragCallback, type GizmoDragKind, } from "./engine";
1
+ export { Engine, DEFAULT_BLOOM_OPTIONS, DEFAULT_VIEW_TRANSFORM, type EngineStats, type EngineOptions, type BloomOptions, type ViewTransformOptions, type LoadModelFromFilesOptions, type MaterialPreset, type MaterialPresetMap, type GizmoDragEvent, type GizmoDragCallback, type GizmoDragKind, } from "./engine";
2
2
  export { parsePmxFolderInput, pmxFileAtRelativePath, type PmxFolderInputResult } from "./folder-upload";
3
3
  export { compileGraph, validateGraph, assignStyleSlots, type CompileOptions, type CompileResult, type StyleSlot, } from "./graph/compile";
4
4
  export type { ShaderGraph, GraphNode, GraphLink, ExposedParam, SocketValue, Diagnostic, } from "./graph/schema";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACvG,OAAO,EACL,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,WAAW,EACX,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC7G,YAAY,EACV,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACvG,OAAO,EACL,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,WAAW,EACX,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC7G,YAAY,EACV,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA"}
@@ -1,4 +1,4 @@
1
- export declare const COMMON_BINDINGS_WGSL = "\n\nstruct CameraUniforms {\n view: mat4x4f,\n projection: mat4x4f,\n viewPos: vec3f,\n _padding: f32,\n};\n\nstruct Light {\n direction: vec4f,\n color: vec4f,\n};\n\nstruct LightUniforms {\n ambientColor: vec4f,\n lights: array<Light, 4>,\n};\n\n// Per-material uniforms. Every material binds this layout even if it ignores fields;\n// the engine keeps one bind group layout across all material pipelines. The PMX\n// classic-material fields (ambient/specular/toon/sphere) are consumed by the\n// mmd_classic preset; NPR presets ignore them.\nstruct MaterialUniforms {\n diffuseColor: vec3f, // PMX diffuse rgb (mmd_classic); reserved for others\n alpha: f32, // 0 \u2192 discard; <1 \u2192 transparent draw call\n ambient: vec3f, // PMX ambient rgb\n shininess: f32, // PMX specular power\n specular: vec3f, // PMX specular rgb\n sphereMode: f32, // 0 none \u00B7 1 multiply (sph) \u00B7 2 add (spa)\n // Skeleton index of the \u982D (head) bone, or -1. Lets the eye shader gate\n // the post-alpha-eye stencil by camera-vs-face hemisphere.\n headBoneIndex: f32,\n _pad0: f32,\n _pad1: f32,\n _pad2: f32,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) normal: vec3f,\n @location(1) uv: vec2f,\n @location(2) worldPos: vec3f,\n // Bind-pose object-space position (the raw pre-skin vertex attribute). Procedural\n // textures (noise bump, sparkle, Generated-coord gradients) key off this instead of\n // worldPos so the pattern rides with the surface \u2014 otherwise the mesh swims through a\n // world-static noise field under any skinning deformation or root (\u30BB\u30F3\u30BF\u30FC) motion.\n // At rest skinMats are identity so restPos == worldPos, which is why existing noise-\n // scale constants stay valid without retuning.\n @location(3) restPos: vec3f,\n};\n\nstruct LightVP { viewProj: mat4x4f, };\n\n@group(0) @binding(0) var<uniform> camera: CameraUniforms;\n@group(0) @binding(1) var<uniform> light: LightUniforms;\n@group(0) @binding(2) var diffuseSampler: sampler;\n@group(0) @binding(3) var shadowMap: texture_depth_2d;\n@group(0) @binding(4) var shadowSampler: sampler_comparison;\n@group(0) @binding(5) var<uniform> lightVP: LightVP;\n// binding(9) brdfLut is declared inside NODES_WGSL (nodes.ts).\n@group(1) @binding(0) var<storage, read> skinMats: array<mat4x4f>;\n@group(2) @binding(0) var diffuseTexture: texture_2d<f32>;\n@group(2) @binding(1) var<uniform> material: MaterialUniforms;\n// mmd_classic inputs; other presets leave them unread (fallback 1\u00D71 whites).\n@group(2) @binding(2) var toonTexture: texture_2d<f32>;\n@group(2) @binding(3) var sphereTexture: texture_2d<f32>;\n\n// Four-bone blended normals can cancel to ~zero on physics-driven parts\n// (opposing bone rotations at 50/50 weights) \u2014 normalize(0) is 0/0 = NaN,\n// which poisons the whole shading stack and flashes through bloom. Fall\n// back to up for degenerate normals instead.\nfn safe_normal(nIn: vec3f) -> vec3f {\n let l2 = dot(nIn, nIn);\n if (l2 < 1e-12) { return vec3f(0.0, 1.0, 0.0); }\n return nIn * inverseSqrt(l2);\n}\n\n";
1
+ export declare const COMMON_BINDINGS_WGSL = "\n\nstruct CameraUniforms {\n view: mat4x4f,\n projection: mat4x4f,\n viewPos: vec3f,\n _padding: f32,\n};\n\nstruct Light {\n direction: vec4f,\n color: vec4f,\n};\n\nstruct LightUniforms {\n ambientColor: vec4f,\n lights: array<Light, 4>,\n};\n\n// Per-material uniforms. Every material binds this layout even if it ignores fields;\n// the engine keeps one bind group layout across all material pipelines. The PMX\n// classic-material fields (ambient/specular/shininess) are carried for graph nodes that\n// want them; most graphs read only diffuseColor + alpha.\nstruct MaterialUniforms {\n diffuseColor: vec3f, // PMX diffuse rgb \u2014 the material_diffuse node reads this\n alpha: f32, // 0 \u2192 discard; <1 \u2192 transparent draw call\n ambient: vec3f, // PMX ambient rgb\n shininess: f32, // PMX specular power\n specular: vec3f, // PMX specular rgb\n sphereMode: f32, // 0 none \u00B7 1 multiply (sph) \u00B7 2 add (spa)\n // Skeleton index of the \u982D (head) bone, or -1. Lets the eye shader gate\n // the post-alpha-eye stencil by camera-vs-face hemisphere.\n headBoneIndex: f32,\n _pad0: f32,\n _pad1: f32,\n _pad2: f32,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) normal: vec3f,\n @location(1) uv: vec2f,\n @location(2) worldPos: vec3f,\n // Bind-pose object-space position (the raw pre-skin vertex attribute). Procedural\n // textures (noise bump, sparkle, Generated-coord gradients) key off this instead of\n // worldPos so the pattern rides with the surface \u2014 otherwise the mesh swims through a\n // world-static noise field under any skinning deformation or root (\u30BB\u30F3\u30BF\u30FC) motion.\n // At rest skinMats are identity so restPos == worldPos, which is why existing noise-\n // scale constants stay valid without retuning.\n @location(3) restPos: vec3f,\n};\n\nstruct LightVP { viewProj: mat4x4f, };\n\n@group(0) @binding(0) var<uniform> camera: CameraUniforms;\n@group(0) @binding(1) var<uniform> light: LightUniforms;\n@group(0) @binding(2) var diffuseSampler: sampler;\n@group(0) @binding(3) var shadowMap: texture_depth_2d;\n@group(0) @binding(4) var shadowSampler: sampler_comparison;\n@group(0) @binding(5) var<uniform> lightVP: LightVP;\n// binding(9) brdfLut is declared inside NODES_WGSL (nodes.ts).\n@group(1) @binding(0) var<storage, read> skinMats: array<mat4x4f>;\n@group(2) @binding(0) var diffuseTexture: texture_2d<f32>;\n@group(2) @binding(1) var<uniform> material: MaterialUniforms;\n// Reserved for future sphere/toon graph nodes; graphs that don't read them get the\n// 1\u00D71 white fallback bound here.\n@group(2) @binding(2) var toonTexture: texture_2d<f32>;\n@group(2) @binding(3) var sphereTexture: texture_2d<f32>;\n\n// Four-bone blended normals can cancel to ~zero on physics-driven parts\n// (opposing bone rotations at 50/50 weights) \u2014 normalize(0) is 0/0 = NaN,\n// which poisons the whole shading stack and flashes through bloom. Fall\n// back to up for degenerate normals instead.\nfn safe_normal(nIn: vec3f) -> vec3f {\n let l2 = dot(nIn, nIn);\n if (l2 < 1e-12) { return vec3f(0.0, 1.0, 0.0); }\n return nIn * inverseSqrt(l2);\n}\n\n";
2
2
  export declare const SAMPLE_SHADOW_WGSL = "\n\nfn sampleShadow(worldPos: vec3f, n: vec3f) -> f32 {\n if (dot(n, -light.lights[0].direction.xyz) <= 0.0) { return 0.0; }\n let biasedPos = worldPos + n * 0.08;\n let lclip = lightVP.viewProj * vec4f(biasedPos, 1.0);\n let ndc = lclip.xyz / max(lclip.w, 1e-6);\n let suv = vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5);\n let cmpZ = ndc.z - 0.001;\n let ts = 1.0 / 2048.0;\n let s00 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f(-ts, -ts), cmpZ);\n let s10 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f(0.0, -ts), cmpZ);\n let s20 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f( ts, -ts), cmpZ);\n let s01 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f(-ts, 0.0), cmpZ);\n let s11 = textureSampleCompareLevel(shadowMap, shadowSampler, suv, cmpZ);\n let s21 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f( ts, 0.0), cmpZ);\n let s02 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f(-ts, ts), cmpZ);\n let s12 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f(0.0, ts), cmpZ);\n let s22 = textureSampleCompareLevel(shadowMap, shadowSampler, suv + vec2f( ts, ts), cmpZ);\n return (s00 + s10 + s20 + s01 + s11 + s21 + s02 + s12 + s22) * (1.0 / 9.0);\n}\n\n";
3
3
  export declare const COMMON_VS_WGSL = "\n\n@vertex fn vs(\n @location(0) position: vec3f,\n @location(1) normal: vec3f,\n @location(2) uv: vec2f,\n @location(3) joints0: vec4<u32>,\n @location(4) weights0: vec4<f32>\n) -> VertexOutput {\n var output: VertexOutput;\n let pos4 = vec4f(position, 1.0);\n let weightSum = weights0.x + weights0.y + weights0.z + weights0.w;\n let invWeightSum = select(1.0, 1.0 / weightSum, weightSum > 0.0001);\n let nw = select(vec4f(1.0, 0.0, 0.0, 0.0), weights0 * invWeightSum, weightSum > 0.0001);\n var skinnedPos = vec4f(0.0);\n var skinnedNrm = vec3f(0.0);\n for (var i = 0u; i < 4u; i++) {\n let m = skinMats[joints0[i]];\n let w = nw[i];\n skinnedPos += (m * pos4) * w;\n skinnedNrm += (mat3x3f(m[0].xyz, m[1].xyz, m[2].xyz) * normal) * w;\n }\n output.position = camera.projection * camera.view * vec4f(skinnedPos.xyz, 1.0);\n output.normal = skinnedNrm;\n output.uv = uv;\n output.worldPos = skinnedPos.xyz;\n output.restPos = position;\n return output;\n}\n\n";
4
4
  export declare const COMMON_FS_OUT_WGSL = "\n\nstruct FSOut {\n @location(0) color: vec4f,\n @location(1) mask: vec4f,\n};\n\n";
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/shaders/materials/common.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,oBAAoB,ulGA8EhC,CAAC;AAOF,eAAO,MAAM,kBAAkB,4xCAsB9B,CAAC;AAQF,eAAO,MAAM,cAAc,s+BA8B1B,CAAC;AAsBF,eAAO,MAAM,kBAAkB,0FAO9B,CAAC;AAMF,eAAO,MAAM,4BAA4B,QACwC,CAAA"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/shaders/materials/common.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,oBAAoB,8pGA+EhC,CAAC;AAOF,eAAO,MAAM,kBAAkB,4xCAsB9B,CAAC;AAQF,eAAO,MAAM,cAAc,s+BA8B1B,CAAC;AAsBF,eAAO,MAAM,kBAAkB,0FAO9B,CAAC;AAMF,eAAO,MAAM,4BAA4B,QACwC,CAAA"}
@@ -39,10 +39,10 @@ struct LightUniforms {
39
39
 
40
40
  // Per-material uniforms. Every material binds this layout even if it ignores fields;
41
41
  // the engine keeps one bind group layout across all material pipelines. The PMX
42
- // classic-material fields (ambient/specular/toon/sphere) are consumed by the
43
- // mmd_classic preset; NPR presets ignore them.
42
+ // classic-material fields (ambient/specular/shininess) are carried for graph nodes that
43
+ // want them; most graphs read only diffuseColor + alpha.
44
44
  struct MaterialUniforms {
45
- diffuseColor: vec3f, // PMX diffuse rgb (mmd_classic); reserved for others
45
+ diffuseColor: vec3f, // PMX diffuse rgb the material_diffuse node reads this
46
46
  alpha: f32, // 0 → discard; <1 → transparent draw call
47
47
  ambient: vec3f, // PMX ambient rgb
48
48
  shininess: f32, // PMX specular power
@@ -82,7 +82,8 @@ struct LightVP { viewProj: mat4x4f, };
82
82
  @group(1) @binding(0) var<storage, read> skinMats: array<mat4x4f>;
83
83
  @group(2) @binding(0) var diffuseTexture: texture_2d<f32>;
84
84
  @group(2) @binding(1) var<uniform> material: MaterialUniforms;
85
- // mmd_classic inputs; other presets leave them unread (fallback 1×1 whites).
85
+ // Reserved for future sphere/toon graph nodes; graphs that don't read them get the
86
+ // 1×1 white fallback bound here.
86
87
  @group(2) @binding(2) var toonTexture: texture_2d<f32>;
87
88
  @group(2) @binding(3) var sphereTexture: texture_2d<f32>;
88
89
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "description": "A lightweight WebGPU engine for real-time 3D MMD/PMX model rendering",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/engine.ts CHANGED
@@ -62,20 +62,12 @@ export type MaterialPreset =
62
62
  | "cloth_smooth"
63
63
  | "cloth_rough"
64
64
 
65
- // What a draw call actually resolves to. "mmd_classic" is the automatic
66
- // authentic-MMD fallback for materials no preset map or name heuristic
67
- // covers — deliberately NOT part of MaterialPreset, so consumer-side
68
- // exhaustive Record<MaterialPreset, …> maps and switches don't have to
69
- // carry an option users never assign.
70
- export type ResolvedMaterialPreset = MaterialPreset | "mmd_classic"
71
-
72
65
  export type MaterialPresetMap = Partial<Record<MaterialPreset, string[]>>
73
66
 
74
- // Substring hints mapping common PMX material names (JP/CN/EN) to presets,
75
- // tried when a material isn't in the model's explicit MaterialPresetMap.
76
- // Ordered: more specific families first (靴下 must hit stockings before 靴
77
- // hits cloth). Anything unmatched falls through to mmd_classic, which renders
78
- // the author-tuned PMX material data faithfully.
67
+ // Substring hints mapping common PMX material names (JP/CN/EN) to a style category,
68
+ // tried when a material isn't in the caller's explicit override map. Ordered: more
69
+ // specific families first (靴下 must hit stockings before 靴 hits cloth). A material
70
+ // matching nothing resolves to null it stays ungrouped (neutral default).
79
71
  const PRESET_NAME_HINTS: Array<[MaterialPreset, string[]]> = [
80
72
  ["stockings", ["靴下", "ソックス", "タイツ", "ニーソ", "袜", "stocking", "socks", "tights"]],
81
73
  [
@@ -117,7 +109,9 @@ const PRESET_NAME_HINTS: Array<[MaterialPreset, string[]]> = [
117
109
  ],
118
110
  ]
119
111
 
120
- function resolvePreset(materialName: string, map: MaterialPresetMap | undefined): ResolvedMaterialPreset {
112
+ // Resolve a material name to a style category (override map first, then name hints), or
113
+ // null if nothing matches — a null-resolving material stays ungrouped (neutral default).
114
+ function resolvePreset(materialName: string, map: MaterialPresetMap | undefined): MaterialPreset | null {
121
115
  if (map) {
122
116
  for (const [preset, names] of Object.entries(map)) {
123
117
  if (names && names.includes(materialName)) return preset as MaterialPreset
@@ -129,13 +123,12 @@ function resolvePreset(materialName: string, map: MaterialPresetMap | undefined)
129
123
  if (lower.includes(hint)) return preset
130
124
  }
131
125
  }
132
- return "mmd_classic"
126
+ return null
133
127
  }
134
128
 
135
- // Default-group recipe per preset label: the shipped graph + its natural pass-integration
136
- // (renderClass, alphaMode). This is the auto-default-groups mapping (docs §8) — the same
137
- // label→integration knowledge the old fixed slots encoded, now producing editable groups.
138
- // mmd_classic has no entry — those materials stay ungrouped (hand-shader path).
129
+ // Default-group recipe per style category: the shipped graph + its natural pass-integration
130
+ // (renderClass, alphaMode). This is the auto-default-groups mapping — the same
131
+ // category→integration knowledge the old fixed slots encoded, now producing editable groups.
139
132
  const PRESET_GROUP_INFO: Partial<Record<MaterialPreset, { graph: ShaderGraph; renderClass: RenderClass; alphaMode: AlphaMode }>> = {
140
133
  default: { graph: DEFAULT_GRAPH, renderClass: "auto", alphaMode: "opaque" },
141
134
  face: { graph: FACE_GRAPH, renderClass: "auto", alphaMode: "opaque" },
@@ -3972,7 +3965,7 @@ export class Engine {
3972
3965
  for (const dc of inst.drawCalls) {
3973
3966
  if (!dc.baseBindGroupEntries) continue // material draw calls only (skip outlines)
3974
3967
  const preset = resolvePreset(dc.materialName, overrides)
3975
- if (preset === "mmd_classic") continue // unmatched → ungrouped
3968
+ if (!preset) continue // unmatched → stays ungrouped (neutral default)
3976
3969
  const arr = buckets.get(preset) ?? []
3977
3970
  if (!arr.includes(dc.materialName)) arr.push(dc.materialName)
3978
3971
  buckets.set(preset, arr)
package/src/index.ts CHANGED
@@ -8,7 +8,6 @@ export {
8
8
  type ViewTransformOptions,
9
9
  type LoadModelFromFilesOptions,
10
10
  type MaterialPreset,
11
- type ResolvedMaterialPreset,
12
11
  type MaterialPresetMap,
13
12
  type GizmoDragEvent,
14
13
  type GizmoDragCallback,
@@ -41,10 +41,10 @@ struct LightUniforms {
41
41
 
42
42
  // Per-material uniforms. Every material binds this layout even if it ignores fields;
43
43
  // the engine keeps one bind group layout across all material pipelines. The PMX
44
- // classic-material fields (ambient/specular/toon/sphere) are consumed by the
45
- // mmd_classic preset; NPR presets ignore them.
44
+ // classic-material fields (ambient/specular/shininess) are carried for graph nodes that
45
+ // want them; most graphs read only diffuseColor + alpha.
46
46
  struct MaterialUniforms {
47
- diffuseColor: vec3f, // PMX diffuse rgb (mmd_classic); reserved for others
47
+ diffuseColor: vec3f, // PMX diffuse rgb the material_diffuse node reads this
48
48
  alpha: f32, // 0 → discard; <1 → transparent draw call
49
49
  ambient: vec3f, // PMX ambient rgb
50
50
  shininess: f32, // PMX specular power
@@ -84,7 +84,8 @@ struct LightVP { viewProj: mat4x4f, };
84
84
  @group(1) @binding(0) var<storage, read> skinMats: array<mat4x4f>;
85
85
  @group(2) @binding(0) var diffuseTexture: texture_2d<f32>;
86
86
  @group(2) @binding(1) var<uniform> material: MaterialUniforms;
87
- // mmd_classic inputs; other presets leave them unread (fallback 1×1 whites).
87
+ // Reserved for future sphere/toon graph nodes; graphs that don't read them get the
88
+ // 1×1 white fallback bound here.
88
89
  @group(2) @binding(2) var toonTexture: texture_2d<f32>;
89
90
  @group(2) @binding(3) var sphereTexture: texture_2d<f32>;
90
91
 
@@ -1,97 +0,0 @@
1
- // M_Body — 仿深空之眼渲染预设v1.0_by_小绿毛猫 "M_Body". Toon + warm rim + rim1/rim2
2
- // stack mixed 50/50 against a Principled BSDF with noise-bumped normal.
3
-
4
- import { NODES_WGSL } from "./nodes"
5
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
6
-
7
- export const BODY_SHADER_WGSL = /* wgsl */ `
8
-
9
- ${NODES_WGSL}
10
- ${COMMON_MATERIAL_PRELUDE_WGSL}
11
-
12
- const BODY_ROUGHNESS: f32 = 0.3;
13
- const BODY_SPECULAR: f32 = 0.5;
14
- const BODY_MIX_NPR: f32 = 0.5;
15
- const BODY_SPEC_CLAMP: f32 = 10.0;
16
- const BODY_RIM2_LAYER_BLEND: f32 = 0.20000000298023224;
17
- const BODY_RIM2_POW: f32 = 1.4300000667572021;
18
- const BODY_RIM2_BG: vec3f = vec3f(1.0, 0.4303792119026184, 0.3315804898738861);
19
- const BODY_WARM_STR: f32 = 0.30000001192092896;
20
-
21
- // smoothstep-based ramp: t*t*(3-2*t) between two color stops
22
- fn ramp_ease(f: f32, p0: f32, c0: vec4f, p1: f32, c1: vec4f) -> vec4f {
23
- let t = saturate((f - p0) / max(p1 - p0, 1e-6));
24
- let ss = t * t * (3.0 - 2.0 * t);
25
- return mix(c0, c1, ss);
26
- }
27
-
28
- @fragment fn fs(input: VertexOutput) -> FSOut {
29
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
30
- // MMD alpha semantics: material alpha × texture alpha. Hair/lace/accessory
31
- // textures cut their shapes in the alpha channel — ignoring it renders each
32
- // card's full quad with the texture's padding color (white shimmer on dark
33
- // hair for models whose textures pad with white).
34
- let alpha = material.alpha * tex_s.a;
35
- if (alpha < 0.001) { discard; }
36
-
37
- let n = safe_normal(input.normal);
38
- let v = normalize(camera.viewPos - input.worldPos);
39
- let l = -light.lights[0].direction.xyz;
40
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
41
- let amb = light.ambientColor.xyz;
42
- let shadow = sampleShadow(input.worldPos, n);
43
-
44
- let tex_color = tex_s.rgb;
45
-
46
- // ═══ NPR STACK ═══
47
- let ndotl_raw = shader_to_rgb_diffuse(n, l, sun, amb, shadow);
48
- let toon = ramp_constant(ndotl_raw, 0.0, vec4f(0,0,0,1), 0.2966, vec4f(1,1,1,1)).r;
49
-
50
- let shadow_tint = hue_sat_id(2.0, 0.3499999940395355, 1.0, tex_color);
51
- let lit_tint = hue_sat_id(1.5, 1.0, 1.0, tex_color);
52
- let toon_color = mix_blend(toon, shadow_tint, lit_tint);
53
- let bc = bright_contrast(toon_color, 0.1, 0.2);
54
-
55
- let emission3 = bc * 4.0;
56
-
57
- let warm_input = clamp(toon + 0.5, 0.0, 1.0);
58
- let warm_color = ramp_cardinal(warm_input, 0.2409,
59
- vec4f(0.2426, 0.068, 0.0588, 1.0), 0.4663,
60
- vec4f(0.6677, 0.5024, 0.5126, 1.0)).rgb;
61
- let warm_emission = warm_color * BODY_WARM_STR;
62
-
63
- let rim1_str = fresnel(2.0, n, v) * layer_weight_facing(0.24000005424022675, n, v);
64
- let rim1 = vec3f(0.984157919883728, 0.6110184788703918, 0.5736401677131653) * rim1_str;
65
-
66
- let facing_raw = layer_weight_facing(BODY_RIM2_LAYER_BLEND, n, v);
67
- let facing_pow = math_power(facing_raw, BODY_RIM2_POW);
68
- let rim2_fac = ramp_ease(facing_pow, 0.0, vec4f(0,0,0,1), 0.5052, vec4f(1,1,1,1)).r;
69
- let rim2_mixed = mix(emission3, BODY_RIM2_BG, rim2_fac);
70
-
71
- let npr_stack = rim1 + rim2_mixed + warm_emission;
72
-
73
- // ═══ PRINCIPLED BSDF with noise bump ═══
74
- // Mapping loc=rot=0 in the Blender graph folds to a plain scale multiply.
75
- // Height in rest space (restPos) so the bump rides with the skin; geometric basis stays
76
- // worldPos so the perturbed normal matches the world-space n (see face.ts note).
77
- let noise_val = tex_noise_d2(input.restPos * vec3f(1.0, 1.0, 1.5), 1.0);
78
- let noise_ramp = ramp_linear(noise_val, 0.0, vec4f(0,0,0,1), 1.0, vec4f(1,1,1,1)).r;
79
- let bumped_n = bump_lh(0.324644535779953, noise_ramp, n, input.worldPos);
80
-
81
- let principled_base = mix_blend(noise_ramp, bc, vec3f(0.6831911206245422, 0.19474034011363983, 0.13732507824897766));
82
- let p_emission = bc * 0.2;
83
-
84
- let principled = eval_principled(
85
- PrincipledIn(principled_base, 0.0, BODY_SPECULAR, BODY_ROUGHNESS, BODY_SPEC_CLAMP, 0.0, 0.0),
86
- bumped_n, l, v, sun, amb, shadow
87
- ) + p_emission;
88
-
89
- let final_color = mix(npr_stack, principled, BODY_MIX_NPR);
90
-
91
- var out: FSOut;
92
- out.color = vec4f(final_color, alpha);
93
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
94
- return out;
95
- }
96
-
97
- `
@@ -1,71 +0,0 @@
1
- // M_Rough_Cloth — NPR graph identical to M_Smooth_Cloth, but the noise bump subtree
2
- // IS live on Principled.Normal and Roughness is raised to 0.8187.
3
-
4
- import { NODES_WGSL } from "./nodes"
5
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
6
-
7
- export const CLOTH_ROUGH_SHADER_WGSL = /* wgsl */ `
8
-
9
- ${NODES_WGSL}
10
- ${COMMON_MATERIAL_PRELUDE_WGSL}
11
-
12
- const CLOTH_R_SPECULAR: f32 = 0.8;
13
- const CLOTH_R_ROUGHNESS: f32 = 0.8187;
14
- const CLOTH_R_TOON_EDGE: f32 = 0.2966;
15
- const CLOTH_R_MIX04_MUL: f32 = 0.5;
16
- const CLOTH_R_EMIT_STR: f32 = 18.200000762939453;
17
- const CLOTH_R_MIX_SHADER_FAC: f32 = 0.8999999761581421;
18
- const CLOTH_R_NOISE_SCALE: f32 = 17.7;
19
- const CLOTH_R_BUMP_STR: f32 = 1.0;
20
- const CLOTH_R_SPEC_CLAMP: f32 = 10.0;
21
-
22
- @fragment fn fs(input: VertexOutput) -> FSOut {
23
- let n = safe_normal(input.normal);
24
- let v = normalize(camera.viewPos - input.worldPos);
25
- let l = -light.lights[0].direction.xyz;
26
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
27
- let amb = light.ambientColor.xyz;
28
- let shadow = sampleShadow(input.worldPos, n);
29
-
30
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
31
- let tex_rgb = tex_s.rgb;
32
- let out_alpha = material.alpha * tex_s.a;
33
- if (out_alpha < 0.001) { discard; }
34
-
35
- // ═══ NPR STACK ═══
36
- let lum_shade = shader_to_rgb_diffuse(n, l, sun, amb, shadow);
37
- let ramp008 = ramp_constant_edge_aa(lum_shade, CLOTH_R_TOON_EDGE, vec4f(0,0,0,1), vec4f(1,1,1,1));
38
- let mix04_fac = math_multiply(ramp008.r, CLOTH_R_MIX04_MUL);
39
-
40
- let dark_tex = hue_sat_id(1.0, 0.19999998807907104, 1.0, tex_rgb);
41
- let mix04 = mix_blend(mix04_fac, dark_tex, tex_rgb);
42
-
43
- let bevel_z = clamp(n.y, 0.0, 1.0);
44
- let mix03 = mix_blend(bevel_z, mix04, dark_tex);
45
-
46
- let hue004 = hue_sat_id(0.800000011920929, 2.0, 1.0, mix03);
47
- let npr_rgb = mix_overlay(1.0, mix03, hue004);
48
- let npr_emission = npr_rgb * CLOTH_R_EMIT_STR;
49
-
50
- // ═══ PRINCIPLED BSDF with noise bump (live in this preset) ═══
51
- // Height in rest space (restPos) so the weave doesn't swim; geometric basis stays
52
- // worldPos so the perturbed normal matches the world-space n (see face.ts note).
53
- let noise_val = tex_noise_d2(input.restPos, CLOTH_R_NOISE_SCALE);
54
- let noise_ramp = ramp_linear(noise_val, 0.0, vec4f(0,0,0,1), 1.0, vec4f(1,1,1,1)).r;
55
- let bumped_n = bump_lh(CLOTH_R_BUMP_STR, noise_ramp, n, input.worldPos);
56
-
57
- let principled_base = hue_sat_id(1.0, 0.800000011920929, 1.0, tex_rgb);
58
- let principled = eval_principled(
59
- PrincipledIn(principled_base, 0.0, CLOTH_R_SPECULAR, CLOTH_R_ROUGHNESS, CLOTH_R_SPEC_CLAMP, 0.0, 0.0),
60
- bumped_n, l, v, sun, amb, shadow
61
- );
62
-
63
- let final_color = mix(npr_emission, principled, CLOTH_R_MIX_SHADER_FAC);
64
-
65
- var out: FSOut;
66
- out.color = vec4f(final_color, out_alpha);
67
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
68
- return out;
69
- }
70
-
71
- `
@@ -1,63 +0,0 @@
1
- // M_Smooth_Cloth — NPR toon + bevel + overlay-boosted emission mixed 10/90 against
2
- // a plain Principled BSDF. Bump subtree is dead in the Blender graph.
3
-
4
- import { NODES_WGSL } from "./nodes"
5
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
6
-
7
- export const CLOTH_SMOOTH_SHADER_WGSL = /* wgsl */ `
8
-
9
- ${NODES_WGSL}
10
- ${COMMON_MATERIAL_PRELUDE_WGSL}
11
-
12
- const CLOTH_SPECULAR: f32 = 0.8;
13
- const CLOTH_ROUGHNESS: f32 = 0.5;
14
- const CLOTH_TOON_EDGE: f32 = 0.2966;
15
- const CLOTH_MIX04_MUL: f32 = 0.5;
16
- const NPR_EMIT_STR: f32 = 18.200000762939453;
17
- const NPR_MIX_SHADER_FAC: f32 = 0.8999999761581421;
18
-
19
- @fragment fn fs(input: VertexOutput) -> FSOut {
20
- let n = safe_normal(input.normal);
21
- let v = normalize(camera.viewPos - input.worldPos);
22
- let l = -light.lights[0].direction.xyz;
23
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
24
- let amb = light.ambientColor.xyz;
25
- let shadow = sampleShadow(input.worldPos, n);
26
-
27
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
28
- let tex_rgb = tex_s.rgb;
29
- let out_alpha = material.alpha * tex_s.a;
30
- if (out_alpha < 0.001) { discard; }
31
-
32
- // ═══ NPR STACK ═══
33
- let lum_shade = shader_to_rgb_diffuse(n, l, sun, amb, shadow);
34
- let ramp008 = ramp_constant_edge_aa(lum_shade, CLOTH_TOON_EDGE, vec4f(0,0,0,1), vec4f(1,1,1,1));
35
- let mix04_fac = math_multiply(ramp008.r, CLOTH_MIX04_MUL);
36
-
37
- let dark_tex = hue_sat_id(1.0, 0.19999998807907104, 1.0, tex_rgb);
38
- let mix04 = mix_blend(mix04_fac, dark_tex, tex_rgb);
39
-
40
- let bevel_z = clamp(n.y, 0.0, 1.0);
41
- let mix03 = mix_blend(bevel_z, mix04, dark_tex);
42
-
43
- let hue004 = hue_sat_id(0.800000011920929, 2.0, 1.0, mix03);
44
- let npr_rgb = mix_overlay(1.0, mix03, hue004);
45
- let npr_emission = npr_rgb * NPR_EMIT_STR;
46
-
47
- // ═══ PRINCIPLED BSDF ═══
48
- let principled_base = hue_sat_id(1.0, 0.800000011920929, 1.0, tex_rgb);
49
- let principled = eval_principled(
50
- PrincipledIn(principled_base, 0.0, CLOTH_SPECULAR, CLOTH_ROUGHNESS, 10.0, 0.0, 0.0),
51
- n, l, v, sun, amb, shadow
52
- );
53
-
54
- // MixShader.001: Shader=自发光.005, Shader_001=原理化BSDF, Fac=0.9
55
- let final_color = mix(npr_emission, principled, NPR_MIX_SHADER_FAC);
56
-
57
- var out: FSOut;
58
- out.color = vec4f(final_color, out_alpha);
59
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
60
- return out;
61
- }
62
-
63
- `
@@ -1,45 +0,0 @@
1
- // Default material — Blender 3.6 Principled BSDF defaults, no NPR stack.
2
- // Metallic=0, Specular=0.5 (F0=0.04), Roughness=0.5. Serves as the EEVEE reference
3
- // path that every NPR material mixes against in its final stage.
4
-
5
- import { NODES_WGSL } from "./nodes"
6
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
7
-
8
- export const DEFAULT_SHADER_WGSL = /* wgsl */ `
9
-
10
- ${NODES_WGSL}
11
- ${COMMON_MATERIAL_PRELUDE_WGSL}
12
-
13
- const DEFAULT_SPECULAR: f32 = 0.5;
14
- const DEFAULT_ROUGHNESS: f32 = 0.5;
15
-
16
- @fragment fn fs(input: VertexOutput) -> FSOut {
17
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
18
- // MMD alpha semantics: material alpha × texture alpha. Hair/lace/accessory
19
- // textures cut their shapes in the alpha channel — ignoring it renders each
20
- // card's full quad with the texture's padding color (white shimmer on dark
21
- // hair for models whose textures pad with white).
22
- let alpha = material.alpha * tex_s.a;
23
- if (alpha < 0.001) { discard; }
24
-
25
- let n = safe_normal(input.normal);
26
- let v = normalize(camera.viewPos - input.worldPos);
27
- let l = -light.lights[0].direction.xyz;
28
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
29
- let amb = light.ambientColor.xyz;
30
- let shadow = sampleShadow(input.worldPos, n);
31
-
32
- let albedo = tex_s.rgb;
33
-
34
- let color = eval_principled(
35
- PrincipledIn(albedo, 0.0, DEFAULT_SPECULAR, DEFAULT_ROUGHNESS, 10.0, 0.0, 0.0),
36
- n, l, v, sun, amb, shadow
37
- );
38
-
39
- var out: FSOut;
40
- out.color = vec4f(color, alpha);
41
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
42
- return out;
43
- }
44
-
45
- `
@@ -1,62 +0,0 @@
1
- // Eye preset — default Principled BSDF + Emission socket set to albedo × 1.5.
2
- // Matches the published preset author's instruction: "keep eyes in the default
3
- // nodegraph, add emission 1.5". Emission feeds bloom pre-tonemap.
4
-
5
- import { NODES_WGSL } from "./nodes"
6
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
7
-
8
- export const EYE_SHADER_WGSL = /* wgsl */ `
9
-
10
- ${NODES_WGSL}
11
- ${COMMON_MATERIAL_PRELUDE_WGSL}
12
-
13
- const EYE_SPECULAR: f32 = 0.5;
14
- const EYE_ROUGHNESS: f32 = 0.5;
15
- const EYE_EMISSION_STRENGTH: f32 = 1.5;
16
-
17
- @fragment fn fs(input: VertexOutput) -> FSOut {
18
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
19
- // MMD alpha semantics: material alpha × texture alpha. Hair/lace/accessory
20
- // textures cut their shapes in the alpha channel — ignoring it renders each
21
- // card's full quad with the texture's padding color (white shimmer on dark
22
- // hair for models whose textures pad with white).
23
- let alpha = material.alpha * tex_s.a;
24
- if (alpha < 0.001) { discard; }
25
-
26
- let n = safe_normal(input.normal);
27
- let v = normalize(camera.viewPos - input.worldPos);
28
-
29
- // Rear-view gate for the post-alpha eye. Many PMX heads are open shells
30
- // (no skull mesh), so from behind nothing occludes the eye — it would draw
31
- // and stamp the see-through stencil straight through the back hair. Mesh
32
- // normals/winding are unreliable (double-sided eye geometry), so gate by
33
- // camera-vs-face hemisphere instead: the 頭 bone's skinning matrix carries
34
- // the head's world rotation (PMX bind pose is rotationless), and PMX
35
- // models face −Z locally. Discard drops color, depth, and stencil.
36
- if (material.headBoneIndex >= 0.0) {
37
- let hm = skinMats[u32(material.headBoneIndex)];
38
- let faceDir = -normalize(hm[2].xyz);
39
- if (dot(faceDir, v) < -0.15) { discard; }
40
- }
41
-
42
- let l = -light.lights[0].direction.xyz;
43
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
44
- let amb = light.ambientColor.xyz;
45
- let shadow = sampleShadow(input.worldPos, n);
46
-
47
- let albedo = tex_s.rgb;
48
-
49
- let shaded = eval_principled(
50
- PrincipledIn(albedo, 0.0, EYE_SPECULAR, EYE_ROUGHNESS, 1e30, 0.0, 0.0),
51
- n, l, v, sun, amb, shadow
52
- );
53
- // Principled Emission socket: emissive = emission_color × strength, added on top.
54
- let emission = albedo * EYE_EMISSION_STRENGTH;
55
-
56
- var out: FSOut;
57
- out.color = vec4f(shaded + emission, alpha);
58
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
59
- return out;
60
- }
61
-
62
- `
@@ -1,97 +0,0 @@
1
- // M_Face — 仿深空之眼渲染预设v1.0_by_小绿毛猫 "M_Face". Toon + warm rim + dual fresnel
2
- // rim + BT.601 bright-tex gate, mixed 50/50 against a Principled BSDF with noise bump.
3
-
4
- import { NODES_WGSL } from "./nodes"
5
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
6
-
7
- export const FACE_SHADER_WGSL = /* wgsl */ `
8
-
9
- ${NODES_WGSL}
10
- ${COMMON_MATERIAL_PRELUDE_WGSL}
11
-
12
- const FACE_SPECULAR: f32 = 0.5;
13
- const FACE_ROUGHNESS: f32 = 0.3;
14
- const FACE_MIX_NPR: f32 = 0.5;
15
- const FACE_SPEC_CLAMP: f32 = 10.0;
16
- const FACE_RIM2_POW: f32 = 0.6300000548362732;
17
- const FACE_RIM2_BG: vec3f = vec3f(1.0, 0.4684903025627136, 0.3698573112487793);
18
- const FACE_WARM_STR: f32 = 0.30000001192092896;
19
- const FACE_BRIGHT_TEX_THRESH: f32 = 0.9300000071525574;
20
-
21
- @fragment fn fs(input: VertexOutput) -> FSOut {
22
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
23
- // MMD alpha semantics: material alpha × texture alpha. Hair/lace/accessory
24
- // textures cut their shapes in the alpha channel — ignoring it renders each
25
- // card's full quad with the texture's padding color (white shimmer on dark
26
- // hair for models whose textures pad with white).
27
- let alpha = material.alpha * tex_s.a;
28
- if (alpha < 0.001) { discard; }
29
-
30
- let n = safe_normal(input.normal);
31
- let v = normalize(camera.viewPos - input.worldPos);
32
- let l = -light.lights[0].direction.xyz;
33
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
34
- let amb = light.ambientColor.xyz;
35
- let shadow = sampleShadow(input.worldPos, n);
36
-
37
- let tex_color = tex_s.rgb;
38
-
39
- // ═══ NPR STACK ═══
40
- let ndotl_raw = shader_to_rgb_diffuse(n, l, sun, amb, shadow);
41
- // ramp_constant_edge_aa: avoids binary fac shimmer on terminator (fwidth + smoothstep).
42
- let toon = ramp_constant_edge_aa(ndotl_raw, 0.2966, vec4f(0,0,0,1), vec4f(1,1,1,1)).r;
43
-
44
- let shadow_tint = hue_sat(0.46000000834465027, 2.0, 0.3499999940395355, 1.0, tex_color);
45
- let lit_tint = hue_sat(0.46000000834465027, 1.600000023841858, 1.5, 1.0, tex_color);
46
- let toon_color = mix_blend(toon, shadow_tint, lit_tint);
47
- let bc = bright_contrast(toon_color, 0.1, 0.2);
48
-
49
- let emission3 = bc * 2.5;
50
-
51
- let warm_input = clamp(toon * 0.5 + 0.5, 0.0, 1.0);
52
- let warm_color = ramp_cardinal(warm_input, 0.2409,
53
- vec4f(0.2426, 0.068, 0.0588, 1.0), 0.4663,
54
- vec4f(0.6677, 0.5024, 0.5126, 1.0)).rgb;
55
- let warm_emission = warm_color * FACE_WARM_STR;
56
-
57
- let rim1_str = fresnel(2.0, n, v) * layer_weight_facing(0.24, n, v);
58
- let rim1 = vec3f(0.984157919883728, 0.6110184788703918, 0.5736401677131653) * rim1_str;
59
-
60
- let rim2_raw = fresnel(1.45, n, v) * layer_weight_fresnel(0.61, n, v);
61
- let rim2_fac = math_power(rim2_raw, FACE_RIM2_POW);
62
- let rim2_mixed = mix(emission3, FACE_RIM2_BG, rim2_fac);
63
-
64
- // Blender implicitly converts Color → Float via BT.601 grayscale when a color output
65
- // feeds a Math node's Value input. Using tex_color.r instead fires on R-dominant skin
66
- // and produces firefly speckles on near-white R pixels — color_to_value matches the
67
- // Blender socket semantic and only gates genuinely near-white painted features.
68
- let tex_gate = math_greater_than(color_to_value(tex_color), FACE_BRIGHT_TEX_THRESH);
69
- let bright_emit = vec3f(tex_gate) * 3.0;
70
-
71
- let npr_stack = rim1 + rim2_mixed + bright_emit + warm_emission;
72
-
73
- // ═══ PRINCIPLED BSDF with noise bump ═══
74
- // Height sampled in rest space (restPos) so the micro-bump doesn't swim under motion;
75
- // bump_lh's geometric basis stays in worldPos so the perturbed normal lands in the same
76
- // world frame as n (screen-space height gradient still pairs correctly with it).
77
- let noise_val = tex_noise_d2(input.restPos * vec3f(1.0, 1.0, 1.5), 1.0);
78
- let noise_ramp = ramp_linear(noise_val, 0.0, vec4f(0,0,0,1), 1.0, vec4f(1,1,1,1)).r;
79
- let bumped_n = bump_lh(0.324644535779953, noise_ramp, n, input.worldPos);
80
-
81
- let principled_base = mix_blend(noise_ramp, bc, vec3f(0.6832, 0.1947, 0.1373));
82
- let p_emission = bc * 0.2;
83
-
84
- let principled = eval_principled(
85
- PrincipledIn(principled_base, 0.0, FACE_SPECULAR, FACE_ROUGHNESS, FACE_SPEC_CLAMP, 0.0, 0.0),
86
- bumped_n, l, v, sun, amb, shadow
87
- ) + p_emission;
88
-
89
- let final_color = mix(npr_stack, principled, FACE_MIX_NPR);
90
-
91
- var out: FSOut;
92
- out.color = vec4f(final_color, alpha);
93
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
94
- return out;
95
- }
96
-
97
- `
@@ -1,92 +0,0 @@
1
- // M_Hair — 仿深空之眼渲染预设v1.0_by_小绿毛猫 "M_Hair". Toon + fresnel rim + bevel +
2
- // bright-tex gate, mixed 80/20 NPR/PBR. MixShader.001 Fac=0.2 keeps Principled subtle.
3
-
4
- import { NODES_WGSL } from "./nodes"
5
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
6
-
7
- export const HAIR_SHADER_WGSL = /* wgsl */ `
8
-
9
- ${NODES_WGSL}
10
- ${COMMON_MATERIAL_PRELUDE_WGSL}
11
-
12
- // Pipeline-override: the engine compiles two variants — the normal opaque hair pipeline
13
- // (IS_OVER_EYES=false) and a second pipeline that re-draws hair fragments stencil-matched
14
- // against the eye stamp with 25% alpha so eyes read through the hair silhouette. Resolved
15
- // at pipeline-compile time; the dead branch is dropped by the shader compiler.
16
- override IS_OVER_EYES: bool = false;
17
-
18
- const HAIR_SPECULAR: f32 = 1.0;
19
- const HAIR_ROUGHNESS: f32 = 0.3;
20
- // EEVEE Light Clamp equivalent (same value as body/face/cloth_rough). Hair
21
- // is the firefly-prone material: physics-animated with the noisiest blended
22
- // normals, so grazing NV spikes the GGX term and flashes white through
23
- // bloom without this.
24
- const HAIR_SPEC_CLAMP: f32 = 10.0;
25
- const HAIR_TEX_GATE_THRESH: f32 = 0.15000000596046448;
26
- const HAIR_RIM2_POW: f32 = 0.6300000548362732;
27
- const HAIR_MIX_BG: vec3f = vec3f(0.1673291176557541);
28
- const HAIR_MIX_NPR: f32 = 0.2;
29
-
30
- @fragment fn fs(input: VertexOutput) -> FSOut {
31
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
32
- // MMD alpha semantics: material alpha × texture alpha. Hair/lace/accessory
33
- // textures cut their shapes in the alpha channel — ignoring it renders each
34
- // card's full quad with the texture's padding color (white shimmer on dark
35
- // hair for models whose textures pad with white).
36
- let alpha = material.alpha * tex_s.a;
37
- if (alpha < 0.001) { discard; }
38
-
39
- let n = safe_normal(input.normal);
40
- let v = normalize(camera.viewPos - input.worldPos);
41
- let l = -light.lights[0].direction.xyz;
42
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
43
- let amb = light.ambientColor.xyz;
44
- let shadow = sampleShadow(input.worldPos, n);
45
-
46
- let tex_color = tex_s.rgb;
47
-
48
- // ═══ NPR STACK ═══
49
- let hue_sat_shadow = hue_sat_id(1.2, 0.5, 1.0, tex_color);
50
- let hue_sat_002 = hue_sat(0.48, 1.2, 0.7, 1.0, hue_sat_shadow);
51
- let hue_sat_001 = hue_sat_id(1.5, 1.0, 1.0, tex_color);
52
-
53
- let ndotl_raw = shader_to_rgb_diffuse(n, l, sun, amb, shadow);
54
- let ramp_008 = ramp_constant(ndotl_raw, 0.0, vec4f(0,0,0,1), 0.2966, vec4f(1,1,1,1)).r;
55
-
56
- let mix_004 = mix_blend(ramp_008, hue_sat_002, hue_sat_001);
57
- let bc = bright_contrast(mix_004, 0.1, 0.2);
58
-
59
- let bevel_z = clamp(n.y, 0.0, 1.0);
60
- let mix_003 = mix_blend(bevel_z, bc, hue_sat_002);
61
-
62
- let rim2_raw = fresnel(1.45, n, v) * layer_weight_fresnel(0.61, n, v);
63
- let rim2_fac = math_power(rim2_raw, HAIR_RIM2_POW);
64
- let mix_shader_002 = mix(mix_003, HAIR_MIX_BG, rim2_fac);
65
-
66
- // GREATER_THAN on a color input uses BT.601 luminance — same socket-semantic fix as face.ts.
67
- let tex_gate = math_greater_than(color_to_value(tex_color), HAIR_TEX_GATE_THRESH);
68
- let gate_emit = vec3f(tex_gate) * 0.1;
69
-
70
- let npr_stack = mix_shader_002 + gate_emit;
71
-
72
- // ═══ PRINCIPLED BSDF ═══
73
- // Graph has a noise→normal_map bump (Strength=0.1) on Principled.Normal, but MixShader.001
74
- // weights Principled at only 0.2 — the bumped spec × that weight is imperceptible, so we
75
- // drop the subtree and keep plain n (saves a tex_noise + bump_lh per hair fragment).
76
- let principled = eval_principled(
77
- PrincipledIn(bc, 0.0, HAIR_SPECULAR, HAIR_ROUGHNESS, HAIR_SPEC_CLAMP, 0.0, 0.0),
78
- n, l, v, sun, amb, shadow
79
- );
80
-
81
- let final_color = mix(npr_stack, principled, HAIR_MIX_NPR);
82
-
83
- var outAlpha = alpha;
84
- if (IS_OVER_EYES) { outAlpha = alpha * 0.25; }
85
-
86
- var out: FSOut;
87
- out.color = vec4f(final_color, outAlpha);
88
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
89
- return out;
90
- }
91
-
92
- `
@@ -1,79 +0,0 @@
1
- // M_Metal — Metallic Principled (Metallic=1.0, Specular=1.0, Roughness=0.3) with a
2
- // reflection-coord Voronoi pattern driving base color for metallic sparkle, plus an
3
- // NPR toon/overlay emission stack mixed at MixShader Fac=0.6967.
4
- //
5
- // Graph's base color chain: 纹理坐标.Reflection → 矢量运算.007(CROSS, Vec2=(0,1,0)) →
6
- // 沃罗诺伊纹理(F1, Color out) → 颜色渐变(linear) → 混合.005. The dumper did not capture
7
- // the VectorMath op — CROSS is assumed based on the hardcoded (0,1,0) Vector_001
8
- // constant (MULTIPLY would zero X/Z producing 1D bands; CROSS produces horizontal ring
9
- // patterns consistent with metallic anisotropy).
10
-
11
- import { NODES_WGSL } from "./nodes"
12
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
13
-
14
- export const METAL_SHADER_WGSL = /* wgsl */ `
15
-
16
- ${NODES_WGSL}
17
- ${COMMON_MATERIAL_PRELUDE_WGSL}
18
-
19
- const METAL_SPECULAR: f32 = 1.0;
20
- const METAL_METALLIC: f32 = 1.0;
21
- const METAL_ROUGHNESS: f32 = 0.3;
22
- const METAL_TOON_EDGE: f32 = 0.2966;
23
- const METAL_MIX04_MUL: f32 = 0.5;
24
- const METAL_EMIT_STR: f32 = 8.100000381469727;
25
- const METAL_MIX_SHADER_FAC: f32 = 0.6967;
26
- const METAL_VORONOI_SCALE: f32 = 4.3;
27
-
28
- @fragment fn fs(input: VertexOutput) -> FSOut {
29
- let n = safe_normal(input.normal);
30
- let v = normalize(camera.viewPos - input.worldPos);
31
- let l = -light.lights[0].direction.xyz;
32
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
33
- let amb = light.ambientColor.xyz;
34
- let shadow = sampleShadow(input.worldPos, n);
35
-
36
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
37
- let tex_rgb = tex_s.rgb;
38
- let out_alpha = material.alpha * tex_s.a;
39
- if (out_alpha < 0.001) { discard; }
40
-
41
- // ═══ NPR STACK ═══
42
- let tex_tint = hue_sat_id(1.0, 0.800000011920929, 1.0, tex_rgb);
43
- let lum_shade = shader_to_rgb_diffuse(n, l, sun, amb, shadow);
44
- let ramp008 = ramp_constant_edge_aa(lum_shade, METAL_TOON_EDGE, vec4f(0,0,0,1), vec4f(1,1,1,1));
45
- let mix04_fac = math_multiply(ramp008.r, METAL_MIX04_MUL);
46
-
47
- let dark_tex = hue_sat_id(1.0, 0.19999998807907104, 1.0, tex_tint);
48
- let mix04 = mix_blend(mix04_fac, dark_tex, tex_tint);
49
-
50
- let hue004 = hue_sat_id(1.0, 2.0, 1.0, mix04);
51
- let npr_rgb = mix_overlay(1.0, mix04, hue004);
52
- let npr_emission = npr_rgb * METAL_EMIT_STR;
53
-
54
- // ═══ PRINCIPLED BSDF (metallic=1, voronoi-driven base) ═══
55
- // Reflection-coord Voronoi produces the metallic sparkle variation.
56
- // VALTORGB takes Color → Fac via Blender's BT.601 implicit color_to_value.
57
- let refl_dir = reflect(-v, n);
58
- let voro_input = cross(refl_dir, vec3f(0.0, 1.0, 0.0));
59
- let voro_rgb = tex_voronoi_color(voro_input, METAL_VORONOI_SCALE);
60
- let voro_scalar = color_to_value(voro_rgb);
61
- let voro_ramp = ramp_linear(voro_scalar, 0.0, vec4f(0,0,0,1), 1.0, vec4f(1,1,1,1)).r;
62
- let hue006 = hue_sat_id(1.5, 1.2999999523162842, 1.0, tex_tint);
63
- let albedo = mix_blend(voro_ramp, vec3f(voro_ramp), hue006);
64
-
65
- // metallic=1 collapses f0 = mix(dielectric, albedo, 1) = albedo; diffuse_weight = 0.
66
- let principled = eval_principled(
67
- PrincipledIn(albedo, METAL_METALLIC, METAL_SPECULAR, METAL_ROUGHNESS, 1e30, 0.0, 0.0),
68
- n, l, v, sun, amb, shadow
69
- );
70
-
71
- let final_color = mix(npr_emission, principled, METAL_MIX_SHADER_FAC);
72
-
73
- var out: FSOut;
74
- out.color = vec4f(final_color, out_alpha);
75
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
76
- return out;
77
- }
78
-
79
- `
@@ -1,68 +0,0 @@
1
- // M_MMDClassic — authentic MMD/MikuMikuDance fixed-pipeline material. Uses the
2
- // PMX material data every model author actually tuned: ambient + diffuse×light
3
- // base, toon-ramp shading (ramp carries the terminator, NOT an N·L multiply),
4
- // sphere map (sph multiply / spa add), and Blinn-Phong specular with the PMX
5
- // shininess. This is the universal fallback for materials no preset map or
6
- // name heuristic covers — it renders what the author saw in MMD/PMXEditor.
7
-
8
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
9
-
10
- export const MMD_CLASSIC_SHADER_WGSL = /* wgsl */ `
11
-
12
- ${COMMON_MATERIAL_PRELUDE_WGSL}
13
-
14
- @fragment fn fs(input: VertexOutput) -> FSOut {
15
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
16
- // MMD alpha semantics: material alpha × texture alpha.
17
- let alpha = material.alpha * tex_s.a;
18
- if (alpha < 0.001) { discard; }
19
-
20
- let n = safe_normal(input.normal);
21
- let v = normalize(camera.viewPos - input.worldPos);
22
- let l = -light.lights[0].direction.xyz;
23
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
24
- let amb = light.ambientColor.xyz;
25
- let shadow = sampleShadow(input.worldPos, n);
26
-
27
- // Sphere-map UV from the view-space normal — sampled up front to keep the
28
- // texture reads in uniform control flow.
29
- let vn = normalize((camera.view * vec4f(n, 0.0)).xyz);
30
- let sph_uv = vec2f(vn.x * 0.5 + 0.5, 0.5 - vn.y * 0.5);
31
- let sphere_rgb = textureSample(sphereTexture, diffuseSampler, sph_uv).rgb;
32
-
33
- // Toon ramp: v runs light (0) → shadow (1); the ramp texture carries the
34
- // terminator shape and shadow tint. Self-shadow pushes toward the shadow
35
- // end by attenuating N·L. Sampled up front for the same uniformity reason.
36
- let ndl = dot(n, l) * shadow;
37
- let toon_v = clamp(0.5 - 0.5 * ndl, 0.0, 1.0);
38
- let toon_rgb = textureSample(toonTexture, diffuseSampler, vec2f(0.5, toon_v)).rgb;
39
-
40
- // MMD base: saturate(ambient + diffuse × light color), modulated by texture.
41
- // The engine's ambient light scales the material-ambient floor so scene
42
- // lighting still has authority over overall exposure.
43
- let base = clamp(material.ambient * max(amb, vec3f(0.35)) + material.diffuseColor * sun, vec3f(0.0), vec3f(1.0));
44
- var color = base * tex_s.rgb * toon_rgb;
45
-
46
- // Sphere map: 1 = sph (multiply), 2 = spa (add). Mode 3 (sub-texture) and
47
- // 0 fall through unchanged.
48
- if (material.sphereMode == 1.0) {
49
- color *= sphere_rgb;
50
- } else if (material.sphereMode == 2.0) {
51
- color += sphere_rgb;
52
- }
53
-
54
- // Blinn-Phong specular with PMX shininess. shininess 0 disables (many
55
- // rigs author 0 to mean "no highlight").
56
- if (material.shininess > 0.0) {
57
- let h = normalize(l + v);
58
- let spec = pow(max(dot(n, h), 0.0), max(material.shininess, 1.0));
59
- color += material.specular * sun * (spec * shadow);
60
- }
61
-
62
- var out: FSOut;
63
- out.color = vec4f(color, alpha);
64
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
65
- return out;
66
- }
67
-
68
- `
@@ -1,124 +0,0 @@
1
- // M_Stockings — 仿深空之眼渲染预设v1.0_by_小绿毛猫 "M_Stockings". A bbox-gradient ×
2
- // facing-rim mask drives a Mix Shader between an HSV-boosted emission and a sheen
3
- // Principled BSDF. Wyman hashed-alpha testing replaces the graph's Alpha=0.95 (which
4
- // would require TAA to hide the dither dots across every pixel).
5
-
6
- import { NODES_WGSL } from "./nodes"
7
- import { COMMON_MATERIAL_PRELUDE_WGSL } from "./common"
8
-
9
- export const STOCKINGS_SHADER_WGSL = /* wgsl */ `
10
-
11
- ${NODES_WGSL}
12
- ${COMMON_MATERIAL_PRELUDE_WGSL}
13
-
14
- // Principled params from dump (Alpha=0.95 intentionally dropped — see hash note below).
15
- const STOCK_METALLIC: f32 = 0.1;
16
- const STOCK_SPECULAR: f32 = 1.0;
17
- const STOCK_ROUGHNESS: f32 = 0.5;
18
- const STOCK_SHEEN: f32 = 0.7017999887466431;
19
- const STOCK_SHEEN_TINT: f32 = 0.5;
20
- // NPR mask ramps
21
- const STOCK_RAMP002_P1: f32 = 0.9565; // EASE [0→black, 0.9565→white]
22
- const STOCK_RAMPFACE_P1: f32 = 0.5435; // EASE [0→black, 0.5435→white]
23
- const STOCK_LW_BLEND: f32 = 0.4; // Layer Weight Blend
24
-
25
- // Wyman & McGuire "Hashed Alpha Testing" (2017) — object-space hash with derivative-aware
26
- // pixel-scale selection, matches Blender EEVEE prepass_frag.glsl::hashed_alpha_threshold.
27
- // Key property: dither pattern is stable in object space (doesn't swim) and stays at
28
- // one-pixel frequency regardless of view distance, which makes it tolerable without TAA.
29
- // The hash grid is fed the bind-pose restPos (not worldPos), so the dots stay pinned to
30
- // the fabric even under root (センター) motion — worldPos would crawl across the surface.
31
- // Since MMD skinning is rigid, length(dpdx(restPos)) == length(dpdx(worldPos)), so the
32
- // pixel-scale selection is unaffected by the space change.
33
- // Grid samples reuse the PCG _hash33 from nodes.ts (integer-lattice inputs, Metal-friendly)
34
- // instead of a fract(sin()) hash — sin compiles to a slow transcendental on Apple's Metal
35
- // backend and this runs per-fragment on every stockings pixel.
36
- fn _hash3d_wm(a: vec3f) -> f32 {
37
- return _hash33(a).x * 0.5 + 0.5;
38
- }
39
- fn hashed_alpha_threshold(co: vec3f) -> f32 {
40
- let alphaHashScale: f32 = 1.0;
41
- let max_deriv = max(length(dpdx(co)), length(dpdy(co)));
42
- let pix_scale = 1.0 / max(alphaHashScale * max_deriv, 1e-6);
43
- let pix_scale_log = log2(pix_scale);
44
- let px_lo = exp2(floor(pix_scale_log));
45
- let px_hi = exp2(ceil(pix_scale_log));
46
- let a_lo = _hash3d_wm(floor(px_lo * co));
47
- let a_hi = _hash3d_wm(floor(px_hi * co));
48
- let fac = fract(pix_scale_log);
49
- let x = mix(a_lo, a_hi, fac);
50
- // CDF remap so discard-probability = (1 - alpha) uniformly across scale transitions
51
- let a = min(fac, 1.0 - fac);
52
- let one_a = 1.0 - a;
53
- let denom = 1.0 / max(2.0 * a * one_a, 1e-6);
54
- let one_x = 1.0 - x;
55
- let case_lo = (x * x) * denom;
56
- let case_mid = (x - 0.5 * a) / max(one_a, 1e-6);
57
- let case_hi = 1.0 - (one_x * one_x) * denom;
58
- var threshold = select(case_hi, select(case_lo, case_mid, x >= a), x < one_a);
59
- return clamp(threshold, 1e-6, 1.0);
60
- }
61
-
62
- // Smoothstep-based EASE ramp (Blender VALTORGB EASE) — 2 stops, saturate+smoothstep between
63
- fn ramp_ease_s(f: f32, p0: f32, p1: f32) -> f32 {
64
- let t = saturate((f - p0) / max(p1 - p0, 1e-6));
65
- return t * t * (3.0 - 2.0 * t);
66
- }
67
-
68
- @fragment fn fs(input: VertexOutput) -> FSOut {
69
- let n = safe_normal(input.normal);
70
- let v = normalize(camera.viewPos - input.worldPos);
71
- let l = -light.lights[0].direction.xyz;
72
- let sun = light.lights[0].color.xyz * light.lights[0].color.w;
73
- let amb = light.ambientColor.xyz;
74
- let shadow = sampleShadow(input.worldPos, n);
75
-
76
- let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
77
- let tex_rgb = tex_s.rgb;
78
- // Alpha HASHED (Blender EEVEE "Hashed" blend mode) per preset author's note — self-overlap
79
- // on the stockings produces sort cracks under alpha blend. Wyman-style object-space hash +
80
- // depth-write is sort-independent. NOTE: Principled.Alpha=0.95 from the dump is DROPPED;
81
- // it relies on TAA to smooth the 5%-everywhere dither, and without TAA it shows as a
82
- // pervasive dot pattern. Hash now gates only on texture/material alpha.
83
- let combined_alpha = material.alpha * tex_s.a;
84
- if (combined_alpha < hashed_alpha_threshold(input.restPos)) { discard; }
85
-
86
- // ═══ NPR MASK ═══ TEX_COORD.Generated → Mapping(Rot=0,π/2,π/2, Loc=(1,1,1)) → Gradient.
87
- // The Blender mapping reduces to gradient.x = 1 - input.y (rot swaps axes, loc offsets).
88
- // We approximate Generated with UV since Y-up PMX has no object bbox in pipeline state.
89
- let gen_coord = vec3f(input.uv, 0.0);
90
- let mapped = mapping_point(gen_coord, vec3f(1.0), vec3f(0.0, 1.5708, 1.5708), vec3f(1.0));
91
- let gradient = tex_gradient_linear(mapped);
92
-
93
- // Ramp.001 LINEAR [0→black, 0.5→white, 1.0→black] — triangular peak at 0.5
94
- let ramp001 = 1.0 - abs(2.0 * gradient - 1.0);
95
- let ramp002 = ramp_ease_s(ramp001, 0.0, STOCK_RAMP002_P1);
96
-
97
- let facing = layer_weight_facing(STOCK_LW_BLEND, n, v);
98
- let ramp_face = ramp_ease_s(facing, 0.0, STOCK_RAMPFACE_P1);
99
-
100
- // Mix.001: MIX blend Fac=0.5, A=white, B=ramp_face
101
- let mix001 = mix(1.0, ramp_face, 0.5);
102
- // Mix: LIGHTEN blend Fac=0.5, A=mix001, B=ramp002
103
- let lighten = max(mix001, ramp002);
104
- let mask = mix(mix001, lighten, 0.5);
105
-
106
- // ═══ EMISSION SHADER ═══ Hue=0.5 (identity), Sat=1.0, Val=5.0 (5× brightness), Fac=1.
107
- let emission = hue_sat_id(1.0, 5.0, 1.0, tex_rgb);
108
-
109
- // ═══ PRINCIPLED BSDF with sheen ═══ metallic=0.1, sheen=0.7, sheen_tint=0.5.
110
- let principled = eval_principled(
111
- PrincipledIn(tex_rgb, STOCK_METALLIC, STOCK_SPECULAR, STOCK_ROUGHNESS, 1e30, STOCK_SHEEN, STOCK_SHEEN_TINT),
112
- n, l, v, sun, amb, shadow
113
- );
114
-
115
- // MIX SHADER: Shader=Emission, Shader_001=Principled, Fac=mask
116
- let final_color = mix(emission, principled, mask);
117
-
118
- var out: FSOut;
119
- out.color = vec4f(final_color, 1.0);
120
- out.mask = vec4f(1.0, 1.0, 0.0, out.color.a);
121
- return out;
122
- }
123
-
124
- `