メインコンテンツまでスキップ

スクリーン

スクリーンは、インターフェースのルートです。Screenコンポーネントを持つエンティティで、その下にあるエレメントはスクリーンの空間の中にレイアウトされます。スクリーンは、インターフェースをカメラのビューの上に描画するかシーン内に配置するか、単位が何を表すか、そしてキャンバスに合わせてどのように拡大・縮小するかを決めます。

スクリーン空間とワールド空間​

パネルが立っている3Dシーンを遠近法で見た図と、ビューの上に描画された、バーとボタンのある平面的なHUD

スクリーン空間のスクリーンは、カメラがどこにあってもカメラのビューの上に描画され、常にキャンバスと同じサイズです。HUDやメニューなど、ワールドではなく画面に属するインターフェースに使います。

ワールド空間のスクリーンは、エンティティのトランスフォームによってシーン内に配置され、シーンの他の部分と一緒に描画されます。壁の看板、機械の上のパネル、XRのメニューなどです。サイズはresolutionで、エンティティのローカル単位で表され、エンティティを中心に配置されます。ワールド空間UIを参照してください。

// カメラのビューの上に、キャンバスと同じサイズで描画される
const hud = new pc.Entity('hud');
hud.addComponent('screen', {
screenSpace: true,
scaleMode: pc.SCALEMODE_BLEND,
referenceResolution: [1280, 720]
});
app.root.addChild(hud);

// シーン内に配置される:640 × 320単位を6.4 × 3.2メートルにスケーリング
const sign = new pc.Entity('sign');
sign.addComponent('screen', {
screenSpace: false,
resolution: [640, 320]
});
sign.setLocalScale(0.01, 0.01, 0.01);
sign.setPosition(0, 2, -5);
app.root.addChild(sign);

どちらの種類のスクリーンにも同じエレメントを配置でき、レイアウトの仕組みも同じです。

単位と解像度​

エレメントの位置とサイズはスクリーンの単位で指定し、y軸は上向きです。1単位が何を表すかは、スクリーンによって異なります。

スクリーン解像度1単位の大きさ
スクリーン空間、Scale ModeがNoneキャンバスの描画バッファのサイズ。キャンバスのサイズが変わるたびに更新されます描画バッファの1ピクセル
スクリーン空間、Scale ModeがBlend同上描画バッファのscaleピクセル。Blendによるスケーリングを参照してください
ワールド空間設定したresolution。デフォルトは640 × 320エンティティのローカル空間の1単位

スクリーン空間のスクリーンは解像度を自分で設定するため、resolutionに書き込んでも効果はありません。キャンバスのサイズが変わると、スクリーンの辺や角にアンカーされたエレメントは、それらと一緒に移動します。

Blendによるスケーリング​

Scale ModeをNoneに設定すると、インターフェースはピクセル単位で作られ、ピクセル単位のサイズを保ちます。設計時のキャンバスにちょうど収まるインターフェースは、それより大きなキャンバスでは小さく見え、小さなキャンバスでは端からはみ出します。Blendでは、インターフェースを基準解像度で設計し、スクリーンがそれを表示先のキャンバスに合わせてスケーリングするため、どこでも比率が保たれます。

小さなキャンバスと大きなキャンバスに表示した同じインターフェース。上段のScale Mode Noneでは、小さなキャンバスからはみ出し、大きなキャンバスでは小さく見える。下段のBlendでは、どちらにも収まるようにスケーリングされる

const screen = new pc.Entity('screen');
screen.addComponent('screen', {
screenSpace: true,
scaleMode: pc.SCALEMODE_BLEND,
referenceResolution: [1280, 720],
scaleBlend: 0.5
});
app.root.addChild(screen);

後から基準解像度を変更するには、referenceResolutionに新しいpc.Vec2を代入します。

スクリーンはキャンバスと基準解像度を軸ごとに比較し、Scale Blendで2つの軸を重み付けします。

scale = (width / reference width) ^ (1 - Scale Blend) × (height / reference height) ^ Scale Blend

基準解像度が1280 × 720の場合、Scale Blendの値にかかわらず、1920 × 1080のキャンバスではインターフェースが1.5倍に、640 × 360のキャンバスでは0.5倍にスケーリングされます。どちらのキャンバスも基準と縦横比が同じだからです。Scale Blendが意味を持つのは、キャンバスの縦横比が異なる場合だけです。スクリーンのscaleプロパティが、現在の倍率を保持します。

Scale Modeは、スクリーン空間のスクリーンにのみ適用されます。ワールド空間のスクリーンは常にスケーリングされないため、代わりにエンティティのスケールでサイズを調整します。

Scale Blendの選び方​

Scale Blendは、インターフェースがキャンバスのどの寸法に従うかを決めます。

Scale Blendインターフェースのスケーリングの基準適した用途
0キャンバスの幅縦長のレイアウトや、常にキャンバスの幅に収まる必要があるインターフェース
0.5幅と高さを均等に縦向きと横向きの両方で表示されるインターフェース。スマートフォンを横に倒してもスケールは変わりません
1キャンバスの高さHUDが上から下まで収まる必要がある、横画面のゲーム

Scale Blendの値ごとの横長と縦長のキャンバス。左が0、中央が0.5、右が1。縦長では、0はインターフェースを幅に収まる大きさまで小さくし、0.5は横長のときと同じサイズを保ち、1は幅が広すぎて収まらなくなる

0.5では、スケールはキャンバスの面積だけで決まるため、スマートフォンを横に倒してもインターフェースのサイズは変わりませんが、横長の基準解像度で設計したレイアウトは、縦長のキャンバスでは幅が広すぎることがあります。キャンバスの縦横比にかかわらず基準の領域全体を画面内に収めるには、余裕の少ない方の軸に従い、キャンバスのサイズが変わるたびに確認し直します。

// 余裕の少ない方の軸に従い、基準の領域全体が画面内に収まるようにする
const fitReference = () => {
const { resolution, referenceResolution } = screen.screen;
const wider = resolution.x / referenceResolution.x > resolution.y / referenceResolution.y;
screen.screen.scaleBlend = wider ? 1 : 0;
};
fitReference();
app.graphicsDevice.on('resizecanvas', fitReference);
Screen Scaling

ピクセル比​

高密度ディスプレイでは、キャンバスの描画バッファのピクセル数が、ページ上のキャンバスのCSSピクセル数より多くなることがあります。これによりレンダリングは鮮明になりますが、描画のコストは高くなります。グラフィックスデバイスのmaxPixelRatioがこの2つの比率の上限を決め、その設定は環境によって異なります。

環境デフォルトの描画バッファ
エンジンmaxPixelRatioが1のため、キャンバスのCSSサイズ。フル解像度にするには、app.graphicsDevice.maxPixelRatioをwindow.devicePixelRatioに設定します
エディターCSSサイズ。レンダリング設定でDevice Pixel Ratioを有効にした場合は、ディスプレイ本来のピクセル比
ReactCSSサイズ。useApp()が返すアプリケーションのグラフィックスデバイスでmaxPixelRatioを設定します
Web Componentsディスプレイ本来のピクセル比。<pc-app>のmax-pixel-ratio属性で上限を設定します

ピクセル比は、2つのスケールモードに異なる影響を与えます。

  • Blend:スクリーンの解像度とスケールが一緒に大きくなるため、ピクセル比が高くなってもページ上のインターフェースのサイズは変わらず、鮮明になるだけです。
  • None:1単位が描画バッファの1ピクセルなので、ピクセル比が高いほどインターフェースは小さくなります。ピクセル比が2の場合、100単位のボタンの幅はCSSピクセルで50になります。

ピクセルパーフェクトな画像​

Scale ModeがNoneの場合、テクスチャと同じサイズのイメージエレメントは各テクセルを描画バッファの1ピクセルとして描画するため、ピクセルアートや小さなアイコンがくっきりと表示されます。このようなエレメントは、整数ピクセルの位置に保ちます。幅や高さが奇数のキャンバスでは中央が2つのピクセルの間に来るため、中央ではなく角にアンカーし、奇数の幅と中央のピボットの組み合わせのように、辺がピクセルの中間に来るサイズは避けます。ピクセルアートをぼかさずに2倍や3倍のサイズで描画するには、テクスチャのminFilterとmagFilterをpc.FILTER_NEARESTに設定します。

レスポンシブレイアウト​

スクリーン空間のインターフェースはキャンバスに従い、キャンバスのサイズはスクリーンの外で決まります。

環境キャンバスのサイズを決めるもの
エンジンアプリケーションのフィルモード。pc.FILLMODE_FILL_WINDOWはウィンドウ全体を埋め、pc.FILLMODE_KEEP_ASPECTはキャンバスのアスペクト比が許す範囲でウィンドウを埋め、pc.FILLMODE_NONEはサイズをCSSに任せます。ウィンドウのサイズが変わったらapp.resizeCanvas()を呼び出します
エディターレンダリング設定のFill ModeとResolution Mode
React<Application>を含む要素。デフォルトでキャンバスがその要素を埋めるためです
Web ComponentsページのCSS。CSSは<pc-app>を<video>要素と同じようにサイズ設定します。キャンバスは常にその中を埋めます

アスペクト比を保つキャンバスでは、Blendでスケーリングされたインターフェースはどのウィンドウでも同じように見え、大きさが変わるだけです。ウィンドウやスマートフォンの画面を埋めるキャンバスでは、レイアウトを適応させる必要があります。

  • 各エレメントを、そのエレメントが属する角や辺にアンカーして、横に広いキャンバスや縦に高いキャンバスでもその辺に追従するようにし、伸縮させたいバーやパネルには分割アンカーを使います。エレメントを参照してください。
  • 中央に配置するコンテンツは、サポートする最小のキャンバスに収まるようにするか、Scale Blendの選び方のように基準の領域全体を画面内に収めます。
  • スマートフォンでは、重要なエレメントをセーフエリアの内側に配置します。
  • テキストは、エレメントに収まるように折り返したり縮小したりできるようにします。テキストエレメントを参照してください。
  • サポートする最小と最大のキャンバスで、縦向きと横向きの両方、そしてピクセル比が1の場合と2以上の場合でテストします。

複数のスクリーン​

アプリケーションは、HUD、ポーズメニュー、ワールド内の看板など、複数のスクリーンを持つことができ、それぞれが自分のエレメントをレイアウトします。スクリーンが重なる場合は、priority(0から127)が高い方が上に描画され、入力も先に判定されます。描画順とパフォーマンスを参照してください。

表示と非表示​

スクリーンのエンティティを無効にするとインターフェース全体が非表示になり、有効にすると再び表示されます。無効なスクリーン上のエレメントは入力を受け取りません。Screenコンポーネントだけを無効にしても、何も非表示にはなりません。

pauseMenu.enabled = true;

Reactでは、スクリーンの<Entity>を表示すべき間だけレンダリングします。<Entity>はenabledプロパティを適用しないためです。Web Componentsでは、その<pc-entity>のenabled属性をfalseに設定します。

関連情報​