@anov/gis-skills-cli 0.0.0-stage → 0.3.3
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/CHANGELOG.md +637 -0
- package/INSTALL.md +481 -0
- package/LICENSE +15 -0
- package/README.md +148 -2
- package/RELEASING.md +162 -0
- package/bin/anov-gis-skills.mjs +470 -0
- package/lib/mcp-config.mjs +273 -0
- package/package.json +43 -4
- package/skills/anovgis-analysis/SKILL.md +585 -0
- package/skills/anovgis-effects/SKILL.md +260 -0
- package/skills/anovgis-imagery-terrain/SKILL.md +505 -0
- package/skills/anovgis-layers/SKILL.md +627 -0
- package/skills/anovgis-materials/SKILL.md +635 -0
- package/skills/anovgis-models-3dtiles/SKILL.md +448 -0
- package/skills/anovgis-pitfalls/SKILL.md +561 -0
- package/skills/anovgis-popup-widget/SKILL.md +474 -0
- package/skills/anovgis-primitives/SKILL.md +482 -0
- package/skills/anovgis-vector-graphics/SKILL.md +602 -0
- package/skills/anovgis-viewer/SKILL.md +618 -0
- package/skills/using-anovgis/DEMO-MAP.md +64 -0
- package/skills/using-anovgis/DEMO-SKILL-MAP.md +248 -0
- package/skills/using-anovgis/DOMAINS.md +183 -0
- package/skills/using-anovgis/REFERENCE.md +114 -0
- package/skills/using-anovgis/SKILL.md +392 -0
- package/skills/using-anovgis/templates/README.md +154 -0
- package/skills/using-anovgis/templates/combo1-vue3-vite.md +295 -0
- package/skills/using-anovgis/templates/combo2-vue2-cli.md +119 -0
- package/skills/using-anovgis/templates/combo3-html-cdn.md +107 -0
- package/skills/using-anovgis/templates/combo4-vanilla-webpack.md +91 -0
- package/skills/using-anovgis/templates/wizard-profiles.md +105 -0
- package/vendor/cesiumjs-skills/LICENSE +201 -0
- package/vendor/cesiumjs-skills/NOTICE +18 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-3d-tiles/SKILL.md +465 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-camera/SKILL.md +500 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-core-utilities/SKILL.md +403 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/REFERENCE.md +397 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/SKILL.md +351 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/01-diffuse-tint.js +38 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/02-texture-swap.js +42 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/03-feature-id-tileset.js +29 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/04-translucent-override.js +37 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/05-vertex-displacement.js +49 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/06-metadata-ramp.js +34 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/07-voxel-shader.js +27 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/README.md +19 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/_sandcastle-template.html +9 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-entities/SKILL.md +389 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-imagery/SKILL.md +471 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-interaction/SKILL.md +423 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-materials-shaders/SKILL.md +292 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-models-particles/SKILL.md +423 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-primitives/SKILL.md +537 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-spatial-math/SKILL.md +358 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-terrain-environment/SKILL.md +401 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-time-properties/SKILL.md +353 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-viewer-setup/SKILL.md +434 -0
- package/vendor/cesiumjs-skills/skills/using-cesiumjs-skills/SKILL.md +35 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cesiumjs-custom-shader
|
|
3
|
+
description: "CustomShader authoring — vertexShaderText and fragmentShaderText against VertexInput, FragmentInput, FeatureIds, Metadata, czm_modelMaterial. Use when reading EXT_mesh_features or EXT_structural_metadata property textures/tables, vertex displacement, or shading VoxelPrimitive."
|
|
4
|
+
---
|
|
5
|
+
# CesiumJS CustomShader
|
|
6
|
+
|
|
7
|
+
Version baseline: CesiumJS 1.142. All imports use ES module style.
|
|
8
|
+
|
|
9
|
+
`CustomShader` injects user GLSL into the `Model` / `Cesium3DTileset` / `VoxelPrimitive` rendering pipeline. It exposes glTF attributes, feature IDs, and `EXT_structural_metadata` to per-vertex and per-fragment code, and returns values through the built-in `czm_modelVertexOutput` and `czm_modelMaterial` structs.
|
|
10
|
+
|
|
11
|
+
Use this skill for **writing the shader body**. Use:
|
|
12
|
+
- `cesiumjs-materials-shaders` — for Fabric `Material`, `ImageBasedLighting`, `PostProcessStage` (bloom, SSAO, FXAA, tonemapping).
|
|
13
|
+
- `cesiumjs-3d-tiles` — for declarative per-feature coloring via `Cesium3DTileStyle`, and for `VoxelPrimitive` setup/configuration.
|
|
14
|
+
- `cesiumjs-models-particles` — for `Model.fromGltfAsync`, animations, `ModelFeature.getProperty()`.
|
|
15
|
+
|
|
16
|
+
## Out of scope
|
|
17
|
+
|
|
18
|
+
- **Fabric `Material`** for entity polylines/polygons/walls — see `cesiumjs-materials-shaders`.
|
|
19
|
+
- **`PostProcessStage`** screen-space effects — see `cesiumjs-materials-shaders`.
|
|
20
|
+
- **`ImageBasedLighting`** — see `cesiumjs-materials-shaders`.
|
|
21
|
+
- **`Cesium3DTileStyle`** declarative JSON styling — see `cesiumjs-3d-tiles`. **Do not combine with CustomShader on the same tileset.**
|
|
22
|
+
- **Authoring `EXT_structural_metadata` / `EXT_mesh_features` in glTF** — tooling concern, not runtime.
|
|
23
|
+
|
|
24
|
+
## Minimal example
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { CustomShader, Model } from "cesium";
|
|
28
|
+
|
|
29
|
+
const shader = new CustomShader({
|
|
30
|
+
fragmentShaderText: `
|
|
31
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
32
|
+
material.diffuse = vec3(1.0, 0.0, 0.0);
|
|
33
|
+
material.alpha = 0.8;
|
|
34
|
+
}
|
|
35
|
+
`,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const model = await Model.fromGltfAsync({ url: "./aircraft.glb", customShader: shader });
|
|
39
|
+
viewer.scene.primitives.add(model);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Applying a CustomShader
|
|
43
|
+
|
|
44
|
+
**Model** — constructor option or mutable property:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
const model = await Model.fromGltfAsync({ url, customShader });
|
|
48
|
+
model.customShader = newShader; // hot-swap
|
|
49
|
+
model.customShader = undefined; // clear
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Cesium3DTileset** — constructor option or mutable property. Only `Model`-backed tile content is affected (not native I3S or other formats):
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
const tileset = await Cesium3DTileset.fromUrl(url, { customShader });
|
|
56
|
+
tileset.customShader = newShader;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
> Per the `Cesium3DTileset.customShader` JSDoc: *"Using custom shaders with a `Cesium3DTileStyle` may lead to undefined behavior."* The property is also marked `@experimental` — it uses 3D Tiles spec surface that is not final and may change without Cesium's standard deprecation policy.
|
|
60
|
+
|
|
61
|
+
**VoxelPrimitive** — fragment-only subset (see "VoxelPrimitive shader subset" below):
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const voxelPrimitive = new VoxelPrimitive({ provider, customShader });
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The engine calls `customShader.update(frameState)` automatically each frame. When finished with a CustomShader, call `customShader.destroy()` to release GPU texture resources owned by its `TextureManager`.
|
|
68
|
+
|
|
69
|
+
## Constructor reference
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
new CustomShader({
|
|
73
|
+
mode, // CustomShaderMode — default MODIFY_MATERIAL
|
|
74
|
+
lightingModel, // LightingModel — if omitted, model's default is preserved
|
|
75
|
+
translucencyMode, // CustomShaderTranslucencyMode — default INHERIT
|
|
76
|
+
uniforms, // { [name]: { type: UniformType, value } } — default {}
|
|
77
|
+
varyings, // { [name]: VaryingType } — default {}
|
|
78
|
+
vertexShaderText, // string or undefined
|
|
79
|
+
fragmentShaderText, // string or undefined
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Either `vertexShaderText` or `fragmentShaderText` is typically required. See `REFERENCE.md` for exhaustive enum values.
|
|
84
|
+
|
|
85
|
+
## Shader function signatures
|
|
86
|
+
|
|
87
|
+
The runtime calls these from generated pipeline stages. Parameter names are part of the contract — renaming them breaks the shader.
|
|
88
|
+
|
|
89
|
+
```glsl
|
|
90
|
+
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) { ... }
|
|
91
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) { ... }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Uniforms
|
|
95
|
+
|
|
96
|
+
Declare uniforms with `{ type, value }`. The type is a `UniformType` value; the JS value type must match (e.g. `VEC3` → `Cartesian3`). Uniforms are accessible in GLSL by their declared name.
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
import { CustomShader, UniformType, TextureUniform, Cartesian3 } from "cesium";
|
|
100
|
+
|
|
101
|
+
const shader = new CustomShader({
|
|
102
|
+
uniforms: {
|
|
103
|
+
u_tint: { type: UniformType.VEC3, value: new Cartesian3(1.0, 0.5, 0.2) },
|
|
104
|
+
u_time: { type: UniformType.FLOAT, value: 0.0 },
|
|
105
|
+
u_detail: { type: UniformType.SAMPLER_2D, value: new TextureUniform({ url: "./detail.png", repeat: true }) },
|
|
106
|
+
},
|
|
107
|
+
fragmentShaderText: `
|
|
108
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
109
|
+
vec3 d = texture(u_detail, fsInput.attributes.texCoord_0).rgb;
|
|
110
|
+
material.diffuse = mix(material.diffuse, u_tint, d.r + 0.1 * sin(u_time));
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Update at runtime. For Cartesian/Matrix values, setUniform clones into existing storage.
|
|
116
|
+
shader.setUniform("u_time", performance.now() / 1000);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`TextureUniform` accepts either `url` (string or `Resource`) or `typedArray` + `width` + `height` — **exactly one** (constructor throws otherwise). Other options: `repeat` (default `true`), `pixelFormat`, `pixelDatatype`, `minificationFilter`, `magnificationFilter`, `maximumAnisotropy`.
|
|
120
|
+
|
|
121
|
+
**`SAMPLER_CUBE` is declared on `UniformType` but rejected at construction** — throws `DeveloperError("CustomShader does not support samplerCube uniforms")`. Only `SAMPLER_2D` is supported.
|
|
122
|
+
|
|
123
|
+
## Varyings
|
|
124
|
+
|
|
125
|
+
Declared varyings are emitted as `out <type> <name>` in the vertex shader and `in <type> <name>` in the fragment shader. Write in vertex, read in fragment.
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
import { CustomShader, VaryingType } from "cesium";
|
|
129
|
+
|
|
130
|
+
const shader = new CustomShader({
|
|
131
|
+
varyings: { v_worldHeight: VaryingType.FLOAT },
|
|
132
|
+
vertexShaderText: `
|
|
133
|
+
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
|
|
134
|
+
v_worldHeight = vsInput.attributes.positionMC.z;
|
|
135
|
+
}
|
|
136
|
+
`,
|
|
137
|
+
fragmentShaderText: `
|
|
138
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
139
|
+
float t = clamp(v_worldHeight / 100.0, 0.0, 1.0);
|
|
140
|
+
material.diffuse = mix(vec3(0.2,0.4,0.8), vec3(1.0,0.8,0.2), t);
|
|
141
|
+
}
|
|
142
|
+
`,
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`VaryingType` supports `FLOAT`, `VEC2`–`VEC4`, `MAT2`–`MAT4`. No `INT`/`BOOL`/`SAMPLER` variants.
|
|
147
|
+
|
|
148
|
+
## Modes & lighting
|
|
149
|
+
|
|
150
|
+
**`CustomShaderMode`:**
|
|
151
|
+
- `MODIFY_MATERIAL` (default) — runs after the material stage, before lighting. `czm_modelMaterial` is populated with PBR/texture results; the shader refines them.
|
|
152
|
+
- `REPLACE_MATERIAL` — skips the material stage entirely. Shader sets every field procedurally. Cheaper when the source material is not needed.
|
|
153
|
+
|
|
154
|
+
**`LightingModel`:**
|
|
155
|
+
- `UNLIT` — skip lighting; `material.diffuse` becomes the final color (alpha still applied). Flat-shaded.
|
|
156
|
+
- `PBR` — physically-based with IBL when available.
|
|
157
|
+
- *Omitted* — preserves the model's default lighting. Omit unless overriding intentionally.
|
|
158
|
+
|
|
159
|
+
Pair `REPLACE_MATERIAL` + `UNLIT` for pure procedural flat shading (no material sampling, no lighting).
|
|
160
|
+
|
|
161
|
+
## Translucency
|
|
162
|
+
|
|
163
|
+
`CustomShaderTranslucencyMode` governs how alpha writes interact with the render pass:
|
|
164
|
+
|
|
165
|
+
- `INHERIT` (default) — alpha is only honored if the source material is translucent.
|
|
166
|
+
- `OPAQUE` — force opaque pass.
|
|
167
|
+
- `TRANSLUCENT` — force translucent pass.
|
|
168
|
+
|
|
169
|
+
**Pitfall:** writing `material.alpha` on an opaque model with `INHERIT` silently does nothing. Set `translucencyMode: CustomShaderTranslucencyMode.TRANSLUCENT` to make alpha writes effective. See `examples/04-translucent-override.js`.
|
|
170
|
+
|
|
171
|
+
## Attributes
|
|
172
|
+
|
|
173
|
+
`vsInput.attributes` and `fsInput.attributes` expose glTF vertex attributes. Names are case-sensitive and coordinate-space suffixes are required — the constructor rejects bare `position`/`normal`/`tangent`/`bitangent`.
|
|
174
|
+
|
|
175
|
+
Common fields (full table in `REFERENCE.md`):
|
|
176
|
+
- `positionMC` — model coords, valid in VS and FS
|
|
177
|
+
- `positionWC` — world (ECEF) coords, **fragment only**, low-precision
|
|
178
|
+
- `positionEC` — eye coords, **fragment only**
|
|
179
|
+
- `normalMC` / `normalEC` — vertex / fragment
|
|
180
|
+
- `tangentMC` / `tangentEC`, `bitangentMC` / `bitangentEC`
|
|
181
|
+
- `texCoord_N`, `color_N`, `joints_N`, `weights_N`
|
|
182
|
+
|
|
183
|
+
> **Coordinate-space validation.** The constructor scans shader text and throws `DeveloperError("<name> is not available in the <stage> shader. Did you mean <alt> instead?")` for invalid combinations. Examples: `positionEC` in vertex, `normalMC` in fragment.
|
|
184
|
+
|
|
185
|
+
Custom underscore-prefixed glTF attributes (`_FEATURE_ID_0`, `_SURFACE_TEMP`) are lowercased and un-prefixed: `fsInput.attributes.surface_temp`.
|
|
186
|
+
|
|
187
|
+
## FeatureIds
|
|
188
|
+
|
|
189
|
+
`vsInput.featureIds` / `fsInput.featureIds` unify three glTF sources into one struct:
|
|
190
|
+
|
|
191
|
+
- `featureId_N` — feature ID attributes and implicit attributes from `EXT_mesh_features` (N is the array index in the primitive's `featureIds` array). Also covers feature ID **textures**, which are fragment-shader-only.
|
|
192
|
+
- `instanceFeatureId_N` — per-instance feature IDs from `EXT_instance_features` + `EXT_mesh_gpu_instancing`.
|
|
193
|
+
- Named aliases — if glTF specifies `"label": "perVertex"`, then `featureIds.perVertex` is also available.
|
|
194
|
+
- Legacy 3D Tiles 1.0 `BATCH_ID` / `_BATCHID` → transparently renamed to `featureId_0`.
|
|
195
|
+
|
|
196
|
+
GLSL type is always `int`. WebGL 1 loses precision above 2^24.
|
|
197
|
+
|
|
198
|
+
```glsl
|
|
199
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
200
|
+
int id = fsInput.featureIds.featureId_0;
|
|
201
|
+
if (id == 0) material.diffuse = vec3(1.0, 0.2, 0.2); // roof
|
|
202
|
+
else if (id == 1) material.diffuse = vec3(0.2, 0.8, 0.2); // wall
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
See `examples/03-feature-id-tileset.js`.
|
|
207
|
+
|
|
208
|
+
## Metadata
|
|
209
|
+
|
|
210
|
+
`EXT_structural_metadata` surfaces three source types (all addressable from shaders as of 1.139):
|
|
211
|
+
|
|
212
|
+
- **Property attributes** — per-vertex. Vertex and fragment shaders.
|
|
213
|
+
- **Property textures** — per-texel. **Fragment only.**
|
|
214
|
+
- **Property tables** — per-feature, keyed by feature ID. **Added in 1.139 (#13124).**
|
|
215
|
+
|
|
216
|
+
```glsl
|
|
217
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
218
|
+
float t = fsInput.metadata.temperature;
|
|
219
|
+
float tMin = fsInput.metadataStatistics.temperature.minValue;
|
|
220
|
+
float tMax = fsInput.metadataStatistics.temperature.maxValue;
|
|
221
|
+
float v = (t - tMin) / (tMax - tMin);
|
|
222
|
+
material.diffuse = vec3(v, 0.0, 1.0 - v);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Property ID sanitization** (GLSL identifier rules):
|
|
227
|
+
- Non-alphanumeric runs → single `_` (`temperature ℃` → `temperature_`)
|
|
228
|
+
- Leading `gl_` stripped (`gl_custom` → `custom`)
|
|
229
|
+
- Leading digit prefixed with `_` (`12345` → `_12345`)
|
|
230
|
+
- Post-sanitization collisions → undefined behavior
|
|
231
|
+
|
|
232
|
+
**Sibling structs:** `metadataClass.<prop>.noData | defaultValue | minValue | maxValue` (class-schema bounds) and `metadataStatistics.<prop>.minValue | maxValue | mean | median | standardDeviation | variance | sum` (populated only when `tileset.json` declares `statistics`).
|
|
233
|
+
|
|
234
|
+
> **1.139 breaking change (#13135):** unsigned integer metadata is no longer cast to signed int. Assigning a `UINT` property to a GLSL `int` (`int x = fsInput.metadata.myUint;`) no longer compiles. Use the matching unsigned type.
|
|
235
|
+
|
|
236
|
+
**Public assets without `EXT_structural_metadata` on a `.glb` are scarce** — most real-world metadata lives on 3D Tiles. See `examples/06-metadata-ramp.js` (Cesium3DTileset target).
|
|
237
|
+
|
|
238
|
+
## czm_modelVertexOutput & czm_modelMaterial
|
|
239
|
+
|
|
240
|
+
**`czm_modelVertexOutput`** (vertex shader's `inout vsOutput`):
|
|
241
|
+
```glsl
|
|
242
|
+
struct czm_modelVertexOutput {
|
|
243
|
+
vec3 positionMC; // initialized to vsInput.attributes.positionMC
|
|
244
|
+
float pointSize; // overrides gl_PointSize and Cesium3DTileStyle point sizing
|
|
245
|
+
};
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
> **Gotcha:** mutating `positionMC` displaces vertices but does **not** update the primitive's bounding sphere. Heavily displaced vertices can be frustum-culled.
|
|
249
|
+
|
|
250
|
+
**`czm_modelMaterial`** (fragment shader's `inout material`). All colors are linear RGB. Conditional fields `specularWeight` / `anisotropic*` / `clearcoatFactor`... appear only when `KHR_materials_specular` / `_anisotropy` / `_clearcoat` is active on the primitive (see `REFERENCE.md` for the full `#ifdef`-guarded struct):
|
|
251
|
+
|
|
252
|
+
```glsl
|
|
253
|
+
struct czm_modelMaterial {
|
|
254
|
+
vec4 baseColor; vec3 diffuse; float alpha;
|
|
255
|
+
vec3 specular; float roughness;
|
|
256
|
+
vec3 normalEC; float occlusion; vec3 emissive;
|
|
257
|
+
// + conditional PBR extension fields
|
|
258
|
+
};
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Built-in `czm_*` automatic uniforms
|
|
262
|
+
|
|
263
|
+
Available without declaration. Most useful for CustomShader: `czm_frameNumber`, `czm_pi`, `czm_model`, `czm_view`, `czm_projection`, `czm_modelView`, `czm_normal`, `czm_lightDirectionEC`, `czm_sunDirectionWC`, `czm_eyeHeight`, `czm_sceneMode`, `czm_viewerPositionWC`, `czm_splitPosition`. Full catalog in `REFERENCE.md`.
|
|
264
|
+
|
|
265
|
+
## VoxelPrimitive shader subset
|
|
266
|
+
|
|
267
|
+
Fragment-only. Executes at every raymarching step along the view ray; the final pixel composites all steps. Supplying `vertexShaderText` is silently ignored.
|
|
268
|
+
|
|
269
|
+
Reduced struct availability:
|
|
270
|
+
- `fsInput.attributes` — only `positionEC` and `normalEC`.
|
|
271
|
+
- `fsInput.featureIds` — **not present**.
|
|
272
|
+
- `fsInput.metadata` — fully supported.
|
|
273
|
+
- `fsInput.metadataClass` — **not present**.
|
|
274
|
+
- `fsInput.metadataStatistics` — only `minValue` and `maxValue`.
|
|
275
|
+
|
|
276
|
+
Assigning `customShader = undefined` falls back to `VoxelPrimitive.DefaultCustomShader`. See `examples/07-voxel-shader.js`. For `VoxelPrimitive` setup (provider, shape, modelMatrix, nearestSampling), see `cesiumjs-3d-tiles`.
|
|
277
|
+
|
|
278
|
+
> **1.130 breaking change (#12636):** `fsInput.voxel.positionUv | positionShapeUv | positionLocal` were removed. Use `fsInput.attributes.positionEC` instead. `fsInput.voxel.surfaceNormal` → `fsInput.attributes.normalEC`.
|
|
279
|
+
> **1.142 fix (#13517):** the built-in default voxel shader handles common metadata types more robustly. Keep a custom shader only when you need explicit classification, coloring, filtering, or raymarch-step logic.
|
|
280
|
+
|
|
281
|
+
## Common patterns
|
|
282
|
+
|
|
283
|
+
| File | Target | Demonstrates |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| `examples/01-diffuse-tint.js` | Model | Time uniform driving `material.diffuse` |
|
|
286
|
+
| `examples/02-texture-swap.js` | Model | `TextureUniform`, `SAMPLER_2D`, `setUniform` |
|
|
287
|
+
| `examples/03-feature-id-tileset.js` | Cesium3DTileset | `fsInput.featureIds.featureId_0` classification coloring |
|
|
288
|
+
| `examples/04-translucent-override.js` | Model (opaque source) | `CustomShaderTranslucencyMode.TRANSLUCENT` |
|
|
289
|
+
| `examples/05-vertex-displacement.js` | Model | `vsOutput.positionMC` + normal offset |
|
|
290
|
+
| `examples/06-metadata-ramp.js` | Cesium3DTileset | `fsInput.metadata.<prop>` + `metadataStatistics` normalization |
|
|
291
|
+
| `examples/07-voxel-shader.js` | VoxelPrimitive | FS-only subset, per-voxel metadata |
|
|
292
|
+
|
|
293
|
+
## CesiumJS 1.139-1.142 version notes
|
|
294
|
+
|
|
295
|
+
Verbatim from upstream `CHANGES.md`:
|
|
296
|
+
|
|
297
|
+
**Breaking (1.139, #13135):**
|
|
298
|
+
> Custom Shaders that rely on metadata derived from the `EXT_structural_metadata` extension no longer cast unsigned integer metadata types to signed integers. Any existing custom shaders that assign UINT-type metadata to local integers (e.g. `int myMetadata = vsInput.metadata.myUintMetadata`) will no longer compile.
|
|
299
|
+
|
|
300
|
+
**Breaking (1.139, #13170):** Fixed precision of point cloud attributes when accessed in a custom fragment shader.
|
|
301
|
+
|
|
302
|
+
**Addition (1.139, #13124):** Access to metadata from property tables (previously only attributes/textures).
|
|
303
|
+
|
|
304
|
+
**Addition (1.139, #13135):** More metadata types via property textures.
|
|
305
|
+
|
|
306
|
+
**Fix (1.139, #13231):** Metadata variable regex extended to `metadataClass` and `metadataStatistics`.
|
|
307
|
+
|
|
308
|
+
**Fix (1.139.1, #13247):** NGA-GPM local extension + custom shader regression fix.
|
|
309
|
+
|
|
310
|
+
**Fix (1.140, #13258):** Custom shaders are no longer disabled for primitives with missing metadata when the metadata exists on the class definition.
|
|
311
|
+
|
|
312
|
+
**Addition (1.140, #13323):** Limited double-precision metadata support via downcasting.
|
|
313
|
+
|
|
314
|
+
**Fix (1.142, #13517):** Improved default voxel shader for common metadata types.
|
|
315
|
+
|
|
316
|
+
**Breaking (1.130, #12636):** Voxel `FragmentInput` restructured (see VoxelPrimitive section).
|
|
317
|
+
|
|
318
|
+
## Gotchas & pitfalls
|
|
319
|
+
|
|
320
|
+
1. **Coordinate-space suffix required.** `positionEC` in vertex, `normalMC` in fragment, or any bare `position`/`normal`/`tangent`/`bitangent` throws `DeveloperError` at construction with a suggested alternative.
|
|
321
|
+
2. **`positionMC` is valid in fragment shader** — despite the `MC` suffix. Only `normalMC`/`tangentMC`/`bitangentMC` are FS-rejected.
|
|
322
|
+
3. **Vertex displacement does not update bounding sphere.** Displaced vertices may be frustum-culled unexpectedly.
|
|
323
|
+
4. **`Cesium3DTileStyle` + CustomShader = undefined behavior.** Per upstream JSDoc. Choose one per tileset.
|
|
324
|
+
5. **`SAMPLER_CUBE` rejected at construction.** Use `SAMPLER_2D` only.
|
|
325
|
+
6. **Parameter-name contract.** `vsInput`, `vsOutput`, `fsInput`, `material` are scanned by regex — renaming breaks codegen.
|
|
326
|
+
7. **`TextureUniform` URL-vs-typedArray XOR.** Supplying both or neither throws. `typedArray` requires `width` + `height`.
|
|
327
|
+
8. **Alpha writes on opaque models are silently ignored under `INHERIT`.** Set `translucencyMode: TRANSLUCENT`.
|
|
328
|
+
9. **`customShader.destroy()` required.** Call when disposing of a shader that holds texture uniforms — otherwise its `TextureManager` leaks GPU resources.
|
|
329
|
+
10. **`vsOutput.pointSize` overrides `Cesium3DTileStyle` point sizing.** Don't set it unless intended.
|
|
330
|
+
11. **Metadata property IDs are sanitized.** Non-alphanumeric → `_`; leading `gl_` stripped; collisions are undefined behavior.
|
|
331
|
+
12. **UINT metadata now preserves signedness (1.139+, #13135).** Use `uint x = fsInput.metadata.prop;`, not `int x = ...`.
|
|
332
|
+
13. **`customShader` on `Cesium3DTileset` is `@experimental`.** May change without Cesium's standard deprecation policy.
|
|
333
|
+
14. **Tilesets: only `Model`-backed tile content uses CustomShader.** Native I3S and other formats are unaffected.
|
|
334
|
+
|
|
335
|
+
## Performance tips
|
|
336
|
+
|
|
337
|
+
- `REPLACE_MATERIAL` skips the material stage (textures, PBR inputs not sampled).
|
|
338
|
+
- `LightingModel.UNLIT` skips lighting math — combine with `REPLACE_MATERIAL` for flat procedural shading.
|
|
339
|
+
- Write to varyings in vertex rather than recomputing per-fragment.
|
|
340
|
+
- Avoid per-frame `setUniform` of `SAMPLER_2D` — it triggers async texture reload. Use `url` once and hold the reference.
|
|
341
|
+
- Call `customShader.destroy()` on teardown to release GPU texture resources.
|
|
342
|
+
|
|
343
|
+
## See also
|
|
344
|
+
|
|
345
|
+
- **`REFERENCE.md`** — full struct tables (`Attributes`, `FeatureIds`, `Metadata`/`Class`/`Statistics`), enum value tables, built-in `czm_*` uniform catalog, coordinate-space validation error reference.
|
|
346
|
+
- **`examples/`** — seven compile-tested snippets. `examples/_sandcastle-template.html` is the internal scaffold; `examples/README.md` documents the layout.
|
|
347
|
+
- **`cesiumjs-materials-shaders`** — Fabric `Material`, `ImageBasedLighting`, `PostProcessStage`.
|
|
348
|
+
- **`cesiumjs-3d-tiles`** — `Cesium3DTileStyle`, `Cesium3DTileset` setup, `VoxelPrimitive` instantiation.
|
|
349
|
+
- **`cesiumjs-models-particles`** — `Model.fromGltfAsync`, `ModelFeature.getProperty()`, animations.
|
|
350
|
+
- **`cesiumjs-primitives`** — Fabric on Appearances for classic Primitive geometry.
|
|
351
|
+
- **CesiumJS Custom Shader Guide** — `Documentation/CustomShaderGuide/README.md` on `CesiumGS/cesium` `main`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// 01-diffuse-tint.js — Time-driven diffuse tint on a Model.
|
|
2
|
+
// Asset: Sandcastle-provided SampleData/models/CesiumAir/Cesium_Air.glb.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
CustomShader,
|
|
6
|
+
UniformType,
|
|
7
|
+
Cartesian3,
|
|
8
|
+
Model,
|
|
9
|
+
HeadingPitchRoll,
|
|
10
|
+
Transforms,
|
|
11
|
+
} from "cesium";
|
|
12
|
+
|
|
13
|
+
const tintShader = new CustomShader({
|
|
14
|
+
uniforms: {
|
|
15
|
+
u_tint: { type: UniformType.VEC3, value: new Cartesian3(1.0, 0.5, 0.2) },
|
|
16
|
+
u_time: { type: UniformType.FLOAT, value: 0.0 },
|
|
17
|
+
},
|
|
18
|
+
fragmentShaderText: `
|
|
19
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
20
|
+
float pulse = 0.5 + 0.5 * sin(u_time);
|
|
21
|
+
material.diffuse = mix(material.diffuse, u_tint, pulse);
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const position = Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000);
|
|
27
|
+
const model = await Model.fromGltfAsync({
|
|
28
|
+
url: "../../SampleData/models/CesiumAir/Cesium_Air.glb",
|
|
29
|
+
modelMatrix: Transforms.headingPitchRollToFixedFrame(position, new HeadingPitchRoll()),
|
|
30
|
+
customShader: tintShader,
|
|
31
|
+
});
|
|
32
|
+
viewer.scene.primitives.add(model);
|
|
33
|
+
viewer.camera.flyToBoundingSphere(model.boundingSphere, { duration: 0 });
|
|
34
|
+
|
|
35
|
+
const start = performance.now();
|
|
36
|
+
viewer.scene.postUpdate.addEventListener(() => {
|
|
37
|
+
tintShader.setUniform("u_time", (performance.now() - start) / 1000.0);
|
|
38
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// 02-texture-swap.js — Animated texture uniform via SAMPLER_2D + TextureUniform.
|
|
2
|
+
// Assets: Sandcastle SampleData — CesiumAir + cesium_stripes.png.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
CustomShader,
|
|
6
|
+
UniformType,
|
|
7
|
+
TextureUniform,
|
|
8
|
+
Model,
|
|
9
|
+
Cartesian3,
|
|
10
|
+
HeadingPitchRoll,
|
|
11
|
+
Transforms,
|
|
12
|
+
} from "cesium";
|
|
13
|
+
|
|
14
|
+
const stripeShader = new CustomShader({
|
|
15
|
+
uniforms: {
|
|
16
|
+
u_time: { type: UniformType.FLOAT, value: 0.0 },
|
|
17
|
+
u_stripes: {
|
|
18
|
+
type: UniformType.SAMPLER_2D,
|
|
19
|
+
value: new TextureUniform({ url: "../../SampleData/cesium_stripes.png", repeat: true }),
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
fragmentShaderText: `
|
|
23
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
24
|
+
vec2 uv = fsInput.attributes.texCoord_0 + vec2(0.1 * u_time, 0.0);
|
|
25
|
+
material.diffuse = texture(u_stripes, uv).rgb;
|
|
26
|
+
}
|
|
27
|
+
`,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const position = Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000);
|
|
31
|
+
const model = await Model.fromGltfAsync({
|
|
32
|
+
url: "../../SampleData/models/CesiumAir/Cesium_Air.glb",
|
|
33
|
+
modelMatrix: Transforms.headingPitchRollToFixedFrame(position, new HeadingPitchRoll()),
|
|
34
|
+
customShader: stripeShader,
|
|
35
|
+
});
|
|
36
|
+
viewer.scene.primitives.add(model);
|
|
37
|
+
viewer.camera.flyToBoundingSphere(model.boundingSphere, { duration: 0 });
|
|
38
|
+
|
|
39
|
+
const start = performance.now();
|
|
40
|
+
viewer.scene.postUpdate.addEventListener(() => {
|
|
41
|
+
stripeShader.setUniform("u_time", (performance.now() - start) / 1000.0);
|
|
42
|
+
});
|
package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/03-feature-id-tileset.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// 03-feature-id-tileset.js — Classification coloring by feature ID on a 3D Tileset.
|
|
2
|
+
// Asset: CesiumGS/3d-tiles-samples — FeatureIdAttributeAndPropertyTable (real EXT_mesh_features).
|
|
3
|
+
// https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/glTF/EXT_structural_metadata/FeatureIdAttributeAndPropertyTable/tileset.json
|
|
4
|
+
// Fallback: CesiumGS/cesium — BatchedWithBatchTable (legacy 3D Tiles 1.0 BATCH_ID, remaps to featureId_0).
|
|
5
|
+
|
|
6
|
+
import { CustomShader, LightingModel, Cesium3DTileset } from "cesium";
|
|
7
|
+
|
|
8
|
+
const classifyShader = new CustomShader({
|
|
9
|
+
lightingModel: LightingModel.UNLIT,
|
|
10
|
+
fragmentShaderText: `
|
|
11
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
12
|
+
int id = fsInput.featureIds.featureId_0;
|
|
13
|
+
if (id == 0) {
|
|
14
|
+
material.diffuse = vec3(1.0, 0.3, 0.3); // class 0 — red
|
|
15
|
+
} else if (id == 1) {
|
|
16
|
+
material.diffuse = vec3(0.3, 1.0, 0.3); // class 1 — green
|
|
17
|
+
} else {
|
|
18
|
+
material.diffuse = vec3(0.3, 0.3, 1.0); // other — blue
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const tileset = await Cesium3DTileset.fromUrl(
|
|
25
|
+
"https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/glTF/EXT_structural_metadata/FeatureIdAttributeAndPropertyTable/tileset.json",
|
|
26
|
+
{ customShader: classifyShader },
|
|
27
|
+
);
|
|
28
|
+
viewer.scene.primitives.add(tileset);
|
|
29
|
+
viewer.zoomTo(tileset);
|
package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/04-translucent-override.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// 04-translucent-override.js — Force translucent pass on an opaque source model.
|
|
2
|
+
// Without translucencyMode: TRANSLUCENT the material.alpha write is silently ignored
|
|
3
|
+
// (INHERIT honors the source material, which here is opaque).
|
|
4
|
+
// Asset: Sandcastle SampleData CesiumAir.
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
CustomShader,
|
|
8
|
+
CustomShaderTranslucencyMode,
|
|
9
|
+
UniformType,
|
|
10
|
+
Model,
|
|
11
|
+
Cartesian3,
|
|
12
|
+
HeadingPitchRoll,
|
|
13
|
+
Transforms,
|
|
14
|
+
} from "cesium";
|
|
15
|
+
|
|
16
|
+
const xrayShader = new CustomShader({
|
|
17
|
+
translucencyMode: CustomShaderTranslucencyMode.TRANSLUCENT,
|
|
18
|
+
uniforms: {
|
|
19
|
+
u_alpha: { type: UniformType.FLOAT, value: 0.35 },
|
|
20
|
+
},
|
|
21
|
+
fragmentShaderText: `
|
|
22
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
23
|
+
// Cool-tint x-ray look
|
|
24
|
+
material.diffuse = mix(material.diffuse, vec3(0.4, 0.7, 1.0), 0.6);
|
|
25
|
+
material.alpha = u_alpha;
|
|
26
|
+
}
|
|
27
|
+
`,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const position = Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000);
|
|
31
|
+
const model = await Model.fromGltfAsync({
|
|
32
|
+
url: "../../SampleData/models/CesiumAir/Cesium_Air.glb",
|
|
33
|
+
modelMatrix: Transforms.headingPitchRollToFixedFrame(position, new HeadingPitchRoll()),
|
|
34
|
+
customShader: xrayShader,
|
|
35
|
+
});
|
|
36
|
+
viewer.scene.primitives.add(model);
|
|
37
|
+
viewer.camera.flyToBoundingSphere(model.boundingSphere, { duration: 0 });
|
package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/05-vertex-displacement.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// 05-vertex-displacement.js — Normal-offset vertex displacement with a varying.
|
|
2
|
+
// Warning: vsOutput.positionMC writes do NOT update the primitive bounding sphere —
|
|
3
|
+
// heavily displaced meshes can be frustum-culled unexpectedly. Use modest amplitudes.
|
|
4
|
+
// Asset: Sandcastle SampleData CesiumAir.
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
CustomShader,
|
|
8
|
+
UniformType,
|
|
9
|
+
VaryingType,
|
|
10
|
+
Model,
|
|
11
|
+
Cartesian3,
|
|
12
|
+
HeadingPitchRoll,
|
|
13
|
+
Transforms,
|
|
14
|
+
} from "cesium";
|
|
15
|
+
|
|
16
|
+
const waveShader = new CustomShader({
|
|
17
|
+
uniforms: {
|
|
18
|
+
u_amp: { type: UniformType.FLOAT, value: 0.5 },
|
|
19
|
+
u_time: { type: UniformType.FLOAT, value: 0.0 },
|
|
20
|
+
},
|
|
21
|
+
varyings: { v_disp: VaryingType.FLOAT },
|
|
22
|
+
vertexShaderText: `
|
|
23
|
+
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
|
|
24
|
+
float d = sin(vsInput.attributes.positionMC.x * 0.5 + u_time * 2.0) * u_amp;
|
|
25
|
+
vsOutput.positionMC += vsInput.attributes.normalMC * d;
|
|
26
|
+
v_disp = d;
|
|
27
|
+
}
|
|
28
|
+
`,
|
|
29
|
+
fragmentShaderText: `
|
|
30
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
31
|
+
float t = clamp(v_disp / 1.0 + 0.5, 0.0, 1.0);
|
|
32
|
+
material.diffuse = mix(vec3(0.2, 0.3, 1.0), vec3(1.0, 0.3, 0.2), t);
|
|
33
|
+
}
|
|
34
|
+
`,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const position = Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000);
|
|
38
|
+
const model = await Model.fromGltfAsync({
|
|
39
|
+
url: "../../SampleData/models/CesiumAir/Cesium_Air.glb",
|
|
40
|
+
modelMatrix: Transforms.headingPitchRollToFixedFrame(position, new HeadingPitchRoll()),
|
|
41
|
+
customShader: waveShader,
|
|
42
|
+
});
|
|
43
|
+
viewer.scene.primitives.add(model);
|
|
44
|
+
viewer.camera.flyToBoundingSphere(model.boundingSphere, { duration: 0 });
|
|
45
|
+
|
|
46
|
+
const start = performance.now();
|
|
47
|
+
viewer.scene.postUpdate.addEventListener(() => {
|
|
48
|
+
waveShader.setUniform("u_time", (performance.now() - start) / 1000.0);
|
|
49
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// 06-metadata-ramp.js — Fragment-shader color ramp driven by EXT_structural_metadata
|
|
2
|
+
// property texture (per-texel). The `insulation` property is UINT8 with normalized:true,
|
|
3
|
+
// so it arrives in GLSL as a float in [0, 1] — map directly through a color ramp.
|
|
4
|
+
// Asset: CesiumGS/3d-tiles-samples — SimplePropertyTexture (EXT_structural_metadata
|
|
5
|
+
// with three UINT8 scalar properties via propertyTextures).
|
|
6
|
+
// https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/glTF/EXT_structural_metadata/SimplePropertyTexture/tileset.json
|
|
7
|
+
//
|
|
8
|
+
// Note on assets: public .glb files carrying EXT_structural_metadata are scarce. The skill
|
|
9
|
+
// documents this example on a Cesium3DTileset only; the shader surface is identical on Model.
|
|
10
|
+
//
|
|
11
|
+
// Note on types: after 1.139 (#13135), unsigned metadata preserves its signedness — for
|
|
12
|
+
// non-normalized UINT8 properties such as `insideTemperature` you would write
|
|
13
|
+
// `uint t = fsInput.metadata.insideTemperature; float f = float(t) / 255.0;`. `insulation`
|
|
14
|
+
// is declared `normalized: true`, so the runtime delivers a float in [0, 1] directly.
|
|
15
|
+
|
|
16
|
+
import { CustomShader, LightingModel, Cesium3DTileset } from "cesium";
|
|
17
|
+
|
|
18
|
+
const rampShader = new CustomShader({
|
|
19
|
+
lightingModel: LightingModel.UNLIT,
|
|
20
|
+
fragmentShaderText: `
|
|
21
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
22
|
+
float t = fsInput.metadata.insulation; // normalized UINT8 → float in [0, 1]
|
|
23
|
+
// cool → warm ramp: thin insulation (0) is cold/blue, thick (1) is warm/red
|
|
24
|
+
material.diffuse = mix(vec3(0.1, 0.3, 0.9), vec3(1.0, 0.3, 0.1), t);
|
|
25
|
+
}
|
|
26
|
+
`,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const tileset = await Cesium3DTileset.fromUrl(
|
|
30
|
+
"https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/glTF/EXT_structural_metadata/SimplePropertyTexture/tileset.json",
|
|
31
|
+
{ customShader: rampShader },
|
|
32
|
+
);
|
|
33
|
+
viewer.scene.primitives.add(tileset);
|
|
34
|
+
viewer.zoomTo(tileset);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// 07-voxel-shader.js — Fragment-only custom shader on a VoxelPrimitive.
|
|
2
|
+
// Reduced struct availability: attributes.positionEC and attributes.normalEC only,
|
|
3
|
+
// no FeatureIds, no MetadataClass, metadataStatistics has only min/max.
|
|
4
|
+
// Asset: CesiumGS/cesium Specs — VoxelBox3DTiles (SCALAR FLOAT32 property `a`).
|
|
5
|
+
// https://raw.githubusercontent.com/CesiumGS/cesium/main/Specs/Data/Cesium3DTiles/Voxel/VoxelBox3DTiles/tileset.json
|
|
6
|
+
|
|
7
|
+
import { CustomShader, Cesium3DTilesVoxelProvider, VoxelPrimitive } from "cesium";
|
|
8
|
+
|
|
9
|
+
const voxelShader = new CustomShader({
|
|
10
|
+
fragmentShaderText: `
|
|
11
|
+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
|
|
12
|
+
float v = fsInput.metadata.a;
|
|
13
|
+
// cool → warm gradient, semi-transparent so raymarching accumulates
|
|
14
|
+
material.diffuse = mix(vec3(0.1, 0.2, 0.8), vec3(1.0, 0.6, 0.1), v);
|
|
15
|
+
material.alpha = 0.3 * v;
|
|
16
|
+
}
|
|
17
|
+
`,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const provider = await Cesium3DTilesVoxelProvider.fromUrl(
|
|
21
|
+
"https://raw.githubusercontent.com/CesiumGS/cesium/main/Specs/Data/Cesium3DTiles/Voxel/VoxelBox3DTiles/tileset.json",
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const voxelPrimitive = new VoxelPrimitive({ provider, customShader: voxelShader });
|
|
25
|
+
viewer.scene.primitives.add(voxelPrimitive);
|
|
26
|
+
voxelPrimitive.nearestSampling = true;
|
|
27
|
+
viewer.camera.flyToBoundingSphere(voxelPrimitive.boundingSphere, { duration: 0 });
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Custom Shader Examples
|
|
2
|
+
|
|
3
|
+
Compile-tested snippets referenced from `../SKILL.md`.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- `0N-<name>.js` — the **user-facing snippet**. Imports from `cesium`, creates a `CustomShader`, and shows the attachment call. No viewer boilerplate. These are what the skill links to.
|
|
8
|
+
- `_sandcastle-template.html` — internal scaffold used **only during compile-testing**. Each `.js` snippet is injected into this template and opened in Sandcastle to verify it renders without GLSL errors. Underscore prefix marks it as non-product tooling.
|
|
9
|
+
|
|
10
|
+
## Assets
|
|
11
|
+
|
|
12
|
+
All assets are fetched from public `raw.githubusercontent.com` URLs — no Ion token required. The specific dataset each example uses is documented in the snippet's opening comment.
|
|
13
|
+
|
|
14
|
+
## Running locally
|
|
15
|
+
|
|
16
|
+
1. Open `https://sandcastle.cesium.com/`.
|
|
17
|
+
2. Paste `_sandcastle-template.html` into the HTML tab.
|
|
18
|
+
3. Paste one of the `0N-*.js` snippets into the JS tab inside the marked `// <-- snippet -->` region.
|
|
19
|
+
4. Click **Run**.
|
package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/_sandcastle-template.html
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<!-- Sandcastle scaffold for compile-testing Custom Shader snippets.
|
|
2
|
+
Open https://sandcastle.cesium.com/, paste this into the HTML tab,
|
|
3
|
+
and paste one of the 0N-*.js snippets into the marked region in the JS tab. -->
|
|
4
|
+
<style>
|
|
5
|
+
@import url(../templates/bucket.css);
|
|
6
|
+
</style>
|
|
7
|
+
<div id="cesiumContainer" class="fullSize"></div>
|
|
8
|
+
<div id="loadingOverlay"><h1>Loading...</h1></div>
|
|
9
|
+
<div id="toolbar"></div>
|