パラメータ
目次
はじめに
前回のHGIMG4のイベント関連で出てきた パラメータについて、一部を少し掘り下げてみようと思います。 ここで言うパラメータは、命令の引数のことではなく、HGIMG4で取り扱うノードオブジェクトが持つさまざまな情報のことです。 次のような命令で取り扱います。
命令 | パラメータ操作 | event_系命令 |
---|---|---|
gpsetprm | 値を上書き | event_prmset |
gpsetprmon | 指定ビットをON | event_prmon |
gpsetprmoff | 指定ビットをOFF | event_prmoff |
gpgetprm | 値を取得 | - |
マニュアル(HDL)に記載されているような設定を扱うことができます。
たくさんあるので、個人的に気になったPRMSET_FLAG
とPRMSET_MODE
、PRMSET_ALPHA
について少し調査しました。
PRMSET_FLAG
PRMSET_FLAG
「オブジェクト登録フラグ」は、マニュアルには説明がありません。(HSP3.7Bβ4現在)
HGIMG3にも同名のPRMSET_FLAG
「存在フラグ」という名前のパラメータがありましたが、HGIMG4のものとは動作が異なります。
基本的には常に1を持っています。
マニュアルの説明では、基本的に呼び出しのみで利用する事になっていますが、gpsetprm
で値を書き込むことができてしまいます。
0を指定するとオブジェクトが破棄され、0以外は挙動に影響ありません。
影響ないならユーサー側で好きに使っていい領域!便利!とも考えたのですが、どうやらそうもいかないようです。
この動作は保証されているわけでなく、決められていないので影響がない、という状況のようです。
将来、仕様が変わってしまうと挙動に影響が出る可能性もあるので、「呼び出しのみ」と書かれている項目は呼び出しのみで使ったほうが良さそうです。
本来の用途は何なのでしょうね。
オブジェクトが使用できるかどうかを確認するフラグかとも考えたのですが、delobj
などでオブジェクトが破棄されてしまえば、gpgetprm
で情報を取得しようとするとエラーになるのでPRMSET_FLAG
の状態取得ができません。
うーん。
PRMSET_MODE
PRMSET_MODE
パラメータを指定すると、ノードオブジェクトに対して動作モードを設定できます。
ラベルによって、表示/非表示やワイヤーフレーム表示の切り替え、自動移動のON/OFFなど、さまざまな情報を設定できます。
詳しくは、マニュアル参照。
HGIMG4プログラミングガイド 17.オブジェクトのモード設定
https://www.onionsoft.net/hsp/v37/doclib/hgimg4.html#MODE_OBJ
大変有益な機能なのですが、設定できるモードについて個別の詳しい説明が不足しています。
OBJ_HIDE
、OBJ_TIMER
、OBJ_LATE
、OBJ_MOVE
については、HGIMG4プログラミングガイド内で触れられている部分がありますが、その他については概要を記述した1行程度の情報しかありません。
これではどんな機能があるのかを把握しにくいので、調べてわかった使い方と、既存の情報についてをまとめて記載してみました。
まずは、どんなラベルがあるのか。HGIMG4プログラミングガイドにまとめてありますが、setobjmode
にHGIMG3も合わせた情報があったので表に追加してみました。
HGIMG3でも使用しているラベルは、hgimg3.txtに説明が載っていることがあるので参考にできそうです。
ただし、必ずしもhgimg3.txtの説明と同じ動作をすることが保証されているわけではない点に注意が必要です。
ラベル | 内容 | HGIMG3 | HGIMG4 |
---|---|---|---|
OBJ_HIDE | 非表示(画面から消す) | ● | ● |
OBJ_CLIP | 3Dクリッピングを有効にする | ● | |
OBJ_XFRONT | 正面属性(常に画面に正面を向く) | ● | ● |
OBJ_WIRE | ワイヤーフレームで描画する | ● | |
OBJ_MOVE | 自動移動を行なう(XYZ移動量を参照する) | ● | ● |
OBJ_FLIP | ボーダー領域で反転する | ● | ● |
OBJ_BORDER | ボーダー領域を有効にする | ● | ● |
OBJ_2D | 2Dスプライト | ● | ● |
OBJ_TIMER | タイマーを有効にする | ● | |
OBJ_LATE | 後から描画される(半透明オブジェクト用) | ● | ● |
OBJ_FIRST | 常に最初に描かれる | ● | |
OBJ_SORT | 自動的に奥から描かれる(3Dオブジェクト用) | ● | |
OBJ_LOOKAT | 特定オブジェクトの方向を常に向く | ● | |
OBJ_LAND | Y座標を常に一定に保つ | ● | |
OBJ_GROUND | 地面として認識される | ● | |
OBJ_STAND | 地面の上に配置する | ● | |
OBJ_GRAVITY | 重力計算を有効にする | ● | |
OBJ_STATIC | 障害物として認識される | ● | |
OBJ_BOUND | 地面で反発する(メッシュマップコリジョン用) | ● | |
OBJ_ALIEN | ターゲットに向ける(メッシュマップコリジョン用) | ● | |
OBJ_WALKCLIP | 移動の制限を受ける(メッシュマップコリジョン用) | ● | |
OBJ_EMITTER | エミッター発生オブジェクトになる | ● |
HGIMG3とHGIMG4で重複するラベルが結構ありますね。重複するものは、hgimg3.txtも参考にすると理解が深まると思います。 HGIMG3にはあって、HGIMG4にはないラベルが結構あります。これについては、実装方法が変わった影響で不要になったものとかもあるので、あまり気にしなくていいと思います。
一覧表ができたので、次は個別の機能について概略を整理しました。といっても資料はないので、実際に使ってみた結果などが根拠です。
- OBJ_HIDE
- 非表示(画面から消す)
-
画面上に表示されません。表示されないだけで、実体は存在しています。描画だけが行われない状態です。
物理特性を設定すれば、衝突判定も行われます。
少ないポリゴン数で衝突判定用のオブジェクトを使って非表示にし、画面上の同じ位置にはポリゴン数が多い複雑な形状のモデルを置く、という運用ができるので便利な機能です。 - OBJ_CLIP
- 3Dクリッピングを有効にする
- 名前から推測すると、有効にするとカメラに写っていない場合は描画しない機能だと思います。 ポリゴン数が大きいノードオブジェクトを使う際に処理負荷が軽くなるのだと思います。 確認は保留。
- OBJ_XFRONT
- 正面属性(常に画面に正面を向く)
-
X回転軸がカメラのX回転軸と同期します。
gpplate
を使うと、カメラに対して常に同じ面を同じ向きで表示する板を配置できます。 詳細は後述。 - OBJ_WIRE
- ワイヤーフレームで描画する
- ワイヤーフレームで表示します。面が表示されずに、頂点同士を結ぶ辺だけの表示になります。
- OBJ_MOVE
- 自動移動を行なう(XYZ移動量を参照する)
-
dirグループ(移動ベクトル)による自動移動を行うようになります。dirグループに0より大きい値を設定して、このパラメータをONにすることで自動移動が有効になります。
dirグループとOBJ_MOVEの両方を設定しなければ見た目の変化はありません。
HGIMG4プログラミングガイド 13.3D動作の概要
https://www.onionsoft.net/hsp/v37/doclib/hgimg4.html#3DABSTRACT - OBJ_FLIP
- ボーダー領域で反転する
-
HGIMG4付属のサンプルtest12.hspで動きを確認できます。
ボーダー領域から外に出ようとした場合に、壁にあたって反射するような動きをするみたいです。
基本的に
OBJ_BORDER
とセットで使うものだと思います。 - OBJ_BORDER
- ボーダー領域を有効にする
-
HGIMG4付属のサンプルtest12.hspで動きを確認できます。
ボーダー領域を有効にして、使用できるようにします。ボーダー領域の説明がないのですが、描画エリアとどう違うんだろうか…。
基本的に
OBJ_FLIP
とセットで使うものだと思います。というか、OBJ_FLIP
でしかボーダー領域を使用していません。 - OBJ_2D
- 2Dスプライト
- スプライト関連?説明もサンプルもなく、hgimg3でも同じ状況です。
- OBJ_TIMER
- タイマーを有効にする
-
オブジェクトタイマーが有効になります。
PRMSET_TIMER
で指定したフレーム数が経過すると、オブジェクトは破棄されます。 詳しくは、HGIMG4プログラミングガイド「オブジェクトタイマー」を参照。HGIMG3とは、挙動が異なるので移行してきた方は注意。
https://www.onionsoft.net/hsp/v37/doclib/hgimg4.html#TIMER_OBJ - OBJ_LATE
- 後から描画される(半透明オブジェクト用)
-
半透明オブジェクトを表示する際に使用します。
半透明オブジェクトの描画結果は、表示する順番の影響を受けます。 半透明オブジェクトを期待した通りの描画を行うためには、必ず不透明オブジェクトを描画し終わった後に半透明オブジェクトを描画しなければいけません。 しかしオブジェクトを描画する順番は、オブジェクトを作成した順番で決定されます。
OBJ_LATE
を有効にすると、OBJ_LATE
が無効になっているオブジェクト(不透明オブジェクト)よりも後に描画されるようになります。
少しわかりにくいので、詳細は後述します。
自分が使いそうなものを中心に、ざっくりまとめてみました。 説明し足りない項目については、あとで掘り下げます。
PRMSET_MODE サンプル
言葉だけの説明だと確認が面倒ですよね。ということでサンプルです。キーボードのカーソルキーで動かせます。
#include "hgimg4.as"
title "HGIMG4 Test"
gpreset
setcls CLSMODE_SOLID, $808080 ; 画面クリア設定
setpos GPOBJ_CAMERA, 0, 2, 10 ; カメラ位置を設定
; 箱ノード
gptexmat id_texmat, "res/qbox.png"
gpbox id_box, 1, -1, id_texmat
setpos id_box, 0, 0.5, -3
gppbind id_box, 1, 0.5 ; 箱の物理設定を行なう
gppset id_box, GPPSET_ANGULAR_FACTOR, 0,0,0 ; 回転を固定
; 箱ノード量産
dim id_boxc, 11
repeat 11
dx = 2. * cnt - 10
gpbox id_boxc(cnt), 1, -1, id_texmat
setpos id_boxc(cnt), dx, 0.5, 0.0
; 半透明テスト
;gpsetprm id_boxc(cnt), PRMSET_ALPHA, 127
; フェードテスト
;gpsetprm id_boxc(cnt), PRMSET_FADE, -1
; 移動テスト
setdir id_boxc(cnt), 0, 0.01, 0
; タイマーをセット
; 指定フレーム数後にオブジェクト削除
gpsetprm id_boxc(cnt), PRMSET_TIMER, 1000
loop
; パラメータ設定
gpsetprm id_boxc( 1), PRMSET_MODE, OBJ_HIDE ; 非表示(画面から消す)
gpsetprm id_boxc( 2), PRMSET_MODE, OBJ_CLIP ; 3Dクリッピングを有効にする
gpsetprm id_boxc( 3), PRMSET_MODE, OBJ_XFRONT ; 正面属性(常に画面に正面を向く)
gpsetprm id_boxc( 4), PRMSET_MODE, OBJ_WIRE ; ワイヤーフレームで描画する
gpsetprm id_boxc( 5), PRMSET_MODE, OBJ_MOVE ; 自動移動を行なう(XYZ移動量を参照する)
gpsetprm id_boxc( 6), PRMSET_MODE, OBJ_FLIP ; ボーダー領域で反転する
gpsetprm id_boxc( 7), PRMSET_MODE, OBJ_BORDER ; ボーダー領域を有効にする
gpsetprm id_boxc( 8), PRMSET_MODE, OBJ_2D ; 2Dスプライト
gpsetprm id_boxc( 9), PRMSET_MODE, OBJ_TIMER ; タイマーを有効にする
gpsetprm id_boxc(10), PRMSET_MODE, OBJ_LATE ; 後から描画される(半透明オブジェクト用)
; 床ノードを追加
gpfloor id_floor, 30,30, $404040
gppbind id_floor, 0 ; 床の物理設定を行なう
repeat
stick key,15
if key&128 : end
; 箱
objexist id_box
if stat = 0 {
; カーソルキーで箱を動かす
if key&1 : gppapply id_box, GPPAPPLY_IMPULSE, -0.1, 0 , 0
if key&4 : gppapply id_box, GPPAPPLY_IMPULSE, 0.1, 0 , 0
if key&8 : gppapply id_box, GPPAPPLY_IMPULSE, 0,0, 0.1
if key&2 : gppapply id_box, GPPAPPLY_IMPULSE, 0,0, -0.1
; カメラを自機に向ける
getpos id_box,dx,dy,dz
gplookat GPOBJ_CAMERA, dx,dy,dz
}
redraw 0
gpdraw
; 箱の量産品
repeat 11
objexist id_boxc(cnt)
if stat = 0 {
getpos id_boxc(cnt), px, py, pz
gpcnvaxis vx, vy, vz, px, py-0.5, pz+0.5, 0
pos vx, vy
gpgetprm v, id_boxc(cnt), PRMSET_MODE
mes "PRMSET_MODE\n" + strf("0x%04X", v)
if v & OBJ_HIDE : mes "OBJ_HIDE"
if v & OBJ_CLIP : mes "OBJ_CLIP"
if v & OBJ_XFRONT : mes "OBJ_XFRONT"
if v & OBJ_WIRE : mes "OBJ_WIRE"
if v & OBJ_MOVE : mes "OBJ_MOVE"
if v & OBJ_FLIP : mes "OBJ_FLIP"
if v & OBJ_BORDER : mes "OBJ_BORDER"
if v & OBJ_2D : mes "OBJ_2D"
if v & OBJ_TIMER : mes "OBJ_TIMER"
if v & OBJ_LATE : mes "OBJ_LATE"
if v & OBJ_TIMER {
gpgetprm v, id_boxc(cnt), PRMSET_TIMER
mes "Timer:" + v
}
}
loop
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
loop
OBJ_MOVE
やOBJ_TIMER
を有効にしたオブジェクトは、いつの間にか画面から消えてしまうのでご注意ください。
また、コメントを外せば半透明やフェードも試せますが…、サンプルとしては分かりにくいので、あまり意味はなかったかも。
正面属性 OBJ_XFRONT
正面属性(常に画面に正面を向く)という名前だけ聞くとビルボードかな?と思ってしまったのですが、調べてみると違う動作をするものでした。
ビルボードというのは、常にカメラに対して「同じ側の面を向く」ように、オブジェクトのY軸回転が自動的に制御されるものです。 一方で正面属性は、常にカメラに対して「同じ面を向けて、上下左右の向きも同じ方向を向く」ように、オブジェクト姿勢が自動的に制御されるものです。
具体的には、こういう仕組みで制御されています。 正面属性を持つノードは、X回転軸がカメラのX回転軸とまったく同じ方向と姿勢を向くように回転されます。 この動きによって、ノードのZ軸が必ずカメラの方向を向きますし、X軸もカメラと同じなので傾いたりもしません。
なお、正面属性を指定したノードは、getang
による姿勢変更後の値を取得できますが、setang
による姿勢変更はできません。
言葉だけの説明だとわかりにくいのでサンプル書きました。
説明の動きは、gpbox
でやってみると理解の助けになります。
; 正面属性
;
; カーソルキーとZ,Xキーでカメラを動かせます。
;
#include "hgimg4.as"
title "HGIMG4 Test"
gpreset
setcls CLSMODE_SOLID, $808080 ; 画面クリア設定
camx = 0.0
camy = 2.0
camz = 7.0
setpos GPOBJ_CAMERA, camx, camy, camz
; 箱ノード
gptexmat id_texmat, "res/qbox.png"
gpbox id_box, 1, -1, id_texmat
setpos id_box, 0, 0, 0
; ノード量産
; カメラの周りに円柱状に配置。
; カメラの後ろには、配置していません。
dim id_obj, 180
id = 0
repeat 10
dy = 2.0 * (cnt-5)
repeat 18, 18
dx = 10.0 * cos(deg2rad(10.0 * cnt)) + camx
dz = 10.0 * sin(deg2rad(10.0 * cnt)) + camz
;gpplate id_obj( id ), 1, 1, -1, id_texmat
gpbox id_obj( id ), 1, -1, id_texmat
setpos id_obj( id ), dx, dy, dz
; 正面属性(常に画面に正面を向く)
gpsetprm id_obj( id ), PRMSET_MODE, OBJ_XFRONT
id++
loop
loop
repeat
stick key,15 + 2048 + 4096
if key&128 : end
; カーソルキーでカメラを動かす
r = deg2rad( 1)
if key & 1 : addang GPOBJ_CAMERA, 0, r, 0
if key & 4 : addang GPOBJ_CAMERA, 0, -r, 0
if key & 8 : addang GPOBJ_CAMERA, -r, 0, 0
if key & 2 : addang GPOBJ_CAMERA, r, 0, 0
if key & $0800 : addang GPOBJ_CAMERA, 0, 0, -r ; Z
if key & $1000 : addang GPOBJ_CAMERA, 0, 0, r ; X
redraw 0
gpdraw
; 箱の量産品
repeat 180
getpos id_obj(cnt), px, py, pz
gpcnvaxis vx, vy, vz, px, py-0.5, pz, 0
pos vx, vy
getang id_obj(cnt), x,y,z
;mes strf( "%3.1f, %3.1f, %3.1f", rad2deg(x), rad2deg(y), rad2deg(z) )
; 効果がない
;setang id_obj(cnt), 0,0,0
loop
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
loop
- カメラを操作できます。カーソルキーで移動、Z、Xキーで回転させることができます。
- 実行直後、中央に表示される箱は動きません。動かない箱は、カメラの姿勢を把握するための目印です。
- 背景に配置した箱はすべて、正面属性を付与しています。
- 正面属性が付与された箱は、常にカメラに対して同じ面を同じ向きで表示していることが確認できます。
箱gpbox
だと起きていることは理解しやすいのですが、運用を考えると使い道が思いつきません。
この機能は、主にgpplate
を使った表現を想定したものだと思われます。
gpplate
に正面属性を適用すると、常にカメラに対して表面を見せるように姿勢が自動調整されます。
gpplate id_obj( id ), 1, 1, -1, id_texmat
これなら活用方法がすぐに思いつきますね。パーティクルとして使う。 キャラクターの頭の上座標に、アイコンを表示する。 ヘッドアップディスプレイのような演出として使用する。 などの運用方法ができそうですね。
半透明オブジェクトの描画
半透明オブジェクトを取り扱う場合、内部での「描画順」がとても重要です。 HGIMG4は、描画順にしたがってオブジェクトを1個ずつ描画します。 先に書いたオブジェクトと同じ方向にある、より遠くにあるオブジェクトは描画を行いません。 先に書いたオブジェクトで隠れてしまって見えないはずだからです。
ところが、先に書いたオブジェクトが半透明だった場合、隠れたオブジェクトは見えるはずなので、描画されないというのは困ります。
この問題は、遠くにあるものから順に描画されるような「描画順」になってくれていれば解決します。 しかし現在(HSP3.7β4)のHGIMG4にはこの機能がなく、基本的に「描画順=オブジェクトを作成した順番」です。
これでは、常に半透明オブジェクトの作成順を気にする必要がありとても不便です。 そこでHGIMG4では、「不透明オブジェクトをすべて描画し終わってから、半透明オブジェクトを描画する」という方法でこの問題を解決しています。 全部のオブジェクトを奥行きでソートして描画順を決めるよりも、はるかに低負荷で効果的な実装方法ですね。
しかしこの方法にも問題が残っていて、半透明オブジェクトどうしが重なった場合は、オブジェクト作成順で描画されてしまうので、半透明なのに透けない問題が発生する場合もあります。 半透明オブジェクトどうしの重なりを正しく描画したい場合は、オブジェクトの作成順を調整する必要があります。
半透明オブジェクトの実装
半透明オブジェクトを取り扱う場合、大きく分けて以下のようなケースがあります。
- オブジェクトノード全体を半透明にする場合
- テクスチャを使ってオブジェクトの一部を半透明にする場合
いずれの場合も、描画順番を気にする必要があるという共通事項がありますが、実装時の作業内容が若干異なります。 違いを確認するため、表にしてみました。
描画結果 | 必要な処置 (全体) | 必要な処置 (テクスチャ) |
---|---|---|
非表示 | OBJ_HIDE を設定 | テクスチャ画像のα値に 0 を指定する |
半透明 | PRMSET_ALPHA を設定 | テクスチャ画像にα値(1~254)を指定する |
不透明 | なし | テクスチャ画像に不透明(α値=0)を指定する |
オブジェクト全体を半透明にするためPRMSET_ALPHA
を使用した場合、OBJ_LATE
を設定する必要はありません。
楽でいいのですが、設定する値によって挙動が異なるので、表にまとめました。
PRMSET_ALPHA | 描画結果 | 補足説明 |
---|---|---|
0 | 非表示 | PRMSET_ALPHA で0にすると見えなくなるだけですが、PRMSET_FADE で0になるとオブジェクトが破棄されます。 |
1~254 | 半透明 | 自動で不透明のオブジェクトよりも後に描画されるようになります。OBJ_LATE をONにしたときと同じ挙動です。ただしOBJ_LATE がONになるわけではない。ややこしい。 |
255 | 不透明 | 通常の表示なので何もしなくて良い。 |
PRMSET_ALPHA
を使用すると、HGIMG4側はオブジェクトが「半透明」であることを知ることができます。なのでHGIMG4側が描画順を勝手に設定してくれます。
しかしテクスチャの場合は、半透明か不透明かをHGIMG4側は知ることができません。
ユーザー側が、HGIMG4にプログラムする際、OBJ_LATE
を使って描画順を最後にする必要がある事を知らせる必要があります。
αチャンネル | 描画結果 | 必要な処置 | 補足説明 |
---|---|---|---|
0 | 表示されない | なし | 標準でピクセルのカットオフが適用される。カットオフされたピクセルは、完全な透明になる。 |
1~254 | 半透明 | OBJ_LATE を有効にする。 | 描画順の影響を受けるため、不透明のオブジェクトよりも後に描画する必要がある。 |
255 | 不透明 | なし | 通常の表示なので何もしなくて良い。 |
半透明を使用した場合、上記の対応を行っても半透明同士が重なった際に、適切な描画が行われない場合もあります。 原因は、描画順(オブジェクト作成順)が描画結果に影響を与えるためです。 適切な描画結果を得るためには、手動でZ座標をソートして奥から順番に描画する必要がありますが、現在のHGIMG4(HSP3.7β3)にはその機能はありません。 正しくない描画結果がなるべく目立たなくなるようにうまく工夫したほうが解決は早いと思います。 将来的にこの問題はHGIMG4側が解決してくれる計画らしいので、それをあてにするのもありですね。
サンプルを使って描画順の動作確認してみます。
; 半透明の描画順序
#include "hgimg4.as"
gpreset
setcls CLSMODE_SOLID, $808080 ; 画面クリア設定
setpos GPOBJ_CAMERA, 0, 2, 10 ; カメラ位置を設定
; 箱ノード用テクスチャ
gptexmat id_texmat, "res/qbox.png"
; 箱ノード量産
dim id_boxc, 6
repeat 6
gpbox id_boxc(cnt), 1, -1, id_texmat
loop
; 左の3つ
setpos id_boxc(0), -2.0, 0.5, 0.0 ; 先に描画されるため、
setpos id_boxc(1), -1.5, 1.0, -1.0 ; 奥のオブジェクトの深度情報を遮ってしまい、
setpos id_boxc(2), -1.0, 1.5, -2.0 ; 奥側が描画されない。
; 右の3つ
setpos id_boxc(3), 1.0, 1.5, -2.0
setpos id_boxc(4), 1.5, 1.0, -1.0
setpos id_boxc(5), 2.0, 0.5, 0.0
; 左の3つ
gpsetprm id_boxc(0), PRMSET_ALPHA, 127
;gpsetprm id_boxc(1), PRMSET_ALPHA, 254 ; 255
gpsetprm id_boxc(2), PRMSET_ALPHA, 127
; 右の3つ
gpsetprm id_boxc(3), PRMSET_ALPHA, 127
;gpsetprm id_boxc(4), PRMSET_ALPHA, 254 ; 255
gpsetprm id_boxc(5), PRMSET_ALPHA, 127
; 後から描画される(半透明オブジェクト用)
;gpsetprm id_boxc(1), PRMSET_MODE, OBJ_LATE
; 床ノードを追加
gpfloor id_floor, 30,30, $404040
*main
stick key,15
if key&128 : end
redraw 0
gpdraw
;pos 10,10
;mes "(ID) PRMSET_MODE, PRMSET_ALPHA"
;repeat 6
; gpgetprm m, id_boxc(cnt), PRMSET_MODE
; gpgetprm a, id_boxc(cnt), PRMSET_ALPHA
; mes "(" + cnt + ") " + strf("0x%04X, %d", m, a)
;loop
redraw 1
await 1000/60
goto *main
箱ノード3個を2グループ左右に配置しています。不透明オブジェクト1つを半透明オブジェクト2つではさむような形で配置しています。 左右のグループでは、オブジェクトを作成する順番が異なります。左のグループは手前から奥に、右のグループは奥から手前の順に作成しています。全体としては、左の箱から順にオブジェクトを作成しました。
不透明と半透明のオブジェクトが重なった場合は、とくに支障はありません。
PRMSET_ALPHA
が指定されたオブジェクトは、自動的に不透明オブジェクトの後に描画される設定となるためです。
すべて半透明オブジェクトになると描画順の影響が確認しやすくなります。
gpsetprm id_boxc(1), PRMSET_ALPHA, 254
…
gpsetprm id_boxc(4), PRMSET_ALPHA, 254
すべての箱ノードが半透明オブジェクトになったので、オブジェクト作成順がそのまま描画順になります。 左側のグループは手前から奥に向かって描画しているので、一番手前の箱が描画されると、その影で隠れている部分はもう描画されません。 描画されないので、透けて見えるはずがありません。
右側のグループは奥から手前の順に描画されるので、透けて見えるべき部分が先に描画されるためちゃんと透けて見えます。
半透明オブジェクト用のオプション、OBJ_LATE
(後から描画される)を試してみます。
透過色を使用したテクスチャを使用している場合は、このような処置が必要になります。
id_boxc(1)
、id_boxc(4)
のPRMSET_ALPHA
を無効にして、不透明オブジェクトに戻しておいてください。次のように記述して、不透明オブジェクトにOBJ_LATE
を追加してみます。
gpsetprm id_boxc(1), PRMSET_MODE, OBJ_LATE
これで他の半透明オブジェクトと同じタイミングで描画されるようになりました。 同じタイミングならオブジェクト作成順が優先されるので、手前の半透明オブジェクト描画後に描画されます。 透けているのに描画されませんね。
半透明オブジェクトどうしの重なりがある場合は、描画順を理解していないと想定通りの描画になりません。
理解していても想定通りの描画に出来ない場合もあります。オブジェクトを作成する順番を工夫してもダメな場合は、あきらめましょう。(´・ω・`)→マテリアルの設定変更参照。
まとめ
パラメータは、機能がたくさんある割に情報不足で困りますね。 ここであまり説明していない項目については、次のいずれかです。気になる方は、ご自身で調査してください。
- マニュアルに説明があるので十分じゃないかと思っている。
- 自分が使わなさそうだから保留した。
- よくわからない機能だから保留した。
- 面倒だから誰か調査してほしい。
OBJ_2D
を使ってる方はいるんですが、どこで使い方調べたんだろう。