deck.gl でカスタムシェーダーを使う
概要
Deck.glでは開発者がシェーダーをカスタマイズする方法がいくつか用意されています。
ここではLayerExtensionを使って独自のシェーダーコードを追加する方法を紹介します。
サンプル
LayerExtensionを用いてScatterplotLayerに、オリジナルのフラグメントシェーダーを挿入し、出力結果をクロス(十字)に変換します。
解説
Deck.glのレイヤークラスには、あらかじめレイヤーを拡張するためのextensionsプロパティが用意されています。
extensionsの機能の一つとして、deck.glが生成するシェーダーをフックしてオリジナルなシェーダーコードを注入(inject)することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import { ScatterplotLayer, LayerExtension } from "deck.gl"; //LayerExtensionを継承し、オリジナルなエクステンションを作成する class injectionShader extends LayerExtension { // getShaders() { return { inject: { "fs:#decl": ` //フラグメントシェーダーの冒頭にコードを挿入する uniform bool changeCloss; `, "fs:#main-end": ` //フラグメントシェーダーのmain関数の最後にコードを注入する if(changeCloss){ if (abs(unitPosition.x) < 0.2 || abs(unitPosition.y) < 0.2) { gl_FragColor = vFillColor; } else { discard; } } ` } }; } //親レイヤーから呼び出される関数 updateState(params) { //親レイヤーのプロパティからchageClossの値を取得 const { changeCloss = true } = params.props; for (const model of this.getModels()) { //changeClossの値をuniformsとして渡す model.setUniforms({ changeCloss }); } } } export function renderLayers(props) { const { data, checkBtn } = props; //カスタムエクステンションをインスタンス化 const extension = new injectionShader(); const layes = [ new ScatterplotLayer({ id: "hexagon-layer", data, pickable: true, opacity: 0.8, stroked: true, filled: true, radiusScale: 6, radiusMinPixels: 1, radiusMaxPixels: 300, lineWidthMinPixels: 1, getPosition: (d) => d.position, getRadius: 300, getFillColor: (d) => [255, 0, 0], getLineColor: (d) => [255, 255, 255], changeCloss: checkBtn, extensions: [extension] //エクステンションを設定 }) ]; return layes; } |
上記のコードでは、チェックボックスにチェックが入るとtrueの値が親レイヤーのchangeClossプロパティを経由してフラグメントシェーダーにuniform変数として渡されます。
その後、シェーダーをフックするカスタムコード「fs:#main-end」に入力されたコードがシェーダーのmain関数の最後に注入され実行されます。
コードを注入する場所はあらかじめいくつか用意されています。詳しくはリンク先ページの「Standard Shader Hooks」の章を参照してください。