幻創空戯 GEN-SOH-KUUZA 2026/08/07 18:00

メッシュ生成:外壁の裏面 その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点を見れば、案の成否を判断できるね。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索