cesiumjs-materials-shaders について
CesiumJSでマテリアル、シェーダー、ポストプロセス効果を作成する開発者向けのガイドです。Fabricマテリアル、カスタムシェーダー、イメージベース照明、スクリーンスペース処理を説明します。
主な機能
- 01Primitive向けFabricマテリアルの作成
- 02CustomShaderによるGLSLの挿入
- 03イメージベース照明の設定
- 04組み込みまたは独自のポストプロセス追加
活用シーン
- 01Primitiveの表面への模様やテクスチャ適用
- 02GLSLによるモデルやタイルセットの描画変更
- 03ブルーム、ぼかし、シルエット効果の追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cesiumgs/ cesiumjs-skills --skill cesiumjs-materials-shadersインストール後、Claude Code で/cesiumjs-materials-shadersを入力して読み込まれたか確認します。
詳細
CesiumJS のマテリアル、シェーダー、ポストプロセス
バージョンの基準:CesiumJS 1.144(2026 年 8 月)。すべてのインポートで ES モジュール形式を使用します。
マテリアルシステム(Fabric JSON)
Material は、Fabric と呼ばれる JSON スキーマを通じて プリミティブ の表面の外観を定義します。マテリアルは GLSL にコンパイルされ、MaterialAppearance または PolylineMaterialAppearance で使用されます。
マテリアルの画像の読み込み中、CesiumJS はプレースホルダーテクスチャを描画します。デフォルトでは白です。1.144 以降、静的な Texture.defaultColor を設定すると、マテリアルの構築中に白く点滅するのを防ぐため、プレースホルダーの色を変更できます。Texture クラスは実行時には公開されていますが、公開されている TypeScript 定義には含まれていないため、TypeScript の呼び出し側ではキャストが必要です。
組み込みのマテリアルタイプ
表面: Color(色)、Image(画像、繰り返し)、DiffuseMap、AlphaMap、SpecularMap、EmissionMap(画像、チャンネル、繰り返し)、BumpMap、NormalMap(画像、チャンネル、強度、繰り返し)。
パターン: Grid(色、セルのアルファ値、線の数、線の太さ)、Stripe(偶数色、奇数色、繰り返し)、Checkerboard(明色、暗色、繰り返し)、Dot(明色、暗色、繰り返し)。
エフェクト: Water(基本水色、ブレンド色、法線マップ、頻度、アニメーション速度、振幅)、RimLighting(色、リム色、幅)、Fade(フェードイン色、フェードアウト色、最大距離)。
地形: ElevationContour(色、間隔、幅)、ElevationRamp(画像、最小高度、最大高度)。
ポリライン: PolylineArrow(色)、PolylineDash(色、間隔の色、ダッシュの長さ、ダッシュパターン)、PolylineGlow(色、発光の強さ、テーパーの強さ)、PolylineOutline(色、アウトライン色、アウトライン幅)。
マテリアルの作成
import { Material, Color, Cartesian2 } from "cesium";
// Shorthand with fromType (preferred for built-in types)
const colorMat = Material.fromType("Color", { color: new Color(1.0, 0.0, 0.0, 0.5) });
// Full Fabric notation
const gridMat = new Material({
fabric: {
type: "Grid",
uniforms: { color: Color.GREEN, cellAlpha: 0.1, lineCount: new Cartesian2(8, 8) },
},
});
// Async loading -- awaits textures before first frame, no flicker
const imageMat = await Material.fromTypeAsync("Image", { image: "./textures/facade.png" });
Fabric マテリアルはプリミティブの外観に使用します。WaterMaterialProperty など、存在しないエンティティコンストラクターは使用しないでください。組み込みの水マテリアルを使うには、Material.fromType("Water", ...) を作成し、Primitive の MaterialAppearance に適用します。
GLSL ソースを使ったカスタム Fabric
インライン GLSL には source を使用します。uniforms で宣言したユニフォームは、シェーダー内で名前を指定して利用できます。
import { Material, Color } from "cesium";
const pulseMaterial = new Material({
fabric: {
uniforms: { color: Color.CYAN, speed: 2.0 },
source: `czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
float pulse = sin(czm_frameNumber * speed * 0.01) * 0.5 + 0.5;
material.diffuse = color.rgb;
material.alpha = color.a * pulse;
return material;
}`,
},
translucent: true,
});
プリミティブへのマテリアルの適用
import { Primitive, GeometryInstance, RectangleGeometry, Rectangle,
MaterialAppearance, Material, Color, Cartesian2 } from "cesium";
viewer.scene.primitives.add(new Primitive({
geometryInstances: new GeometryInstance({
geometry: new RectangleGeometry({ rectangle: Rectangle.fromDegrees(-100, 30, -90, 40) }),
}),
appearance: new MaterialAppearance({
material: Material.fromType("Checkerboard", {
lightColor: Color.WHITE, darkColor: Color.BLACK, repeat: new Cartesian2(4, 4),
}),
}),
}));
サブマテリアルの合成(Fabric の materials + components)
import { Material, Color } from "cesium";
const compositeMat = new Material({ fabric: {
materials: {
gridMaterial: { type: "Grid" },
colorMaterial: { type: "Color", uniforms: { color: Color.BLUE } },
},
components: {
diffuse: "gridMaterial.diffuse + 0.2 * colorMaterial.diffuse",
alpha: "min(gridMaterial.alpha, colorMaterial.alpha)",
},
}});
CustomShader
CustomShader は、頂点属性、フィーチャー ID、EXT_structural_metadata にアクセスしながら、ユーザーの GLSL を Model、Cesium3DTileset、VoxelPrimitive の描画に挿入します。
シェーダーの作成方法(構造体のリファレンス、メタデータへのアクセス、フィーチャー ID、ボクセルのサブセット、1.139 の破壊的変更、7 つの実例)については、cesiumjs-custom-shader スキルを参照してください。 CustomShader の統合範囲はこのスキルが担当し、作成方法の詳細はそちらで説明しています。
最小限の例:
import { CustomShader, Model } from "cesium";
const shader = new CustomShader({
fragmentShaderText: `
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
material.diffuse = vec3(1.0, 0.5, 0.0);
}
`,
});
const model = await Model.fromGltfAsync({ url: "./building.glb", customShader: shader });
viewer.scene.primitives.add(model);
ImageBasedLighting
Model と Cesium3DTileset の PBR イメージベースドライティングを制御します。imageBasedLightingFactor(Cartesian2)は、拡散反射(x)と鏡面反射(y)を 0 から 1 の範囲でスケーリングします。拡散反射には sphericalHarmonicCoefficients(Cartesian3 の配列 9 個、L0~L2)を使用します。鏡面反射には specularEnvironmentMaps(KTX2 キューブマップの URL)を使用します。
import { ImageBasedLighting, Model, Cartesian2, Cartesian3 } from "cesium";
const coefficients = [ // 9 Cartesian3 values for L0..L2 bands
new Cartesian3(0.35, 0.35, 0.38), new Cartesian3(0.11, 0.11, 0.11),
new Cartesian3(0.04, 0.04, 0.04), new Cartesian3(-0.08, -0.08, -0.08),
new Cartesian3(-0.02, -0.02, -0.02), new Cartesian3(0.04, 0.04, 0.04),
new Cartesian3(-0.06, -0.06, -0.06), new Cartesian3(0.01, 0.01, 0.01),
new Cartesian3(-0.03, -0.03, -0.03),
];
const ibl = new ImageBasedLighting({
imageBasedLightingFactor: new Cartesian2(1.0, 1.0),
sphericalHarmonicCoefficients: coefficients,
specularEnvironmentMaps: "./environment/specular.ktx2",
});
const model = await Model.fromGltfAsync({ url: "./helmet.glb", imageBasedLighting: ibl });
viewer.scene.primitives.add(model);
// Disable: model.imageBasedLighting.imageBasedLightingFactor = new Cartesian2(0.0, 0.0);
ポストプロセス
viewer.scene.postProcessStages(PostProcessStageCollection)を通じたスクリーン空間のパイプラインです。ステージは順番に実行され、それぞれが colorTexture と depthTexture を読み取ります。
組み込みエフェクト(PostProcessStageLibrary)
すべてのファクトリー関数は、viewer.scene.postProcessStages.add()を介して追加する必要があるステージコンポジットを返します。
createBloomStage()(contrast、brightness、glowOnly、delta、sigma、stepSize)、createBlurStage()(delta、sigma、stepSize)、createDepthOfFieldStage()(focalDistance、delta、sigma、stepSize)、createEdgeDetectionStage()(color、length)、createSilhouetteStage([edgeStage])(エッジ検出ステージをシルエットコンポジットでラップします)、createBlackAndWhiteStage()(gradations)、createBrightnessStage()(brightness)、createNightVisionStage()、createLensFlareStage()(intensity、distortion、ghostDispersal、haloWidth)。
ファクトリーを使ったブルーム(postProcessStages.addで個別のブルームインスタンスを追加する場合に使用します):
import { PostProcessStageLibrary } from "cesium";
const bloom = viewer.scene.postProcessStages.add(
PostProcessStageLibrary.createBloomStage()
);
bloom.enabled = true;
bloom.uniforms.contrast = 128.0;
bloom.uniforms.brightness = -0.3;
bloom.uniforms.glowOnly = false;
bloom.uniforms.delta = 1.0;
bloom.uniforms.sigma = 3.78;
bloom.uniforms.stepSize = 5.0;
ファクトリーを使ったシルエット(エッジ検出ステージをシルエットコンポジットに渡します):
import { PostProcessStageLibrary, Color } from "cesium";
const edgeStage = PostProcessStageLibrary.createEdgeDetectionStage();
edgeStage.uniforms.color = Color.YELLOW;
edgeStage.uniforms.length = 0.25;
const silhouette = PostProcessStageLibrary.createSilhouetteStage([edgeStage]);
viewer.scene.postProcessStages.add(silhouette);
コレクションステージ(Bloom、AO、FXAA、Tonemapping)
コレクションには、ブルーム、アンビエントオクルージョン、FXAAの組み込みコンポジットが常に用意されており、これらにadd()は必要ありません。TonemappingのデフォルトはPBR_NEUTRALです。
import { Tonemapper, PostProcessStageLibrary } from "cesium";
// Bloom (collection shortcut — always present, no add() needed)
viewer.scene.postProcessStages.bloom.enabled = true;
viewer.scene.postProcessStages.bloom.uniforms.contrast = 128.0;
viewer.scene.postProcessStages.bloom.uniforms.brightness = -0.3;
// Ambient Occlusion (HBAO)
viewer.scene.postProcessStages.ambientOcclusion.enabled = true;
viewer.scene.postProcessStages.ambientOcclusion.uniforms.intensity = 3.0;
// FXAA
viewer.scene.postProcessStages.fxaa.enabled = true;
// Tonemapping: REINHARD, MODIFIED_REINHARD, FILMIC, ACES, PBR_NEUTRAL (default)
viewer.scene.postProcessStages.tonemapper = Tonemapper.ACES;
viewer.scene.postProcessStages.exposure = 1.2; // <1 darker, >1 brighter
// Depth of field (added via library)
const dof = viewer.scene.postProcessStages.add(
PostProcessStageLibrary.createDepthOfFieldStage()
);
dof.uniforms.focalDistance = 500.0; // meters from camera
dof.uniforms.sigma = 3.8;
夜景/ブルームのビジュアル評価: 周囲の暗い領域を保ちながら、明るい街の灯りが光って見えるようにブルームを適用します。夜景画像の下にOSMベースレイヤーがある場合は、ベースレイヤーの
alpha/brightnessを下げ、ブルームを控えめにします(brightnessをより負の値にし、露出を下げます)。これにより、ラベルや地面が白く飛ぶのを防げます。黄色い霞がかかった淡い昼間の地図は、夜景の灯りを描画できているとは言えません。
カスタムPostProcessStage
カスタムステージは、colorTexture、depthTexture(sampler2D)、v_textureCoordinates(vec2)を受け取ります。out_FragColorで出力します。Uniformsには定数または関数を指定でき、関数はフレームごとに再評価されます。
import { PostProcessStage } from "cesium";
const sepia = viewer.scene.postProcessStages.add(new PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture; in vec2 v_textureCoordinates; uniform float intensity;
void main() {
vec4 c = texture(colorTexture, v_textureCoordinates);
float gray = dot(c.rgb, vec3(0.299, 0.587, 0.114));
out_FragColor = vec4(mix(c.rgb, gray * vec3(1.2, 1.0, 0.8), intensity), c.a);
}`,
uniforms: { intensity: () => 0.8 }, // function uniform, re-evaluated each frame
}));
選択したフィーチャーのハイライト表示
フラグメントシェーダーでczm_selected()を使用し、フィーチャーをstage.selectedに割り当てます。
import { PostProcessStage, Color } from "cesium";
const highlight = viewer.scene.postProcessStages.add(new PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture; in vec2 v_textureCoordinates; uniform vec4 highlight;
void main() {
vec4 color = texture(colorTexture, v_textureCoordinates);
if (czm_selected()) {
out_FragColor = vec4(mix(color.rgb, highlight.rgb, highlight.a), 1.0);
} else { out_FragColor = color; }
}`,
uniforms: { highlight: () => new Color(1.0, 1.0, 0.0, 0.5) },
}));
highlight.selected = [pickedFeature];
PostProcessStageComposite
import { PostProcessStage, PostProcessStageComposite, PostProcessStageLibrary } from "cesium";
const blur = PostProcessStageLibrary.createBlurStage();
const combine = new PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture; uniform sampler2D blurTexture;
in vec2 v_textureCoordinates;
void main() {
vec4 orig = texture(colorTexture, v_textureCoordinates);
vec4 blurred = texture(blurTexture, v_textureCoordinates);
out_FragColor = mix(orig, blurred, 0.5);
}`,
uniforms: { blurTexture: blur.name }, // reference another stage's output by name
});
viewer.scene.postProcessStages.add(new PostProcessStageComposite({
stages: [blur, combine],
inputPreviousStageTexture: false, // both read the original scene texture
}));
ステージの管理
viewer.scene.postProcessStages.remove(sepia); // remove specific stage
dof.enabled = false; // disable without removing
viewer.scene.postProcessStages.removeAll(); // remove all custom stages
BlendingState
PrimitiveのAppearance.renderStateで使用する、事前定義済みのブレンドプリセットです。
| プリセット | 動作 |
|---|---|
BlendingState.DISABLED | ブレンドなし |
BlendingState.ALPHA_BLEND | 標準アルファ:src*srcA + dst*(1-srcA) |
BlendingState.PRE_MULTIPLIED_ALPHA_BLEND | 乗算済みアルファ:src + dst*(1-srcA) |
BlendingState.ADDITIVE_BLEND | 加算:src*srcA + dst |
import { MaterialAppearance, BlendingState, Material, Color } from "cesium";
const appearance = new MaterialAppearance({
material: Material.fromType("Color", { color: Color.RED.withAlpha(0.5) }),
renderState: { depthTest: { enabled: true }, blending: BlendingState.ALPHA_BLEND },
});
パフォーマンスのヒント
- 組み込みタイプには
Material.fromType()を優先して使用します。シェーダープログラムがキャッシュされるため、再コンパイルを避けられます。 - テクスチャマテリアルには
Material.fromTypeAsync()を使用し、デフォルトテクスチャのちらつきを防ぎます。 - 負荷の高いステージで処理するピクセル数を減らすには、
PostProcessStage.textureScaleを1.0未満(例:0.5)に設定します。 - 使用していない組み込みステージ(
bloom.enabled = falseなど)を無効にします。有効なステージはGPUリソースを消費します。 - エフェクトを
PostProcessStageCompositeにまとめ、中間テクスチャの割り当てを減らします。 PostProcessStageの数を最小限に抑えます。各ステージで全画面描画呼び出しとフレームバッファーが必要です。
関連項目
- cesiumjs-custom-shader --
Model.customShader、Cesium3DTileset.customShader、VoxelPrimitive.customShader向けのGLSL作成(構造体のリファレンス、メタデータ、フィーチャーID) - cesiumjs-primitives -- Primitive APIオブジェクトでのジオメトリ、Appearance、Materialの適用
- cesiumjs-3d-tiles -- Cesium3DTilesetの読み込みとスタイル設定
- cesiumjs-models-particles -- Modelの読み込みとglTF