reze-engine 0.65.0 → 0.66.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/engine.d.ts +156 -42
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +876 -186
- package/dist/graph/compile.d.ts.map +1 -1
- package/dist/graph/compile.js +5 -0
- package/dist/graph/presets/body.d.ts.map +1 -1
- package/dist/graph/presets/body.js +26 -24
- package/dist/graph/presets/cloth_rough.js +8 -8
- package/dist/graph/presets/cloth_smooth.js +8 -8
- package/dist/graph/presets/default.js +4 -4
- package/dist/graph/presets/eye.js +10 -10
- package/dist/graph/presets/face.d.ts.map +1 -1
- package/dist/graph/presets/face.js +28 -26
- package/dist/graph/presets/hair.js +6 -6
- package/dist/graph/presets/metal.js +8 -8
- package/dist/graph/presets/stockings.d.ts.map +1 -1
- package/dist/graph/presets/stockings.js +4 -11
- package/dist/graph/presets/unlit.d.ts.map +1 -1
- package/dist/graph/presets/unlit.js +9 -13
- package/dist/graph/registry.d.ts.map +1 -1
- package/dist/graph/registry.js +128 -157
- package/dist/graph/render-class.d.ts +5 -2
- package/dist/graph/render-class.d.ts.map +1 -1
- package/dist/graph/slots.d.ts.map +1 -1
- package/dist/graph/slots.js +5 -1
- package/dist/model.d.ts +14 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +27 -1
- package/dist/pmx-loader.d.ts +4 -0
- package/dist/pmx-loader.d.ts.map +1 -1
- package/dist/pmx-loader.js +11 -2
- package/dist/shaders/anchor-table.d.ts +11 -0
- package/dist/shaders/anchor-table.d.ts.map +1 -1
- package/dist/shaders/anchor-table.js +9 -3
- package/dist/shaders/directives.d.ts +42 -5
- package/dist/shaders/directives.d.ts.map +1 -1
- package/dist/shaders/directives.js +51 -4
- package/dist/shaders/lights.d.ts +11 -7
- package/dist/shaders/lights.d.ts.map +1 -1
- package/dist/shaders/lights.js +315 -271
- package/dist/shaders/materials/common.d.ts.map +1 -1
- package/dist/shaders/materials/common.js +26 -3
- 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 +191 -271
- package/dist/shaders/passes/composite.d.ts +1 -1
- package/dist/shaders/passes/composite.d.ts.map +1 -1
- package/dist/shaders/passes/composite.js +3 -5
- package/dist/shaders/passes/ground.js +1 -1
- package/dist/shaders/passes/particles.d.ts.map +1 -1
- package/dist/shaders/passes/particles.js +9 -3
- package/dist/shaders/passes/probe.d.ts +45 -0
- package/dist/shaders/passes/probe.d.ts.map +1 -0
- package/dist/shaders/passes/probe.js +230 -0
- package/dist/shaders/passes/scene-contract.d.ts +13 -0
- package/dist/shaders/passes/scene-contract.d.ts.map +1 -1
- package/dist/shaders/passes/scene-contract.js +4 -0
- package/dist/shaders/scene-light-api.d.ts.map +1 -1
- package/dist/shaders/scene-light-api.js +1 -0
- package/dist/unity/globals.d.ts +7 -0
- package/dist/unity/globals.d.ts.map +1 -1
- package/dist/unity/globals.js +4 -3
- package/dist/unity/host.d.ts +3 -0
- package/dist/unity/host.d.ts.map +1 -1
- package/dist/unity/host.js +41 -7
- package/dist/unity/looks.d.ts +42 -0
- package/dist/unity/looks.d.ts.map +1 -1
- package/dist/unity/looks.js +131 -4
- package/dist/unity/stage.d.ts +17 -0
- package/dist/unity/stage.d.ts.map +1 -1
- package/dist/unity/stage.js +22 -5
- package/package.json +1 -1
- package/src/engine.ts +949 -215
- package/src/graph/compile.ts +4 -0
- package/src/graph/presets/body.ts +26 -24
- package/src/graph/presets/cloth_rough.ts +8 -8
- package/src/graph/presets/cloth_smooth.ts +8 -8
- package/src/graph/presets/default.ts +4 -4
- package/src/graph/presets/eye.ts +10 -10
- package/src/graph/presets/face.ts +28 -26
- package/src/graph/presets/hair.ts +6 -6
- package/src/graph/presets/metal.ts +8 -8
- package/src/graph/presets/stockings.ts +4 -11
- package/src/graph/presets/unlit.ts +9 -13
- package/src/graph/registry.ts +133 -158
- package/src/graph/render-class.ts +5 -2
- package/src/graph/slots.ts +5 -1
- package/src/model.ts +33 -1
- package/src/pmx-loader.ts +11 -2
- package/src/shaders/anchor-table.ts +15 -3
- package/src/shaders/directives.ts +88 -6
- package/src/shaders/lights.ts +464 -415
- package/src/shaders/materials/common.ts +26 -3
- package/src/shaders/materials/nodes.ts +191 -271
- package/src/shaders/passes/composite.ts +3 -5
- package/src/shaders/passes/ground.ts +1 -1
- package/src/shaders/passes/particles.ts +9 -3
- package/src/shaders/passes/probe.ts +240 -0
- package/src/shaders/passes/scene-contract.ts +17 -0
- package/src/shaders/scene-light-api.ts +1 -0
- package/src/unity/globals.ts +7 -3
- package/src/unity/host.ts +36 -6
- package/src/unity/looks.ts +161 -7
- package/src/unity/stage.ts +28 -5
- package/dist/physics-debug.d.ts +0 -30
- package/dist/physics-debug.d.ts.map +0 -1
- package/dist/physics-debug.js +0 -526
- package/dist/shaders/agx-lut.d.ts +0 -11
- package/dist/shaders/agx-lut.d.ts.map +0 -1
- package/dist/shaders/agx-lut.js +0 -29
- package/dist/shaders/dfg_lut.d.ts +0 -3
- package/dist/shaders/dfg_lut.d.ts.map +0 -1
- package/dist/shaders/dfg_lut.js +0 -129
- package/dist/shaders/ltc_mag_lut.d.ts +0 -3
- package/dist/shaders/ltc_mag_lut.d.ts.map +0 -1
- package/dist/shaders/ltc_mag_lut.js +0 -1033
- package/dist/shaders/materials/body.d.ts +0 -2
- package/dist/shaders/materials/body.d.ts.map +0 -1
- package/dist/shaders/materials/body.js +0 -95
- package/dist/shaders/materials/cloth_rough.d.ts +0 -2
- package/dist/shaders/materials/cloth_rough.d.ts.map +0 -1
- package/dist/shaders/materials/cloth_rough.js +0 -69
- package/dist/shaders/materials/cloth_smooth.d.ts +0 -2
- package/dist/shaders/materials/cloth_smooth.d.ts.map +0 -1
- package/dist/shaders/materials/cloth_smooth.js +0 -61
- package/dist/shaders/materials/default.d.ts +0 -2
- package/dist/shaders/materials/default.d.ts.map +0 -1
- package/dist/shaders/materials/default.js +0 -43
- package/dist/shaders/materials/eye.d.ts +0 -2
- package/dist/shaders/materials/eye.d.ts.map +0 -1
- package/dist/shaders/materials/eye.js +0 -60
- package/dist/shaders/materials/face.d.ts +0 -2
- package/dist/shaders/materials/face.d.ts.map +0 -1
- package/dist/shaders/materials/face.js +0 -95
- package/dist/shaders/materials/hair.d.ts +0 -2
- package/dist/shaders/materials/hair.d.ts.map +0 -1
- package/dist/shaders/materials/hair.js +0 -90
- package/dist/shaders/materials/metal.d.ts +0 -2
- package/dist/shaders/materials/metal.d.ts.map +0 -1
- package/dist/shaders/materials/metal.js +0 -77
- package/dist/shaders/materials/mmd_classic.d.ts +0 -2
- package/dist/shaders/materials/mmd_classic.d.ts.map +0 -1
- package/dist/shaders/materials/mmd_classic.js +0 -66
- package/dist/shaders/materials/stockings.d.ts +0 -2
- package/dist/shaders/materials/stockings.d.ts.map +0 -1
- package/dist/shaders/materials/stockings.js +0 -122
- package/dist/shaders/passes/physics-debug.d.ts +0 -2
- package/dist/shaders/passes/physics-debug.d.ts.map +0 -1
- package/dist/shaders/passes/physics-debug.js +0 -69
- package/src/shaders/dfg_lut.ts +0 -131
- package/src/shaders/ltc_mag_lut.ts +0 -1035
|
@@ -97,7 +97,7 @@ type CompositeEffectSource = {
|
|
|
97
97
|
* Depends on `viewU` and `_rzCast` being declared by the including module, and
|
|
98
98
|
* on nothing else: no textures, no samplers.
|
|
99
99
|
*/
|
|
100
|
-
export declare const EFFECT_SCENE_API = "\n// \u2500\u2500 The effect API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Named rz*, for the engine. The prefix earns its place twice: user code is\n// concatenated into THIS module, so an unprefixed rzAnchor() would collide with\n// exactly the helper an author would write, and the old bg* prefix stopped being\n// true in 0.41.0 when effects gained a mount over the finished frame.\n//\n// The bg* names below are permanent aliases, not a deprecation with an end date.\n// A published link is immutable, so a scene pinned to a bg* effect has to keep\n// compiling forever. They are one-line and inlined; no new function gets one.\n\n/** Canvas size in pixels \u2014 for aspect correction. */\nfn rzResolution() -> vec2f { return viewU[6].zw; }\n\n/** The camera's world position. */\nfn rzCameraPos() -> vec3f { return viewU[10].xyz; }\n\n/** How many characters the SCENE holds, up to four \u2014 the number the cast api\n * narrows to this effect's own subjects. See subjectMaskApi. */\nfn _rzCastLive() -> i32 { return i32(viewU[10].w); }\n\n/**\n * A world point as the camera sees it: xy the uv it lands on, z its distance\n * along the VIEW AXIS in metres.\n *\n * The exact inverse of the ray this pass builds per pixel, so it is the cheap way\n * to work with anything anchored in the world. Marching a curve or a trail in 3D\n * costs a distance evaluation per sample per pixel; projecting its points once\n * and measuring in 2D costs a subtraction, which is the difference between a\n * ribbon that runs at 4K and one that does not.\n *\n * z is directly comparable to the depth handed to foreground(), so occlusion is\n * a single test: draw where your z is nearer than the scene's. It is returned\n * SIGNED and unclamped \u2014 behind the camera is negative, and worth rejecting\n * before you use the uv, which is meaningless there.\n */\nfn rzProject(p: vec3f) -> vec3f {\n let d = p - viewU[10].xyz;\n let z = dot(d, viewU[5].xyz);\n // Guard only the divide. z itself is returned as it is, so the caller can see\n // the sign; clamping it here would put points behind the lens on the horizon.\n let inv = 1.0 / select(z, 1e-4, z < 1e-4);\n let ndc = vec2f(dot(d, viewU[3].xyz) * inv / viewU[3].w, dot(d, viewU[4].xyz) * inv / viewU[4].w);\n return vec3f(ndc * 0.5 + 0.5, z);\n}\n\nfn rzCamPos() -> vec3f { return rzCameraPos(); }\nfn rzCameraRight() -> vec3f { return viewU[3].xyz; }\nfn rzCameraUp() -> vec3f { return viewU[4].xyz; }\nfn rzCameraForward() -> vec3f { return viewU[5].xyz; }\n\n// The cast \u2014 subjects, anchors, trails \u2014 is CAST_API, shared verbatim with the\n// particle and trail modules. It used to be written out here, a second time, and\n// the two copies had drifted: this one had rzAnchor and that one did not.\n\nconst RZ_SUBJECTS: i32 = 4;\nconst RZ_SAMPLES: i32 = 128;\n/** The anchor ADDRESS SPACE \u2014 how many an effect may declare, not how many it\n * did. RZ_TRAIL_SLOTS is the per-effect number and is not this one; the two\n * being one number was the old trail bug. */\nconst RZ_MAX_ANCHORS: i32 = 48;\nconst RZ_TRAIL_SAMPLES: i32 = 128;\n\nstruct RzSubject {\n /** On the FLOOR, under the body \u2014 where a ring or a magic circle belongs. */\n root: vec3f,\n /** At the hips, the middle of the body \u2014 where an aura belongs. */\n center: vec3f,\n /** Bounding sphere: xyz centre, w radius. Deliberately generous \u2014 cull with it. */\n bounds: vec4f,\n /**\n * How much of this character is still THERE: 1 whole, 0 gone.\n *\n * What setModelDissolve last set on them, which the material pass has already\n * acted on by the time an effect runs \u2014 so an effect drawing what LEAVES a\n * dissolving body (sparks, ash, a ghost) reads the same number the body was\n * taken apart with, rather than keeping a clock of its own and hoping the two\n * agree. 1 on a scene that never dissolves anybody.\n */\n dissolve: f32,\n /**\n * Where she LOOKS: a unit direction from between the eyes, in world space.\n * Exact while her eyes are on something (Engine.setEyeTracking); otherwise\n * the motion's own eye turn undone through the range map \u2014 an eye bone\n * turns a fraction of the way toward what it looks at, and this gives back\n * the whole of it. An effect that should go where the look goes \u2014 a beam,\n * a light \u2014 takes this rather than an eye bone's axis, and it holds in\n * either mode. Zero, with looking false, only for a model without eyes.\n */\n gaze: vec3f,\n looking: bool,\n /** False past the end of the cast, and every field is then zero. */\n valid: bool,\n}\n\nstruct RzAnchor {\n pos: vec3f,\n /** World units per second, from the previous frame. Direction for a trail,\n * magnitude for anything that should react to how hard someone is moving. */\n vel: vec3f,\n /** The bone's forward axis \u2014 which way a foot points, where a head looks. */\n fwd: vec3f,\n /** False when this rig has no such bone. Check it: the alternative is drawing\n * a hand effect at the world origin on every model that spells it differently. */\n valid: bool,\n}\n\n/**\n * How many characters THIS EFFECT is on, up to four.\n *\n * Not how many the scene holds. An effect applies to the whole cast unless the\n * scene says otherwise (Engine.setEffectSubjects), and where it says otherwise\n * this counts only the models named \u2014 so an effect aimed at one dancer sees one\n * subject, at index 0, and an author who wrote a loop over the cast gets the\n * targeting for free.\n *\n * Which is the whole design: the FILTER IS IN THE INDEX SPACE, not in the\n * shaders. There is no mask an effect can read, because an effect asking \"am I\n * allowed on this one\" is an effect that can get the answer wrong, and 18 of the\n * shipped built-ins would have had to be rewritten to ask at all.\n */\nfn rzSubjectCount() -> i32 {\n let live = _rzCastLive();\n let mask = _rzSubjectMask();\n var n = 0;\n for (var i = 0; i < live; i++) {\n if ((mask & (1u << u32(i))) != 0u) { n++; }\n }\n return n;\n}\n\n/** This effect's i-th subject \u2192 the scene's slot, or -1 past its own count.\n * Every accessor below goes through it, which is what keeps one effect's\n * subject 1 from being another's. */\nfn _rzSubjectSlot(i: i32) -> i32 {\n if (i < 0) { return -1; }\n let live = _rzCastLive();\n let mask = _rzSubjectMask();\n var n = 0;\n for (var s = 0; s < live; s++) {\n if ((mask & (1u << u32(s))) == 0u) { continue; }\n if (n == i) { return s; }\n n++;\n }\n return -1;\n}\n\n/** Which model this is, stable across a scene \u2014 for per-subject variation. */\nfn rzSubjectId(i: i32) -> u32 {\n let g = _rzSubjectSlot(i);\n if (g < 0) { return 0u; }\n return u32(_rzCast[g * 4 + 1].w);\n}\n\nfn rzSubject(i: i32) -> RzSubject {\n var s: RzSubject;\n let g = _rzSubjectSlot(i);\n s.valid = g >= 0;\n if (!s.valid) { return s; }\n let b = g * 4;\n s.root = _rzCast[b].xyz;\n s.dissolve = _rzCast[b].w;\n s.center = _rzCast[b + 1].xyz;\n s.bounds = _rzCast[b + 2];\n s.gaze = _rzCast[b + 3].xyz;\n s.looking = _rzCast[b + 3].w > 0.5;\n return s;\n}\n\n/**\n * Where a named bone is, this frame.\n *\n * The slot is the author's own: the Nth #anchor in their file, in the order\n * they wrote them. _rzSlot turns that into the scene's address, which is what\n * keeps two effects that both anchor to a wrist from reading each other's.\n */\nfn rzAnchor(subject: i32, slot: i32) -> RzAnchor {\n var a: RzAnchor;\n a.valid = false;\n let g = _rzSlot(slot);\n let s = _rzSubjectSlot(subject);\n if (s < 0 || g < 0 || g >= RZ_MAX_ANCHORS) { return a; }\n let b = 16 + (g * 4 + s) * 3;\n a.valid = _rzCast[b].w > 0.5;\n a.pos = _rzCast[b].xyz;\n a.vel = _rzCast[b + 1].xyz;\n a.fwd = _rzCast[b + 2].xyz;\n return a;\n}\n\n/**\n * How many samples of a path are recorded \u2014 0 for an anchor that asked for no\n * trail, and for one that has not moved yet.\n *\n * Bounded by the anchor cap, NOT by how many anchors asked for a trail. Those\n * are different index spaces: storage is addressed by anchor slot, so an\n * untrailed #anchor followed by a trailed one put the trail at index 1 with a\n * bound of 1 and rzTrail returned zero \u2014 a ribbon that silently did not draw.\n */\nfn rzTrailCount(subject: i32, slot: i32) -> i32 {\n let g = _rzSlot(slot);\n let s = _rzSubjectSlot(subject);\n if (s < 0 || g < 0 || g >= RZ_MAX_ANCHORS) { return 0; }\n return i32(_rzCast[16 + (g * 4 + s) * 3 + 2].w);\n}\n\n/** Sample i of a path: xyz where it was, w how many seconds ago. i = 0 is now. */\nfn rzTrail(subject: i32, slot: i32, i: i32) -> vec4f {\n let n = rzTrailCount(subject, slot);\n if (i < 0 || i >= n) { return vec4f(0.0); }\n let base = 592 + (_rzSlot(slot) * 4 + _rzSubjectSlot(subject)) * RZ_TRAIL_SAMPLES;\n return _rzCast[base + i];\n}\n\n\n// The hashes, the noise and rzFalloff \u2014 EFFECT_MATH_API, the same text the\n// particle and trail modules get. The field module used to be missing most of\n// it, so a helper an author wrote for one mount failed to compile in another\n// for no reason visible in the file.\n\nfn rzHash11(x: f32) -> f32 {\n var p = fract(x * 0.1031);\n p = p * (p + 33.33);\n return fract(p * (p + p));\n}\nfn rzHash21(p: vec2f) -> f32 {\n var p3 = fract(vec3f(p.x, p.y, p.x) * 0.1031);\n p3 = p3 + dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\n/** Three independent randoms from one seed \u2014 the usual need when spawning. */\nfn rzHash13(x: f32) -> vec3f {\n return vec3f(rzHash11(x), rzHash11(x + 17.13), rzHash11(x + 41.71));\n}\n/**\n * Compact-support falloff: 1 at the centre, exactly 0 at r, smooth between.\n *\n * It reaches exactly zero rather than merely getting small, because a glow that\n * never quite ends has to be culled somewhere, and culling it wherever it looks\n * close enough is what put a visible hard edge on the first halo effect.\n */\nfn rzFalloff(d: f32, r: f32) -> f32 {\n let x = clamp(d / max(r, 1e-6), 0.0, 1.0);\n let f = 1.0 - x;\n return f * f * f;\n}\nfn rzHash31(p: vec3f) -> f32 {\n var p3 = fract(p * 0.1031);\n p3 = p3 + dot(p3, p3.zyx + 31.32);\n return fract((p3.x + p3.y) * p3.z);\n}\nfn rzValueNoise(p: vec3f) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let u = f * f * (3.0 - 2.0 * f);\n let n000 = rzHash31(i);\n let n100 = rzHash31(i + vec3f(1.0, 0.0, 0.0));\n let n010 = rzHash31(i + vec3f(0.0, 1.0, 0.0));\n let n110 = rzHash31(i + vec3f(1.0, 1.0, 0.0));\n let n001 = rzHash31(i + vec3f(0.0, 0.0, 1.0));\n let n101 = rzHash31(i + vec3f(1.0, 0.0, 1.0));\n let n011 = rzHash31(i + vec3f(0.0, 1.0, 1.0));\n let n111 = rzHash31(i + vec3f(1.0, 1.0, 1.0));\n let x00 = mix(n000, n100, u.x);\n let x10 = mix(n010, n110, u.x);\n let x01 = mix(n001, n101, u.x);\n let x11 = mix(n011, n111, u.x);\n return mix(mix(x00, x10, u.y), mix(x01, x11, u.y), u.z);\n}\n/** Divergence-free flow \u2014 the field a wisp of smoke follows without a solver. */\nfn rzCurlNoise(p: vec3f) -> vec3f {\n let e = 0.1;\n let dx = vec3f(e, 0.0, 0.0);\n let dy = vec3f(0.0, e, 0.0);\n let dz = vec3f(0.0, 0.0, e);\n let x0 = rzValueNoise(p - dx); let x1 = rzValueNoise(p + dx);\n let y0 = rzValueNoise(p - dy); let y1 = rzValueNoise(p + dy);\n let z0 = rzValueNoise(p - dz); let z1 = rzValueNoise(p + dz);\n return normalize(vec3f((y1 - y0) - (z1 - z0), (z1 - z0) - (x1 - x0), (x1 - x0) - (y1 - y0)) + vec3f(1e-6));\n}\n\nstruct Particle {\n pos: vec3f,\n age: f32,\n vel: vec3f,\n life: f32,\n size: f32,\n rot: f32,\n seed: f32,\n // Aspect along the direction of travel. 1 or less is a square billboard; a\n // raindrop is 10 or 20. Zero-initialised, so an effect that never sets it gets\n // the square it expects.\n stretch: f32,\n}\n\n\n\nfn bgResolution() -> vec2f { return rzResolution(); }\nfn bgCameraPos() -> vec3f { return rzCameraPos(); }\nfn bgSubjectCount() -> i32 { return rzSubjectCount(); }\n\n/**\n * Where a character IS, in world space \u2014 at the hips, not on the floor.\n *\n * An effect that wants to RESPOND to the cast \u2014 a glow that follows someone,\n * dust kicked up where they are \u2014 needs to know where they are, and the ray and\n * the depth cannot tell it: they describe the pixel, not the scene.\n *\n * The value is model.position + \u30BB\u30F3\u30BF\u30FC + \u5168\u3066\u306E\u89AA. \u30BB\u30F3\u30BF\u30FC sits at hip\n * height on every standard MMD rig, so this is a point in the middle of the\n * body. It is NOT the contact point: a ripple drawn here appears at the waist.\n * Ground effects want the .xz of this and their own floor height, which is what\n * the effects that shipped against it already do.\n *\n * The comment here used to claim it was \"between the feet on the floor\", which\n * is where that habit came from. Left as it is regardless of the name: a\n * published link is immutable, so every shared scene pinning an effect that\n * reads this depends on it meaning exactly what it has always meant.\n *\n * Clamped rather than bounds-checked: an effect looping past the count reads the\n * last subject instead of sampling whatever follows the array, which is a wrong\n * ripple rather than an undefined one.\n *\n * THE INDEX IS THE EFFECT'S OWN, like every other cast accessor \u2014 Dry Ice, Water,\n * Holy Light and Bloody Ash all read this one and all of them should place their\n * fog, their ripple and their shaft under the model the scene aimed them at. The\n * mapping is the identity for an effect aimed at nobody in particular, which is\n * every scene published before one could be aimed.\n */\nfn rzSubjectHip(i: i32) -> vec3f { return viewU[11 + clamp(_rzSubjectSlot(i), 0, 3)].xyz; }\n\nfn bgSubjectPos(i: i32) -> vec3f { return rzSubjectHip(i); }\n\n/** Where in the WORLD the scene drew this pixel \u2014 the depth handed to\n * foreground() turned into a place. Without it an effect can only think in\n * distances from the lens, which is no use to anything that belongs somewhere:\n * fog lying on the ground has to know where the ground is.\n *\n * depth measures along the VIEW AXIS, not along the ray, so it is divided by\n * the ray's projection onto camera-forward before being walked out. At the far\n * plane (nothing drawn) this lands a very long way off, which is what a sky\n * should do to anything reading it. */\nfn rzWorldPos(ray: vec3f, depth: f32) -> vec3f {\n let axis = max(dot(normalize(ray), viewU[5].xyz), 1e-4);\n return rzCameraPos() + normalize(ray) * (depth / axis);\n}\n\nfn bgWorldPos(ray: vec3f, depth: f32) -> vec3f { return rzWorldPos(ray, depth); }\n\n/** What an effect returns for one of its lights. */\nstruct RzLight {\n pos: vec3f,\n color: vec3f,\n intensity: f32,\n radius: f32,\n}\n\n\n/** Color grading, applied to the tonemapped SCENE (not the background \u2014 see the\n * call site). The core is ASC CDL, the film-industry interchange standard:\n *\n * out = (in \u00B7 slope + offset) ^ power then saturation (SOP \u2192 SAT)\n *\n * Using the real standard rather than invented controls means a look authored\n * here maps onto any grading tool. slope/offset/power are derived on the CPU\n * from the UI's shadow/midtone/highlight colors (see setColorGrading), so the\n * per-pixel cost is one mul-add, one pow, one lerp. */\nfn grade(c: vec3f) -> vec3f {\n var x = pow(max(c * viewU[9].xyz + viewU[7].xyz, vec3f(0.0)), viewU[8].xyz);\n // Contrast pivots on 0.5 \u2014 display-referred midpoint, since we grade post-Filmic.\n x = (x - vec3f(0.5)) * viewU[7].w + vec3f(0.5);\n // Rec.709 luma, matching the ASC SAT node.\n let luma = dot(x, vec3f(0.2126, 0.7152, 0.0722));\n return max(mix(vec3f(luma), x, viewU[8].w), vec3f(0.0));\n}\n\n";
|
|
100
|
+
export declare const EFFECT_SCENE_API = "\n// \u2500\u2500 The effect API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Named rz*, for the engine. The prefix earns its place twice: user code is\n// concatenated into THIS module, so an unprefixed rzAnchor() would collide with\n// exactly the helper an author would write, and the old bg* prefix stopped being\n// true in 0.41.0 when effects gained a mount over the finished frame.\n//\n// The bg* names below are permanent aliases, not a deprecation with an end date.\n// A published link is immutable, so a scene pinned to a bg* effect has to keep\n// compiling forever. They are one-line and inlined; no new function gets one.\n\n/** Canvas size in pixels \u2014 for aspect correction. */\nfn rzResolution() -> vec2f { return viewU[6].zw; }\n\n/** The camera's world position. */\nfn rzCameraPos() -> vec3f { return viewU[10].xyz; }\n\n/** How many characters the SCENE holds, up to four \u2014 the number the cast api\n * narrows to this effect's own subjects. See subjectMaskApi. */\nfn _rzCastLive() -> i32 { return i32(viewU[10].w); }\n\n/**\n * A world point as the camera sees it: xy the uv it lands on, z its distance\n * along the VIEW AXIS in metres.\n *\n * The exact inverse of the ray this pass builds per pixel, so it is the cheap way\n * to work with anything anchored in the world. Marching a curve or a trail in 3D\n * costs a distance evaluation per sample per pixel; projecting its points once\n * and measuring in 2D costs a subtraction, which is the difference between a\n * ribbon that runs at 4K and one that does not.\n *\n * z is directly comparable to the depth handed to foreground(), so occlusion is\n * a single test: draw where your z is nearer than the scene's. It is returned\n * SIGNED and unclamped \u2014 behind the camera is negative, and worth rejecting\n * before you use the uv, which is meaningless there.\n */\nfn rzProject(p: vec3f) -> vec3f {\n let d = p - viewU[10].xyz;\n let z = dot(d, viewU[5].xyz);\n // Guard only the divide. z itself is returned as it is, so the caller can see\n // the sign; clamping it here would put points behind the lens on the horizon.\n let inv = 1.0 / select(z, 1e-4, z < 1e-4);\n let ndc = vec2f(dot(d, viewU[3].xyz) * inv / viewU[3].w, dot(d, viewU[4].xyz) * inv / viewU[4].w);\n return vec3f(ndc * 0.5 + 0.5, z);\n}\n\nfn rzCamPos() -> vec3f { return rzCameraPos(); }\nfn rzCameraRight() -> vec3f { return viewU[3].xyz; }\nfn rzCameraUp() -> vec3f { return viewU[4].xyz; }\nfn rzCameraForward() -> vec3f { return viewU[5].xyz; }\n\n// The cast \u2014 subjects, anchors, trails \u2014 is CAST_API, shared verbatim with the\n// particle and trail modules. It used to be written out here, a second time, and\n// the two copies had drifted: this one had rzAnchor and that one did not.\n\nconst RZ_SUBJECTS: i32 = 4;\nconst RZ_SAMPLES: i32 = 128;\n/** The anchor ADDRESS SPACE \u2014 how many an effect may declare, not how many it\n * did. RZ_TRAIL_SLOTS is the per-effect number and is not this one; the two\n * being one number was the old trail bug. */\nconst RZ_MAX_ANCHORS: i32 = 48;\nconst RZ_TRAIL_SAMPLES: i32 = 128;\n\nstruct RzSubject {\n /** On the FLOOR, under the body \u2014 where a ring or a magic circle belongs. */\n root: vec3f,\n /** At the hips, the middle of the body \u2014 where an aura belongs. */\n center: vec3f,\n /** Bounding sphere: xyz centre, w radius. Deliberately generous \u2014 cull with it. */\n bounds: vec4f,\n /**\n * How much of this character is still THERE: 1 whole, 0 gone.\n *\n * What setModelDissolve last set on them, which the material pass has already\n * acted on by the time an effect runs \u2014 so an effect drawing what LEAVES a\n * dissolving body (sparks, ash, a ghost) reads the same number the body was\n * taken apart with, rather than keeping a clock of its own and hoping the two\n * agree. 1 on a scene that never dissolves anybody.\n */\n dissolve: f32,\n /**\n * Where she LOOKS: a unit direction from between the eyes, in world space.\n * Exact while her eyes are on something (Engine.setEyeTracking); otherwise\n * the motion's own eye turn undone through the range map \u2014 an eye bone\n * turns a fraction of the way toward what it looks at, and this gives back\n * the whole of it. An effect that should go where the look goes \u2014 a beam,\n * a light \u2014 takes this rather than an eye bone's axis, and it holds in\n * either mode. Zero, with looking false, only for a model without eyes.\n */\n gaze: vec3f,\n looking: bool,\n /** False past the end of the cast, and every field is then zero. */\n valid: bool,\n}\n\nstruct RzAnchor {\n pos: vec3f,\n /** World units per second, from the previous frame. Direction for a trail,\n * magnitude for anything that should react to how hard someone is moving. */\n vel: vec3f,\n /** The bone's forward axis \u2014 which way a foot points, where a head looks. */\n fwd: vec3f,\n /** False when this rig has no such bone. Check it: the alternative is drawing\n * a hand effect at the world origin on every model that spells it differently. */\n valid: bool,\n}\n\n/**\n * How many characters THIS EFFECT is on, up to four.\n *\n * Not how many the scene holds. An effect applies to the whole cast unless the\n * scene says otherwise (Engine.setEffectSubjects), and where it says otherwise\n * this counts only the models named \u2014 so an effect aimed at one dancer sees one\n * subject, at index 0, and an author who wrote a loop over the cast gets the\n * targeting for free.\n *\n * Which is the whole design: the FILTER IS IN THE INDEX SPACE, not in the\n * shaders. There is no mask an effect can read, because an effect asking \"am I\n * allowed on this one\" is an effect that can get the answer wrong, and 18 of the\n * shipped built-ins would have had to be rewritten to ask at all.\n */\nfn rzSubjectCount() -> i32 {\n let live = _rzCastLive();\n let mask = _rzSubjectMask();\n var n = 0;\n for (var i = 0; i < live; i++) {\n if ((mask & (1u << u32(i))) != 0u) { n++; }\n }\n return n;\n}\n\n/** This effect's i-th subject \u2192 the scene's slot, or -1 past its own count.\n * Every accessor below goes through it, which is what keeps one effect's\n * subject 1 from being another's. */\nfn _rzSubjectSlot(i: i32) -> i32 {\n if (i < 0) { return -1; }\n let live = _rzCastLive();\n let mask = _rzSubjectMask();\n var n = 0;\n for (var s = 0; s < live; s++) {\n if ((mask & (1u << u32(s))) == 0u) { continue; }\n if (n == i) { return s; }\n n++;\n }\n return -1;\n}\n\n/** Which model this is, stable across a scene \u2014 for per-subject variation. */\nfn rzSubjectId(i: i32) -> u32 {\n let g = _rzSubjectSlot(i);\n if (g < 0) { return 0u; }\n return u32(_rzCast[g * 4 + 1].w);\n}\n\nfn rzSubject(i: i32) -> RzSubject {\n var s: RzSubject;\n let g = _rzSubjectSlot(i);\n s.valid = g >= 0;\n if (!s.valid) { return s; }\n let b = g * 4;\n s.root = _rzCast[b].xyz;\n s.dissolve = _rzCast[b].w;\n s.center = _rzCast[b + 1].xyz;\n s.bounds = _rzCast[b + 2];\n s.gaze = _rzCast[b + 3].xyz;\n s.looking = _rzCast[b + 3].w > 0.5;\n return s;\n}\n\n/**\n * Where a named bone is, this frame.\n *\n * The slot is the author's own: the Nth #anchor in their file, in the order\n * they wrote them. _rzSlot turns that into the scene's address, which is what\n * keeps two effects that both anchor to a wrist from reading each other's.\n */\nfn rzAnchor(subject: i32, slot: i32) -> RzAnchor {\n var a: RzAnchor;\n a.valid = false;\n let g = _rzSlot(slot);\n let s = _rzSubjectSlot(subject);\n if (s < 0 || g < 0 || g >= RZ_MAX_ANCHORS) { return a; }\n let b = 16 + (g * 4 + s) * 3;\n a.valid = _rzCast[b].w > 0.5;\n a.pos = _rzCast[b].xyz;\n a.vel = _rzCast[b + 1].xyz;\n a.fwd = _rzCast[b + 2].xyz;\n return a;\n}\n\n/**\n * How many samples of a path are recorded \u2014 0 for an anchor that asked for no\n * trail, and for one that has not moved yet.\n *\n * Bounded by the anchor cap, NOT by how many anchors asked for a trail. Those\n * are different index spaces: storage is addressed by anchor slot, so an\n * untrailed #anchor followed by a trailed one put the trail at index 1 with a\n * bound of 1 and rzTrail returned zero \u2014 a ribbon that silently did not draw.\n */\nfn rzTrailCount(subject: i32, slot: i32) -> i32 {\n let g = _rzSlot(slot);\n let s = _rzSubjectSlot(subject);\n if (s < 0 || g < 0 || g >= RZ_MAX_ANCHORS) { return 0; }\n return i32(_rzCast[16 + (g * 4 + s) * 3 + 2].w);\n}\n\n/** Sample i of a path: xyz where it was, w how many seconds ago. i = 0 is now. */\nfn rzTrail(subject: i32, slot: i32, i: i32) -> vec4f {\n let n = rzTrailCount(subject, slot);\n if (i < 0 || i >= n) { return vec4f(0.0); }\n let base = 592 + (_rzSlot(slot) * 4 + _rzSubjectSlot(subject)) * RZ_TRAIL_SAMPLES;\n return _rzCast[base + i];\n}\n\n\n// The hashes, the noise and rzFalloff \u2014 EFFECT_MATH_API, the same text the\n// particle and trail modules get. The field module used to be missing most of\n// it, so a helper an author wrote for one mount failed to compile in another\n// for no reason visible in the file.\n\nfn rzHash11(x: f32) -> f32 {\n var p = fract(x * 0.1031);\n p = p * (p + 33.33);\n return fract(p * (p + p));\n}\nfn rzHash21(p: vec2f) -> f32 {\n var p3 = fract(vec3f(p.x, p.y, p.x) * 0.1031);\n p3 = p3 + dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\n/** Three independent randoms from one seed \u2014 the usual need when spawning. */\nfn rzHash13(x: f32) -> vec3f {\n return vec3f(rzHash11(x), rzHash11(x + 17.13), rzHash11(x + 41.71));\n}\n/**\n * Compact-support falloff: 1 at the centre, exactly 0 at r, smooth between.\n *\n * It reaches exactly zero rather than merely getting small, because a glow that\n * never quite ends has to be culled somewhere, and culling it wherever it looks\n * close enough is what put a visible hard edge on the first halo effect.\n */\nfn rzFalloff(d: f32, r: f32) -> f32 {\n let x = clamp(d / max(r, 1e-6), 0.0, 1.0);\n let f = 1.0 - x;\n return f * f * f;\n}\nfn rzHash31(p: vec3f) -> f32 {\n var p3 = fract(p * 0.1031);\n p3 = p3 + dot(p3, p3.zyx + 31.32);\n return fract((p3.x + p3.y) * p3.z);\n}\nfn rzValueNoise(p: vec3f) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let u = f * f * (3.0 - 2.0 * f);\n let n000 = rzHash31(i);\n let n100 = rzHash31(i + vec3f(1.0, 0.0, 0.0));\n let n010 = rzHash31(i + vec3f(0.0, 1.0, 0.0));\n let n110 = rzHash31(i + vec3f(1.0, 1.0, 0.0));\n let n001 = rzHash31(i + vec3f(0.0, 0.0, 1.0));\n let n101 = rzHash31(i + vec3f(1.0, 0.0, 1.0));\n let n011 = rzHash31(i + vec3f(0.0, 1.0, 1.0));\n let n111 = rzHash31(i + vec3f(1.0, 1.0, 1.0));\n let x00 = mix(n000, n100, u.x);\n let x10 = mix(n010, n110, u.x);\n let x01 = mix(n001, n101, u.x);\n let x11 = mix(n011, n111, u.x);\n return mix(mix(x00, x10, u.y), mix(x01, x11, u.y), u.z);\n}\n/** Divergence-free flow \u2014 the field a wisp of smoke follows without a solver. */\nfn rzCurlNoise(p: vec3f) -> vec3f {\n let e = 0.1;\n let dx = vec3f(e, 0.0, 0.0);\n let dy = vec3f(0.0, e, 0.0);\n let dz = vec3f(0.0, 0.0, e);\n let x0 = rzValueNoise(p - dx); let x1 = rzValueNoise(p + dx);\n let y0 = rzValueNoise(p - dy); let y1 = rzValueNoise(p + dy);\n let z0 = rzValueNoise(p - dz); let z1 = rzValueNoise(p + dz);\n return normalize(vec3f((y1 - y0) - (z1 - z0), (z1 - z0) - (x1 - x0), (x1 - x0) - (y1 - y0)) + vec3f(1e-6));\n}\n\nstruct Particle {\n pos: vec3f,\n age: f32,\n vel: vec3f,\n life: f32,\n size: f32,\n rot: f32,\n seed: f32,\n // Aspect along the direction of travel. 1 or less is a square billboard; a\n // raindrop is 10 or 20. Zero-initialised, so an effect that never sets it gets\n // the square it expects.\n stretch: f32,\n}\n\n\n\nfn bgResolution() -> vec2f { return rzResolution(); }\nfn bgCameraPos() -> vec3f { return rzCameraPos(); }\nfn bgSubjectCount() -> i32 { return rzSubjectCount(); }\n\n/**\n * Where a character IS, in world space \u2014 at the hips, not on the floor.\n *\n * An effect that wants to RESPOND to the cast \u2014 a glow that follows someone,\n * dust kicked up where they are \u2014 needs to know where they are, and the ray and\n * the depth cannot tell it: they describe the pixel, not the scene.\n *\n * The value is model.position + \u30BB\u30F3\u30BF\u30FC + \u5168\u3066\u306E\u89AA. \u30BB\u30F3\u30BF\u30FC sits at hip\n * height on every standard MMD rig, so this is a point in the middle of the\n * body. It is NOT the contact point: a ripple drawn here appears at the waist.\n * Ground effects want the .xz of this and their own floor height, which is what\n * the effects that shipped against it already do.\n *\n * The comment here used to claim it was \"between the feet on the floor\", which\n * is where that habit came from. Left as it is regardless of the name: a\n * published link is immutable, so every shared scene pinning an effect that\n * reads this depends on it meaning exactly what it has always meant.\n *\n * Clamped rather than bounds-checked: an effect looping past the count reads the\n * last subject instead of sampling whatever follows the array, which is a wrong\n * ripple rather than an undefined one.\n *\n * THE INDEX IS THE EFFECT'S OWN, like every other cast accessor \u2014 Dry Ice, Water,\n * Holy Light and Bloody Ash all read this one and all of them should place their\n * fog, their ripple and their shaft under the model the scene aimed them at. The\n * mapping is the identity for an effect aimed at nobody in particular, which is\n * every scene published before one could be aimed.\n */\nfn rzSubjectHip(i: i32) -> vec3f { return viewU[11 + clamp(_rzSubjectSlot(i), 0, 3)].xyz; }\n\nfn bgSubjectPos(i: i32) -> vec3f { return rzSubjectHip(i); }\n\n/** Where in the WORLD the scene drew this pixel \u2014 the depth handed to\n * foreground() turned into a place. Without it an effect can only think in\n * distances from the lens, which is no use to anything that belongs somewhere:\n * fog lying on the ground has to know where the ground is.\n *\n * depth measures along the VIEW AXIS, not along the ray, so it is divided by\n * the ray's projection onto camera-forward before being walked out. At the far\n * plane (nothing drawn) this lands a very long way off, which is what a sky\n * should do to anything reading it. */\nfn rzWorldPos(ray: vec3f, depth: f32) -> vec3f {\n let axis = max(dot(normalize(ray), viewU[5].xyz), 1e-4);\n return rzCameraPos() + normalize(ray) * (depth / axis);\n}\n\nfn bgWorldPos(ray: vec3f, depth: f32) -> vec3f { return rzWorldPos(ray, depth); }\n\n/** What an effect returns for one of its lights. */\nstruct RzLight {\n pos: vec3f,\n color: vec3f,\n intensity: f32,\n radius: f32,\n /** Its bulb: the distance inside which it stops getting brighter. 0 is the\n * engine's default; a glow worn on a hand wants one the size of the glow. */\n near: f32,\n}\n\n\n/** Color grading, applied to the tonemapped SCENE (not the background \u2014 see the\n * call site). The core is ASC CDL, the film-industry interchange standard:\n *\n * out = (in \u00B7 slope + offset) ^ power then saturation (SOP \u2192 SAT)\n *\n * Using the real standard rather than invented controls means a look authored\n * here maps onto any grading tool. slope/offset/power are derived on the CPU\n * from the UI's shadow/midtone/highlight colors (see setColorGrading), so the\n * per-pixel cost is one mul-add, one pow, one lerp. */\nfn grade(c: vec3f) -> vec3f {\n var x = pow(max(c * viewU[9].xyz + viewU[7].xyz, vec3f(0.0)), viewU[8].xyz);\n // Contrast pivots on 0.5 \u2014 display-referred midpoint, since we grade post-Filmic.\n x = (x - vec3f(0.5)) * viewU[7].w + vec3f(0.5);\n // Rec.709 luma, matching the ASC SAT node.\n let luma = dot(x, vec3f(0.2126, 0.7152, 0.0722));\n return max(mix(vec3f(luma), x, viewU[8].w), vec3f(0.0));\n}\n\n";
|
|
101
101
|
export declare function buildCompositeShader(effect?: CompositeEffectSource | null): string;
|
|
102
102
|
/**
|
|
103
103
|
* The field pass: the user's background/foreground mounts at half resolution,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/composite.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAgC+B;AAC/B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,EAAE,CAIhG;AAID,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAEzG,KAAK,qBAAqB,GAAG;IAC3B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAA;IAClB,4DAA4D;IAC5D,aAAa,EAAE,OAAO,CAAA;IACtB,oEAAoE;IACpE,aAAa,EAAE,OAAO,CAAA;IACtB;6DACyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAA;IAChB;mFAC+E;IAC/E,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;yEAGqE;IACrE,UAAU,EAAE,MAAM,CAAA;IAClB;;8EAE0E;IAC1E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAwRD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/composite.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAgC+B;AAC/B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,EAAE,CAIhG;AAID,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAEzG,KAAK,qBAAqB,GAAG;IAC3B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAA;IAClB,4DAA4D;IAC5D,aAAa,EAAE,OAAO,CAAA;IACtB,oEAAoE;IACpE,aAAa,EAAE,OAAO,CAAA;IACtB;6DACyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAA;IAChB;mFAC+E;IAC/E,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;yEAGqE;IACrE,UAAU,EAAE,MAAM,CAAA;IAClB;;8EAE0E;IAC1E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAwRD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,g6fAuI5B,CAAA;AA4MD,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,IAAI,GAAG,MAAM,CAclF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CA2GtE;AAED,iFAAiF;AACjF,eAAO,MAAM,qBAAqB,QAA6B,CAAA"}
|
|
@@ -600,11 +600,9 @@ const COMPOSITE_BODY = /* wgsl */ `
|
|
|
600
600
|
// ── Film grain, on the SCENE ONLY ─────────────────────────────────────────
|
|
601
601
|
//
|
|
602
602
|
// Applied here, before the background is composited under, so it rides on what
|
|
603
|
-
// the engine drew and nothing else
|
|
604
|
-
//
|
|
605
|
-
//
|
|
606
|
-
// rather than match it. A clean CG figure on a grainy plate is one of the
|
|
607
|
-
// loudest tells there is — the noise gives it away long before the geometry.
|
|
603
|
+
// the engine drew and nothing else: a backdrop photo or video already carries
|
|
604
|
+
// its own grain, and a second helping over the top would grade the picture
|
|
605
|
+
// rather than match it.
|
|
608
606
|
//
|
|
609
607
|
// Multiplicative and weighted toward the mid-tones, which is how film behaves:
|
|
610
608
|
// little grain in the blacks, and the highlights clip it off.
|
|
@@ -141,7 +141,7 @@ struct MirrorVP { viewProj: mat4x4f, params: vec4f, };
|
|
|
141
141
|
struct MirrorClip { plane: vec4f, on: f32, _p0: f32, _p1: f32, _p2: f32, };
|
|
142
142
|
@group(0) @binding(14) var<uniform> clip: MirrorClip;
|
|
143
143
|
${WORLD_AMBIENT_WGSL}
|
|
144
|
-
${lightsApi(0, 6, "1u")}
|
|
144
|
+
${lightsApi(0, 6, "1u", { binding: 15, sampler: "linearSampler" })}
|
|
145
145
|
|
|
146
146
|
struct VO { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, };
|
|
147
147
|
@vertex fn vs(@location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f) -> VO {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"particles.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/particles.ts"],"names":[],"mappings":"AAgCA,sEAAsE;AACtE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb;;mFAE+E;IAC/E,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAkCD,qDAAqD;AACrD;0EAC0E;AAC1E,KAAK,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAA;AAEpD,KAAK,cAAc,GAAG;IACpB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,aAAa,CAAA;IACpB,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAA;IACd;;+BAE2B;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;iEAK6D;IAC7D,KAAK,EAAE,OAAO,CAAA;IACd;;;;;;;yEAOqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;;;;;kFAO8E;IAC9E,IAAI,EAAE,OAAO,CAAA;IACb;;;wEAGoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB;mDAC+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,0FAA0F;AAC1F,eAAO,MAAM,sBAAsB,KAAK,CAAA;AACxC,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;;sDAEsD;AACtD,eAAO,MAAM,yBAAyB,KAAK,CAAA;AAC3C,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;uCACuC;AACvC,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,eAAO,MAAM,gCAAgC,KAAK,CAAA;AAClD,eAAO,MAAM,6BAA6B,KAAK,CAAA;AAE/C,oEAAoE;AACpE,eAAO,MAAM,eAAe,KAAK,CAAA;AAwDjC;;2EAE2E;AAC3E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CASnJ;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CA6ExF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"particles.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/particles.ts"],"names":[],"mappings":"AAgCA,sEAAsE;AACtE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb;;mFAE+E;IAC/E,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAkCD,qDAAqD;AACrD;0EAC0E;AAC1E,KAAK,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAA;AAEpD,KAAK,cAAc,GAAG;IACpB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,aAAa,CAAA;IACpB,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAA;IACd;;+BAE2B;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;iEAK6D;IAC7D,KAAK,EAAE,OAAO,CAAA;IACd;;;;;;;yEAOqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;;;;;kFAO8E;IAC9E,IAAI,EAAE,OAAO,CAAA;IACb;;;wEAGoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB;mDAC+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,0FAA0F;AAC1F,eAAO,MAAM,sBAAsB,KAAK,CAAA;AACxC,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;;sDAEsD;AACtD,eAAO,MAAM,yBAAyB,KAAK,CAAA;AAC3C,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;uCACuC;AACvC,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,eAAO,MAAM,gCAAgC,KAAK,CAAA;AAClD,eAAO,MAAM,6BAA6B,KAAK,CAAA;AAE/C,oEAAoE;AACpE,eAAO,MAAM,eAAe,KAAK,CAAA;AAwDjC;;2EAE2E;AAC3E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CASnJ;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CA6ExF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAuMvF"}
|
|
@@ -290,9 +290,15 @@ ${src.orient ? ` // the author's own plane (particleOrient): a card on a surfac
|
|
|
290
290
|
let o = particleOrient(p, ii);
|
|
291
291
|
right = o[0];
|
|
292
292
|
up = o[1];
|
|
293
|
-
` : ""}
|
|
293
|
+
` : ""}${/\bfn\s+particlePivot\s*\(/.test(src.wgsl) ? ` // the card's pivot (particlePivot, in half-size units of the quad): the
|
|
294
|
+
// corners are offset by it BEFORE the turn, so the card turns about its
|
|
295
|
+
// pivot rather than its centre — Unity's renderer pivot, a lighthouse beam
|
|
296
|
+
// whose card starts at the lamp instead of straddling it
|
|
297
|
+
let cp = c + particlePivot(p, ii);
|
|
298
|
+
` : ` let cp = c;
|
|
299
|
+
`} let s = sin(p.rot);
|
|
294
300
|
let k = cos(p.rot);
|
|
295
|
-
var r = vec2f(
|
|
301
|
+
var r = vec2f(cp.x * k - cp.y * s, cp.x * s + cp.y * k);
|
|
296
302
|
// Stretched along the direction of travel ON SCREEN — which is not the world
|
|
297
303
|
// direction once the camera is off-axis. Rain falling straight down is nearly
|
|
298
304
|
// a point when viewed from above and a long streak from the side, and taking
|
|
@@ -304,7 +310,7 @@ ${src.orient ? ` // the author's own plane (particleOrient): a card on a surfac
|
|
|
304
310
|
let vlen = length(vec2f(vr, vu));
|
|
305
311
|
if (vlen > 1e-5) {
|
|
306
312
|
let d = vec2f(vr, vu) / vlen;
|
|
307
|
-
r = vec2f(d.y, -d.x) *
|
|
313
|
+
r = vec2f(d.y, -d.x) * cp.x + d * (cp.y * p.stretch);
|
|
308
314
|
}
|
|
309
315
|
}
|
|
310
316
|
let world = p.pos + (right * r.x + up * r.y) * p.size;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Face size of the capture, and of the cube the materials read. The game
|
|
2
|
+
* bakes 64²; the capture is twice that so the base level is antialiased. */
|
|
3
|
+
export declare const PROBE_CAPTURE_SIZE = 128;
|
|
4
|
+
export declare const PROBE_SIZE = 64;
|
|
5
|
+
/** 64² down to 1²: seven levels, the game's own count. */
|
|
6
|
+
export declare const PROBE_LEVELS = 7;
|
|
7
|
+
export declare const PROBE_CAPTURE_LEVELS = 8;
|
|
8
|
+
/**
|
|
9
|
+
* The perceptual roughness level m of the probe was convolved with, on
|
|
10
|
+
* Unity's probe curve: m = r·(1.7 − 0.7r)·6 (UNITY_SPECCUBE_LOD_STEPS), the
|
|
11
|
+
* convention the game's baked probes follow and its lookup (×8, clamped at 6)
|
|
12
|
+
* reads against. Level 0 is the unblurred capture.
|
|
13
|
+
*/
|
|
14
|
+
export declare function probeLevelRoughness(level: number): number;
|
|
15
|
+
/**
|
|
16
|
+
* The perceptual roughness level m of the sky's equirect chain was convolved
|
|
17
|
+
* with: the engine's own lookup is lod = sqrt(r)·(levels − 1), so level m is
|
|
18
|
+
* r = (m / (levels − 1))².
|
|
19
|
+
*/
|
|
20
|
+
export declare function skyLevelRoughness(level: number, levels: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* The compose step: the stage as captured, with the world's sky laid in
|
|
23
|
+
* behind it wherever the capture's coverage says nothing was drawn — an open
|
|
24
|
+
* stage reflects its sky, an interior its walls. Built on the material
|
|
25
|
+
* prelude for rzWorldSpecularLod, which knows every kind of sky the scene may
|
|
26
|
+
* have (an HDRI, a gradient, one colour). Only the bindings it reads end up in
|
|
27
|
+
* its layout ("auto"): the light uniform, the sampler and the sky at group 0,
|
|
28
|
+
* and its own three past the material set's.
|
|
29
|
+
*/
|
|
30
|
+
export declare const PROBE_COMPOSE_WGSL: string;
|
|
31
|
+
/**
|
|
32
|
+
* The cube's own passes: a mip from the level above (mode 0 — one bilinear
|
|
33
|
+
* tap at the child texel's direction is the 2×2 average), and the GGX
|
|
34
|
+
* convolution into the probe the materials read (mode 1).
|
|
35
|
+
*/
|
|
36
|
+
export declare const PROBE_FILTER_WGSL: string;
|
|
37
|
+
/**
|
|
38
|
+
* The sky's mips, convolved: level m of the equirect the materials read
|
|
39
|
+
* (rzWorldSpecularLod) becomes the GGX-filtered sky at the roughness that
|
|
40
|
+
* level stands for, sampled from the box-averaged chain the upload built.
|
|
41
|
+
* Directions follow the composite's dome: u = 0.5 + atan2(x, z)/2π,
|
|
42
|
+
* v = 0.5 − asin(y)/π.
|
|
43
|
+
*/
|
|
44
|
+
export declare const SKY_PREFILTER_WGSL: string;
|
|
45
|
+
//# sourceMappingURL=probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/probe.ts"],"names":[],"mappings":"AAgBA;6EAC6E;AAC7E,eAAO,MAAM,kBAAkB,MAAM,CAAA;AACrC,eAAO,MAAM,UAAU,KAAK,CAAA;AAC5B,0DAA0D;AAC1D,eAAO,MAAM,YAAY,IAAI,CAAA;AAC7B,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAIvE;AA+DD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,QAmB9B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAoC7B,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,QAmD9B,CAAA"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// The reflection probe's GPU passes, and the sky's prefilter.
|
|
2
|
+
//
|
|
3
|
+
// A game does not reflect the sky alone: it bakes a cube of the stage itself
|
|
4
|
+
// from somewhere in the middle of it, prefilters it down its mips with the
|
|
5
|
+
// specular lobe, and every surface reads it box-projected onto the stage's
|
|
6
|
+
// bounds. The engine does the same once a stage has loaded (Engine:
|
|
7
|
+
// captureReflectionProbe): six renders of the stage into a 128² cube, the
|
|
8
|
+
// sky laid in wherever nothing was drawn, a mip chain, then a GGX convolution
|
|
9
|
+
// into the 64² cube the materials sample (rzProbeSpecular in nodes.ts).
|
|
10
|
+
//
|
|
11
|
+
// The world's sky gets the same convolution down its equirect mips, in place
|
|
12
|
+
// of the box average they were built from.
|
|
13
|
+
import { NODES_WGSL } from "../materials/nodes";
|
|
14
|
+
import { COMMON_MATERIAL_PRELUDE_WGSL, DISSOLVE_WGSL } from "../materials/common";
|
|
15
|
+
/** Face size of the capture, and of the cube the materials read. The game
|
|
16
|
+
* bakes 64²; the capture is twice that so the base level is antialiased. */
|
|
17
|
+
export const PROBE_CAPTURE_SIZE = 128;
|
|
18
|
+
export const PROBE_SIZE = 64;
|
|
19
|
+
/** 64² down to 1²: seven levels, the game's own count. */
|
|
20
|
+
export const PROBE_LEVELS = 7;
|
|
21
|
+
export const PROBE_CAPTURE_LEVELS = 8;
|
|
22
|
+
/**
|
|
23
|
+
* The perceptual roughness level m of the probe was convolved with, on
|
|
24
|
+
* Unity's probe curve: m = r·(1.7 − 0.7r)·6 (UNITY_SPECCUBE_LOD_STEPS), the
|
|
25
|
+
* convention the game's baked probes follow and its lookup (×8, clamped at 6)
|
|
26
|
+
* reads against. Level 0 is the unblurred capture.
|
|
27
|
+
*/
|
|
28
|
+
export function probeLevelRoughness(level) {
|
|
29
|
+
if (level <= 0)
|
|
30
|
+
return 0;
|
|
31
|
+
const m = Math.min(level, 6);
|
|
32
|
+
return Math.min((10.2 - Math.sqrt(Math.max(104.04 - 16.8 * m, 0))) / 8.4, 1);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The perceptual roughness level m of the sky's equirect chain was convolved
|
|
36
|
+
* with: the engine's own lookup is lod = sqrt(r)·(levels − 1), so level m is
|
|
37
|
+
* r = (m / (levels − 1))².
|
|
38
|
+
*/
|
|
39
|
+
export function skyLevelRoughness(level, levels) {
|
|
40
|
+
if (level <= 0 || levels <= 1)
|
|
41
|
+
return 0;
|
|
42
|
+
const t = level / (levels - 1);
|
|
43
|
+
return Math.min(t * t, 1);
|
|
44
|
+
}
|
|
45
|
+
/** A cube face's direction for a uv on it (uv.y down), in the convention the
|
|
46
|
+
* GPU samples a cube with — the same one the capture cameras render. */
|
|
47
|
+
const FACE_DIR_WGSL = /* wgsl */ `
|
|
48
|
+
fn rz_face_dir(face: u32, uv: vec2f) -> vec3f {
|
|
49
|
+
let s = uv.x * 2.0 - 1.0;
|
|
50
|
+
let t = uv.y * 2.0 - 1.0;
|
|
51
|
+
switch face {
|
|
52
|
+
case 0u: { return normalize(vec3f(1.0, -t, -s)); }
|
|
53
|
+
case 1u: { return normalize(vec3f(-1.0, -t, s)); }
|
|
54
|
+
case 2u: { return normalize(vec3f(s, 1.0, t)); }
|
|
55
|
+
case 3u: { return normalize(vec3f(s, -1.0, -t)); }
|
|
56
|
+
case 4u: { return normalize(vec3f(s, -t, 1.0)); }
|
|
57
|
+
default: { return normalize(vec3f(-s, -t, -1.0)); }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
struct RzFullOut { @builtin(position) pos: vec4f, @location(0) uv: vec2f };
|
|
62
|
+
|
|
63
|
+
@vertex fn vs_full(@builtin(vertex_index) i: u32) -> RzFullOut {
|
|
64
|
+
var o: RzFullOut;
|
|
65
|
+
let x = f32(i32(i / 2u) * 4 - 1);
|
|
66
|
+
let y = f32(i32(i % 2u) * 4 - 1);
|
|
67
|
+
o.pos = vec4f(x, y, 0.0, 1.0);
|
|
68
|
+
o.uv = vec2f(x * 0.5 + 0.5, 0.5 - y * 0.5);
|
|
69
|
+
return o;
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
/** GGX importance sampling, the filtered kind (Křivánek & Colbert): each
|
|
73
|
+
* sample reads the source at the mip whose texel matches its solid angle, so
|
|
74
|
+
* a few dozen taps integrate a wide lobe without the fireflies a point sample
|
|
75
|
+
* of a bright lamp would leave. */
|
|
76
|
+
const GGX_SAMPLING_WGSL = /* wgsl */ `
|
|
77
|
+
fn rz_hammersley(i: u32, n: u32) -> vec2f {
|
|
78
|
+
var b = (i << 16u) | (i >> 16u);
|
|
79
|
+
b = ((b & 0x55555555u) << 1u) | ((b & 0xAAAAAAAAu) >> 1u);
|
|
80
|
+
b = ((b & 0x33333333u) << 2u) | ((b & 0xCCCCCCCCu) >> 2u);
|
|
81
|
+
b = ((b & 0x0F0F0F0Fu) << 4u) | ((b & 0xF0F0F0F0u) >> 4u);
|
|
82
|
+
b = ((b & 0x00FF00FFu) << 8u) | ((b & 0xFF00FF00u) >> 8u);
|
|
83
|
+
return vec2f(f32(i) / f32(n), f32(b) * 2.3283064365386963e-10);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** A half vector about N for the lobe at alpha = a (= perceptual r²). */
|
|
87
|
+
fn rz_ggx_half(xi: vec2f, N: vec3f, a: f32) -> vec3f {
|
|
88
|
+
let phi = 6.283185307 * xi.x;
|
|
89
|
+
let cosT = sqrt((1.0 - xi.y) / (1.0 + (a * a - 1.0) * xi.y));
|
|
90
|
+
let sinT = sqrt(max(1.0 - cosT * cosT, 0.0));
|
|
91
|
+
let h = vec3f(sinT * cos(phi), sinT * sin(phi), cosT);
|
|
92
|
+
let up = select(vec3f(1.0, 0.0, 0.0), vec3f(0.0, 0.0, 1.0), abs(N.z) < 0.999);
|
|
93
|
+
let tx = normalize(cross(up, N));
|
|
94
|
+
let ty = cross(N, tx);
|
|
95
|
+
return normalize(tx * h.x + ty * h.y + N * h.z);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
fn rz_ggx_d(nh: f32, a: f32) -> f32 {
|
|
99
|
+
let a2 = a * a;
|
|
100
|
+
let d = nh * nh * (a2 - 1.0) + 1.0;
|
|
101
|
+
return a2 / (3.141592653589793 * d * d);
|
|
102
|
+
}
|
|
103
|
+
`;
|
|
104
|
+
/**
|
|
105
|
+
* The compose step: the stage as captured, with the world's sky laid in
|
|
106
|
+
* behind it wherever the capture's coverage says nothing was drawn — an open
|
|
107
|
+
* stage reflects its sky, an interior its walls. Built on the material
|
|
108
|
+
* prelude for rzWorldSpecularLod, which knows every kind of sky the scene may
|
|
109
|
+
* have (an HDRI, a gradient, one colour). Only the bindings it reads end up in
|
|
110
|
+
* its layout ("auto"): the light uniform, the sampler and the sky at group 0,
|
|
111
|
+
* and its own three past the material set's.
|
|
112
|
+
*/
|
|
113
|
+
export const PROBE_COMPOSE_WGSL = NODES_WGSL +
|
|
114
|
+
COMMON_MATERIAL_PRELUDE_WGSL +
|
|
115
|
+
DISSOLVE_WGSL +
|
|
116
|
+
FACE_DIR_WGSL +
|
|
117
|
+
/* wgsl */ `
|
|
118
|
+
struct RzProbeStep { face: u32, lod: f32, roughness: f32, srcSize: f32 };
|
|
119
|
+
@group(0) @binding(20) var rzCaptureColor: texture_2d_array<f32>;
|
|
120
|
+
@group(0) @binding(21) var rzCaptureAux: texture_2d_array<f32>;
|
|
121
|
+
@group(0) @binding(22) var<uniform> rzStep: RzProbeStep;
|
|
122
|
+
|
|
123
|
+
@fragment fn fs_compose(in: RzFullOut) -> @location(0) vec4f {
|
|
124
|
+
let size = textureDimensions(rzCaptureColor);
|
|
125
|
+
let px = vec2u(min(in.pos.xy, vec2f(size) - vec2f(1.0)));
|
|
126
|
+
let c = textureLoad(rzCaptureColor, px, rzStep.face, 0).rgb;
|
|
127
|
+
let cover = saturate(textureLoad(rzCaptureAux, px, rzStep.face, 0).g);
|
|
128
|
+
let sky = rzWorldSpecularLod(rz_face_dir(rzStep.face, in.uv), 0.0, 0.0);
|
|
129
|
+
return vec4f(c + sky * (1.0 - cover), 1.0);
|
|
130
|
+
}
|
|
131
|
+
`;
|
|
132
|
+
/**
|
|
133
|
+
* The cube's own passes: a mip from the level above (mode 0 — one bilinear
|
|
134
|
+
* tap at the child texel's direction is the 2×2 average), and the GGX
|
|
135
|
+
* convolution into the probe the materials read (mode 1).
|
|
136
|
+
*/
|
|
137
|
+
export const PROBE_FILTER_WGSL = FACE_DIR_WGSL +
|
|
138
|
+
GGX_SAMPLING_WGSL +
|
|
139
|
+
/* wgsl */ `
|
|
140
|
+
struct RzProbeStep { face: u32, lod: f32, roughness: f32, srcSize: f32, mode: u32 };
|
|
141
|
+
@group(0) @binding(0) var rzSrc: texture_cube<f32>;
|
|
142
|
+
@group(0) @binding(1) var rzSamp: sampler;
|
|
143
|
+
@group(0) @binding(2) var<uniform> rzStep: RzProbeStep;
|
|
144
|
+
|
|
145
|
+
const RZ_PROBE_SAMPLES: u32 = 128u;
|
|
146
|
+
|
|
147
|
+
@fragment fn fs_filter(in: RzFullOut) -> @location(0) vec4f {
|
|
148
|
+
let N = rz_face_dir(rzStep.face, in.uv);
|
|
149
|
+
let r = rzStep.roughness;
|
|
150
|
+
if (rzStep.mode == 0u || r < 0.002) {
|
|
151
|
+
return vec4f(textureSampleLevel(rzSrc, rzSamp, N, rzStep.lod).rgb, 1.0);
|
|
152
|
+
}
|
|
153
|
+
let a = r * r;
|
|
154
|
+
let texelSolid = 4.0 * 3.141592653589793 / (6.0 * rzStep.srcSize * rzStep.srcSize);
|
|
155
|
+
let maxLod = f32(textureNumLevels(rzSrc) - 1u);
|
|
156
|
+
var sum = vec3f(0.0);
|
|
157
|
+
var weight = 0.0;
|
|
158
|
+
for (var i = 0u; i < RZ_PROBE_SAMPLES; i++) {
|
|
159
|
+
let H = rz_ggx_half(rz_hammersley(i, RZ_PROBE_SAMPLES), N, a);
|
|
160
|
+
let L = 2.0 * dot(N, H) * H - N;
|
|
161
|
+
let nl = dot(N, L);
|
|
162
|
+
if (nl <= 0.0) { continue; }
|
|
163
|
+
// N = V: the pdf over L is D·(N·H)/(4·V·H) = D/4.
|
|
164
|
+
let pdf = rz_ggx_d(saturate(dot(N, H)), a) * 0.25;
|
|
165
|
+
let sampleSolid = 1.0 / (f32(RZ_PROBE_SAMPLES) * pdf + 1e-6);
|
|
166
|
+
let lod = clamp(0.5 * log2(sampleSolid / texelSolid) + 1.0, 0.0, maxLod);
|
|
167
|
+
sum += textureSampleLevel(rzSrc, rzSamp, L, lod).rgb * nl;
|
|
168
|
+
weight += nl;
|
|
169
|
+
}
|
|
170
|
+
return vec4f(sum / max(weight, 1e-4), 1.0);
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
/**
|
|
174
|
+
* The sky's mips, convolved: level m of the equirect the materials read
|
|
175
|
+
* (rzWorldSpecularLod) becomes the GGX-filtered sky at the roughness that
|
|
176
|
+
* level stands for, sampled from the box-averaged chain the upload built.
|
|
177
|
+
* Directions follow the composite's dome: u = 0.5 + atan2(x, z)/2π,
|
|
178
|
+
* v = 0.5 − asin(y)/π.
|
|
179
|
+
*/
|
|
180
|
+
export const SKY_PREFILTER_WGSL = GGX_SAMPLING_WGSL +
|
|
181
|
+
/* wgsl */ `
|
|
182
|
+
struct RzFullOut { @builtin(position) pos: vec4f, @location(0) uv: vec2f };
|
|
183
|
+
|
|
184
|
+
@vertex fn vs_full(@builtin(vertex_index) i: u32) -> RzFullOut {
|
|
185
|
+
var o: RzFullOut;
|
|
186
|
+
let x = f32(i32(i / 2u) * 4 - 1);
|
|
187
|
+
let y = f32(i32(i % 2u) * 4 - 1);
|
|
188
|
+
o.pos = vec4f(x, y, 0.0, 1.0);
|
|
189
|
+
o.uv = vec2f(x * 0.5 + 0.5, 0.5 - y * 0.5);
|
|
190
|
+
return o;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
struct RzSkyStep { roughness: f32, srcWidth: f32, srcHeight: f32, spare: f32 };
|
|
194
|
+
@group(0) @binding(0) var rzSky: texture_2d<f32>;
|
|
195
|
+
@group(0) @binding(1) var rzSamp: sampler;
|
|
196
|
+
@group(0) @binding(2) var<uniform> rzStep: RzSkyStep;
|
|
197
|
+
|
|
198
|
+
const RZ_SKY_SAMPLES: u32 = 64u;
|
|
199
|
+
|
|
200
|
+
fn rz_sky_dir(uv: vec2f) -> vec3f {
|
|
201
|
+
let phi = (uv.x - 0.5) * 6.283185307;
|
|
202
|
+
let lat = (0.5 - uv.y) * 3.141592653589793;
|
|
203
|
+
return vec3f(cos(lat) * sin(phi), sin(lat), cos(lat) * cos(phi));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
fn rz_sky_uv(d: vec3f) -> vec2f {
|
|
207
|
+
return vec2f(0.5 + atan2(d.x, d.z) * 0.15915494309, 0.5 - asin(clamp(d.y, -1.0, 1.0)) * 0.31830988618);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@fragment fn fs_sky(in: RzFullOut) -> @location(0) vec4f {
|
|
211
|
+
let N = rz_sky_dir(in.uv);
|
|
212
|
+
let a = rzStep.roughness * rzStep.roughness;
|
|
213
|
+
let texelSolid = 4.0 * 3.141592653589793 / (rzStep.srcWidth * rzStep.srcHeight);
|
|
214
|
+
let maxLod = f32(textureNumLevels(rzSky) - 1u);
|
|
215
|
+
var sum = vec3f(0.0);
|
|
216
|
+
var weight = 0.0;
|
|
217
|
+
for (var i = 0u; i < RZ_SKY_SAMPLES; i++) {
|
|
218
|
+
let H = rz_ggx_half(rz_hammersley(i, RZ_SKY_SAMPLES), N, a);
|
|
219
|
+
let L = 2.0 * dot(N, H) * H - N;
|
|
220
|
+
let nl = dot(N, L);
|
|
221
|
+
if (nl <= 0.0) { continue; }
|
|
222
|
+
let pdf = rz_ggx_d(saturate(dot(N, H)), a) * 0.25;
|
|
223
|
+
let sampleSolid = 1.0 / (f32(RZ_SKY_SAMPLES) * pdf + 1e-6);
|
|
224
|
+
let lod = clamp(0.5 * log2(sampleSolid / texelSolid) + 1.0, 0.0, maxLod);
|
|
225
|
+
sum += textureSampleLevel(rzSky, rzSamp, rz_sky_uv(L), lod).rgb * nl;
|
|
226
|
+
weight += nl;
|
|
227
|
+
}
|
|
228
|
+
return vec4f(sum / max(weight, 1e-4), 1.0);
|
|
229
|
+
}
|
|
230
|
+
`;
|
|
@@ -73,6 +73,12 @@ type SceneRenderClass =
|
|
|
73
73
|
* X309's night sky was. Out of WRITES_ID for the mirror's reason — a sheet of
|
|
74
74
|
* light is not an object anything should be able to pick or outline. */
|
|
75
75
|
| "material-additive"
|
|
76
|
+
/** A material whose colour arrives ALREADY weighted by its coverage — a
|
|
77
|
+
* game's glass (Blend One OneMinusSrcAlpha): the pane's diffuse fades with
|
|
78
|
+
* its alpha while its reflection does not, which a src-alpha blend cannot
|
|
79
|
+
* express. Out of WRITES_ID for the mirror's reason: a window is not what a
|
|
80
|
+
* click on the figure behind it means. */
|
|
81
|
+
| "material-premultiplied"
|
|
76
82
|
/** Particles and ribbons in their default, non-additive mode. */
|
|
77
83
|
| "particle"
|
|
78
84
|
/** Particles declaring `#blend additive` — LIGHT rather than matter, so
|
|
@@ -85,6 +91,13 @@ type SceneRenderClass =
|
|
|
85
91
|
* whole, and an ordinary alpha-over aux so a ribbon's mask does not
|
|
86
92
|
* saturate along every overlap. */
|
|
87
93
|
| "trail"
|
|
94
|
+
/** Ribbons declaring `#blend over` — MATTER rather than light: laid over
|
|
95
|
+
* what is behind them by their own alpha, the way a game's trail material
|
|
96
|
+
* with Blend One OneMinusSrcAlpha draws. A dark band then darkens, which an
|
|
97
|
+
* additive ribbon can never do; it is how a deep-blue smoke tail reads as a
|
|
98
|
+
* tail at all. The fragment writes straight colour, so the colour blend is
|
|
99
|
+
* src-alpha like any other alpha-over class. */
|
|
100
|
+
| "trail-over"
|
|
88
101
|
/** The transparent depth prepass: it exists to write DEPTH after the fabric's
|
|
89
102
|
* colour blended, so an outline drawn later is occluded behind it. It must
|
|
90
103
|
* therefore write no colour at all — the targets exist only to make the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-contract.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/scene-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;uDAEuD;AACvD,MAAM,MAAM,YAAY,GAAG;IACzB,+CAA+C;IAC/C,GAAG,EAAE,gBAAgB,CAAA;IACrB,iEAAiE;IACjE,GAAG,EAAE,gBAAgB,CAAA;CACtB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,gBAA6B,CAAA;AAkB3D,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAE3C;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;GAMG;AACH,KAAK,gBAAgB;AACnB,2DAA2D;AACzD,UAAU;AACZ;;+CAE+C;GAC7C,QAAQ;AACV,uEAAuE;GACrE,SAAS;AACX;;;;6EAI6E;GAC3E,QAAQ;AACV;;;;;;yEAMyE;GACvE,mBAAmB;AACrB,iEAAiE;GAC/D,UAAU;AACZ;;;mDAGmD;GACjD,mBAAmB;AACrB;;;oCAGoC;GAClC,OAAO;AACT;;;kDAGkD;GAChD,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"scene-contract.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/scene-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;uDAEuD;AACvD,MAAM,MAAM,YAAY,GAAG;IACzB,+CAA+C;IAC/C,GAAG,EAAE,gBAAgB,CAAA;IACrB,iEAAiE;IACjE,GAAG,EAAE,gBAAgB,CAAA;CACtB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,gBAA6B,CAAA;AAkB3D,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAE3C;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;GAMG;AACH,KAAK,gBAAgB;AACnB,2DAA2D;AACzD,UAAU;AACZ;;+CAE+C;GAC7C,QAAQ;AACV,uEAAuE;GACrE,SAAS;AACX;;;;6EAI6E;GAC3E,QAAQ;AACV;;;;;;yEAMyE;GACvE,mBAAmB;AACrB;;;;2CAI2C;GACzC,wBAAwB;AAC1B,iEAAiE;GAC/D,UAAU;AACZ;;;mDAGmD;GACjD,mBAAmB;AACrB;;;oCAGoC;GAClC,OAAO;AACT;;;;;iDAKiD;GAC/C,YAAY;AACd;;;kDAGkD;GAChD,eAAe,CAAA;AA6FnB;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,YAAY,GAAG,mBAAmB,EAAE,CAoBhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAE3E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAmB7E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD"}
|
|
@@ -114,6 +114,9 @@ const BLENDS = {
|
|
|
114
114
|
// The same pair the additive particles use: light into the colour target, and
|
|
115
115
|
// coverage that still accumulates so bloom and the composite can see it.
|
|
116
116
|
"material-additive": [ADD_KEEP_ALPHA, ADD_BOTH],
|
|
117
|
+
// The colour premultiplied by the graph (game_pbr's glass); the aux is
|
|
118
|
+
// written straight, as every material's is.
|
|
119
|
+
"material-premultiplied": [PREMULTIPLIED_OVER, ALPHA_OVER],
|
|
117
120
|
// PREMULTIPLIED, like the ground and for the same reason: what a mirror
|
|
118
121
|
// writes is a sample of the HDR target, and that target already holds colour
|
|
119
122
|
// premultiplied by its own alpha. Handed to the src-alpha blend it would be
|
|
@@ -132,6 +135,7 @@ const BLENDS = {
|
|
|
132
135
|
particle: [PREMULTIPLIED_OVER, ALPHA_OVER],
|
|
133
136
|
"particle-additive": [ADD_KEEP_ALPHA, ADD_BOTH],
|
|
134
137
|
trail: [ADD_PREMULTIPLIED, ALPHA_OVER],
|
|
138
|
+
"trail-over": [ALPHA_OVER, ALPHA_OVER],
|
|
135
139
|
};
|
|
136
140
|
/**
|
|
137
141
|
* The colour targets a scene-pass pipeline of this class declares, in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-light-api.d.ts","sourceRoot":"","sources":["../../src/shaders/scene-light-api.ts"],"names":[],"mappings":"AAkBA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,GAAG,MAAM,WAwBzC,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,aAAa,OAAO,CAAA;AAEjC,eAAO,MAAM,aAAa,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,EAAE,SAAS,MAAM,EAAE,IAAI,MAAM,WAkChF,CAAA;AAED,+DAA+D;AAC/D,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"scene-light-api.d.ts","sourceRoot":"","sources":["../../src/shaders/scene-light-api.ts"],"names":[],"mappings":"AAkBA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,GAAG,MAAM,WAwBzC,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,aAAa,OAAO,CAAA;AAEjC,eAAO,MAAM,aAAa,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,EAAE,SAAS,MAAM,EAAE,IAAI,MAAM,WAkChF,CAAA;AAED,+DAA+D;AAC/D,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA4CjF"}
|
|
@@ -126,6 +126,7 @@ export function sceneLightApi(on, group, binding) {
|
|
|
126
126
|
return /* wgsl */ `
|
|
127
127
|
fn rzShadow(p: vec3f) -> f32 { return 1.0; }
|
|
128
128
|
fn rzWorldAmbient(n: vec3f) -> vec3f { return vec3f(0.0); }
|
|
129
|
+
fn rzWorldAmbientAvg() -> vec3f { return vec3f(0.0); }
|
|
129
130
|
`;
|
|
130
131
|
}
|
|
131
132
|
const n = SHADOW_CASCADES.length;
|
package/dist/unity/globals.d.ts
CHANGED
|
@@ -43,6 +43,13 @@ export type UnityFrameInput = {
|
|
|
43
43
|
/** The direction the main light travels, unit; null for none. */
|
|
44
44
|
sunDirection: [number, number, number] | null;
|
|
45
45
|
sunColor: [number, number, number];
|
|
46
|
+
/** A game stage's own main light as its pipeline packed it (recorded), which
|
|
47
|
+
* its shaders get in place of sunColor; null for the scene sun's. */
|
|
48
|
+
sunUnity?: {
|
|
49
|
+
color: number[];
|
|
50
|
+
simColor: number[];
|
|
51
|
+
simColorNoInt: number[];
|
|
52
|
+
} | null;
|
|
46
53
|
sunShadow: number;
|
|
47
54
|
lights: UnityLight[];
|
|
48
55
|
/** Ambient as the engine's folded SH9 (27 floats, ibl.ts), or null for flat. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../../src/unity/globals.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../../src/unity/globals.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAEzC,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;AAExC,MAAM,MAAM,UAAU,GAAG;IACvB,oCAAoC;IACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,qCAAqC;IACrC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,6DAA6D;IAC7D,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAA;IACd;;;6EAGyE;IACzE,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,MAAM,EAAE,CAAA;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;QAC7B,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;QAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,iEAAiE;IACjE,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC7C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC;0EACsE;IACtE,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAA;IAClF,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,gFAAgF;IAChF,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IACnC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC;;+BAE2B;IAC3B,MAAM,EAAE;QACN,QAAQ,EAAE,QAAQ,EAAE,CAAA;QACpB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;QACzB,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,OAAO,EAAE;YAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAChE,GAAG,IAAI,CAAA;IACR;;8EAE0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAAA;CAC9C,CAAA;AAID,iCAAiC;AACjC,wBAAgB,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,YAAY,CAS3D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,QAAQ,GAAG,YAAY,CAmDjD;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAEpD;AAED,kCAAkC;AAClC,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAEpD;AAED,2CAA2C;AAC3C,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAEnF;AAED,+CAA+C;AAC/C,wBAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAEtE;AAED,+CAA+C;AAC/C,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAE9C;AAED,0EAA0E;AAC1E,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,YAAY,CAI/C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAU9G;AAED,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAuOjF"}
|
package/dist/unity/globals.js
CHANGED
|
@@ -157,12 +157,13 @@ export function unityFrameGlobals(f) {
|
|
|
157
157
|
if (f.sunDirection) {
|
|
158
158
|
const d = gameDir(f.sunDirection);
|
|
159
159
|
g.SimMainLightDir = [-d[0], -d[1], -d[2], 0];
|
|
160
|
-
|
|
161
|
-
g.
|
|
160
|
+
const u = f.sunUnity;
|
|
161
|
+
g.SimMainLightColor = u ? u.simColor.slice(0, 4) : [...f.sunColor, 1];
|
|
162
|
+
g.SimMainLightColorNoInt = u ? u.simColorNoInt.slice(0, 4) : [...f.sunColor, 1];
|
|
162
163
|
// As the game's pipeline leaves it (recorded): the way the light travels.
|
|
163
164
|
g._MainLightPosition = [d[0], d[1], d[2], 0];
|
|
164
165
|
g.sim_ShadowLightDirection = [-d[0], -d[1], -d[2], 0];
|
|
165
|
-
g._MainLightColor = [...f.sunColor, 1];
|
|
166
|
+
g._MainLightColor = u ? u.color.slice(0, 4) : [...f.sunColor, 1];
|
|
166
167
|
}
|
|
167
168
|
else {
|
|
168
169
|
g.SimMainLightDir = [0, 0, 0, 0];
|
package/dist/unity/host.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export type NativeShader = {
|
|
|
38
38
|
export type NativeValue = number | ArrayLike<number> | ArrayLike<ArrayLike<number>>;
|
|
39
39
|
/** Name -> value; the first source that has a name wins. */
|
|
40
40
|
export type ValueSource = Record<string, NativeValue | undefined>;
|
|
41
|
+
/** Whether two values carry the same numbers (and the same integer-ness). */
|
|
42
|
+
export declare function sameValue(a: NativeValue, b: NativeValue): boolean;
|
|
41
43
|
/** One vertex stream a draw binds, by the semantic a shader input names. */
|
|
42
44
|
export type NativeStream = {
|
|
43
45
|
buffer: GPUBuffer;
|
|
@@ -108,6 +110,7 @@ export declare class NativeHost {
|
|
|
108
110
|
white: GPUTextureView;
|
|
109
111
|
black: GPUTextureView;
|
|
110
112
|
blackCube: GPUTextureView;
|
|
113
|
+
emptyVolume: GPUTextureView;
|
|
111
114
|
depth: GPUTextureView;
|
|
112
115
|
comparison: GPUSampler;
|
|
113
116
|
});
|
package/dist/unity/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/unity/host.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAmE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAA;AAEzG,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AACD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AACD,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,CAAA;AACpE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACrC,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CACjE,CAAA;AACD,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,gBAAgB,CAAA;CACvB,CAAA;AAED;+EAC+E;AAC/E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;AACnF,4DAA4D;AAC5D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,CAAA;AAEjE,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,eAAe,CAAA;CACxB,CAAA;AAKD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/unity/host.ts"],"names":[],"mappings":"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"}
|