はじめに
PlayCanvasで動的にCubemapのテクスチャを読み込みSkyboxを変更するための手順となります。
準備
- PlayCanvasアカウント ( https://playcanvas.jp/ )
- Skybox用のテクスチャ 本記事では、「Poly Haven」を使います。
PolyHavenからテクスチャをダウンロード
ページにアクセスしBurnt warehouseのHDR画像をダウンロードします。
Texture Toolsで6面のテクスチャを作成
次に、Cubemapの画像を作成します。Webで完結するツールががあるのでこちらを利用します。
GitHubにて「playcanvas/playcanvas-tools」、OSSで公開されています。
- Texture Tools ( https://playcanvas.com/texture-tool ) にアクセス
2.ダウンロードしたテクスチャをドラッグアンドドロップでアップロードし、「Reproject」 をクリックします。
3.「Export TO HDR」をクリックして6面のテクスチャ画像をダウンロードします。
PlayCanvasにインポート & Cubemapアセット作成
次に、PlayCanvasにアップロードをし、Cubemapのアセットを作成します。
PlayCanvasエディタでCubemapアセットを作成し、「Prefilter Cubemap」をクリックします
PlayCanvas エディタからCubemapのアセットをダウンロード
ダウンロードされたファイルはこのような形式でダウンロードされます。dds
ファイル、png
ファイル6つ含まれたZipファイルがダウンロードされます。
ダウンロードしたファイルを管理しやすいように名前の変更をします。
外部のホスティングサービスにCubemapをホスト
先ほどダウンロードした.ddsファイル
/ pngファイル
をホスティングサービスにアップロードします。
アップロードが完了したら、CubemapのURLをコピーしておきます。
今回アップロードしたURLはこちらとなります。
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burnt-warehouse.dds
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_posx.png
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_negx.png
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_posy.png
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_negy.png
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_posz.png
https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_negz.png
スクリプトの設定
最後に、プロジェクトのCubemapはこちらをPlayCanvasで読み込むスクリプトを作成します。
var LoadCubemap = pc.createScript('loadCubemap');
LoadCubemap.prototype.initialize = function () {
const cubemap = new pc.Asset('Cubemap', 'cubemap', {
url: "https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burnt-warehouse.dds"
}, {
magFilter: pc.FILTER_LINEAR,
minFilter: pc.FILTER_LINEAR_MIPMAP_LINEAR,
anisotropy: 1,
type: pc.TEXTURETYPE_RGBM,
textures: [
`https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_posx.png`,
`https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_negx.png`,
`https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_posy.png`,
`https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_negy.png`,
`https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_posz.png`,
`https://playcanvas-cubemap-test.vercel.app/cubemaps/burnt-warehouse/burunt-warehouse_negz.png`,
]
});
cubemap.loadFaces = true;
cubemap.on('load', () => {
this.app.scene.setSkybox(cubemap.resources);
});
this.app.assets.add(cubemap);
this.app.assets.load(cubemap);
};
PlayCanvasエディタで、新しいスクリプトを作成します、このURLに先ほどコピーしたCubemapのURLを指定します。
スクリプトの入ったPlayCanvasのアプリを実行
「Launch」をクリックして、プロジェクトを実行します。
正しく実行されると、生成したCubemapが表示されます。
ボタンをクリックで複数のSkyboxを切り替える
この方法使って複数のSkyboxを切り替えることもできます。上記の画像のデモでは、複数のCubemapアセットを読み込んでいます。プロジェクトはパブリックのプロジェクトとなっておりますのでこちらからプロジェクトをご確認下さい。
スクリプトを設定
var LoadCubemapButton = pc.createScript("loadCubemapbutton");
LoadCubemapButton.attributes.add("assetBaseUrl", { type: "string", default: "https://playcanvas-cubemap-test.vercel.app/cubemaps/helipad/" });
LoadCubemapButton.attributes.add("dds", { type: "string", default: "Helipad.dds" });
LoadCubemapButton.attributes.add("face", { type: "string", default: "Helipad" });
LoadCubemapButton.attributes.add("anisotropy", { type: "number", default: 1 });
LoadCubemapButton.attributes.add("skyboxMip", { type: "number", default: 1 });
LoadCubemapButton.attributes.add("skyboxIntensity", { type: "number", default: 1 });
LoadCubemapButton.attributes.add("skyboxLuminance", { type: "number", default: 0 });
LoadCubemapButton.attributes.add("textureType", {
type: "string",
enum: [{ TEXTURETYPE_DEFAULT: "default" }, { TEXTURETYPE_RGBE: "rgbe" }, { TEXTURE_TYPE_RGBM: "rgbm" }, { TEXTURETYPE_RGBP: "rgbp" }, { TEXTURETYPE_SWIZZLEGGGR: "swizzleGGGR" }],
default: "rgbm",
});
LoadCubemapButton.prototype.initialize = function () {
// ボタンのクリックイベントをリッスン
this.entity.button.on("click", this.loadCubemapFromUrl, this);
};
LoadCubemapButton.prototype.loadCubemapFromUrl = function () {
// Cubemapアセットを作成
const cubemap = new pc.Asset(
this.dds,
"cubemap",
{
url: `${this.assetBaseUrl}${this.dds}`,
},
{
magFilter: pc.FILTER_LINEAR,
minFilter: pc.FILTER_LINEAR_MIPMAP_LINEAR,
anisotropy: this.anisotropy,
type: this.textureType,
textures: [
`${this.assetBaseUrl}${this.face}_posx.png`,
`${this.assetBaseUrl}${this.face}_negx.png`,
`${this.assetBaseUrl}${this.face}_posy.png`,
`${this.assetBaseUrl}${this.face}_negy.png`,
`${this.assetBaseUrl}${this.face}_posz.png`,
`${this.assetBaseUrl}${this.face}_negz.png`,
],
}
);
cubemap.loadFaces = true;
// Cubemapアセットのが読み込まれたら、スカイボックスに設定
cubemap.on("load", () => {
// 読み込まれたCubemapをシーンのスカイボックスに設定
this.app.scene.setSkybox(cubemap.resources);
// スカイボックスプロパティを設定
this.app.scene.skyboxMip = this.skyboxMip;
this.app.scene.skyboxIntensity = this.skyboxIntensity;
this.app.scene.skyboxLuminance = this.skyboxLuminance;
});
// アセットレジストリにCubemapアセットを追加
this.app.assets.add(cubemap);
// Cubemapアセットをロード
this.app.assets.load(cubemap);
};
エンティティにスクリプトを設定
作成したボタンに対してloadCubemapButton
のスクリプトを設定します。
まとめ
PlayCanvasをして動的にCubemapをロードしてSkyboxを変更しました。これで複数のプロジェクトから利用ができるようになります。