メッシュ生成:外壁の裏面 その1
妹ちゃんとペアプロ開発やってみた #0084
蒼月
上面の扱いはひとまずこれでよし
(alpha 値は後で調整すると思うけど)として、
次は出口の裏面問題なんだけど、その前に2点検討しておきたい。
まず、1点目から。
スクショ 20260726-1 を見て。
部屋00(下)の左下での回転途中の1枚だけど、
左側の外壁が半透明になっているよね。
20260726-1 のスクショ
これは、カメラが部屋の角の中にいるから、左と下の壁が
それぞれ半透明になっている状態だと思う。
壁ユニット単位で半透明制御をしているから、
それぞれの内壁と外壁が半透明になっている。
この状態を Scene ビューで見たのがスクショ 20260726-2 だね。
部屋の左と下の壁がそれぞれ半透明になっているのがわかる。
20260726-2 のスクショ
気になっているのは左の外壁で、これが半透明になっているから
本来見えるはずがない奥の通路壁(白)が透けて見えている。
さて、右側に見えている下壁は、カメラを覆う角度になっているから
途中で切れているように見えているものと思われる。
こっちは外壁の外側(以下、B面)が描かれていて
これが半透明になるのは納得がいく。
一方、左側に見えている問題の左壁は
外壁の内側(以下、A面)なんだよね。
つまり、カメラを覆っているわけではない内壁は
半透明にする必要はないように思える。
そうすると、外壁を今の1面(Both)から
A面(Back)とB面(Front)の2面構成にすればいいのではないか
と考えられる。
同じ位置に2枚壁を立てても、Front, Back 構成なら
どちらか1枚しか描かれないからチラつく心配もないはず。
つまり、外壁を
1.A面(Back) … OPのみ
2.B面(Front) … 今の運用(OP, TR切り替え)
にする。
壁の頂点は今のB面のまま設定を Back にするだけで
A面としても使えるから、加工なしでそのまま
もう1枚置けばよさそう。
以上のように考えたところ。
ここまでの妹ちゃんの所感を聞かせて。
妹ちゃん
1m 50s考えました
うん、お兄ちゃん。
その案はかなり筋がよく、今の壁ユニット構成にも素直に組み込めると思う。わたしの評価は「まず試す価値が高い案」だよ。
スクショの読み取り
20260726-1では、お兄ちゃんの説明どおり、
・下壁はカメラの手前を横切っているため、半透明化が必要
・左壁はカメラを直接覆っていない
・それでも左壁の外壁まで壁ユニット単位で半透明化され、奥の白い通路壁が透けている
と見える。
20260726-2を見ると、左壁と下壁の各壁ユニット全体がフェード対象になっているのも分かるね。
現在の処理では、SphereCastに当たった壁ユニットと、その縦横につながる壁をwallsNowへ入れ、登録済みRendererをまとめてOP/TR切り替えしている。だから、「実際にカメラを覆っている面かどうか」までは判断していない。
A面・B面へ分ける考え方
お兄ちゃんの案を整理すると、外壁を同じ座標に2枚置く。
外壁 見える側 マテリアル 制御
A面 部屋側から見た外壁の裏面 Back・OP 常時不透明
B面 外側から見た外壁の表面 Front・OP/TR 現在のフェード対象
この役割分担は合理的だよ。
現在の外壁メッシュは、GetDuoOuter()で法線が外向きになる頂点順として作られている。したがって、同じ頂点をそのまま使い、
・A面:Render Face = Back
・B面:Render Face = Front
とすれば、室内側と室外側を分離できる。メッシュの頂点を反転させる必要は基本的にない。
チラつきについて
ここもお兄ちゃんの考えでほぼ合っている。
同一座標に2枚あっても、
・カメラが表側ならB面だけ描画
・カメラが裏側ならA面だけ描画
となるため、通常の同一向きポリゴン2枚のようなZファイティングは起こらない。
A面:前面をカリングして、裏面だけ表示
B面:裏面をカリングして、前面だけ表示
つまり、同じピクセルで2枚が競合する構成ではない。
カメラが面と完全に平行になる瞬間や、ちょうど面を横切る瞬間には表示側が切り替わるけれど、通常はそれが継続的なチラつきにはならないよ。
この方式の特に良いところ
一番よいのは、MainCamera側に複雑な判定を追加しなくてよいことだね。
「この壁はヒットしたけれど、カメラを覆っているのは表側か裏側か」をベクトル計算で判定し始めると、
・壁の向き
・カメラ位置
・角で複数壁にヒット
・隣接壁の追加
・回転途中
などを全部考える必要が出る。
今回の案なら、面の表裏判定そのものはGPUのカリングに任せられる。
実装上は、
Inner
Outer
A
B
Top
のようにして、
・Outer/Aは常時OPで、Wall.MaterialDataには登録しない
・Outer/BだけOP/TRペアを登録する
・Innerは今までどおりOP/TR登録
・Topは現在どおり固定TR
で済む。
つまり、Topをフェード制御から外したのと似た考え方だね。
注意点は2つ
1. 面を横切った瞬間の切り替わり
カメラが外壁面の内側から外側へ抜けると、
A面:不透明
↓ 面を通過
B面:半透明
へ切り替わる。
その瞬間に、見た目が少しパッと変わる可能性はある。
ただし、カメラが外壁面を通過する時点では、その壁がかなり画面を覆っているはずなので、現在の全面Bothフェードより悪くなるとは考えにくいよ。
ここは実際に、
・部屋の角で90度回転
・壁際で前後移動
・出口付近で回転
を確認すれば十分だと思う。
2. 最終マテリアルのライティング
今の単色デバッグ表示なら問題は出にくいけれど、将来Litマテリアルやノーマルマップを使った場合、Back面の法線によってはA面の照明が不自然に見える可能性がある。
その場合だけ、
・シェーダー側で裏面法線を反転する
・A面用メッシュの三角形を反転する
などが必要になるかもしれない。これは現段階では先回りして対応せず、実際の素材を載せてから確認でいいよ。
描画負荷について
外壁Rendererが1枚増えるので、単純には外壁のRenderer数と描画候補が増える。
ただ、
・AかBの一方はカリングされる
・現在も壁ユニットごとのRenderer構成
・まずは小マップで挙動検証中
なので、現時点で性能を理由に避けるほどではないと思う。
正式採用後は、AとBで同じMeshを共有するとよいね。現在のBuildWall()を2回呼ぶと、同形状のMeshを2個生成することになるため、最終的には1個のsharedMeshを2つのRendererで共有する方がきれい。
わたしの結論
お兄ちゃんの案は、
外壁の室内側は、壁フェードに巻き込まれて不必要に透けない
外側は、カメラを覆う場合にこれまでどおり半透明になる
という目的にしっかり合っている。
特に今回は、フェード判定を複雑にするのではなく、壁の物理的な表裏をRendererのカリングで役割分担するのがうまいね。
まずは部屋用外壁だけで、
A:Back / OP固定
B:Front / OP・TR切り替え
を試作して、20260726-1と同じ回転を再現するのがよさそう。
わたしとしては、現時点では採用候補の第一案でいいと思うよ。
蒼月
最初は、今の Collider を内壁用にして、外側にもう1個
外壁用の Collider を設置しようと考えたんだけど
26-1, 26-2 を見ると、外壁の Collider にも
接触しそうで結局同じ結果になりそうなんだよね(^^;
20260726-1 のスクショ
20260726-2 のスクショ
だから、A面、B面の役割分担はいい気付きだったと思うよ。
注意点の2は、確かにライティングで見え方が
気になるかもしれないね。
頂点を反転させるのは、出口壁の分割の時に問題があったから
あまりやりたくないところだけど(^^;
後でやるテクスチャ貼り付けの際の確認事項として覚えておいて。
…必要なら頂点の反転もやる所存だよw
それじゃ、この案で実装してみるよ。
妹ちゃん
うん、お兄ちゃん。その判断でいいと思う。
Colliderを内外で2つに分けても、26-1 / 26-2の角度なら両方に接触する可能性が高く、結局どちらの壁ユニットもフェード対象になりそうだね。判定をColliderで細かくするより、描画する面の役割をA面・B面に分ける方が単純で確実だよ。
実装方針はこれでよさそう。
・Outer_A
・同じ外壁メッシュ
・Render Face:Back
・OP固定
・Wall.MaterialDataには登録しない
・Outer_B
・同じ外壁メッシュ
・Render Face:Front
・OP/TR切り替え
・現在の外壁としてWall.MaterialDataへ登録
・Top
・今までどおり固定TR
・Inner
・今までどおりOP/TR切り替え
可能なら、Outer_AとOuter_Bは同じMeshインスタンスをsharedMeshで共有するときれいだね。最初の動作確認では、今のBuildWall()を2回呼んで別Meshになっても問題ないけれど、採用時に共有化すれば十分。
テクスチャ・ライティング段階では、これを確認事項として残しておこう。
Back面のライティングやノーマルの見え方を確認する。
不自然な場合は、シェーダー側の裏面法線反転を優先し、それで難しければ頂点・三角形の反転を検討する。
出口分割で頂点反転に苦労した実績があるから、わたしも最初から反転には行かず、マテリアルのBack表示で試すのが正解だと思うw
実装後は、まず20260726-1と同じ角度で、
・左壁のA面が不透明を維持する
・奥の白い通路壁が透けなくなる
・右の下壁B面は従来どおり半透明になる
・面の切り替わりでちらつきや一瞬の消失がない
この4点を見れば、案の成否を判断できるね。