bplinejs 0.0.101-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +215 -0
- package/docs/API.md +471 -0
- package/lib/Camera/index.d.ts +88 -0
- package/lib/Camera/index.js +178 -0
- package/lib/Camera/index.js.map +1 -0
- package/lib/Color/index.d.ts +99 -0
- package/lib/Color/index.js +178 -0
- package/lib/Color/index.js.map +1 -0
- package/lib/Geometry/Geo.d.ts +131 -0
- package/lib/Geometry/Geo.js +180 -0
- package/lib/Geometry/Geo.js.map +1 -0
- package/lib/Geometry/Poly2D.d.ts +53 -0
- package/lib/Geometry/Poly2D.js +133 -0
- package/lib/Geometry/Poly2D.js.map +1 -0
- package/lib/Geometry/Rect2d.d.ts +89 -0
- package/lib/Geometry/Rect2d.js +128 -0
- package/lib/Geometry/Rect2d.js.map +1 -0
- package/lib/Geometry/index.d.ts +6 -0
- package/lib/Geometry/index.js +4 -0
- package/lib/Group/index.d.ts +70 -0
- package/lib/Group/index.js +110 -0
- package/lib/Group/index.js.map +1 -0
- package/lib/ID.d.ts +6 -0
- package/lib/ID.js +15 -0
- package/lib/ID.js.map +1 -0
- package/lib/IMesh/index.d.ts +104 -0
- package/lib/IMesh/index.js +333 -0
- package/lib/IMesh/index.js.map +1 -0
- package/lib/Material/Material.d.ts +158 -0
- package/lib/Material/Material.js +229 -0
- package/lib/Material/Material.js.map +1 -0
- package/lib/Material/baseMaterial.d.ts +15 -0
- package/lib/Material/baseMaterial.js +24 -0
- package/lib/Material/baseMaterial.js.map +1 -0
- package/lib/Material/index.d.ts +4 -0
- package/lib/Material/index.js +3 -0
- package/lib/Material/shaders/base/poly/fragment.js +6 -0
- package/lib/Material/shaders/base/poly/fragment.js.map +1 -0
- package/lib/Material/shaders/base/poly/vertex.js +6 -0
- package/lib/Material/shaders/base/poly/vertex.js.map +1 -0
- package/lib/Material/shaders/base/rect/fragment.js +6 -0
- package/lib/Material/shaders/base/rect/fragment.js.map +1 -0
- package/lib/Material/shaders/base/rect/vertex.js +6 -0
- package/lib/Material/shaders/base/rect/vertex.js.map +1 -0
- package/lib/Material/shaders/line/fragment.js +6 -0
- package/lib/Material/shaders/line/fragment.js.map +1 -0
- package/lib/Material/shaders/line/vertex.js +6 -0
- package/lib/Material/shaders/line/vertex.js.map +1 -0
- package/lib/Mesh/index.d.ts +154 -0
- package/lib/Mesh/index.js +254 -0
- package/lib/Mesh/index.js.map +1 -0
- package/lib/Object/index.d.ts +95 -0
- package/lib/Object/index.js +212 -0
- package/lib/Object/index.js.map +1 -0
- package/lib/Raws/index.d.ts +87 -0
- package/lib/Raws/index.js +164 -0
- package/lib/Raws/index.js.map +1 -0
- package/lib/Render/BufferManager.d.ts +93 -0
- package/lib/Render/BufferManager.js +281 -0
- package/lib/Render/BufferManager.js.map +1 -0
- package/lib/Render/DepthManager.d.ts +22 -0
- package/lib/Render/DepthManager.js +95 -0
- package/lib/Render/DepthManager.js.map +1 -0
- package/lib/Render/DestroyManager.d.ts +74 -0
- package/lib/Render/DestroyManager.js +221 -0
- package/lib/Render/DestroyManager.js.map +1 -0
- package/lib/Render/DevelopmentValidator.d.ts +73 -0
- package/lib/Render/DevelopmentValidator.js +188 -0
- package/lib/Render/DevelopmentValidator.js.map +1 -0
- package/lib/Render/DrawCallManager.d.ts +58 -0
- package/lib/Render/DrawCallManager.js +267 -0
- package/lib/Render/DrawCallManager.js.map +1 -0
- package/lib/Render/PipelineManager.d.ts +46 -0
- package/lib/Render/PipelineManager.js +254 -0
- package/lib/Render/PipelineManager.js.map +1 -0
- package/lib/Render/SamplerManager.d.ts +26 -0
- package/lib/Render/SamplerManager.js +42 -0
- package/lib/Render/SamplerManager.js.map +1 -0
- package/lib/Render/SceneUpdate.d.ts +9 -0
- package/lib/Render/SceneUpdate.js +18 -0
- package/lib/Render/SceneUpdate.js.map +1 -0
- package/lib/Render/TextureManager.d.ts +33 -0
- package/lib/Render/TextureManager.js +152 -0
- package/lib/Render/TextureManager.js.map +1 -0
- package/lib/Render/index.d.ts +212 -0
- package/lib/Render/index.js +347 -0
- package/lib/Render/index.js.map +1 -0
- package/lib/Render/types.d.ts +191 -0
- package/lib/Scene/index.d.ts +124 -0
- package/lib/Scene/index.js +225 -0
- package/lib/Scene/index.js.map +1 -0
- package/lib/Style/EdgeStyle.d.ts +28 -0
- package/lib/Style/EdgeStyle.js +67 -0
- package/lib/Style/EdgeStyle.js.map +1 -0
- package/lib/Style/JoinStyle.d.ts +27 -0
- package/lib/Style/JoinStyle.js +53 -0
- package/lib/Style/JoinStyle.js.map +1 -0
- package/lib/Style/PartStyle.d.ts +50 -0
- package/lib/Style/PartStyle.js +92 -0
- package/lib/Style/PartStyle.js.map +1 -0
- package/lib/Style/PointsStyle.d.ts +43 -0
- package/lib/Style/PointsStyle.js +98 -0
- package/lib/Style/PointsStyle.js.map +1 -0
- package/lib/Style/SolidStyle.d.ts +37 -0
- package/lib/Style/SolidStyle.js +83 -0
- package/lib/Style/SolidStyle.js.map +1 -0
- package/lib/Style/TexturedStyle.d.ts +29 -0
- package/lib/Style/TexturedStyle.js +66 -0
- package/lib/Style/TexturedStyle.js.map +1 -0
- package/lib/Style/WireframeStyle.d.ts +7 -0
- package/lib/Style/WireframeStyle.js +13 -0
- package/lib/Style/WireframeStyle.js.map +1 -0
- package/lib/Style/WriteStyleData.d.ts +10 -0
- package/lib/Style/WriteStyleData.js +59 -0
- package/lib/Style/WriteStyleData.js.map +1 -0
- package/lib/Style/index.d.ts +50 -0
- package/lib/Style/index.js +92 -0
- package/lib/Style/index.js.map +1 -0
- package/lib/Style/types.d.ts +21 -0
- package/lib/Texture/Layers.d.ts +26 -0
- package/lib/Texture/Layers.js +42 -0
- package/lib/Texture/Layers.js.map +1 -0
- package/lib/Texture/index.d.ts +116 -0
- package/lib/Texture/index.js +198 -0
- package/lib/Texture/index.js.map +1 -0
- package/lib/global-types.d.ts +8 -0
- package/lib/index.d.ts +43 -0
- package/lib/index.js +34 -0
- package/package.json +130 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/scripts/IMesh/index.ts"],"sourcesContent":["import { Mat3, Vec2 } from \"bpmatrixjs/Math\";\nimport type { VersionedMath } from \"bpmatrixjs/Math\";\nimport Mesh from \"../Mesh\";\nimport type { Geometry2d, Material2d } from \"../global-types\";\nimport { GETID } from \"../ID\";\nimport Raws, { Raw } from \"../Raws\";\nimport type { RawChange, RawOptions, RawSubscriber } from \"../Raws\";\nimport Style, { STYLE_STRIDE, WriteStyleData } from \"../Style\";\nimport TextureLayers from \"../Texture/Layers\";\nimport type { TextureLike } from \"../Texture\";\n\n/** 实例管理设置;raw 为构建时选择,避免丢失的原始值被误认为可以恢复。 */\nexport interface IMeshOptions {\n /** 保留原始值和订阅,默认 true,构建后不可切换。 */\n raw?: boolean;\n /** 初始槽数,默认 2,必须是正整数。 */\n capacity?: number;\n /** 扩容倍率,默认 2,必须是不小于 2 的整数。 */\n growthFactor?: number;\n}\n\n/** 共用 Geometry / Material 的实例网格,每个槽位独立储存世界矩阵和样式。 */\nclass IMesh extends Mesh implements RawSubscriber {\n /** 对象类型;Scene 仍通过 Mesh 基类识别。 */\n public override readonly type: string = \"IMesh\";\n private readonly _raw: boolean;\n private readonly _raws: Raws = new Raws();\n private _growthFactor: number = 2;\n private readonly _ids: number[] = [];\n private readonly _pendingMatrices = new Set<number>();\n private readonly _pendingStyles = new Set<number>();\n private readonly _local: Mat3 = new Mat3();\n private readonly _world: Mat3 = new Mat3();\n // 不代理时也保留图片资源身份,但不保留 Vec2 / Style 或它们的订阅。\n private readonly _sources: (TextureLike | undefined)[][] = [];\n private readonly _textures: readonly TextureLayers[] = [new TextureLayers(), new TextureLayers(), new TextureLayers()];\n private readonly _layerIndices: Map<TextureLike | undefined, number>[] = [new Map<TextureLike | undefined, number>(), new Map<TextureLike | undefined, number>(), new Map<TextureLike | undefined, number>()];\n private _layersPending: boolean = false;\n\n /**\n * @param data 共用几何模板,提前启用需要生成的分区\n * @param material 共用管线和采样器设置,不接管其 Style\n * @param options 默认管理原始值,容量 2,按 2 倍扩容\n */\n public constructor(data: Geometry2d, material: Material2d, options: IMeshOptions = {}) {\n // 在 Mesh 订阅共享资源之前检查参数,失败时不留下无法取得的订阅对象。\n ValidateOptions(options);\n super(data, material, false);\n this._raw = options.raw ?? true;\n this._count = 0;\n this._capacity = 0;\n this.growthFactor = options.growthFactor ?? 2;\n try {\n this.capacity = options.capacity ?? 2;\n } catch (error) {\n super.dispose();\n throw error;\n }\n }\n\n /** 是否保留并订阅原始值,只读。 */\n public get raw(): boolean { return this._raw; }\n /** 原始记录按稳定 ID 查询;raw=false 时 Map 为空。 */\n public get raws(): Raws { return this._raws; }\n /** 扩容倍率,默认 2;达到 100000 槽后每批追加 100000。 */\n public get growthFactor(): number { return this._growthFactor; }\n /** @param value 不小于 2 的整数倍率,不改变已有记录 */\n public set growthFactor(value: number) {\n if (!Number.isSafeInteger(value) || value < 2) throw new RangeError(\"growthFactor must be an integer >= 2.\");\n this._growthFactor = value;\n }\n /** 已分配的槽数,不等于有效条数 count。 */\n public override get capacity(): number { return this._capacity; }\n /**\n * 显式预留容量;不缩容、不丢弃记录。GPU 限制在 Render 上传前校验。\n * @param value 不小于 count 的正整数\n */\n public set capacity(value: number) {\n this.assertActive();\n if (!Number.isSafeInteger(value) || value < 1 || value < this._count) throw new RangeError(\"Invalid capacity.\");\n if (value <= this._capacity) return;\n if (value > Math.floor(0xFFFFFFFF / (STYLE_STRIDE * 4))) throw new RangeError(\"CPU array capacity exceeds 4 GiB.\");\n const matrices: Float32Array<ArrayBuffer> = new Float32Array(value * 12);\n const styles: Float32Array<ArrayBuffer> = new Float32Array(value * STYLE_STRIDE);\n matrices.set(this._matrixData.subarray(0, this._count * 12));\n styles.set(this._styleData.subarray(0, this._count * STYLE_STRIDE));\n this._matrixData = matrices;\n this._styleData = styles;\n this._capacity = value;\n this._matrixVersion++;\n this._styleVersion++;\n this.updateVersion();\n }\n /** 三套独立图片层表;普通 Mesh 在相同绑定位置只使用一层。 */\n public override get textures(): readonly TextureLayers[] {\n this.updateTextureLayers();\n return this._textures;\n }\n\n /**\n * 按 push 顺序绘制,返回 ID 而非槽位。raw=false 冻结本次调用时的世界矩阵。\n * @param options 原始值;省略 style 使用当前材质样式\n * @returns 稳定 ID,通过 raws.map.get(id) 获取受管记录\n */\n public push(options: RawOptions = {}): number {\n this.assertActive();\n const values = this.resolve(options);\n this.ensureCapacity(this._count + 1);\n this.ensureWorldMatrix();\n const index: number = this._count;\n const record: Raw | undefined = this._raw ? new Raw(index, values) : undefined;\n const id: number = record?.id ?? GETID();\n this._count++;\n this._ids.push(id);\n if (record !== undefined) {\n this._raws.add(record);\n record.add(this);\n }\n this.writeMatrix(index, values);\n this.writeStyle(index, values.style, values.enabled);\n this.setSources(index, values.style);\n this._matrixVersion++;\n this._styleVersion++;\n this.updateVersion();\n return id;\n }\n\n /**\n * 手动完整覆盖一个槽位,省略值使用默认值,不是局部 patch。\n * raw=false 不建立订阅,按当前 IMesh 世界矩阵重新计算这个槽位。\n * @param index 连续数组下标\n * @param options 新的完整原始值\n */\n public updateAt(index: number, options: RawOptions): void {\n this.assertActive();\n if (!Number.isSafeInteger(index) || index < 0 || index >= this._count) throw new RangeError(\"Invalid slot index.\");\n const values = this.resolve(options);\n const record = this._raws.map.get(this._ids[index]);\n if (record !== undefined) {\n record.position = values.position;\n record.rotation = values.rotation;\n record.scale = values.scale;\n record.style = values.style;\n record.enabled = values.enabled;\n }\n this.ensureWorldMatrix();\n this.writeMatrix(index, values);\n this.writeStyle(index, values.style, values.enabled);\n this.setSources(index, values.style);\n this._pendingMatrices.delete(index);\n this._pendingStyles.delete(index);\n this._matrixVersion++;\n this._styleVersion++;\n this.updateVersion();\n }\n\n /**\n * 变化只登记槽位;共享 Style 可以通知多个记录,不同步上传 GPU。\n * @param record 来源记录\n * @param change 变化区域\n */\n public onRawChange(record: Raw, change: RawChange): void {\n if (this._disposed || this._raws.map.get(record.id) !== record) return;\n if (change === \"matrix\") this._pendingMatrices.add(record.index);\n else if (change !== \"textureData\" && change !== \"sampler\") this._pendingStyles.add(record.index);\n if (change === \"texture\") this.setSources(record.index, record.style);\n this._materialPending = true;\n }\n\n /**\n * 只在受管模式下由父级世界矩阵变化安排全体矩阵重算。\n * @param source 数学对象\n * @param field 关联字段\n */\n public override onMathChange(source: VersionedMath, field: string): void {\n super.onMathChange(source, field);\n if (!this._raw && field === \"worldMatrix\") this._matrixPending = false;\n }\n\n /** 按待处理槽位打包,静止帧不重新分配数组;世界矩阵仅储存一份。 */\n public override updateInstanceData(): void {\n this.assertActive();\n this.ensureWorldMatrix();\n if (this._geometryPending && this.data !== undefined) this.material?.addGeometryType(this.data.type);\n let matricesChanged: boolean = false;\n let stylesChanged: boolean = false;\n if (this._raw && this._matrixPending) {\n for (const record of this._raws.map.values()) this.writeMatrix(record.index, record);\n matricesChanged = this._count > 0;\n } else {\n for (const index of this._pendingMatrices) {\n const record = this._raws.map.get(this._ids[index]);\n if (record !== undefined) { this.writeMatrix(index, record); matricesChanged = true; }\n }\n }\n this.updateTextureLayers();\n for (const index of this._pendingStyles) {\n const record = this._raws.map.get(this._ids[index]);\n if (record !== undefined) { this.writeStyle(index, record.style, record.enabled); stylesChanged = true; }\n }\n if (matricesChanged) this._matrixVersion++;\n if (stylesChanged) this._styleVersion++;\n this._pendingMatrices.clear();\n this._pendingStyles.clear();\n this._matrixPending = false;\n this._stylePending = false;\n this._geometryPending = false;\n this._materialPending = false;\n }\n\n /** 清空记录并解绑,保留已分配 CPU 容量供后续 push 使用。 */\n public clear(): void {\n this.assertActive();\n this._raws.clear();\n this._count = 0;\n this._ids.length = 0;\n this._sources.length = 0;\n this._pendingMatrices.clear();\n this._pendingStyles.clear();\n for (const texture of this._textures) texture.set([]);\n for (const indices of this._layerIndices) indices.clear();\n this._layersPending = false;\n this._matrixVersion++;\n this._styleVersion++;\n this.updateVersion();\n this.getScene(this)?.updateVersion();\n }\n /** 解除原始记录、贴图层表和资源订阅,不销毁共享几何、材质或图片。 */\n public override dispose(): void {\n if (this._disposed) return;\n this.clear();\n for (const texture of this._textures) texture.dispose();\n super.dispose();\n }\n\n /** @param count 即将使用的条数 */\n private ensureCapacity(count: number): void {\n let capacity: number = this._capacity;\n while (capacity < count) capacity = capacity < 100000\n ? Math.min(capacity * this._growthFactor, 100000)\n : Math.ceil(count / 100000) * 100000;\n if (capacity !== this._capacity) this.capacity = capacity;\n }\n /** @param options 完整输入 @returns 校验后的值,不保留临时默认对象 */\n private resolve(options: RawOptions): Required<RawOptions> {\n const values = {\n position: options.position ?? new Vec2(), rotation: options.rotation ?? 0,\n scale: options.scale ?? new Vec2(1, 1), style: options.style ?? this.material?.style ?? new Style(),\n enabled: options.enabled ?? true,\n };\n if (![values.position.x, values.position.y, values.scale.x, values.scale.y, values.rotation].every(Number.isFinite)) {\n throw new RangeError(\"Transform components must be finite.\");\n }\n return values;\n }\n /** @param index 槽位 @param values 局部变换,输出只保存 world * local */\n private writeMatrix(index: number, values: Required<RawOptions> | Raw): void {\n const c: number = Math.cos(values.rotation);\n const s: number = Math.sin(values.rotation);\n this._local.set([c * values.scale.x, s * values.scale.x, 0, -s * values.scale.y, c * values.scale.y, 0, values.position.x, values.position.y, 1]);\n this._world.mul(this.worldMatrix, this._local);\n this._matrixData.set(this._world.GPUData, index * 12);\n }\n /** @param index 槽位 @param style 样式 @param enabled 整条记录开关 */\n private writeStyle(index: number, style: Style, enabled: boolean): void {\n const offset: number = index * STYLE_STRIDE;\n WriteStyleData(style, this._styleData, offset);\n if (!enabled) this._styleData.fill(0, offset + 36, offset + 40);\n this.writeLayers(index);\n }\n /** @param index 槽位 @param style 只截取图片引用,不保留整个 Style */\n private setSources(index: number, style: Style): void {\n const previous = this._sources.at(index);\n const next = [style.solid.texture, style.edge.texture, style.points.texture];\n if (previous !== undefined && next.every((texture, part): boolean => texture === previous[part])) return;\n this._sources[index] = next;\n this._layersPending = true;\n this.getScene(this)?.updateVersion();\n }\n /** 图片引用变化时才重建去重层表,避免反复换图后无限积累废弃层。 */\n private updateTextureLayers(): void {\n if (!this._layersPending) return;\n for (let part = 0; part < 3; part++) {\n const indices = this._layerIndices[part];\n const layers: (TextureLike | undefined)[] = [];\n indices.clear();\n for (const sources of this._sources) {\n const texture = sources[part];\n if (!indices.has(texture)) { indices.set(texture, layers.length); layers.push(texture); }\n }\n this._textures[part].set(layers);\n }\n for (let index = 0; index < this._count; index++) this.writeLayers(index);\n this._styleVersion++;\n this._layersPending = false;\n }\n /** @param index 将三套纹理层号写到样式最后一个 vec4 */\n private writeLayers(index: number): void {\n for (let part = 0; part < 3; part++) {\n this._styleData[index * STYLE_STRIDE + 40 + part] = this._layerIndices[part].get(this._sources[index]?.[part]) ?? 0;\n }\n }\n /** 拦截销毁后复用。 */\n private assertActive(): void {\n if (this._disposed) throw new Error(\"Disposed IMesh cannot be reused.\");\n }\n}\n\nexport default IMesh;\nexport type { RawOptions } from \"../Raws\";\n\n/** @param options 构建选项;不创建任何订阅或分配大数组 */\nconst ValidateOptions = (options: IMeshOptions): void => {\n const capacity: number = options.capacity ?? 2;\n const factor: number = options.growthFactor ?? 2;\n if (!Number.isSafeInteger(capacity) || capacity < 1 || capacity > Math.floor(0xFFFFFFFF / (STYLE_STRIDE * 4))) {\n throw new RangeError(\"Invalid initial capacity.\");\n }\n if (!Number.isSafeInteger(factor) || factor < 2) throw new RangeError(\"growthFactor must be an integer >= 2.\");\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/// <reference types="@webgpu/types" preserve="true" />
|
|
2
|
+
import Style from "../Style";
|
|
3
|
+
import type { StyleChange, StyleSubscriber, BorderAlign, PixelAligned } from "../Style";
|
|
4
|
+
interface MaterialBuffersLike {
|
|
5
|
+
uniform?: number;
|
|
6
|
+
texture?: number;
|
|
7
|
+
sampler?: number;
|
|
8
|
+
}
|
|
9
|
+
interface ShadersLike {
|
|
10
|
+
polyVertexShader?: string;
|
|
11
|
+
polyFragmentShader?: string;
|
|
12
|
+
rectVertexShader?: string;
|
|
13
|
+
rectFragmentShader?: string;
|
|
14
|
+
}
|
|
15
|
+
/** 通知类别不是独立版本;材质仍只有一个 version。 */
|
|
16
|
+
type MaterialChangeKind = "all" | "style" | "pipeline" | "texture" | "textureData" | "sampler";
|
|
17
|
+
/** 材质变化影响:样式数组、场景资源引用分别处理。 */
|
|
18
|
+
interface MaterialChange {
|
|
19
|
+
readonly source: MaterialLike;
|
|
20
|
+
readonly style: boolean;
|
|
21
|
+
readonly resources: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** 材质消费者,回调只安排下一帧工作。 */
|
|
24
|
+
interface MaterialSubscriber {
|
|
25
|
+
onMaterialChange(change: MaterialChange): void;
|
|
26
|
+
}
|
|
27
|
+
interface MaterialLike extends StyleSubscriber {
|
|
28
|
+
readonly id: number;
|
|
29
|
+
readonly type: string;
|
|
30
|
+
readonly key: string;
|
|
31
|
+
readonly version: number;
|
|
32
|
+
style: Style;
|
|
33
|
+
transparent: boolean;
|
|
34
|
+
depthTest: boolean;
|
|
35
|
+
depthWrite: boolean;
|
|
36
|
+
cullMode: GPUCullMode;
|
|
37
|
+
addGeometryType(type: string): void;
|
|
38
|
+
getPipelineKey(type: string): string;
|
|
39
|
+
rectVertexShader: string | undefined;
|
|
40
|
+
rectFragmentShader: string | undefined;
|
|
41
|
+
polyVertexShader: string | undefined;
|
|
42
|
+
polyFragmentShader: string | undefined;
|
|
43
|
+
updateKey(): void;
|
|
44
|
+
updateVersion(kind?: MaterialChangeKind): void;
|
|
45
|
+
add(subscriber: MaterialSubscriber): void;
|
|
46
|
+
delete(subscriber: MaterialSubscriber): void;
|
|
47
|
+
dispose(): void;
|
|
48
|
+
}
|
|
49
|
+
/** 材质只持有 Shader、固定管线状态及 Style 引用,不重复保存显示参数。 */
|
|
50
|
+
declare abstract class Material implements MaterialLike {
|
|
51
|
+
/** 全局材质 ID。 */
|
|
52
|
+
readonly id: number;
|
|
53
|
+
/** 材质类型。 */
|
|
54
|
+
abstract readonly type: string;
|
|
55
|
+
private _version;
|
|
56
|
+
private _key;
|
|
57
|
+
/** 缓存完整几何管线键,避免每个 Mesh 每帧拼接和散列 Shader 长字符串。 */
|
|
58
|
+
private readonly _pipelineKeys;
|
|
59
|
+
private _style;
|
|
60
|
+
private _disposed;
|
|
61
|
+
private readonly _subscribers;
|
|
62
|
+
private _transparent;
|
|
63
|
+
private _depthTest;
|
|
64
|
+
private _depthWrite;
|
|
65
|
+
private _cullMode;
|
|
66
|
+
private readonly _geometryTypes;
|
|
67
|
+
private readonly _shaders;
|
|
68
|
+
/** @param style 共享样式,默认各分区关闭 */
|
|
69
|
+
protected constructor(style?: Style);
|
|
70
|
+
/** 当前共享样式。 */
|
|
71
|
+
get style(): Style;
|
|
72
|
+
/** @param value 新样式;解绑旧引用,并更新材质版本及 Pipeline key */
|
|
73
|
+
set style(value: Style);
|
|
74
|
+
/** @param change 样式变化;区分数值、贴图引用和贴图内容,避免无关缓冲重复上传 */
|
|
75
|
+
onStyleChange(change: StyleChange): void;
|
|
76
|
+
/** 最终停止使用时解绑 Style,不销毁共享贴图或 GPU 缓存。 */
|
|
77
|
+
dispose(): void;
|
|
78
|
+
/**
|
|
79
|
+
* 关联使用当前材质的消费者,Set 自动去重。
|
|
80
|
+
* @param subscriber Mesh 或其他材质消费者
|
|
81
|
+
*/
|
|
82
|
+
add(subscriber: MaterialSubscriber): void;
|
|
83
|
+
/**
|
|
84
|
+
* 解绑消费者,不销毁共享 Style、Texture 或 GPU 缓存。
|
|
85
|
+
* @param subscriber 需要解绑的消费者
|
|
86
|
+
*/
|
|
87
|
+
delete(subscriber: MaterialSubscriber): void;
|
|
88
|
+
/** 单一材质版本。 */
|
|
89
|
+
get version(): number;
|
|
90
|
+
/** 固定管线状态与 Shader 对应的缓存键。 */
|
|
91
|
+
get key(): string;
|
|
92
|
+
/**
|
|
93
|
+
* 递增单一版本并通知消费者,颜色变化不会改变 key。
|
|
94
|
+
* @param kind 影响范围,手动调用默认全部失效
|
|
95
|
+
*/
|
|
96
|
+
updateVersion(kind?: MaterialChangeKind): void;
|
|
97
|
+
/** 所有分区共用的透明混合状态。 */
|
|
98
|
+
get transparent(): boolean;
|
|
99
|
+
/** @param value 是否开启透明混合 */
|
|
100
|
+
set transparent(value: boolean);
|
|
101
|
+
/** 是否比较深度,默认 false;关闭时作为最后绘制的覆盖层。 */
|
|
102
|
+
get depthTest(): boolean;
|
|
103
|
+
/** @param value 是否执行深度比较,不自动改变 depthWrite / transparent */
|
|
104
|
+
set depthTest(value: boolean);
|
|
105
|
+
/** 是否记录通过测试的片元深度,默认 false;普通透明物体通常应关闭。 */
|
|
106
|
+
get depthWrite(): boolean;
|
|
107
|
+
/** @param value 是否写入深度,不自动改变 depthTest / transparent */
|
|
108
|
+
set depthWrite(value: boolean);
|
|
109
|
+
/** 所有三角面共用的剔除状态。 */
|
|
110
|
+
get cullMode(): GPUCullMode;
|
|
111
|
+
/** @param value 要剔除的面 */
|
|
112
|
+
set cullMode(value: GPUCullMode);
|
|
113
|
+
/**
|
|
114
|
+
* 追加已使用的几何类型标记;Rect2d 对应 rect,重复绑定不递增版本。
|
|
115
|
+
* @param type Geometry.type
|
|
116
|
+
* @returns 无返回值
|
|
117
|
+
*/
|
|
118
|
+
addGeometryType(type: string): void;
|
|
119
|
+
/**
|
|
120
|
+
* 获取指定几何类型的管线缓存键。
|
|
121
|
+
* 材质 key 描述共享状态,类型后缀区分同一材质的不同几何模板。
|
|
122
|
+
* @param type Geometry.type
|
|
123
|
+
* @returns 当前几何对应的管线键
|
|
124
|
+
*/
|
|
125
|
+
getPipelineKey(type: string): string;
|
|
126
|
+
/**
|
|
127
|
+
* 设置矩形合并三角面顶点着色器源码。
|
|
128
|
+
* @param vertexShader 顶点着色器源码
|
|
129
|
+
*/
|
|
130
|
+
set rectVertexShader(vertexShader: string | undefined);
|
|
131
|
+
/**
|
|
132
|
+
* 获取矩形合并三角面顶点着色器源码。
|
|
133
|
+
* @returns 顶点着色器源码
|
|
134
|
+
*/
|
|
135
|
+
get rectVertexShader(): string | undefined;
|
|
136
|
+
/**
|
|
137
|
+
* 设置矩形合并三角面片元着色器源码。
|
|
138
|
+
* @param fragmentShader 片元着色器源码
|
|
139
|
+
*/
|
|
140
|
+
set rectFragmentShader(fragmentShader: string | undefined);
|
|
141
|
+
/**
|
|
142
|
+
* 获取矩形合并三角面片元着色器源码。
|
|
143
|
+
* @returns 片元着色器源码
|
|
144
|
+
*/
|
|
145
|
+
get rectFragmentShader(): string | undefined;
|
|
146
|
+
/** 多边形合并三角面顶点 Shader。 */
|
|
147
|
+
get polyVertexShader(): string | undefined;
|
|
148
|
+
/** @param value 多边形顶点 Shader 源码,修改后重建管线 */
|
|
149
|
+
set polyVertexShader(value: string | undefined);
|
|
150
|
+
/** 多边形填充、边框和点型片段 Shader。 */
|
|
151
|
+
get polyFragmentShader(): string | undefined;
|
|
152
|
+
/** @param value 多边形片段 Shader 源码,修改后重建管线 */
|
|
153
|
+
set polyFragmentShader(value: string | undefined);
|
|
154
|
+
/** 原生线开关决定是否需要附加 line-list 管线,其余分区通过 Uniform 控制。 */
|
|
155
|
+
updateKey(): void;
|
|
156
|
+
}
|
|
157
|
+
export default Material;
|
|
158
|
+
export type { BorderAlign, MaterialBuffersLike, MaterialChange, MaterialChangeKind, MaterialLike, MaterialSubscriber, PixelAligned, ShadersLike };
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { GETID } from "../ID.js";
|
|
2
|
+
import Style from "../Style/index.js";
|
|
3
|
+
//#region src/scripts/Material/Material.ts
|
|
4
|
+
/** 材质只持有 Shader、固定管线状态及 Style 引用,不重复保存显示参数。 */
|
|
5
|
+
var Material = class {
|
|
6
|
+
/** 全局材质 ID。 */
|
|
7
|
+
id = GETID();
|
|
8
|
+
_version = 0;
|
|
9
|
+
_key = "";
|
|
10
|
+
/** 缓存完整几何管线键,避免每个 Mesh 每帧拼接和散列 Shader 长字符串。 */
|
|
11
|
+
_pipelineKeys = /* @__PURE__ */ new Map();
|
|
12
|
+
_style;
|
|
13
|
+
_disposed = false;
|
|
14
|
+
_subscribers = /* @__PURE__ */ new Set();
|
|
15
|
+
_transparent = false;
|
|
16
|
+
_depthTest = false;
|
|
17
|
+
_depthWrite = false;
|
|
18
|
+
_cullMode = "back";
|
|
19
|
+
_geometryTypes = /* @__PURE__ */ new Set();
|
|
20
|
+
_shaders = {};
|
|
21
|
+
/** @param style 共享样式,默认各分区关闭 */
|
|
22
|
+
constructor(style = new Style()) {
|
|
23
|
+
this._style = style;
|
|
24
|
+
style.add(this);
|
|
25
|
+
}
|
|
26
|
+
/** 当前共享样式。 */
|
|
27
|
+
get style() {
|
|
28
|
+
return this._style;
|
|
29
|
+
}
|
|
30
|
+
/** @param value 新样式;解绑旧引用,并更新材质版本及 Pipeline key */
|
|
31
|
+
set style(value) {
|
|
32
|
+
if (this._disposed) throw new Error("Disposed material cannot be reused.");
|
|
33
|
+
if (this._style === value) return;
|
|
34
|
+
this._style.delete(this);
|
|
35
|
+
this._style = value;
|
|
36
|
+
value.add(this);
|
|
37
|
+
this.updateVersion();
|
|
38
|
+
}
|
|
39
|
+
/** @param change 样式变化;区分数值、贴图引用和贴图内容,避免无关缓冲重复上传 */
|
|
40
|
+
onStyleChange(change) {
|
|
41
|
+
if (this._disposed || change.source !== this._style) return;
|
|
42
|
+
const kind = change.field === "texture" ? "texture" : change.field === "textureData" ? "textureData" : change.field === "addressModeU" || change.field === "addressModeV" ? "sampler" : "style";
|
|
43
|
+
this.updateVersion(kind);
|
|
44
|
+
}
|
|
45
|
+
/** 最终停止使用时解绑 Style,不销毁共享贴图或 GPU 缓存。 */
|
|
46
|
+
dispose() {
|
|
47
|
+
this._style.delete(this);
|
|
48
|
+
this._subscribers.clear();
|
|
49
|
+
this._disposed = true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 关联使用当前材质的消费者,Set 自动去重。
|
|
53
|
+
* @param subscriber Mesh 或其他材质消费者
|
|
54
|
+
*/
|
|
55
|
+
add(subscriber) {
|
|
56
|
+
if (this._disposed) throw new Error("Disposed material cannot be reused.");
|
|
57
|
+
this._subscribers.add(subscriber);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 解绑消费者,不销毁共享 Style、Texture 或 GPU 缓存。
|
|
61
|
+
* @param subscriber 需要解绑的消费者
|
|
62
|
+
*/
|
|
63
|
+
delete(subscriber) {
|
|
64
|
+
this._subscribers.delete(subscriber);
|
|
65
|
+
}
|
|
66
|
+
/** 单一材质版本。 */
|
|
67
|
+
get version() {
|
|
68
|
+
return this._version;
|
|
69
|
+
}
|
|
70
|
+
/** 固定管线状态与 Shader 对应的缓存键。 */
|
|
71
|
+
get key() {
|
|
72
|
+
return this._key;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 递增单一版本并通知消费者,颜色变化不会改变 key。
|
|
76
|
+
* @param kind 影响范围,手动调用默认全部失效
|
|
77
|
+
*/
|
|
78
|
+
updateVersion(kind = "all") {
|
|
79
|
+
const previousKey = this._key;
|
|
80
|
+
this._version++;
|
|
81
|
+
this.updateKey();
|
|
82
|
+
const change = Object.freeze({
|
|
83
|
+
source: this,
|
|
84
|
+
style: kind === "all" || kind === "style",
|
|
85
|
+
resources: kind === "all" || kind === "texture" || previousKey !== this._key
|
|
86
|
+
});
|
|
87
|
+
for (const subscriber of [...this._subscribers]) subscriber.onMaterialChange(change);
|
|
88
|
+
}
|
|
89
|
+
/** 所有分区共用的透明混合状态。 */
|
|
90
|
+
get transparent() {
|
|
91
|
+
return this._transparent;
|
|
92
|
+
}
|
|
93
|
+
/** @param value 是否开启透明混合 */
|
|
94
|
+
set transparent(value) {
|
|
95
|
+
if (this._transparent === value) return;
|
|
96
|
+
this._transparent = value;
|
|
97
|
+
this.updateVersion("pipeline");
|
|
98
|
+
}
|
|
99
|
+
/** 是否比较深度,默认 false;关闭时作为最后绘制的覆盖层。 */
|
|
100
|
+
get depthTest() {
|
|
101
|
+
return this._depthTest;
|
|
102
|
+
}
|
|
103
|
+
/** @param value 是否执行深度比较,不自动改变 depthWrite / transparent */
|
|
104
|
+
set depthTest(value) {
|
|
105
|
+
if (this._depthTest === value) return;
|
|
106
|
+
this._depthTest = value;
|
|
107
|
+
this.updateVersion("pipeline");
|
|
108
|
+
}
|
|
109
|
+
/** 是否记录通过测试的片元深度,默认 false;普通透明物体通常应关闭。 */
|
|
110
|
+
get depthWrite() {
|
|
111
|
+
return this._depthWrite;
|
|
112
|
+
}
|
|
113
|
+
/** @param value 是否写入深度,不自动改变 depthTest / transparent */
|
|
114
|
+
set depthWrite(value) {
|
|
115
|
+
if (this._depthWrite === value) return;
|
|
116
|
+
this._depthWrite = value;
|
|
117
|
+
this.updateVersion("pipeline");
|
|
118
|
+
}
|
|
119
|
+
/** 所有三角面共用的剔除状态。 */
|
|
120
|
+
get cullMode() {
|
|
121
|
+
return this._cullMode;
|
|
122
|
+
}
|
|
123
|
+
/** @param value 要剔除的面 */
|
|
124
|
+
set cullMode(value) {
|
|
125
|
+
if (this._cullMode === value) return;
|
|
126
|
+
this._cullMode = value;
|
|
127
|
+
this.updateVersion("pipeline");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 追加已使用的几何类型标记;Rect2d 对应 rect,重复绑定不递增版本。
|
|
131
|
+
* @param type Geometry.type
|
|
132
|
+
* @returns 无返回值
|
|
133
|
+
*/
|
|
134
|
+
addGeometryType(type) {
|
|
135
|
+
const tag = type === "Rect2d" ? "rect" : type === "Poly2D" ? "poly" : type;
|
|
136
|
+
if (this._geometryTypes.has(tag)) return;
|
|
137
|
+
this._geometryTypes.add(tag);
|
|
138
|
+
this.updateVersion("pipeline");
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 获取指定几何类型的管线缓存键。
|
|
142
|
+
* 材质 key 描述共享状态,类型后缀区分同一材质的不同几何模板。
|
|
143
|
+
* @param type Geometry.type
|
|
144
|
+
* @returns 当前几何对应的管线键
|
|
145
|
+
*/
|
|
146
|
+
getPipelineKey(type) {
|
|
147
|
+
let key = this._pipelineKeys.get(type);
|
|
148
|
+
if (key === void 0) {
|
|
149
|
+
key = this.key + "_" + (type === "Rect2d" ? "rect" : type === "Poly2D" ? "poly" : type);
|
|
150
|
+
this._pipelineKeys.set(type, key);
|
|
151
|
+
}
|
|
152
|
+
return key;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 设置矩形合并三角面顶点着色器源码。
|
|
156
|
+
* @param vertexShader 顶点着色器源码
|
|
157
|
+
*/
|
|
158
|
+
set rectVertexShader(vertexShader) {
|
|
159
|
+
if (this._shaders.rectVertexShader === vertexShader) return;
|
|
160
|
+
this._shaders.rectVertexShader = vertexShader;
|
|
161
|
+
this.updateVersion("pipeline");
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 获取矩形合并三角面顶点着色器源码。
|
|
165
|
+
* @returns 顶点着色器源码
|
|
166
|
+
*/
|
|
167
|
+
get rectVertexShader() {
|
|
168
|
+
return this._shaders.rectVertexShader;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 设置矩形合并三角面片元着色器源码。
|
|
172
|
+
* @param fragmentShader 片元着色器源码
|
|
173
|
+
*/
|
|
174
|
+
set rectFragmentShader(fragmentShader) {
|
|
175
|
+
if (this._shaders.rectFragmentShader === fragmentShader) return;
|
|
176
|
+
this._shaders.rectFragmentShader = fragmentShader;
|
|
177
|
+
this.updateVersion("pipeline");
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 获取矩形合并三角面片元着色器源码。
|
|
181
|
+
* @returns 片元着色器源码
|
|
182
|
+
*/
|
|
183
|
+
get rectFragmentShader() {
|
|
184
|
+
return this._shaders.rectFragmentShader;
|
|
185
|
+
}
|
|
186
|
+
/** 多边形合并三角面顶点 Shader。 */
|
|
187
|
+
get polyVertexShader() {
|
|
188
|
+
return this._shaders.polyVertexShader;
|
|
189
|
+
}
|
|
190
|
+
/** @param value 多边形顶点 Shader 源码,修改后重建管线 */
|
|
191
|
+
set polyVertexShader(value) {
|
|
192
|
+
if (this._shaders.polyVertexShader === value) return;
|
|
193
|
+
this._shaders.polyVertexShader = value;
|
|
194
|
+
this.updateVersion("pipeline");
|
|
195
|
+
}
|
|
196
|
+
/** 多边形填充、边框和点型片段 Shader。 */
|
|
197
|
+
get polyFragmentShader() {
|
|
198
|
+
return this._shaders.polyFragmentShader;
|
|
199
|
+
}
|
|
200
|
+
/** @param value 多边形片段 Shader 源码,修改后重建管线 */
|
|
201
|
+
set polyFragmentShader(value) {
|
|
202
|
+
if (this._shaders.polyFragmentShader === value) return;
|
|
203
|
+
this._shaders.polyFragmentShader = value;
|
|
204
|
+
this.updateVersion("pipeline");
|
|
205
|
+
}
|
|
206
|
+
/** 原生线开关决定是否需要附加 line-list 管线,其余分区通过 Uniform 控制。 */
|
|
207
|
+
updateKey() {
|
|
208
|
+
const key = JSON.stringify([
|
|
209
|
+
this.type,
|
|
210
|
+
this._transparent,
|
|
211
|
+
this._cullMode,
|
|
212
|
+
this._depthTest,
|
|
213
|
+
this._depthWrite,
|
|
214
|
+
this._style.wireframe.enabled,
|
|
215
|
+
this._shaders.rectVertexShader,
|
|
216
|
+
this._shaders.rectFragmentShader,
|
|
217
|
+
this._shaders.polyVertexShader,
|
|
218
|
+
this._shaders.polyFragmentShader
|
|
219
|
+
]) + [...this._geometryTypes].sort().map((tag) => "_" + tag).join("");
|
|
220
|
+
if (key !== this._key) {
|
|
221
|
+
this._key = key;
|
|
222
|
+
this._pipelineKeys.clear();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
//#endregion
|
|
227
|
+
export { Material as default };
|
|
228
|
+
|
|
229
|
+
//# sourceMappingURL=Material.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Material.js","names":[],"sources":["../../src/scripts/Material/Material.ts"],"sourcesContent":["/// <reference types=\"@webgpu/types\" preserve=\"true\" />\nimport { GETID } from \"../ID\";\nimport Style from \"../Style\";\nimport type { StyleChange, StyleSubscriber, BorderAlign, PixelAligned } from \"../Style\";\n\ninterface MaterialBuffersLike {\n uniform?: number;\n texture?: number;\n sampler?: number;\n}\ninterface ShadersLike {\n polyVertexShader?: string;\n polyFragmentShader?: string;\n rectVertexShader?: string;\n rectFragmentShader?: string;\n}\n/** 通知类别不是独立版本;材质仍只有一个 version。 */\ntype MaterialChangeKind = \"all\" | \"style\" | \"pipeline\" | \"texture\" | \"textureData\" | \"sampler\";\n/** 材质变化影响:样式数组、场景资源引用分别处理。 */\ninterface MaterialChange {\n readonly source: MaterialLike;\n readonly style: boolean;\n readonly resources: boolean;\n}\n/** 材质消费者,回调只安排下一帧工作。 */\ninterface MaterialSubscriber {\n onMaterialChange(change: MaterialChange): void;\n}\ninterface MaterialLike extends StyleSubscriber {\n readonly id: number;\n readonly type: string;\n readonly key: string;\n readonly version: number;\n style: Style;\n transparent: boolean;\n depthTest: boolean;\n depthWrite: boolean;\n cullMode: GPUCullMode;\n addGeometryType(type: string): void;\n getPipelineKey(type: string): string;\n rectVertexShader: string | undefined;\n rectFragmentShader: string | undefined;\n polyVertexShader: string | undefined;\n polyFragmentShader: string | undefined;\n updateKey(): void;\n updateVersion(kind?: MaterialChangeKind): void;\n add(subscriber: MaterialSubscriber): void;\n delete(subscriber: MaterialSubscriber): void;\n dispose(): void;\n}\n/** 材质只持有 Shader、固定管线状态及 Style 引用,不重复保存显示参数。 */\nabstract class Material implements MaterialLike {\n /** 全局材质 ID。 */\n public readonly id: number = GETID();\n /** 材质类型。 */\n public abstract readonly type: string;\n private _version: number = 0;\n private _key: string = \"\";\n /** 缓存完整几何管线键,避免每个 Mesh 每帧拼接和散列 Shader 长字符串。 */\n private readonly _pipelineKeys = new Map<string, string>();\n private _style: Style;\n private _disposed: boolean = false;\n private readonly _subscribers = new Set<MaterialSubscriber>();\n private _transparent: boolean = false;\n private _depthTest: boolean = false;\n private _depthWrite: boolean = false;\n private _cullMode: GPUCullMode = \"back\";\n private readonly _geometryTypes = new Set<string>();\n private readonly _shaders: ShadersLike = {};\n\n /** @param style 共享样式,默认各分区关闭 */\n protected constructor(style: Style = new Style()) {\n this._style = style;\n style.add(this);\n }\n /** 当前共享样式。 */\n public get style(): Style { return this._style; }\n /** @param value 新样式;解绑旧引用,并更新材质版本及 Pipeline key */\n public set style(value: Style) {\n if (this._disposed) throw new Error(\"Disposed material cannot be reused.\");\n if (this._style === value) return;\n this._style.delete(this);\n this._style = value;\n value.add(this);\n this.updateVersion();\n }\n /** @param change 样式变化;区分数值、贴图引用和贴图内容,避免无关缓冲重复上传 */\n public onStyleChange(change: StyleChange): void {\n if (this._disposed || change.source !== this._style) return;\n const kind: MaterialChangeKind = change.field === \"texture\" ? \"texture\"\n : change.field === \"textureData\" ? \"textureData\"\n : change.field === \"addressModeU\" || change.field === \"addressModeV\" ? \"sampler\" : \"style\";\n this.updateVersion(kind);\n }\n /** 最终停止使用时解绑 Style,不销毁共享贴图或 GPU 缓存。 */\n public dispose(): void {\n this._style.delete(this);\n this._subscribers.clear();\n this._disposed = true;\n }\n /**\n * 关联使用当前材质的消费者,Set 自动去重。\n * @param subscriber Mesh 或其他材质消费者\n */\n public add(subscriber: MaterialSubscriber): void {\n if (this._disposed) throw new Error(\"Disposed material cannot be reused.\");\n this._subscribers.add(subscriber);\n }\n /**\n * 解绑消费者,不销毁共享 Style、Texture 或 GPU 缓存。\n * @param subscriber 需要解绑的消费者\n */\n public delete(subscriber: MaterialSubscriber): void {\n this._subscribers.delete(subscriber);\n }\n /** 单一材质版本。 */\n public get version(): number { return this._version; }\n /** 固定管线状态与 Shader 对应的缓存键。 */\n public get key(): string { return this._key; }\n /**\n * 递增单一版本并通知消费者,颜色变化不会改变 key。\n * @param kind 影响范围,手动调用默认全部失效\n */\n public updateVersion(kind: MaterialChangeKind = \"all\"): void {\n const previousKey: string = this._key;\n this._version++;\n this.updateKey();\n const change: MaterialChange = Object.freeze({\n source: this,\n style: kind === \"all\" || kind === \"style\",\n resources: kind === \"all\" || kind === \"texture\" || previousKey !== this._key,\n });\n for (const subscriber of [...this._subscribers]) subscriber.onMaterialChange(change);\n }\n /** 所有分区共用的透明混合状态。 */\n public get transparent(): boolean { return this._transparent; }\n /** @param value 是否开启透明混合 */\n public set transparent(value: boolean) {\n if (this._transparent === value) return;\n this._transparent = value;\n this.updateVersion(\"pipeline\");\n }\n /** 是否比较深度,默认 false;关闭时作为最后绘制的覆盖层。 */\n public get depthTest(): boolean { return this._depthTest; }\n /** @param value 是否执行深度比较,不自动改变 depthWrite / transparent */\n public set depthTest(value: boolean) {\n if (this._depthTest === value) return;\n this._depthTest = value;\n this.updateVersion(\"pipeline\");\n }\n /** 是否记录通过测试的片元深度,默认 false;普通透明物体通常应关闭。 */\n public get depthWrite(): boolean { return this._depthWrite; }\n /** @param value 是否写入深度,不自动改变 depthTest / transparent */\n public set depthWrite(value: boolean) {\n if (this._depthWrite === value) return;\n this._depthWrite = value;\n this.updateVersion(\"pipeline\");\n }\n /** 所有三角面共用的剔除状态。 */\n public get cullMode(): GPUCullMode { return this._cullMode; }\n /** @param value 要剔除的面 */\n public set cullMode(value: GPUCullMode) {\n if (this._cullMode === value) return;\n this._cullMode = value;\n this.updateVersion(\"pipeline\");\n }\n /**\n * 追加已使用的几何类型标记;Rect2d 对应 rect,重复绑定不递增版本。\n * @param type Geometry.type\n * @returns 无返回值\n */\n public addGeometryType(type: string): void {\n const tag: string = type === \"Rect2d\" ? \"rect\" : type === \"Poly2D\" ? \"poly\" : type;\n if (this._geometryTypes.has(tag)) {\n return;\n }\n this._geometryTypes.add(tag);\n this.updateVersion(\"pipeline\");\n }\n\n /**\n * 获取指定几何类型的管线缓存键。\n * 材质 key 描述共享状态,类型后缀区分同一材质的不同几何模板。\n * @param type Geometry.type\n * @returns 当前几何对应的管线键\n */\n public getPipelineKey(type: string): string {\n let key: string | undefined = this._pipelineKeys.get(type);\n if (key === undefined) {\n key = this.key + \"_\" + (type === \"Rect2d\" ? \"rect\" : type === \"Poly2D\" ? \"poly\" : type);\n this._pipelineKeys.set(type, key);\n }\n return key;\n }\n\n /**\n * 设置矩形合并三角面顶点着色器源码。\n * @param vertexShader 顶点着色器源码\n */\n public set rectVertexShader(vertexShader: string | undefined) {\n if (this._shaders.rectVertexShader === vertexShader) {\n return;\n }\n\n this._shaders.rectVertexShader = vertexShader;\n this.updateVersion(\"pipeline\");\n }\n\n /**\n * 获取矩形合并三角面顶点着色器源码。\n * @returns 顶点着色器源码\n */\n public get rectVertexShader(): string | undefined {\n return this._shaders.rectVertexShader;\n }\n\n /**\n * 设置矩形合并三角面片元着色器源码。\n * @param fragmentShader 片元着色器源码\n */\n public set rectFragmentShader(fragmentShader: string | undefined) {\n if (this._shaders.rectFragmentShader === fragmentShader) {\n return;\n }\n\n this._shaders.rectFragmentShader = fragmentShader;\n this.updateVersion(\"pipeline\");\n }\n\n /**\n * 获取矩形合并三角面片元着色器源码。\n * @returns 片元着色器源码\n */\n public get rectFragmentShader(): string | undefined {\n return this._shaders.rectFragmentShader;\n }\n\n /** 多边形合并三角面顶点 Shader。 */\n public get polyVertexShader(): string | undefined { return this._shaders.polyVertexShader; }\n /** @param value 多边形顶点 Shader 源码,修改后重建管线 */\n public set polyVertexShader(value: string | undefined) {\n if (this._shaders.polyVertexShader === value) return;\n this._shaders.polyVertexShader = value;\n this.updateVersion(\"pipeline\");\n }\n /** 多边形填充、边框和点型片段 Shader。 */\n public get polyFragmentShader(): string | undefined { return this._shaders.polyFragmentShader; }\n /** @param value 多边形片段 Shader 源码,修改后重建管线 */\n public set polyFragmentShader(value: string | undefined) {\n if (this._shaders.polyFragmentShader === value) return;\n this._shaders.polyFragmentShader = value;\n this.updateVersion(\"pipeline\");\n }\n\n\n /** 原生线开关决定是否需要附加 line-list 管线,其余分区通过 Uniform 控制。 */\n public updateKey(): void {\n const key: string = JSON.stringify([\n this.type, this._transparent, this._cullMode, this._depthTest, this._depthWrite,\n this._style.wireframe.enabled,\n this._shaders.rectVertexShader, this._shaders.rectFragmentShader,\n this._shaders.polyVertexShader, this._shaders.polyFragmentShader,\n ]) + [...this._geometryTypes].sort().map((tag: string): string => \"_\" + tag).join(\"\");\n if (key !== this._key) {\n this._key = key;\n this._pipelineKeys.clear();\n }\n }\n}\nexport default Material;\nexport type { BorderAlign, MaterialBuffersLike, MaterialChange, MaterialChangeKind, MaterialLike, MaterialSubscriber, PixelAligned, ShadersLike };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Material from "./Material";
|
|
2
|
+
import type { MaterialLike } from "./Material";
|
|
3
|
+
import type Style from "../Style";
|
|
4
|
+
interface BaseMaterialLike extends MaterialLike {
|
|
5
|
+
readonly type: "BaseMaterial";
|
|
6
|
+
}
|
|
7
|
+
/** 矩形与多边形材质;按几何类型选择 Shader,四套显示参数均从 Style 获取。 */
|
|
8
|
+
declare class BaseMaterial extends Material implements BaseMaterialLike {
|
|
9
|
+
/** 对象类型。 */
|
|
10
|
+
readonly type: "BaseMaterial";
|
|
11
|
+
/** @param style 共享样式,通常与对应 Geometry 使用同一对象 */
|
|
12
|
+
constructor(style?: Style);
|
|
13
|
+
}
|
|
14
|
+
export default BaseMaterial;
|
|
15
|
+
export type { BaseMaterialLike };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Material from "./Material.js";
|
|
2
|
+
import vertex_default from "./shaders/base/rect/vertex.js";
|
|
3
|
+
import fragment_default from "./shaders/base/rect/fragment.js";
|
|
4
|
+
import vertex_default$1 from "./shaders/base/poly/vertex.js";
|
|
5
|
+
import fragment_default$1 from "./shaders/base/poly/fragment.js";
|
|
6
|
+
//#region src/scripts/Material/baseMaterial.ts
|
|
7
|
+
/** 矩形与多边形材质;按几何类型选择 Shader,四套显示参数均从 Style 获取。 */
|
|
8
|
+
var BaseMaterial = class extends Material {
|
|
9
|
+
/** 对象类型。 */
|
|
10
|
+
type = "BaseMaterial";
|
|
11
|
+
/** @param style 共享样式,通常与对应 Geometry 使用同一对象 */
|
|
12
|
+
constructor(style) {
|
|
13
|
+
super(style);
|
|
14
|
+
this.rectVertexShader = vertex_default;
|
|
15
|
+
this.rectFragmentShader = fragment_default;
|
|
16
|
+
this.polyVertexShader = vertex_default$1;
|
|
17
|
+
this.polyFragmentShader = fragment_default$1;
|
|
18
|
+
this.updateKey();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { BaseMaterial as default };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=baseMaterial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseMaterial.js","names":[],"sources":["../../src/scripts/Material/baseMaterial.ts"],"sourcesContent":["import Material from \"./Material\";\nimport type { MaterialLike } from \"./Material\";\nimport type Style from \"../Style\";\nimport rectVertexShader from \"./shaders/base/rect/vertex.shader?raw\";\nimport rectFragmentShader from \"./shaders/base/rect/fragment.shader?raw\";\nimport polyVertexShader from \"./shaders/base/poly/vertex.shader?raw\";\nimport polyFragmentShader from \"./shaders/base/poly/fragment.shader?raw\";\n\ninterface BaseMaterialLike extends MaterialLike {\n readonly type: \"BaseMaterial\";\n}\n\n/** 矩形与多边形材质;按几何类型选择 Shader,四套显示参数均从 Style 获取。 */\nclass BaseMaterial extends Material implements BaseMaterialLike {\n /** 对象类型。 */\n public readonly type = \"BaseMaterial\" as const;\n /** @param style 共享样式,通常与对应 Geometry 使用同一对象 */\n public constructor(style?: Style) {\n super(style);\n this.rectVertexShader = rectVertexShader;\n this.rectFragmentShader = rectFragmentShader;\n this.polyVertexShader = polyVertexShader;\n this.polyFragmentShader = polyFragmentShader;\n this.updateKey();\n }\n}\nexport default BaseMaterial;\nexport type { BaseMaterialLike };\n"],"mappings":";;;;;;;AAaA,IAAM,eAAN,cAA2B,SAAqC;;CAE5D,OAAuB;;CAEvB,YAAmB,OAAe;EAC9B,MAAM,KAAK;EACX,KAAK,mBAAmB;EACxB,KAAK,qBAAqB;EAC1B,KAAK,mBAAmB;EACxB,KAAK,qBAAqB;EAC1B,KAAK,UAAU;CACnB;AACJ"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as BaseMaterial } from "./baseMaterial";
|
|
2
|
+
export { default as Material } from "./Material";
|
|
3
|
+
export type { BaseMaterialLike } from "./baseMaterial";
|
|
4
|
+
export type { BorderAlign, MaterialBuffersLike, MaterialChange, MaterialChangeKind, MaterialLike, MaterialSubscriber, PixelAligned, ShadersLike } from "./Material";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/scripts/Material/shaders/base/poly/fragment.shader?raw
|
|
2
|
+
var fragment_default = "struct MaterialUniform {\n solidColor: vec4f,\n sdfBorderColor: vec4f,\n edgeColor: vec4f,\n pointsColor: vec4f,\n wireframeColor: vec4f,\n // opacity、SDF width、align、pixelAligned。\n solid: vec4f,\n // opacity、实体 width、align、pixelAligned。\n edge: vec4f,\n // opacity、pixelAligned、补位、补位。\n points: vec4f,\n // opacity,其余为补位。\n wireframe: vec4f,\n // solid、wireframe、edge、points 开关。\n enabled: vec4f,\n // solid、edge、points 的纹理层号,普通 Mesh 均为 0。\n textureLayers: vec4f,\n};\n\nstruct RenderCameraUniform {\n zoom: f32,\n dpr: f32,\n _padding0: f32,\n _padding1: f32,\n};\n\nstruct GeometryUniform {\n width: f32,\n height: f32,\n radius: f32,\n _padding0: f32,\n};\n\n// 当前 Render 的 DPR 与 Camera 缩放参数。\n@group(0) @binding(3) var<uniform> renderCameraUniform: RenderCameraUniform;\n// 当前 Geometry 的包围盒宽高、保留项与边框宽度,供后续 SDF 计算使用。\n@group(0) @binding(4) var<uniform> geometryUniform: GeometryUniform;\n// 材质背景颜色,同时作为贴图颜色乘数。\n@group(1) @binding(0) var<storage, read> materialStyles: array<MaterialUniform>;\n// 材质当前使用的二维贴图。\n@group(1) @binding(1) var textureMap: texture_2d_array<f32>;\n// 控制贴图过滤和寻址方式。\n@group(1) @binding(2) var textureSampler: sampler;\n// 三种几何各自的贴图和 Sampler 同时绑定,不能在一次 DrawCall 中途切换绑定。\n@group(1) @binding(3) var edgeTexture: texture_2d_array<f32>;\n@group(1) @binding(4) var edgeSampler: sampler;\n@group(1) @binding(5) var pointsTexture: texture_2d_array<f32>;\n@group(1) @binding(6) var pointsSampler: sampler;\n\nstruct FragmentInput {\n @location(0) uv: vec2f,\n @location(1) localPosition: vec2f,\n @location(2) @interpolate(flat) vertexType: f32,\n @location(3) @interpolate(flat) instanceIndex: u32,\n};\n\n// 填充轮廓已由几何三角面决定。多边形边框走 vertexType=0.5,不使用矩形 SDF。\nfn ShadePoly(textureColor: vec4f, materialUniform: MaterialUniform) -> vec4f {\n var color = textureColor * materialUniform.solidColor;\n color.a *= materialUniform.solid.x;\n if (color.a <= 0.0) { discard; }\n return color;\n}\n\n@fragment\nfn main(input: FragmentInput) -> @location(0) vec4f {\n let materialUniform = materialStyles[input.instanceIndex];\n // 使用几何提供的 UV,允许非中心原点和自定义纹理坐标。\n let fillUv = input.uv;\n // vertexType 在三角面内不插值,但不同图元仍可能进入不同分支。\n // 导数在分支前统一求值,再使用 textureSampleGrad,避免非一致控制流中的隐式导数报错。\n let fillDx = dpdx(fillUv);\n let fillDy = dpdy(fillUv);\n let uvDx = dpdx(input.uv);\n let uvDy = dpdy(input.uv);\n if (input.vertexType == 0.0) {\n if (materialUniform.enabled.x == 0.0) { discard; }\n return ShadePoly(textureSampleGrad(textureMap, textureSampler, fillUv, i32(materialUniform.textureLayers.x), fillDx, fillDy), materialUniform);\n }\n var color: vec4f;\n var opacity: f32;\n if (input.vertexType == 0.5) {\n if (materialUniform.enabled.z == 0.0) { discard; }\n color = textureSampleGrad(edgeTexture, edgeSampler, input.uv, i32(materialUniform.textureLayers.y), uvDx, uvDy) * materialUniform.edgeColor;\n opacity = materialUniform.edge.x;\n } else {\n if (materialUniform.enabled.w == 0.0) { discard; }\n color = textureSampleGrad(pointsTexture, pointsSampler, input.uv, i32(materialUniform.textureLayers.z), uvDx, uvDy) * materialUniform.pointsColor;\n opacity = materialUniform.points.x;\n }\n let alpha = color.a * opacity;\n if (alpha <= 0.0) { discard; }\n return vec4f(color.rgb, alpha);\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { fragment_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=fragment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragment.js","names":[],"sources":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/scripts/Material/shaders/base/poly/vertex.shader?raw
|
|
2
|
+
var vertex_default = "// 深度来自队列层级,而不是提交顺序。矩阵和样式数组不因倒序绘制而搬动。\nstruct DrawDepth {\n base: u32,\n count: u32,\n reverse: u32,\n _padding: u32,\n};\n@group(0) @binding(5) var<uniform> drawDepth: DrawDepth;\n\nfn ResolveIndex(index: u32) -> u32 {\n return select(index, drawDepth.count - 1u - index, drawDepth.reverse != 0u);\n}\n\nfn GetDepth(index: u32) -> f32 {\n // 24 位整数除以 2^24,depth32float 可以精确表示;实际深度避开清空值 1。\n return 1.0 - f32(drawDepth.base + index + 1u) / 16777216.0;\n}\n\nstruct VertexInput {\n // WebGPU 自动提供实例编号;普通 Mesh 只绘制一次,因此为 0。\n @builtin(instance_index) instanceIndex: u32,\n @location(0) position: vec2f,\n @location(1) uv: vec2f,\n // 当前为二维轮廓外法线,先接入顶点管线供后续边框与特效使用。\n @location(2) normal: vec2f,\n @location(3) miterScale: f32,\n // 关键点所属中心,其他类型填零。\n @location(4) center: vec2f,\n @location(5) vertexType: f32,\n};\n\nstruct RenderCameraUniform {\n zoom: f32,\n dpr: f32,\n _padding0: f32,\n _padding1: f32,\n};\n\nstruct MaterialUniform {\n solidColor: vec4f,\n sdfBorderColor: vec4f,\n edgeColor: vec4f,\n pointsColor: vec4f,\n wireframeColor: vec4f,\n // opacity、SDF width、align、pixelAligned。\n solid: vec4f,\n // opacity、实体 width、align、pixelAligned。\n edge: vec4f,\n // opacity、pixelAligned、补位、补位。\n points: vec4f,\n // opacity,其余为补位。\n wireframe: vec4f,\n // solid、wireframe、edge、points 开关。\n enabled: vec4f,\n // solid、edge、points 的纹理层号,普通 Mesh 均为 0。\n textureLayers: vec4f,\n};\n\nstruct GeometryUniform {\n width: f32,\n height: f32,\n radius: f32,\n borderWidth: f32,\n};\n\n// 每个 Mesh 的世界矩阵。\n@group(0) @binding(0) var<storage, read> modelMatrices: array<mat3x3<f32>>;\n// 当前相机的视图矩阵。\n@group(0) @binding(1) var<uniform> viewMatrix: mat3x3<f32>;\n// 当前相机的正交投影矩阵。\n@group(0) @binding(2) var<uniform> orthogonalMatrix: mat3x3<f32>;\n// 当前 Render 的 DPR 与 Camera 缩放参数。\n@group(0) @binding(3) var<uniform> renderCameraUniform: RenderCameraUniform;\n// 当前 Geometry 的包围盒宽高、保留项与边框宽度。\n@group(0) @binding(4) var<uniform> geometryUniform: GeometryUniform;\n// BaseMaterial 实例样式,边框和点型可独立显示。\n@group(1) @binding(0) var<storage, read> materialStyles: array<MaterialUniform>;\n\nstruct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) uv: vec2f,\n @location(1) localPosition: vec2f,\n @location(2) @interpolate(flat) vertexType: f32,\n // 原样传给片段阶段,禁止在三角面内插值。\n @location(3) @interpolate(flat) instanceIndex: u32,\n};\n\n// 多边形实体已完成三角剖分,直接变换顶点,不按矩形宽高做 SDF 外扩。\nfn TransformSolid(input: VertexInput, resolvedIndex: u32, modelMatrix: mat3x3<f32>) -> VertexOutput {\n let localPosition = vec3f(input.position, 1.0);\n let clipPosition = orthogonalMatrix * viewMatrix * modelMatrix * localPosition;\n var output: VertexOutput;\n output.position = vec4f(clipPosition.xy, GetDepth(resolvedIndex), 1.0);\n output.instanceIndex = resolvedIndex;\n output.vertexType = 0.0;\n output.uv = input.uv;\n output.localPosition = input.position;\n return output;\n}\n\n// 宽边框使用逆转置变换法线,避免非等比缩放影响屏幕宽度。\nfn getViewNormal(localNormal: vec2f, modelViewMatrix: mat3x3<f32>) -> vec2f {\n let a = modelViewMatrix[0].x;\n let b = modelViewMatrix[0].y;\n let c = modelViewMatrix[1].x;\n let d = modelViewMatrix[1].y;\n let determinant = a * d - b * c;\n let determinantSign = select(-1.0, 1.0, determinant >= 0.0);\n let transformedNormal = vec2f(\n d * localNormal.x - b * localNormal.y,\n -c * localNormal.x + a * localNormal.y,\n ) * determinantSign;\n let normalLength = length(transformedNormal);\n let safeNormalLength = max(normalLength, 0.000001);\n\n return transformedNormal / safeNormalLength;\n}\n\n@vertex\nfn main(input: VertexInput) -> VertexOutput {\n // 保留入口 builtin 原值;用独立编号读取矩阵、样式并传给片段阶段。\n let resolvedIndex = ResolveIndex(input.instanceIndex);\n let modelMatrix = modelMatrices[resolvedIndex];\n let materialUniform = materialStyles[resolvedIndex];\n if (input.vertexType == 0.0 && materialUniform.enabled.x != 0.0) {\n return TransformSolid(input, resolvedIndex, modelMatrix);\n }\n\n var output: VertexOutput;\n output.instanceIndex = resolvedIndex;\n output.vertexType = input.vertexType;\n output.uv = input.uv;\n // 同一个三角面的三个顶点类型一致,关闭某类时让整面退化到裁剪区外。\n if ((input.vertexType == 0.0 && materialUniform.enabled.x == 0.0)\n || (input.vertexType == 0.5 && materialUniform.enabled.z == 0.0)\n || (input.vertexType == 1.0 && materialUniform.enabled.w == 0.0)) {\n output.position = vec4f(2.0, 2.0, 0.0, 1.0);\n return output;\n }\n\n let modelViewMatrix = viewMatrix * modelMatrix;\n let safeZoom = max(abs(renderCameraUniform.zoom), 0.000001);\n let pixelAligned = select(materialUniform.points.y, materialUniform.edge.w, input.vertexType == 0.5);\n let zoomScale = mix(1.0 / safeZoom, 1.0, pixelAligned);\n var viewPosition: vec3f;\n if (input.vertexType == 0.5) {\n viewPosition = modelViewMatrix * vec3f(input.position, 1.0);\n let viewNormal = getViewNormal(input.normal, modelViewMatrix);\n let sideOffset = mix(-(1.0 - materialUniform.edge.z), materialUniform.edge.z, input.uv.y);\n let offset = geometryUniform.borderWidth * input.miterScale * sideOffset * zoomScale;\n viewPosition.x += viewNormal.x * offset;\n viewPosition.y += viewNormal.y * offset;\n output.uv.x *= mix(safeZoom, 1.0, materialUniform.edge.w);\n } else {\n // 点型中心跟随模型,局部偏移独立缩放,保持屏幕朝向和原有像素单位。\n viewPosition = modelViewMatrix * vec3f(input.center, 1.0);\n let offset = (input.position - input.center) * zoomScale;\n viewPosition.x += offset.x;\n viewPosition.y += offset.y;\n }\n let clipPosition = orthogonalMatrix * viewPosition;\n output.position = vec4f(clipPosition.xy, GetDepth(resolvedIndex), 1.0);\n return output;\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { vertex_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=vertex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vertex.js","names":[],"sources":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/scripts/Material/shaders/base/rect/fragment.shader?raw
|
|
2
|
+
var fragment_default = "struct MaterialUniform {\n solidColor: vec4f,\n sdfBorderColor: vec4f,\n edgeColor: vec4f,\n pointsColor: vec4f,\n wireframeColor: vec4f,\n // opacity、SDF width、align、pixelAligned。\n solid: vec4f,\n // opacity、实体 width、align、pixelAligned。\n edge: vec4f,\n // opacity、pixelAligned、补位、补位。\n points: vec4f,\n // opacity,其余为补位。\n wireframe: vec4f,\n // solid、wireframe、edge、points 开关。\n enabled: vec4f,\n // solid、edge、points 的纹理层号,普通 Mesh 均为 0。\n textureLayers: vec4f,\n};\n\nstruct RenderCameraUniform {\n zoom: f32,\n dpr: f32,\n _padding0: f32,\n _padding1: f32,\n};\n\nstruct GeometryUniform {\n width: f32,\n height: f32,\n radius: f32,\n _padding0: f32,\n};\n\n// 当前 Render 的 DPR 与 Camera 缩放参数。\n@group(0) @binding(3) var<uniform> renderCameraUniform: RenderCameraUniform;\n// 当前 Geometry 的宽度、高度与圆角参数,供后续 SDF 计算使用。\n@group(0) @binding(4) var<uniform> geometryUniform: GeometryUniform;\n// 材质背景颜色,同时作为贴图颜色乘数。\n@group(1) @binding(0) var<storage, read> materialStyles: array<MaterialUniform>;\n// 材质当前使用的二维贴图。\n@group(1) @binding(1) var textureMap: texture_2d_array<f32>;\n// 控制贴图过滤和寻址方式。\n@group(1) @binding(2) var textureSampler: sampler;\n// 三种几何各自的贴图和 Sampler 同时绑定,不能在一次 DrawCall 中途切换绑定。\n@group(1) @binding(3) var edgeTexture: texture_2d_array<f32>;\n@group(1) @binding(4) var edgeSampler: sampler;\n@group(1) @binding(5) var pointsTexture: texture_2d_array<f32>;\n@group(1) @binding(6) var pointsSampler: sampler;\n\nstruct FragmentInput {\n @location(0) uv: vec2f,\n @location(1) localPosition: vec2f,\n @location(2) @interpolate(flat) vertexType: f32,\n @location(3) @interpolate(flat) instanceIndex: u32,\n};\n\n// 计算点到圆角矩形边界的有符号距离:内部为负,边界为 0,外部为正。\nfn RoundedRectDistance(position: vec2f, halfSize: vec2f, radius: f32) -> f32 {\n let safeRadius = clamp(radius, 0.0, min(halfSize.x, halfSize.y));\n let cornerOffset = abs(position) - (halfSize - vec2f(safeRadius));\n\n return length(max(cornerOffset, vec2f(0.0)))\n + min(max(cornerOffset.x, cornerOffset.y), 0.0)\n - safeRadius;\n}\n\nfn ShadeRect(input: FragmentInput, textureColor: vec4f, materialUniform: MaterialUniform) -> vec4f {\n let geometrySize = vec2f(geometryUniform.width, geometryUniform.height);\n let halfSize = geometrySize * 0.5;\n var outputColor = textureColor * materialUniform.solidColor;\n\n let safeZoom = max(abs(renderCameraUniform.zoom), 0.000001);\n let borderZoomScale = mix(1.0 / safeZoom, 1.0, materialUniform.solid.w);\n let borderWidth = materialUniform.solid.y * borderZoomScale;\n let outward = borderWidth * materialUniform.solid.z;\n let inward = borderWidth * (1.0 - materialUniform.solid.z);\n let originalRadius = clamp(geometryUniform.radius, 0.0, min(halfSize.x, halfSize.y));\n let outerHalfSize = halfSize + vec2f(outward);\n let innerHalfSize = max(halfSize - vec2f(inward), vec2f(0.0));\n // 原始直角保持直角;只有原矩形存在圆角时,内外半径才跟随边框偏移。\n let outerRadius = select(0.0, originalRadius + outward, originalRadius > 0.0);\n let innerRadius = select(0.0, max(originalRadius - inward, 0.0), originalRadius > 0.0);\n let outerDistance = RoundedRectDistance(input.localPosition, outerHalfSize, outerRadius);\n let innerDistance = RoundedRectDistance(input.localPosition, innerHalfSize, innerRadius);\n let hasInner = innerHalfSize.x > 0.0 && innerHalfSize.y > 0.0;\n\n if (outerDistance > 0.0) {\n discard;\n }\n\n if (materialUniform.solid.y > 0.0 && (!hasInner || innerDistance >= 0.0)) {\n outputColor = materialUniform.sdfBorderColor;\n }\n\n // opacity 作用于包含贴图在内的最终输出,而不是修改背景颜色本身。\n outputColor.a *= materialUniform.solid.x;\n // 透明空洞不写颜色或深度;半透明仍由材质混合与深度开关决定。\n if (outputColor.a <= 0.0) { discard; }\n return outputColor;\n}\n\n@fragment\nfn main(input: FragmentInput) -> @location(0) vec4f {\n let materialUniform = materialStyles[input.instanceIndex];\n let geometrySize = max(vec2f(geometryUniform.width, geometryUniform.height), vec2f(0.000001));\n let fillUv = input.localPosition / geometrySize + vec2f(0.5);\n // vertexType 在三角面内不插值,但不同图元仍可能进入不同分支。\n // 导数在分支前统一求值,再使用 textureSampleGrad,避免非一致控制流中的隐式导数报错。\n let fillDx = dpdx(fillUv);\n let fillDy = dpdy(fillUv);\n let uvDx = dpdx(input.uv);\n let uvDy = dpdy(input.uv);\n if (input.vertexType == 0.0) {\n if (materialUniform.enabled.x == 0.0) { discard; }\n return ShadeRect(input, textureSampleGrad(textureMap, textureSampler, fillUv, i32(materialUniform.textureLayers.x), fillDx, fillDy), materialUniform);\n }\n var color: vec4f;\n var opacity: f32;\n if (input.vertexType == 0.5) {\n if (materialUniform.enabled.z == 0.0) { discard; }\n color = textureSampleGrad(edgeTexture, edgeSampler, input.uv, i32(materialUniform.textureLayers.y), uvDx, uvDy) * materialUniform.edgeColor;\n opacity = materialUniform.edge.x;\n } else {\n if (materialUniform.enabled.w == 0.0) { discard; }\n color = textureSampleGrad(pointsTexture, pointsSampler, input.uv, i32(materialUniform.textureLayers.z), uvDx, uvDy) * materialUniform.pointsColor;\n opacity = materialUniform.points.x;\n }\n let alpha = color.a * opacity;\n if (alpha <= 0.0) { discard; }\n return vec4f(color.rgb, alpha);\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { fragment_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=fragment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragment.js","names":[],"sources":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/scripts/Material/shaders/base/rect/vertex.shader?raw
|
|
2
|
+
var vertex_default = "\n// 深度来自队列层级,而不是提交顺序。矩阵和样式数组不因倒序绘制而搬动。\nstruct DrawDepth {\n base: u32,\n count: u32,\n reverse: u32,\n _padding: u32,\n};\n@group(0) @binding(5) var<uniform> drawDepth: DrawDepth;\n\nfn ResolveIndex(index: u32) -> u32 {\n return select(index, drawDepth.count - 1u - index, drawDepth.reverse != 0u);\n}\n\nfn GetDepth(index: u32) -> f32 {\n // 24 位整数除以 2^24,depth32float 可以精确表示;实际深度避开清空值 1。\n return 1.0 - f32(drawDepth.base + index + 1u) / 16777216.0;\n}\n\nstruct VertexInput {\n // WebGPU 自动提供实例编号;普通 Mesh 只绘制一次,因此为 0。\n @builtin(instance_index) instanceIndex: u32,\n @location(0) position: vec2f,\n @location(1) uv: vec2f,\n // 当前为二维轮廓外法线,先接入顶点管线供后续边框与特效使用。\n @location(2) normal: vec2f,\n @location(3) miterScale: f32,\n // 关键点所属中心,其他类型填零。\n @location(4) center: vec2f,\n @location(5) vertexType: f32,\n};\n\nstruct RenderCameraUniform {\n zoom: f32,\n dpr: f32,\n _padding0: f32,\n _padding1: f32,\n};\n\nstruct MaterialUniform {\n solidColor: vec4f,\n sdfBorderColor: vec4f,\n edgeColor: vec4f,\n pointsColor: vec4f,\n wireframeColor: vec4f,\n // opacity、SDF width、align、pixelAligned。\n solid: vec4f,\n // opacity、实体 width、align、pixelAligned。\n edge: vec4f,\n // opacity、pixelAligned、补位、补位。\n points: vec4f,\n // opacity,其余为补位。\n wireframe: vec4f,\n // solid、wireframe、edge、points 开关。\n enabled: vec4f,\n // solid、edge、points 的纹理层号,普通 Mesh 均为 0。\n textureLayers: vec4f,\n};\n\nstruct GeometryUniform {\n width: f32,\n height: f32,\n radius: f32,\n borderWidth: f32,\n};\n\n// 每个 Mesh 的世界矩阵。\n@group(0) @binding(0) var<storage, read> modelMatrices: array<mat3x3<f32>>;\n// 当前相机的视图矩阵。\n@group(0) @binding(1) var<uniform> viewMatrix: mat3x3<f32>;\n// 当前相机的正交投影矩阵。\n@group(0) @binding(2) var<uniform> orthogonalMatrix: mat3x3<f32>;\n// 当前 Render 的 DPR 与 Camera 缩放参数。\n@group(0) @binding(3) var<uniform> renderCameraUniform: RenderCameraUniform;\n// 当前 Geometry 的宽度、高度与圆角参数。\n@group(0) @binding(4) var<uniform> geometryUniform: GeometryUniform;\n// BaseMaterial 参数,顶点阶段后续使用边框宽度和对齐方式扩大承载顶点。\n@group(1) @binding(0) var<storage, read> materialStyles: array<MaterialUniform>;\n\nstruct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) uv: vec2f,\n @location(1) localPosition: vec2f,\n @location(2) @interpolate(flat) vertexType: f32,\n // 原样传给片段阶段,禁止在三角面内插值。\n @location(3) @interpolate(flat) instanceIndex: u32,\n};\n\n// 实体面保留原有矩形 SDF 承载区域扩展逻辑。\nfn TransformSolid(input: VertexInput, resolvedIndex: u32, modelMatrix: mat3x3<f32>, materialUniform: MaterialUniform) -> VertexOutput {\n var output: VertexOutput;\n output.instanceIndex = resolvedIndex;\n // Camera 视口已使用乘过 DPR 的画布尺寸,borderWidth 直接按画布像素处理。\n // 除以 Zoom 后,边框在相机缩放时仍保持固定的屏幕像素宽度。\n let safeZoom = max(abs(renderCameraUniform.zoom), 0.000001);\n let borderZoomScale = mix(1.0 / safeZoom, 1.0, materialUniform.solid.w);\n let outward = materialUniform.solid.y\n * materialUniform.solid.z\n * borderZoomScale;\n let safeWidth = max(abs(geometryUniform.width), 0.000001);\n let safeHeight = max(abs(geometryUniform.height), 0.000001);\n let hasRectSize = geometryUniform.width > 0.0 && geometryUniform.height > 0.0;\n let scaleX = select(1.0, 1.0 + outward * 2.0 / safeWidth, hasRectSize);\n let scaleY = select(1.0, 1.0 + outward * 2.0 / safeHeight, hasRectSize);\n let borderScaleMatrix = mat3x3f(\n scaleX, 0.0, 0.0,\n 0.0, scaleY, 0.0,\n 0.0, 0.0, 1.0,\n );\n let localPosition = borderScaleMatrix * vec3f(input.position, 1.0);\n let worldPosition = modelMatrix * localPosition;\n let viewPosition = viewMatrix * worldPosition;\n let clipPosition = orthogonalMatrix * viewPosition;\n\n output.position = vec4f(clipPosition.xy, GetDepth(resolvedIndex), 1.0);\n output.uv = input.uv;\n // 片元阶段使用放大后的局部坐标计算原矩形内外边界。\n output.localPosition = localPosition.xy;\n\n return output;\n}\n\n// 宽边框使用逆转置变换法线,避免非等比缩放影响屏幕宽度。\nfn getViewNormal(localNormal: vec2f, modelViewMatrix: mat3x3<f32>) -> vec2f {\n let a = modelViewMatrix[0].x;\n let b = modelViewMatrix[0].y;\n let c = modelViewMatrix[1].x;\n let d = modelViewMatrix[1].y;\n let determinant = a * d - b * c;\n let determinantSign = select(-1.0, 1.0, determinant >= 0.0);\n let transformedNormal = vec2f(\n d * localNormal.x - b * localNormal.y,\n -c * localNormal.x + a * localNormal.y,\n ) * determinantSign;\n let normalLength = length(transformedNormal);\n let safeNormalLength = max(normalLength, 0.000001);\n\n return transformedNormal / safeNormalLength;\n}\n\n@vertex\nfn main(input: VertexInput) -> VertexOutput {\n // 保留入口 builtin 原值;用独立编号读取矩阵、样式并传给片段阶段。\n let resolvedIndex = ResolveIndex(input.instanceIndex);\n let modelMatrix = modelMatrices[resolvedIndex];\n let materialUniform = materialStyles[resolvedIndex];\n if (input.vertexType == 0.0 && materialUniform.enabled.x != 0.0) {\n return TransformSolid(input, resolvedIndex, modelMatrix, materialUniform);\n }\n\n var output: VertexOutput;\n output.instanceIndex = resolvedIndex;\n output.vertexType = input.vertexType;\n output.uv = input.uv;\n // 同一个三角面的三个顶点类型一致,关闭某类时让整面退化到裁剪区外。\n if ((input.vertexType == 0.0 && materialUniform.enabled.x == 0.0)\n || (input.vertexType == 0.5 && materialUniform.enabled.z == 0.0)\n || (input.vertexType == 1.0 && materialUniform.enabled.w == 0.0)) {\n output.position = vec4f(2.0, 2.0, 0.0, 1.0);\n return output;\n }\n\n let modelViewMatrix = viewMatrix * modelMatrix;\n let safeZoom = max(abs(renderCameraUniform.zoom), 0.000001);\n let pixelAligned = select(materialUniform.points.y, materialUniform.edge.w, input.vertexType == 0.5);\n let zoomScale = mix(1.0 / safeZoom, 1.0, pixelAligned);\n var viewPosition: vec3f;\n if (input.vertexType == 0.5) {\n viewPosition = modelViewMatrix * vec3f(input.position, 1.0);\n let viewNormal = getViewNormal(input.normal, modelViewMatrix);\n let sideOffset = mix(-(1.0 - materialUniform.edge.z), materialUniform.edge.z, input.uv.y);\n let offset = geometryUniform.borderWidth * input.miterScale * sideOffset * zoomScale;\n viewPosition.x += viewNormal.x * offset;\n viewPosition.y += viewNormal.y * offset;\n output.uv.x *= mix(safeZoom, 1.0, materialUniform.edge.w);\n } else {\n // 点型中心跟随模型,局部偏移独立缩放,保持屏幕朝向和原有像素单位。\n viewPosition = modelViewMatrix * vec3f(input.center, 1.0);\n let offset = (input.position - input.center) * zoomScale;\n viewPosition.x += offset.x;\n viewPosition.y += offset.y;\n }\n let clipPosition = orthogonalMatrix * viewPosition;\n output.position = vec4f(clipPosition.xy, GetDepth(resolvedIndex), 1.0);\n return output;\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { vertex_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=vertex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vertex.js","names":[],"sources":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/scripts/Material/shaders/line/fragment.shader?raw
|
|
2
|
+
var fragment_default = "struct MaterialUniform {\n solidColor: vec4f,\n sdfBorderColor: vec4f,\n edgeColor: vec4f,\n pointsColor: vec4f,\n wireframeColor: vec4f,\n // opacity、SDF width、align、pixelAligned。\n solid: vec4f,\n // opacity、实体 width、align、pixelAligned。\n edge: vec4f,\n // opacity、pixelAligned、补位、补位。\n points: vec4f,\n // opacity,其余为补位。\n wireframe: vec4f,\n // solid、wireframe、edge、points 开关。\n enabled: vec4f,\n // solid、edge、points 的纹理层号,普通 Mesh 均为 0。\n textureLayers: vec4f,\n};\n@group(1) @binding(0) var<storage, read> materialStyles: array<MaterialUniform>;\n\n@fragment\nfn main(@location(0) @interpolate(flat) instanceIndex: u32) -> @location(0) vec4f {\n let materialUniform = materialStyles[instanceIndex];\n if (materialUniform.enabled.y == 0.0) { discard; }\n let color = materialUniform.wireframeColor;\n let alpha = color.a * materialUniform.wireframe.x;\n if (alpha <= 0.0) { discard; }\n return vec4f(color.rgb, alpha);\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { fragment_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=fragment.js.map
|