原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【Unity】ステンシルバッファを使って窓を作る

f:id:Karvan:20210608213544j:plain

全く話題にならない神ゲーム

後学の為に色んな実況者のゲーム実況を観ていたらYouTubeのお勧めが何故かVtuberの切り抜きで溢れている皆さんこんにちは。ロックマン2の実況が面白くて色々観てたらこうなった。でも、Vtuber同じような名前大杉。

そんな中、久しぶりに購入したゲームが神ゲーでした。タイトルは『The Pathless(ザ・パスレス)』。最近流行ってきたトゥーン調のオープンワールドゲームで、『ABZU』の開発会社による新作アクションパズルゲームです。

f:id:Karvan:20210608213647j:plain

美しいグラフィックと爽快感のある操作性が最大の魅力で、フィールド内を移動するだけでも楽しい。加えてフィールド内に点在するパズルもプレイヤーの観察力を問われる内容で程よい難易度。本当に神ゲーと呼ぶにふさわしいと思うのですが、巷では全く話題になってません。実況動画も攻略サイトも殆どないし。

思うにオープンワールドながらもゲームのメインがパズルなのでボス戦以外に戦闘とかないし、NPCと会話や取引するみたいなイベントもなく全く実況向きでない、実際にプレイしてみないと良さが殆ど伝わらない事が原因なのではないかと。

個人的にあまりに惜しいのでこのブログで紹介しています。
とにかく爽快感のあるゲームがやりたい方、異世界を自由に探索するゲームに興味がある方にはうってつけのタイトルだと思いますので、是非、プレイしてください。

 

 ステンシルバッファ

unityのシェーダでステンシルバッファは描画の際に当該のピクセルを画面に表示するかしないかを決める「マスク」を設定する役目を持ちます。

要はマスクなので「描画したい部分」「描画したくない部分」を明確に定義できるというわけです。

ステンシルバッファの操作はStencilのプロパティを使用します。Stencilのプロパティの宣言は次のようになります。

Ref ステンシルに書き込む値
Comp 使用する比較関数
Pass 比較関数が真のときにの操作

 

 ・比較関数

Greater ステンシル値がバッファ値より大きいピクセルのみレンダリング
GEqual ステンシル値がバッファ値以上のピクセルのみレンダリング
Less ステンシル値がバッファ値より小さいピクセルのみレンダリング
LEqual ステンシル値がバッファ値以下のピクセルのみレンダリング
Equal ステンシル値がバッファ値と等しいピクセルのみレンダリング
NotEqual ステンシル値がバッファ値と等しくないピクセルのみレンダリング
Always 常にステンシル テストは成功
Never 常にステンシル テストは失敗

 

・処理

Keep バッファの現在コンテンツを保持します
Zero バッファにゼロを書き込みます
Replace ステンシル値をバッファに書き込みます
IncrSat バッファの現在値を増分させる
DecrSat バッファの現在値を減分させる
Invert すべてのビットを無効にする
IncrWrap バッファの現在値を増分する。値がすでに 255 の場合は 0 にする
DecrWrap バッファの現在値を減分する。値がすでに 0 の場合は 255 にする

 

窓を作る

「描画したくない部分」を作れると言う事は3Dモデルの形状を変更せずに穴を開けられる、と言う事でそれを利用して窓を作ってみます。手順は

  1. 窓となるオブジェクトにStencilでマークするシェーダを適用する
  2. 壁側のオブジェクトにはStencilでマークされた場所以外を描画するシェーダを適用

となります。

まず最初に窓側のオブジェクト用に透明shaderを作ります。

Shader "WriteStencil"
{
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
            
           #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                // 透明にする
                return fixed4(0, 0, 0, 0);
            }
            ENDCG
        }
    }
}

 このシェーダにStencilのプロパティを追加します。(CGPROGRAMの上あたり)

// ステンシルバッファの設定
Stencil
{
    // ステンシルの番号
    Ref 2
    
    // Always: このシェーダでレンダリングされたピクセルのステンシルバッファを「対象」とするという意味
    Comp Always
    
    // Replace: 「対象」としたステンシルバッファにRefの値を書き込む、という意味
    Pass Replace
}

 

壁を作る

壁用に標準的なStandardシェーダを作ります。これはCreateメニューから選んで作ることができます。

f:id:Karvan:20210608215255p:plain

 

この作成したStandardシェーダにStencilのプロパティを追加します。

// 壁側のStencil
Stencil
{
    // ステンシルの番号
    Ref 2
    
    // NotEqual: ステンシル番号がバッファ値と等しくないステンシル番号のピクセルのみレンダリング
    Comp NotEqual
}

 

 結果

作った窓シェーダーと壁シェーダーをそれぞれ3dモデルに適用してみます。

f:id:Karvan:20210608215756g:plain

壁を透過して背景が表示されているのが分かると思います。
ステンシルバッファを利用してモデルを変更することなく窓を作ることができました。

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。