@aethervtt/shard-render 0.0.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/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/assets.d.ts +104 -0
- package/dist/assets.js +213 -0
- package/dist/atmosphere-model.d.ts +96 -0
- package/dist/atmosphere-model.js +370 -0
- package/dist/atmosphere-nodes.d.ts +55 -0
- package/dist/atmosphere-nodes.js +780 -0
- package/dist/atmosphere-plugin.d.ts +5 -0
- package/dist/atmosphere-plugin.js +42 -0
- package/dist/atmosphere-shaders.d.ts +7 -0
- package/dist/atmosphere-shaders.js +595 -0
- package/dist/atmosphere-state.d.ts +72 -0
- package/dist/atmosphere-state.js +18 -0
- package/dist/atmosphere.d.ts +191 -0
- package/dist/atmosphere.js +950 -0
- package/dist/camera.d.ts +83 -0
- package/dist/camera.js +163 -0
- package/dist/clusters.d.ts +68 -0
- package/dist/clusters.js +288 -0
- package/dist/culling-shaders.d.ts +2 -0
- package/dist/culling-shaders.js +203 -0
- package/dist/culling.d.ts +84 -0
- package/dist/culling.js +498 -0
- package/dist/debug-shaders.d.ts +3 -0
- package/dist/debug-shaders.js +207 -0
- package/dist/debug-views.d.ts +60 -0
- package/dist/debug-views.js +197 -0
- package/dist/deferred-plugin.d.ts +5 -0
- package/dist/deferred-plugin.js +20 -0
- package/dist/deferred-shaders.d.ts +2 -0
- package/dist/deferred-shaders.js +151 -0
- package/dist/deferred.d.ts +22 -0
- package/dist/deferred.js +296 -0
- package/dist/deform.d.ts +80 -0
- package/dist/deform.js +213 -0
- package/dist/describe-plugin.d.ts +5 -0
- package/dist/describe-plugin.js +19 -0
- package/dist/display-nodes.d.ts +5 -0
- package/dist/display-nodes.js +189 -0
- package/dist/dynamic-resolution.d.ts +47 -0
- package/dist/dynamic-resolution.js +191 -0
- package/dist/environment-plugin.d.ts +6 -0
- package/dist/environment-plugin.js +44 -0
- package/dist/environment-shaders.d.ts +2 -0
- package/dist/environment-shaders.js +260 -0
- package/dist/environment-state.d.ts +71 -0
- package/dist/environment-state.js +144 -0
- package/dist/environment.d.ts +70 -0
- package/dist/environment.js +529 -0
- package/dist/forward.d.ts +123 -0
- package/dist/forward.js +1216 -0
- package/dist/fxaa.d.ts +2 -0
- package/dist/fxaa.js +65 -0
- package/dist/gizmo-font.d.ts +21 -0
- package/dist/gizmo-font.js +132 -0
- package/dist/gizmos-plugin.d.ts +5 -0
- package/dist/gizmos-plugin.js +34 -0
- package/dist/gizmos.d.ts +156 -0
- package/dist/gizmos.js +772 -0
- package/dist/gpu-assets.d.ts +114 -0
- package/dist/gpu-assets.js +494 -0
- package/dist/graph.d.ts +204 -0
- package/dist/graph.js +417 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +540 -0
- package/dist/instances.d.ts +349 -0
- package/dist/instances.js +1335 -0
- package/dist/large-world.d.ts +13 -0
- package/dist/large-world.js +20 -0
- package/dist/lights.d.ts +160 -0
- package/dist/lights.js +468 -0
- package/dist/material-noise.d.ts +19 -0
- package/dist/material-noise.js +7 -0
- package/dist/material-pipelines.d.ts +46 -0
- package/dist/material-pipelines.js +166 -0
- package/dist/materials.d.ts +108 -0
- package/dist/materials.js +219 -0
- package/dist/noise.d.ts +76 -0
- package/dist/noise.js +286 -0
- package/dist/overlay-registry.d.ts +18 -0
- package/dist/overlay-registry.js +30 -0
- package/dist/overlays.d.ts +35 -0
- package/dist/overlays.js +344 -0
- package/dist/paths.d.ts +20 -0
- package/dist/paths.js +46 -0
- package/dist/picking-plugin.d.ts +2 -0
- package/dist/picking-plugin.js +20 -0
- package/dist/picking.d.ts +94 -0
- package/dist/picking.js +456 -0
- package/dist/pixel-perfect-plugin.d.ts +9 -0
- package/dist/pixel-perfect-plugin.js +135 -0
- package/dist/pixel-perfect.d.ts +27 -0
- package/dist/pixel-perfect.js +70 -0
- package/dist/plugin.d.ts +111 -0
- package/dist/plugin.js +182 -0
- package/dist/pool.d.ts +19 -0
- package/dist/pool.js +43 -0
- package/dist/post-common.d.ts +51 -0
- package/dist/post-common.js +148 -0
- package/dist/post-nodes.d.ts +39 -0
- package/dist/post-nodes.js +849 -0
- package/dist/post-plugin.d.ts +5 -0
- package/dist/post-plugin.js +26 -0
- package/dist/post-shaders.d.ts +8 -0
- package/dist/post-shaders.js +698 -0
- package/dist/post.d.ts +175 -0
- package/dist/post.js +453 -0
- package/dist/readback.d.ts +4 -0
- package/dist/readback.js +95 -0
- package/dist/render-scale.d.ts +53 -0
- package/dist/render-scale.js +63 -0
- package/dist/shaders.d.ts +122 -0
- package/dist/shaders.js +1168 -0
- package/dist/shadows.d.ts +119 -0
- package/dist/shadows.js +562 -0
- package/dist/skin-asset.d.ts +26 -0
- package/dist/skin-asset.js +25 -0
- package/dist/skinning-plugin.d.ts +5 -0
- package/dist/skinning-plugin.js +16 -0
- package/dist/skinning.d.ts +19 -0
- package/dist/skinning.js +343 -0
- package/dist/standard-fields.d.ts +67 -0
- package/dist/standard-fields.js +73 -0
- package/dist/standard.d.ts +7 -0
- package/dist/standard.js +37 -0
- package/dist/stats.d.ts +25 -0
- package/dist/stats.js +18 -0
- package/dist/target.d.ts +55 -0
- package/dist/target.js +70 -0
- package/dist/testing.d.ts +34 -0
- package/dist/testing.js +126 -0
- package/dist/timer.d.ts +28 -0
- package/dist/timer.js +136 -0
- package/dist/view.d.ts +117 -0
- package/dist/view.js +389 -0
- package/dist/visibility.d.ts +10 -0
- package/dist/visibility.js +84 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Patrick Dias
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/assets.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AssetStore } from '@aethervtt/shard-assets';
|
|
2
|
+
import { type Infer, type SchemaContext, ShardError } from '@aethervtt/shard-core';
|
|
3
|
+
import { type Mesh } from '@aethervtt/shard-mesh';
|
|
4
|
+
import { type MaterialType } from './materials.js';
|
|
5
|
+
import { STANDARD_FIELDS, TEXTURE_SLOTS, TextureSlot } from './standard-fields.js';
|
|
6
|
+
import type { RenderTarget } from './target.js';
|
|
7
|
+
export { STANDARD_FIELDS, TEXTURE_SLOTS, TextureSlot };
|
|
8
|
+
export declare const StandardMaterial: import("@aethervtt/shard-core").ComponentDef<{
|
|
9
|
+
baseColor: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Color, "f32">;
|
|
10
|
+
metallic: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
11
|
+
roughness: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
12
|
+
emissive: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Color, "f32">;
|
|
13
|
+
emissiveLuminance: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
14
|
+
doubleSided: import("@aethervtt/shard-core").FieldType<boolean, "u8">;
|
|
15
|
+
alphaMode: import("@aethervtt/shard-core").FieldType<"additive" | "alpha" | "mask" | "opaque" | "premultiplied", "u8">;
|
|
16
|
+
alphaCutoff: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
17
|
+
normalScale: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
18
|
+
occlusionStrength: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
19
|
+
baseColorTexture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
20
|
+
texture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").AssetRef<"Texture"> | null, "object">;
|
|
21
|
+
uv: import("@aethervtt/shard-core").FieldType<number, "u8">;
|
|
22
|
+
offset: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
23
|
+
scale: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
24
|
+
rotation: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
25
|
+
wrap: import("@aethervtt/shard-core").FieldType<"clamp" | "mirror" | "repeat", "u8">;
|
|
26
|
+
filter: import("@aethervtt/shard-core").FieldType<"linear" | "nearest", "u8">;
|
|
27
|
+
}>, "object">;
|
|
28
|
+
metallicRoughnessTexture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
29
|
+
texture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").AssetRef<"Texture"> | null, "object">;
|
|
30
|
+
uv: import("@aethervtt/shard-core").FieldType<number, "u8">;
|
|
31
|
+
offset: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
32
|
+
scale: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
33
|
+
rotation: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
34
|
+
wrap: import("@aethervtt/shard-core").FieldType<"clamp" | "mirror" | "repeat", "u8">;
|
|
35
|
+
filter: import("@aethervtt/shard-core").FieldType<"linear" | "nearest", "u8">;
|
|
36
|
+
}>, "object">;
|
|
37
|
+
normalTexture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
38
|
+
texture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").AssetRef<"Texture"> | null, "object">;
|
|
39
|
+
uv: import("@aethervtt/shard-core").FieldType<number, "u8">;
|
|
40
|
+
offset: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
41
|
+
scale: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
42
|
+
rotation: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
43
|
+
wrap: import("@aethervtt/shard-core").FieldType<"clamp" | "mirror" | "repeat", "u8">;
|
|
44
|
+
filter: import("@aethervtt/shard-core").FieldType<"linear" | "nearest", "u8">;
|
|
45
|
+
}>, "object">;
|
|
46
|
+
occlusionTexture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
47
|
+
texture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").AssetRef<"Texture"> | null, "object">;
|
|
48
|
+
uv: import("@aethervtt/shard-core").FieldType<number, "u8">;
|
|
49
|
+
offset: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
50
|
+
scale: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
51
|
+
rotation: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
52
|
+
wrap: import("@aethervtt/shard-core").FieldType<"clamp" | "mirror" | "repeat", "u8">;
|
|
53
|
+
filter: import("@aethervtt/shard-core").FieldType<"linear" | "nearest", "u8">;
|
|
54
|
+
}>, "object">;
|
|
55
|
+
emissiveTexture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").InferFields<{
|
|
56
|
+
texture: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").AssetRef<"Texture"> | null, "object">;
|
|
57
|
+
uv: import("@aethervtt/shard-core").FieldType<number, "u8">;
|
|
58
|
+
offset: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
59
|
+
scale: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Vec2, "f32">;
|
|
60
|
+
rotation: import("@aethervtt/shard-core").FieldType<number, "f32">;
|
|
61
|
+
wrap: import("@aethervtt/shard-core").FieldType<"clamp" | "mirror" | "repeat", "u8">;
|
|
62
|
+
filter: import("@aethervtt/shard-core").FieldType<"linear" | "nearest", "u8">;
|
|
63
|
+
}>, "object">;
|
|
64
|
+
}>;
|
|
65
|
+
/** The material type of plain StandardMaterial assets. */
|
|
66
|
+
export declare const STANDARD_TYPE: MaterialType;
|
|
67
|
+
export type StandardMaterialValue = Infer<typeof StandardMaterial>;
|
|
68
|
+
/** Any material's value: the standard fields (for standard extensions) plus the type's own. */
|
|
69
|
+
export type MaterialValue = StandardMaterialValue & Record<string, unknown>;
|
|
70
|
+
/**
|
|
71
|
+
* A material: its type and its values, with a version so GPU copies know when to re-upload. When the
|
|
72
|
+
* type is redefined (hot reload), `sync` migrates the values: new fields get their defaults.
|
|
73
|
+
*/
|
|
74
|
+
export declare class MaterialAsset {
|
|
75
|
+
type: MaterialType;
|
|
76
|
+
value: MaterialValue;
|
|
77
|
+
version: number;
|
|
78
|
+
private typeVersion;
|
|
79
|
+
constructor(value?: Record<string, unknown>, type?: MaterialType);
|
|
80
|
+
set(value: Record<string, unknown>): void;
|
|
81
|
+
/** Migrates to the current definition of the type. Returns true if anything changed. */
|
|
82
|
+
sync(): boolean;
|
|
83
|
+
}
|
|
84
|
+
/** The type a material JSON names (`"type"`), defaulting to the standard material. */
|
|
85
|
+
export declare function materialTypeOf(json: unknown): MaterialType;
|
|
86
|
+
/** Material JSON without its `"type"` key (what the type's schema validates). */
|
|
87
|
+
export declare function materialFields(json: unknown): Record<string, unknown>;
|
|
88
|
+
/** Validates material JSON against its type's schema; errors point into the JSON. */
|
|
89
|
+
export declare function validateMaterial(json: unknown, ctx?: SchemaContext): ShardError[];
|
|
90
|
+
/** A MaterialAsset from material JSON (files, scene inline assets, glTF). */
|
|
91
|
+
export declare function materialFromJson(json: unknown, ctx?: SchemaContext): MaterialAsset;
|
|
92
|
+
export declare const Meshes: import("@aethervtt/shard-core").ResourceDef<AssetStore<Mesh, "Mesh">>;
|
|
93
|
+
export declare const Materials: import("@aethervtt/shard-core").ResourceDef<AssetStore<MaterialAsset, "Material">>;
|
|
94
|
+
export declare const RenderTargets: import("@aethervtt/shard-core").ResourceDef<AssetStore<RenderTarget, "RenderTarget">>;
|
|
95
|
+
/** Meshes load from binary artifacts (`encodeMesh`); a reload updates the mesh in place. */
|
|
96
|
+
export declare const MeshAsset: import("@aethervtt/shard-assets").AssetTypeDef<Mesh>;
|
|
97
|
+
/** Materials load from material JSON (any type); a reload bumps the material's version. */
|
|
98
|
+
export declare const MaterialAssetType: import("@aethervtt/shard-assets").AssetTypeDef<MaterialAsset>;
|
|
99
|
+
/**
|
|
100
|
+
* `*.material.json` files. `"type"` names the material type (default: render/StandardMaterial);
|
|
101
|
+
* the rest is validated by that type's schema, with errors pointing into the file.
|
|
102
|
+
*/
|
|
103
|
+
export declare const MaterialImporter: import("@aethervtt/shard-assets").ImporterDef;
|
|
104
|
+
export { AssetStore };
|
package/dist/assets.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { AssetStore, defineAssetType, defineImporter } from "@aethervtt/shard-assets";
|
|
2
|
+
import {
|
|
3
|
+
defineComponent,
|
|
4
|
+
defineResource,
|
|
5
|
+
defineSchema,
|
|
6
|
+
ShardError
|
|
7
|
+
} from "@aethervtt/shard-core";
|
|
8
|
+
import { decodeMesh } from "@aethervtt/shard-mesh";
|
|
9
|
+
import {
|
|
10
|
+
allMaterialTypes,
|
|
11
|
+
findMaterialType,
|
|
12
|
+
registerStandardType
|
|
13
|
+
} from "./materials.js";
|
|
14
|
+
import { STANDARD_FIELDS, TEXTURE_SLOTS, TextureSlot } from "./standard-fields.js";
|
|
15
|
+
const StandardMaterial = defineComponent("render/StandardMaterial", STANDARD_FIELDS, {
|
|
16
|
+
description: "The standard PBR material (GGX). A material asset, not an entity component."
|
|
17
|
+
});
|
|
18
|
+
const STANDARD_TYPE = registerStandardType(StandardMaterial);
|
|
19
|
+
class MaterialAsset {
|
|
20
|
+
type;
|
|
21
|
+
value;
|
|
22
|
+
version = 0;
|
|
23
|
+
typeVersion;
|
|
24
|
+
constructor(value = {}, type = STANDARD_TYPE) {
|
|
25
|
+
this.type = type;
|
|
26
|
+
this.typeVersion = type.version;
|
|
27
|
+
this.value = normalize(type, { ...type.schema.defaults(), ...value });
|
|
28
|
+
}
|
|
29
|
+
set(value) {
|
|
30
|
+
this.value = normalize(this.type, { ...this.value, ...value });
|
|
31
|
+
this.version++;
|
|
32
|
+
}
|
|
33
|
+
/** Migrates to the current definition of the type. Returns true if anything changed. */
|
|
34
|
+
sync() {
|
|
35
|
+
if (this.typeVersion === this.type.version) return false;
|
|
36
|
+
this.typeVersion = this.type.version;
|
|
37
|
+
const defaults = this.type.schema.defaults();
|
|
38
|
+
const next = {};
|
|
39
|
+
for (const key of Object.keys(defaults))
|
|
40
|
+
next[key] = key in this.value ? this.value[key] : defaults[key];
|
|
41
|
+
this.value = normalize(this.type, next);
|
|
42
|
+
this.version++;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function normalize(type, value) {
|
|
47
|
+
return type.standard ? withSlotDefaults(value) : value;
|
|
48
|
+
}
|
|
49
|
+
function materialTypeOf(json) {
|
|
50
|
+
const name = json && typeof json === "object" && typeof json.type === "string" ? json.type : void 0;
|
|
51
|
+
if (!name || name === "render/StandardMaterial") return STANDARD_TYPE;
|
|
52
|
+
const type = findMaterialType(name);
|
|
53
|
+
if (!type) {
|
|
54
|
+
throw new ShardError("render/unknown-material-type", `Unknown material type "${name}"`, {
|
|
55
|
+
path: "/type",
|
|
56
|
+
hint: `Material types: ${allMaterialTypes().map((t) => t.name).join(", ")}. Project types are defined with project.material(...).`
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return type;
|
|
60
|
+
}
|
|
61
|
+
function materialFields(json) {
|
|
62
|
+
if (!json || typeof json !== "object") return {};
|
|
63
|
+
const { type: _, $schema: __, ...rest } = json;
|
|
64
|
+
return rest;
|
|
65
|
+
}
|
|
66
|
+
function validateMaterial(json, ctx) {
|
|
67
|
+
let type;
|
|
68
|
+
try {
|
|
69
|
+
type = materialTypeOf(json);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
return [err];
|
|
72
|
+
}
|
|
73
|
+
return type.schema.validate(materialFields(json), ctx);
|
|
74
|
+
}
|
|
75
|
+
function materialFromJson(json, ctx) {
|
|
76
|
+
const type = materialTypeOf(json);
|
|
77
|
+
return new MaterialAsset(
|
|
78
|
+
type.schema.deserialize(materialFields(json), ctx),
|
|
79
|
+
type
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
function withSlotDefaults(value) {
|
|
83
|
+
const defaults = StandardMaterial.defaults();
|
|
84
|
+
const out = value;
|
|
85
|
+
for (const slot of TEXTURE_SLOTS) out[slot] = { ...defaults[slot], ...out[slot] };
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
const Meshes = defineResource("render/Meshes", {
|
|
89
|
+
description: "Loaded meshes by guid.",
|
|
90
|
+
init: () => new AssetStore("Mesh")
|
|
91
|
+
});
|
|
92
|
+
const Materials = defineResource("render/Materials", {
|
|
93
|
+
description: "Loaded standard materials by guid.",
|
|
94
|
+
init: () => new AssetStore("Material")
|
|
95
|
+
});
|
|
96
|
+
const RenderTargets = defineResource(
|
|
97
|
+
"render/RenderTargets",
|
|
98
|
+
{
|
|
99
|
+
description: "Offscreen render targets cameras can render into.",
|
|
100
|
+
init: () => new AssetStore("RenderTarget")
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
const MeshAsset = defineAssetType("Mesh", {
|
|
104
|
+
store: Meshes,
|
|
105
|
+
load: (artifact) => decodeMesh(artifact.bytes),
|
|
106
|
+
update: (existing, next) => existing.update(next.data())
|
|
107
|
+
});
|
|
108
|
+
const MaterialAssetType = defineAssetType("Material", {
|
|
109
|
+
store: Materials,
|
|
110
|
+
// Texture paths resolve to guids here, so the renderer can look them up directly.
|
|
111
|
+
load: (artifact, ctx) => {
|
|
112
|
+
const resolveAsset = (ref) => {
|
|
113
|
+
const found = ref.path ? ctx.resolve(ref.path) : ref.guid ? ctx.resolve(ref.guid) : void 0;
|
|
114
|
+
return found ? { guid: found.guid, path: ref.path ?? found.path, type: found.type } : void 0;
|
|
115
|
+
};
|
|
116
|
+
const errors = validateMaterial(artifact.json, { resolveAsset });
|
|
117
|
+
if (errors.length > 0) {
|
|
118
|
+
const first = errors[0];
|
|
119
|
+
throw new ShardError("assets/load-failed", `${ctx.path}: ${first.message}`, {
|
|
120
|
+
path: first.path,
|
|
121
|
+
hint: first.hint,
|
|
122
|
+
details: errors
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return materialFromJson(artifact.json, { resolveAsset });
|
|
126
|
+
},
|
|
127
|
+
update: (existing, next) => {
|
|
128
|
+
existing.type = next.type;
|
|
129
|
+
existing.set(next.value);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
const MaterialImporter = defineImporter({
|
|
133
|
+
name: "data/material",
|
|
134
|
+
version: 2,
|
|
135
|
+
extensions: [".material.json"],
|
|
136
|
+
settings: defineSchema("render/MaterialImportSettings", {}, { description: "No settings." }),
|
|
137
|
+
async import(source, ctx) {
|
|
138
|
+
let json;
|
|
139
|
+
try {
|
|
140
|
+
json = JSON.parse(source.text());
|
|
141
|
+
} catch (cause) {
|
|
142
|
+
throw new ShardError("assets/import-failed", `${source.path} isn't valid JSON`, {
|
|
143
|
+
path: source.path,
|
|
144
|
+
cause
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const typeName = json?.type;
|
|
148
|
+
const known = typeof typeName !== "string" || findMaterialType(typeName) !== void 0;
|
|
149
|
+
let normalized = json;
|
|
150
|
+
if (known) {
|
|
151
|
+
const errors = validateMaterial(json);
|
|
152
|
+
if (errors.length > 0) {
|
|
153
|
+
const first = errors[0];
|
|
154
|
+
throw new ShardError(
|
|
155
|
+
"assets/import-failed",
|
|
156
|
+
`${source.path}: ${first.message}${errors.length > 1 ? ` (+${errors.length - 1} more)` : ""}`,
|
|
157
|
+
{ path: first.path, hint: first.hint, details: errors }
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
const type = materialTypeOf(json);
|
|
161
|
+
const fields = type.schema.serialize(type.schema.deserialize(materialFields(json)));
|
|
162
|
+
normalized = type === STANDARD_TYPE ? fields : { type: type.name, ...fields };
|
|
163
|
+
} else {
|
|
164
|
+
ctx.warn(
|
|
165
|
+
`Material type "${typeName}" isn't defined here; it's checked when the game loads it.`,
|
|
166
|
+
"/type"
|
|
167
|
+
);
|
|
168
|
+
normalized = materialFields(json);
|
|
169
|
+
normalized = { type: typeName, ...normalized };
|
|
170
|
+
}
|
|
171
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
172
|
+
const collect = (value) => {
|
|
173
|
+
if (Array.isArray(value)) value.forEach(collect);
|
|
174
|
+
else if (value && typeof value === "object") {
|
|
175
|
+
for (const [k, v] of Object.entries(value)) {
|
|
176
|
+
if (k === "path" && typeof v === "string" && !v.startsWith("procedural:"))
|
|
177
|
+
dependencies.add(v);
|
|
178
|
+
else collect(v);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
collect(normalized);
|
|
183
|
+
return {
|
|
184
|
+
assets: [
|
|
185
|
+
{
|
|
186
|
+
label: "",
|
|
187
|
+
type: "Material",
|
|
188
|
+
json: normalized,
|
|
189
|
+
...dependencies.size ? { dependencies: [...dependencies] } : {}
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
export {
|
|
196
|
+
AssetStore,
|
|
197
|
+
MaterialAsset,
|
|
198
|
+
MaterialAssetType,
|
|
199
|
+
MaterialImporter,
|
|
200
|
+
Materials,
|
|
201
|
+
MeshAsset,
|
|
202
|
+
Meshes,
|
|
203
|
+
RenderTargets,
|
|
204
|
+
STANDARD_FIELDS,
|
|
205
|
+
STANDARD_TYPE,
|
|
206
|
+
StandardMaterial,
|
|
207
|
+
TEXTURE_SLOTS,
|
|
208
|
+
TextureSlot,
|
|
209
|
+
materialFields,
|
|
210
|
+
materialFromJson,
|
|
211
|
+
materialTypeOf,
|
|
212
|
+
validateMaterial
|
|
213
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The atmosphere model on the CPU (spec 0044): the same density profiles, transmittance, and
|
|
3
|
+
* multiple-scattering approximation (Hillaire 2020) the shaders in `atmosphere-shaders.ts` use, so
|
|
4
|
+
* sun light, `sunTransmittanceAt`, and `atmosphere.sample` work headless and agree with the GPU.
|
|
5
|
+
*
|
|
6
|
+
* Everything is in kilometres, relative to the atmosphere's center. Coefficients are per km.
|
|
7
|
+
*/
|
|
8
|
+
/** Atmosphere parameters in shader units (km, 1/km). */
|
|
9
|
+
export interface AtmosphereModel {
|
|
10
|
+
/** Visible surface (or cloud top), top of the atmosphere, and the LUTs' floor (bottom − deck). */
|
|
11
|
+
bottom: number;
|
|
12
|
+
top: number;
|
|
13
|
+
ground: number;
|
|
14
|
+
rayleigh: Float64Array;
|
|
15
|
+
rayleighInvScale: number;
|
|
16
|
+
mieScattering: number;
|
|
17
|
+
mieAbsorption: number;
|
|
18
|
+
mieInvScale: number;
|
|
19
|
+
/** Per channel Cornette-Shanks asymmetry. */
|
|
20
|
+
mieG: Float64Array;
|
|
21
|
+
absorption: Float64Array;
|
|
22
|
+
absorptionCenter: number;
|
|
23
|
+
absorptionWidth: number;
|
|
24
|
+
albedo: Float64Array;
|
|
25
|
+
intensity: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function createModel(): AtmosphereModel;
|
|
28
|
+
export declare const TRANSMITTANCE_W = 256;
|
|
29
|
+
export declare const TRANSMITTANCE_H = 64;
|
|
30
|
+
export declare const MULTISCATTER_SIZE = 32;
|
|
31
|
+
/** Steps for the transmittance LUT and for sun transmittance on the CPU. */
|
|
32
|
+
export declare const TRANSMITTANCE_STEPS = 40;
|
|
33
|
+
/** Scratch medium: scattering and extinction at a point. */
|
|
34
|
+
export interface Medium {
|
|
35
|
+
rayleigh: Float64Array;
|
|
36
|
+
mie: number;
|
|
37
|
+
scattering: Float64Array;
|
|
38
|
+
extinction: Float64Array;
|
|
39
|
+
}
|
|
40
|
+
export declare function createMedium(): Medium;
|
|
41
|
+
/** The medium at altitude `h` km above the bottom (negative inside a gas giant's deck). */
|
|
42
|
+
export declare function mediumAt(m: AtmosphereModel, h: number, out: Medium): Medium;
|
|
43
|
+
/** Near and far distances along a unit ray to a sphere at the origin; NaN when it misses. */
|
|
44
|
+
export declare function raySphere(ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, r: number, out: Float64Array): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Transmittance from a point along a unit direction to the top of the atmosphere, integrated in
|
|
47
|
+
* `steps` midpoint steps. Zero when the ground (the LUT floor) is in the way.
|
|
48
|
+
*/
|
|
49
|
+
export declare function transmittanceToTop(m: AtmosphereModel, px: number, py: number, pz: number, dx: number, dy: number, dz: number, out: Float64Array, steps?: number): Float64Array;
|
|
50
|
+
/** Transmittance LUT unit coordinates (x_mu, x_r) of altitude radius r and view zenith cosine mu. */
|
|
51
|
+
export declare function transmittanceUnit(m: AtmosphereModel, r: number, mu: number, out: Float64Array): Float64Array<ArrayBufferLike>;
|
|
52
|
+
/** The inverse: (r, mu) of transmittance LUT unit coordinates. */
|
|
53
|
+
export declare function transmittanceRMu(m: AtmosphereModel, xMu: number, xR: number, out: Float64Array): Float64Array<ArrayBufferLike>;
|
|
54
|
+
/** A LUT of `w × h` rgb texels, sampled bilinearly with texel centers at unit 0 and 1. */
|
|
55
|
+
export interface Lut {
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
data: Float32Array;
|
|
59
|
+
}
|
|
60
|
+
/** The transmittance LUT, computed like `shard::atmosphere::transmittance_lut`. */
|
|
61
|
+
export declare function transmittanceLut(m: AtmosphereModel): Lut;
|
|
62
|
+
/** Transmittance from radius r toward zenith cosine mu, from the LUT (the ground is not tested). */
|
|
63
|
+
export declare function lookupTransmittance(m: AtmosphereModel, lut: Lut, r: number, mu: number, out: Float64Array): Float64Array;
|
|
64
|
+
/**
|
|
65
|
+
* Hillaire's multiple-scattering LUT: for each altitude and sun zenith, the isotropic
|
|
66
|
+
* second-order luminance L2 over 64 directions and the transfer f_ms, stored as L2 / (1 − f_ms)
|
|
67
|
+
* (per unit illuminance, per unit scattering).
|
|
68
|
+
*/
|
|
69
|
+
export declare function multiscatterLut(m: AtmosphereModel, tlut: Lut): Lut;
|
|
70
|
+
/** Multiple-scattering luminance factor at radius r for a sun at zenith cosine cs. */
|
|
71
|
+
export declare function lookupMultiscatter(m: AtmosphereModel, lut: Lut, r: number, cs: number, out: Float64Array): Float64Array;
|
|
72
|
+
/** Rayleigh phase. */
|
|
73
|
+
export declare const rayleighPhase: (mu: number) => number;
|
|
74
|
+
/** Cornette-Shanks phase with asymmetry g. */
|
|
75
|
+
export declare function miePhase(mu: number, g: number): number;
|
|
76
|
+
/** A sun as the model sees it: direction toward it (unit) and illuminance (lux) per channel. */
|
|
77
|
+
export interface ModelSun {
|
|
78
|
+
direction: ArrayLike<number>;
|
|
79
|
+
illuminance: ArrayLike<number>;
|
|
80
|
+
}
|
|
81
|
+
export interface SkySample {
|
|
82
|
+
/** In-scattered radiance (cd/m²) along the ray, plus the lit ground where it ends on it. */
|
|
83
|
+
radiance: Float64Array;
|
|
84
|
+
/** Transmittance along the ray to where it leaves the atmosphere (0 if it hits the ground). */
|
|
85
|
+
transmittance: Float64Array;
|
|
86
|
+
hitsGround: boolean;
|
|
87
|
+
/** Distance (km) the ray travels through the atmosphere. */
|
|
88
|
+
length: number;
|
|
89
|
+
}
|
|
90
|
+
export declare function createSkySample(): SkySample;
|
|
91
|
+
/**
|
|
92
|
+
* Radiance along a ray from `p` (km, relative to the center) in unit direction `d`, up to
|
|
93
|
+
* `maxT` km: single scattering of every sun, the multiple-scattering LUT, and the lit ground.
|
|
94
|
+
* Same integration as `shard::atmosphere::integrate` (quadratic step distribution).
|
|
95
|
+
*/
|
|
96
|
+
export declare function integrateSky(m: AtmosphereModel, tlut: Lut, mslut: Lut, p: ArrayLike<number>, d: ArrayLike<number>, suns: readonly ModelSun[], out: SkySample, steps?: number, maxT?: number): SkySample;
|