😠

【Unityリファレンス読み下し】Skyboxを読む

2023/01/31に公開

これです。

Tシャツにもなっているので、Unityを触った事がない人でも見た事があるでしょう。
https://suzuri.jp/twoooooda/10228064/t-shirt/s/white?locale=en

このぼんやりとした青と灰色のコントラストは、我々UnityエンジニアのDNAに深く刻み込まれた、
霊的にも強く繋がっている共通の心象風景と言っても過言ではないのです。

はじめに

冗談はさておき、まじめにUnityをやり始めてから、かれこれ6年経ってますが、
ぶっちゃけSkyboxの事をよくわかっていないです。

いや、なにもわからない。俺は雰囲気ですらSkyboxをやっていない...

なのでここいらで一度、仕様だったりできる事だったりを整理してみようと思います。

まずは一次情報から確認せよ、とよく言われますし、公式リファレンスをディグります。

https://docs.unity3d.com/ja/2018.4/Manual/class-Skybox.html

Skybox は、広大に広がる世界に見せるため、画面全体を覆うラッパーです。

Skyboxは、ラッパーらしいです。
(確かにアーティストにこういうのいそうな気がしてきた。)
多分、「何かの間に挟まっているもの」って意味でラッパーって言っているんだろうけど、
わからない、たぶんあまり重要な話ではない気がする。

Unityの公式リファレンス、日本語なのに読めない事が多々ある。
結構同じ気持ちの人は少なからずいると思うので、今回の記事を皮切りに、
公式リファレンスを読んで深ぼってわからんとこを検証して解説する、みたいな連載にしていこうと思います。
順番とかはないです。興味が湧いたやつから順にやっていく。

プロパティ

公式リファレンスに載っているパラメータは、
デフォルトでUnityに入っている『Skybox/6 Sides』というシェーダーのプロパティのようです。

画像を6枚使って全天球画像を表現する仕組みになっているみたいですね。
んで、

  • 色合い
  • 明るさ
  • 縦軸の回転(景色を回すため)

これらが弄れるようになっています。

あくまでこれはこのシェーダーを使う場合の話であって、
『Mobile/Skybox』だと画像と描画順とGIのなんかかんかのパラメータしか弄れない。

詳細

細かい事が書かれていたので読んでみる。

スカイボックスは、地平線上の複雑な景色を印象深くするために、シーン全体の周囲に描画されます。スカイボックスは、すべての不透明オブジェクトが描画された後に、描画されます。スカイボックスのメッシュは、テクスチャ 6枚で構成されたボックスか、テッセレーションされた球のどちらかで描画されます。

スカイボックスは、すべての不透明オブジェクトが描画された後に、描画されます。
これ本当??
背景みたいなもんだから不透明オブジェクトの前に描画しないとダメくない??
自動翻訳間違ってんじゃないの〜?
と思ったので原文確認してみた。

Internally skyboxes are rendered after all opaque objects;

そんな事なかった。
どういう理屈なんだろう、ちょっと気になってきた。
フラグメントシェーダーで描画するレイヤーが2つある、みたいなこと?
適当にお豆腐置いて、FrameDebuggerで確認してみた。

う〜ん、まじだった。
正直理屈はよくわかっていないが、フラグメントシェーダーは最終的な描画に関わるものだと
ぼんやり思いこんでたから、必ずしもそういうことではない、という事が知れたのが良かった。
まじのまじで最後に処理されるのはポストプロセスのフラグメントシェーダーなのかな、きっと...

[1/31追記]
とか色々思ってたんですけど、
『不透明オブジェクト』ってはっきり言ってて、『透明オブジェクト』の時は恐らくその限りではない。
ちゃんと読めてないだけでした。
会社でこの件を話したところ、なぜこういう実装になってるのかというワンポイントアドバイスを得られました。

zバッファ書き込み書き込みoffって描画するとzバッファアクセスコストが半分になるから、背景不透明の最後に描くのは定番

とのことでした、学び。

スカイボックスを実装するには、スカイボックスマテリアルを作成します。次に、シーンにスカイボックスを加えるには、Window > Rendering > Lighting Settings の順に選択し、作成したものを Scene タブのSkybox Material に指定します。

これはまぁ、自分で作ったりアセットストアから手に入れたSkyboxとかを使いたければこうしてね、って話だな。

差し替えてみた、全然印象変わりますね

デフォルトのスカイボックスを上書きしたい場合は、Skybox Component をカメラに追加するのが便利です。例えば、2つのカメラを使ってスクリーンを分け、2番目のカメラに異なるスカイボックスを設定したい場合などです。スカイボックスコンポーネントをカメラに追加したい場合、カメラをクリックしてハイライトさせ、Component->Rendering->Skybox に行ってください。

へぇ、そんなことできるんだ。
スクリプトで切り替えれば良くない?とも思ったけど使い道があるのかもしれない。

こういうSkybox用のマテリアルを用意して、

カメラ2つ作って片方に「Skybox」コンポーネントをつけて、さっきのマテリアルをアタッチ。

できたね

もしかしたらクロスフェードっぽい演出ができるんかなと思って透明度弄ってみたけど、
このマテリアルではできなかった。
完全に前のSkyboxのバッファが上書きされてるのか、
単にTransparentに対応してないシェーダーってだけなのか...
そこら辺は深掘りする必要がありそう。

自作方法

方法としては2つあり、

  • CubeMapシェーダーを使う
    • パノラマ画像をCubeMapとして解釈して描画
  • 6Sidedシェーダーを使う
    • CubeMapよりも綺麗に作れる
    • 画像を自力で6枚用意しなければいけないのが面倒くさい

ぶっちゃけここの記事様がやり方書いてくれてるので、共有
https://www.lovehatetubaki.work/entry/Unity-skybox1

おすすめは6Sidedシェーダーらしい。
画像6枚用意するのがめんどいが、CubeMapより綺麗には作れるらしい。

自宅をSkybox化してみる。

iPhoneでテキトーに撮った自宅のパノラマ画像


全然下の方とかは撮れてない(きったねーので写したくないってのもある)し、
一周しきる前に撮影が終わってしまったので端と端が切れてしまっている。
素材としては最悪だがまぁいいだろ。
真面目に作ろうと思ったらInsta360とかで撮るのがいいんじゃなかろうか。

Unityにインポートして、然るべき設定をする。

マテリアル作ってシェーダーをSkybox/Cubemapにする。
どうせ素材汚いので。

実際にやってみるとこんな感じ。
水平方向には、端っこの切れ目が気になるくらいだが

上下は目も当てられない。
やっぱり素材が横長すぎたのが原因でしょうね。
スマホ(iPhoneSE2)でテキトーにやるとこれくらいの感じになってしまう。

おわりに

まだ気になってるのは

  • アニメーション付きのSkyboxは作れるのか

    • 無理ではないと思う。できなかったら法線内側の半球メッシュ作ってそれを被せれば良さそう
  • フェードイン・アウトっぽい実装をする方法

    • Skyboxをいくつか用意するというよりは、一個のSkyboxで複数のテクスチャを切り替える実装でいけばいいんかな
  • 6Sidedシェーダーで使う画像の作り方

    • 単純にだるくてやってない
    • 真面目に作ろうと思ったら必要になると思うので、まぁその時やるかな

とりあえず「1からSkybox作れ」って言われた時のとっかかりはできた気がする。

Discussion