見出し画像

【cluster】覗く方向によって異なるものが見えるオブジェクトを作ってみた!

(はじめに)

こんにちは、clusterのこくsayです。最近はVRCのこくsayでもあります。
本記事では、『Stencil(ステンシル)を使って、覗く方向によって異なるものが見えるオブジェクト』の作り方を紹介します。
ちなみに、clusterの見える見えないについては新澤オルトさんがこちらで解説されています。今回はオルトさんの記事でいう3番にあたるものです。
ソースコードをいじるため、何でもいいのでコードエディタを使用することをおすすめします。本記事ではVisual Studioを使用しています。(ほぼコピペで済みますが…)
また、本記事の内容はclusterのワールドでの使用を想定していますがVRChatでも同じ手順で同じことができると思います。

Stencil(ステンシル)ってなに!?

言葉で説明するより見てもらったほうが早いと思います。まずは下の動画を御覧ください。今回この記事で作るものも動画と同じようなものになります。

この動画では、条件Aを満たした場合はAのオブジェクトのみを描画し、条件Bを満たした場合はBのオブジェクトのみを描画し…..ということをシェーダーで設定し描画しています。(今回は、動けばいいだろぉ!?ということで説明をかなり簡潔に書きましたが、詳しく知りたい方はこちらをどうぞ。)

早速作っていきましょう!

1:配置

まず、Scene上にQuadとCubeを配置して、Quadの名前をwindowにします。
最終的に、このwindowを通して覗いた場合のみCubeが見える(通さないと見えない)というのが完成形です。

Quad(window)を手前に、Cubeを奥に配置する。

cubeが大きすぎるためcubeのScaleを(x,y,z)=(0.3,0.3,0.3)に設定します。
次に、下の画像を参考にcubeを囲うようにwindowを前後左右の4面に複製して配置します。
また、inspectorのcubeを選び、ctrl+D でcubeを3つ複製します。

Quad(window)は表裏があるため全て外側が表になるように注意!
(以降の画像ではwindow,cube共に1つしか乗っていませんが)

この時点でHierarchyにwindowが4つcubeが4つ存在しているはずです。

『4:他の条件を作成』まではwindow(1)~(3)とcube(1)~(3)は使用しないので非アクティブ化しておきましょう。(☑を外す)

2:マテリアル作成

次にwindowのマテリアルを作成します。 project内で右クリック→Create>Shader>Unlit Shaderを選択 shaderの名前をwindowShaderに変更。 project内のwindowをダブルクリックでコードエディタを起動 5行目に

_Mask ("Mask", Int) = 1

を追加。
15行目以降に、

                ColorMask 0
                ZWrite Off
             Stencil 
             {
               Ref [_Mask]
               Comp Always
               Pass Replace
             }

を追加。windowShaderはこれで完成です。(今書いたコードについてはStencil(ステンシル)ってなに!?のところで紹介しているサイトに詳しく書かれていますのでそちらを参照してください。)

windowShader

次にCubeのマテリアルを作成していきます。
project内で右クリック→Create>Shader>Standard Surface Shaderを選択 shaderの名前をcubeShaderに変更。
project内のcubeShaderをダブルクリックでコードエディタを起動 5行目に

_Mask("Mask", Int) = 1

を追加。
16行目に

        Stencil 
        {
            Ref [_Mask]
            Comp Equal
        }

を追加。cubeShaderはこれで完成です。(今書いたコードについてはStencil(ステンシル)ってなに!?のところで紹介しているサイト…[省略])

cubeShader

3:マテリアル割り当て

早速、マテリアルを当てていきましょう!
windowShaderを選択して右クリック→Create>Materialを選択。
名前をwindowMaterialに。
cubeShaderも同じ手順で、名前をcubeMaterialに。
windowにwindowMaterialを、cubeにcubeMaterialを割り当てます。
お互いのマテリアルの中を見て、一番上に表示されているMaskの値が同じ値(1)になっていることを確認。
下の画像のようにwindowを通した場合のみcubeが見えたら成功です。

windowを通すとcubeが見える
windowを通ってないcubeの右半分は見えない

4:他の条件を作成

先程、『条件Aを満たした場合はAのオブジェクトのみを描画し、条件Bを満たした場合はBのオブジェクトのみを描画し…..ということをシェーダーで設定し描画しています』と説明しましたがその条件というのがMaskの値になります。windowのMaskの値とcubeのMaskの値が一致する場合のみ描画するということです。
これを使って他の条件を作成してみましょう。
まず、Hierarchyの非アクティブにしていたものを全てアクティブ化(☑を入れる)
projectより、windowMaterialをctrl+Dで3つ複製
windowMaterial1のMaskを2、windowMaterial2のMaskを3、windowMaterial3のMaskを4に設定。(ややこしい…笑)
Hierarchyに存在するwindow(1)~(3)に作成したマテリアルを割り当てる。

window~window(3)


cubeMaterialも上記と同じ手順で作成、割り当て。
加えて、全部白色だと変わってるのかわかりにくいためcubeはマテリアルごとに色を変えます。Maskの下にcolorがあると思うので4つ異なる色に変更します(お好きな色にどうぞ)

cubeMaterial~cubeMaterial(3)


5:完成

これで覗く方向によって違うものが見えるようになりました!
今回はデフォルトのshaderを改変してStencilの機能をつけてあげましたが、もちろん既存のshaderにStencilの機能を付け加えることもできます。

おまけ+注意事項

clusterでunity製のワールド作成をしている人であればお世話になっている人も多いと思われる、ほびわんさんの【無料】ObjectSkyboxシェーダー
今回はおまけでこのshaderにもStencil機能を追加してみましょう。やることは先程と同じですが記載する場所を間違えるとエラーになってしまうため正しい場所に書くようにしましょう!(また、Shaderによっては規約によって改変が禁止されている場合もあります。規約を確認した上で改変をしましょう)

気をつけることは以下の2つのみです。

  • properties内に_Maskを記載する

  • Stencilの記述はSubShader内で行い、CGPROGRAMよりも前に記載する

(動くからこの基準でやっていますが、著者自身もなぜこうしなければいけないのかいまいちわかっていません…圧倒的勉強不足…Shaderつよつよの方、間違ってたら教えてください…)

まず、こちらをunityにインポートします↓

HobionePlanet/Shaders/ObjectSkyboxShader_v1.1よりObjectSkyboxCubeのShaderをダブルクリックしてコードエディタを起動
5行目に


_Mask("Mask", Int) = 1

を追加。

5行目に_Mask追加

39行目に

     Stencil            
     {
         Ref [_Mask]
         Comp Equal
     }

を追加。以上で完成です。

39行目にStencil…を追加

これで保存してunityに戻りマテリアルをセットしてあげるとちゃんと機能していることがわかると思います。


まとめ

お疲れ様でした。
今回は簡潔に書こうと思って書き始めましたがかなり長くなってしまいました…
また、本記事の著者はshader(unity)に関して素人であるため誤った表現や推奨されない処理を記述している可能性があります。
有識者の方で、重大な問題を発見された方がいらっしゃいましたらご連絡ください。
ここまで読んでいただきありがとうございました。


この記事が気に入ったらサポートをしてみませんか?