Unityのレンダーテクスチャを使って鏡を作成する

記事内に広告が含まれています。

以前の記事でReflection Probeを使って鏡を作成しました。

UnityのReflectionProbeを使って鏡を作ってみる
UnityのReflectionProbeを使って鏡を作り、キャラクターを動かして映るかどうかを試していきます。

今回はレンダーテクスチャを使って鏡の機能を作成したいと思います。

レンダーテクスチャはカメラに映った映像をそのままテクスチャに出力し、そのテクスチャをマテリアルに設定してカメラのリアルタイムな映像をゲームオブジェクトに流すことが出来る機能です。

レンダーテクスチャを使ってカメラに映る映像をリアルタイムに描写する
Unityでカメラにレンダーテクスチャを設定しランタイムでテクスチャを更新し表示します。

なので、鏡に見立てたゲームオブジェクトにカメラを配置し、その映像を鏡にレンダーテクスチャを使って映せば鏡の機能が出来そうです。

実際には少し問題が出ますが、とりあえず作ってみましょう。

スポンサーリンク

鏡機能を作成する

それでは鏡機能を作成していきます。

鏡用のゲームオブジェクトを作成する

まずは鏡のゲームオブジェクトを作成します。

ヒエラルキー上で右クリックから3D Object→Quadを選択し、名前をMirrorとします。

Mirrorゲームオブジェクトを選択し、インスペクタのTransformの値を以下のように設定します。

レンダーテクスチャミラーのゲームオブジェクトのTransform

Scaleを調整して鏡のサイズを変更し、Positionを調整して地面に立つような感じにします。

カメラゲームオブジェクトを配置

次に鏡に映す映像を取るカメラを作成します。

ヒエラルキーでMirrorゲームオブジェクトを選択した状態で右クリックからCameraを選択します。

CameraのTransformのRotationを調整し、鏡の前面にCameraのZ方向(青矢印)が向くようにします。

今回は以下のようにしました。

鏡に映す映像を撮るカメラのTransform

シーンビューを見ると以下のように鏡の前面をカメラが映すようにします。

鏡の前面を映すようにカメラの角度を調整する

レンダーテクスチャの作成とカメラへの設定

カメラに映った映像をレンダーテクスチャに出力する必要があるので、新しくレンダーテクスチャを作成します。

Assetsフォルダ内で右クリックし、Create→Render Textureを選択し、名前をMirrorRenderTextureとします。

鏡に映す映像の精度を上げるにはMirrorRenderTextureのインスペクタでSizeの値を増やします。

鏡に映る映像の精度を上げる

デフォルトでは256なので減らす時も増やす時も2で割るか掛けるかした数値を設定します。

例えば512です。

出来たMirrorRenderTextureを先ほど作ったカメラのOutput Textureにドラッグ&ドロップしてカメラ映像をMirrorRenderTextureに出力します。

CameraのOutput TextureにMirrorRenderTextureを設定する

Unityを実行するとMirrorRenderTextureにリアルタイムな映像が出力されていきます。

鏡用マテリアルの作成と設定

MirrorRenderTextureに映像が出力されるようになりましたが、この映像を鏡のゲームオブジェクトに表示する必要があります。

鏡ゲームオブジェクトに設定するマテリアルを作成します。

Assetsフォルダ内で右クリックからCreate→Materialを選択し、名前をMirrorとします。

MirrorマテリアルをヒエラルキーのMirrorゲームオブジェクトにドラッグ&ドロップするか、MirrorゲームオブジェクトのインスペクタでMesh RendererコンポーネントのMaterialsのElement0にMirrorマテリアルをドラッグ&ドロップして設定します。

次にAssetsフォルダにあるMirrorマテリアルのBaseにMirrorRenderTextureを設定します。

こうすることでMirrorRenderTextureにリアルタイムに出力されたテクスチャがマテリアルのBaseに設定され、Mirrorゲームオブジェクトにその映像が表示されるようになります。

床を設置して、キャラクターを配置し、鏡に映像が流れるかを確認してみてください。

鏡に映る映像が逆になる

鏡が出来たような気がしましたが、実際にはカメラに映った映像をそのまま鏡ゲームオブジェクトに表示している為、実際の鏡のようにはならずキャラクターが右に移動すると鏡では左側に移動しているように映ります。

カメラの映像をそのまま鏡ゲームオブジェクトに流すと左右反転してしまう

つまり鏡では左右反転して映像を映さないといけません。

鏡ゲームオブジェクトのScaleを調整して反転する

鏡に映る映像を左右反転させる為にヒエラルキーのMirrorゲームオブジェクトを選択し、インスペクタのTransformのScaleのXの値に-を付けて反転させます。

鏡のTransformのScaleのXにマイナスを付けて反転させる

ScaleのXの数値にマイナスを付けると映像が反転します。

TransformのScaleのXの数値にマイナスを付けて映像が反転した

シェーダーグラフを使って映像を反転する

鏡ゲームオブジェクトのTransformのScaleのXの値にマイナスを付けて反転させることは出来ましたが、Scaleを変更したくない場合や鏡に映る映像にエフェクトを加えたい時はシェーダーグラフを使って左右反転をさせることも出来ます。

シェーダーグラフの使い方については以下の記事を参照してください(URPやHDRP等のスクリプタブルレンダーパイプラインでないと使用出来ません)。

今回はUniversal Render Pipelineに設定したプロジェクトで作成しています。

Unityのシェーダーグラフについて
Unityのシェーダーグラフの使い方と個々のノードについて見ていきます。

映る映像を左右反転させる為にUVについて考えます。

UVMap概要

テクスチャのUVは横軸にU、縦軸にVを取り、それぞれ0~1の値の位置を持ちます。

なので、左右反転させる為にはUの値を1から引けば左右の位置が逆になります。

例えば0の位置であれば一番左ですが、1から引いて1-0=1で一番右に移動し、

1の位置であれば1-1=0で一番左になります。

これをシェーダーグラフで作成していきます。

Assetsフォルダ内で右クリックからCreate→Shader→Universal Render Pipeline→Lit Shader Graphを選択し、名前をMirrorとします。

このMirrorをダブルクリックしシェーダーグラフのウインドウを開きます。

表示するテクスチャをマテリアルのインスペクタで設定出来るようにしたい為、Mirrorシェーダーグラフに_MainTextureという名前のテクスチャプロパティを作成します。

Mirrorにテクスチャプロパティを作成する

テクスチャを反転し表示する処理を以下のように作ります。

テクスチャを左右反転して表示するシェーダーグラフの処理

_MainTextureプロパティをグラフ上にドラッグ&ドロップし、Sample Texture 2DのTextureに接続します。

UVノードからSplitノードを使ってUとVの成分を取得し、RがUなのでOne Minusノードを使って1から引きます。

その計算した値と、Vの成分からVector2の値を作り、それをSample Texture 2DのUVに接続します。

これで左右反転が出来たので、Sample Texture 2DをFragmentのBase Colorに接続します。

One Minusノードを使わずに、Invert Colorsノードを使っても同じように出来ます。

Invert Colorsノードを使った左右反転

Mirrorマテリアルのシェーダーを変更する

AssetsフォルダのMirrorマテリアルを選択し、インスペクタでShaderの部分を押し、Shader Graphs→Mirrorを選択します。

Mirrorマテリアルのシェーダーを変更する

Mirrorマテリアルの_MainTextureにMirrorRenderTextureを設定します。

Mirrorマテリアルの_MainTextureにMirrorRenderTextureを設定する

先ほどMirrorゲームオブジェクトのTransformのScaleのXに-2を設定して左右反転させましたが、今度はシェーダーグラフで反転させるようにしたので、ScaleのXは2に戻しておきます。

Unityを実行して動かすと以下のように映像が左右反転され鏡の機能が出来ました。

シェーダーグラフで映像を左右反転させた結果

鏡機能の調整

鏡機能は出来ましたが、鏡に主人公を近づけると鏡には実際のキャラクターよりも大きく表示されています。

実際のキャラクターよりも鏡に大きく表示されてしまう

そこで少し調整してリアルな感じの表示にしたいと思います。

カメラの位置が鏡の表面と同じ位置にある為に実際よりも大きく表示されているので、カメラを鏡の後ろに移動させ鏡に映る映像を小さくします。

カメラの位置を鏡の位置より少し下げる

上のような位置にカメラを動かしました。

鏡ゲームオブジェクトが邪魔になる

カメラを鏡の後ろに移動させましたが、鏡の後ろ側を撮影するだけでキャラクターを写せなくなりました。

そこで、鏡用のカメラは鏡のゲームオブジェクトを映さないようにします。

Mirrorゲームオブジェクトを選択し、インスペクタのLayerでAdd Layerを押し、新しくMirrorレイヤーを作成し、Mirrorゲームオブジェクトに設定します。

MirrorゲームオブジェクトにMirrorレイヤーを設定する

次にMirrorの子のCameraを選択し、RenderingのCulling MaskでMirrorレイヤーのチェックを外します。

鏡の子のカメラのCullingMaskでMirrorレイヤーのチェックを外す

これでMirrorゲームオブジェクトの子のカメラではMirrorレイヤーを設定したMirrorゲームオブジェクトが写らなくなります。

Unityを実行し、鏡の子のカメラの位置をシーンビューで調整し、Transformの右の3つの丸を押して、CopyからPositionを選択してUnityの実行をやめた後にTransformの3つの丸を押しPaste→Positionを選択し貼り付けます。

今回調整して、以下のようになりました。

鏡の子のカメラ位置を再調整

実行して試すと以下のような感じです。

鏡に映る映像をよりリアルにした結果

鏡の後ろ側に移動してもキャラクターが写ってしまう

鏡に映るキャラクターが鏡の後ろ側に周っても鏡にキャラクターが写ってしまいます。

これはカメラが鏡の後ろ側にあり、映す範囲が鏡の後ろ側からある為です。

カメラの撮影範囲が鏡の後ろ側からになっている

そこでMirrorの子のカメラの映す範囲を鏡のあたりからにします。

Mirrorの子のCameraのCameraコンポーネントのProjectionのClippingPlanesのNearを調整して鏡の前あたりから映るように変更します。

カメラの撮影範囲を鏡の前あたりからにする

これでキャラクターが鏡の後ろ側に移動しても鏡に映らないようになりました。

鏡の後ろ側から表側に出てきてしまう

最後の問題としてMirrorゲームオブジェクトはQuadを使って作成しており、初期状態ではコライダがMesh Collider(メッシュの形状のコライダ)となっています。

コライダが衝突するのはコライダの表面だけで、QuadのMesh Colliderの場合は片方の面しか衝突しません。

そこでMesh Colliderコンポーネントを削除し、Box Colliderコンポーネントに変更して鏡の前面と後面両方で衝突するようにします(Box Colliderでは厚みがありボックスの外側が表面で衝突します)。

MirrorゲームオブジェクトのMeshColliderをBoxColliderに変更する

Box ColliderのSizeのZに少し幅を持たせます。

これはキャラクターを鏡の後ろから衝突させた時にキャラクターの一部が鏡の前面に見えてしまうのを避ける為です。

MirrorゲームオブジェクトのBoxColliderに少し幅を持たせる

実際のBox Colliderの範囲は上のような感じです。

今回はQuadで作ったMirrorゲームオブジェクト自体にBox Colliderを取り付けましたが、Mirrorゲームオブジェクトの後ろ側に鏡を貼り付ける何らかのオブジェクトを用意し、鏡の後ろ側への侵入自体をさせないようにする方がいいかもしれません。

真実の鏡を作成する

鏡機能が出来たので最後に真実の鏡を作成してみます。

真実の鏡は本当の姿を映す鏡です。(´Д`)

ヒエラルキーのキャラクターをCtrl+Dキーを押して複製し、まったく同じアニメーションや動きをする別のキャラクターを作ります。

今回のキャラクターはスタンダードアセットのThirdPersonControllerのキャラクターを使います。

複製したThirdPersonControllerの名前をRealCharacterに変更します。

真実の姿用のキャラクターを複製

Assetsフォルダ内で右クリックからCreate→Materialを選択し、名前をRealとします。

Realマテリアルを選択しインスペクタでBase Map横の色の部分を押し赤色にし、Normal MapにEthan Normals、Occlusion MapにEthanOcclusionを設定します。

RealマテリアルにEthan系のテクスチャを設定する

RealCharacterの子のEthanBodyとEthanGlassesにRealマテリアルを設定します。

お互いのキャラクターが衝突しないようにする

レイヤーに新しくPlayerとRealを作ります。

ヒエラルキーの元のキャラクターのThirdPersonControllerとその子であるEthanBody、EthanGlassesのインスペクタのLayerをPlayerに変更します。

RealCharacterとその子のEthanBody、EthanGlassesのインスペクタでLayerをRealに変更します。

ThirdPersonControllerとRealCharacterのTransformをまったく同じにします。

まったく同じ位置にいるのでお互いがぶつかり合ってしまいます。

そこでPlayerレイヤーとRealレイヤーのコライダがお互いに衝突しないようにします。

UnityメニューのEdit→Project SettingsでPhysicsタブを選択し、Layer Collision MatrixでPlayerとRealが交差する部分のチェックを外します。

PlayerレイヤーとRealレイヤーが衝突しないようにする

これでお互いが衝突しなくなりました。

カメラに映るレイヤーを指定する

鏡に真実の姿であるRealCharacterを映すにはMirrorの子のCameraのRenderingのCullingMaskでPlayerのチェックを外せばいい事になります。

また、MainCameraのRenderingのCullingMaskでRealのレイヤーのチェックを外せばメインカメラにRealCharacterは映らなくなります。

やり方は先ほどMirrorの子のカメラでMirrorレイヤーを外した時と同じなので、同じように設定してください。

これでMainCameraにはThirdPersonController、鏡にはRealCharacterが写ることになります。

真実の鏡機能を作った結果

これで機能が出来ました。

上のようになります。

真実の鏡と言ってもカメラによって映す対象を変更しただけです。(^_^;)

今回の場合は同じ見た目ですが、見た目自体を変更しても出来ます(ただし移動や回転しても同じ位置や回転になるという前提です)。

終わりに

今回鏡のゲームオブジェクトはQuadから作っていますのでオブジェクトを形成する頂点が少ないです。

シェーダーグラフで頂点シェーダーを使って頂点に何らかの処理をさせたい場合はProBuilderや3DCGソフト等を使って頂点が多いオブジェクトを使う必要があります。

今回の場合は左右を反転させるフラグメント(ピクセル)シェーダーしか使っていないので特に問題はありません。

タイトルとURLをコピーしました