おもちゃラボ

Unityで遊びを作ってます

【Unityシェーダ入門】オブジェクトが重なった部分をくり抜く

特定のオブジェクトと重なった部分を透明にくり抜くシェーダを紹介します。このシェーダを使えば、次のように、好きな形で別のオブジェクトをくり抜くことができます。

f:id:nn_hokuson:20170601215112j:plain:w500

オブジェクトの形にくり抜くためには

今回のシェーダの原理は非常に簡単です。まずは抜きたい形のオブジェクトをA、抜かれる側のオブジェクトをBとしておきましょう。

f:id:nn_hokuson:20170601215300p:plain:w300

まずは、オブジェクトAをデプスバッファにだけ書き込み、カラーバッファには書き込まないようにします。これにより、画面には表示されないけれどもデプスバッファには書き込まれた状態になります。

f:id:nn_hokuson:20170601215505p:plain:w400

続いて、オブジェクトBを通常通り描画します。デプスバッファにはすでにオブジェクトAの情報が書き込まれているため、この部分だけは描画されないことになります。

f:id:nn_hokuson:20170601215547p:plain:w400

シェーダの作成

まずはシーンビューに抜くオブジェクト(球)と、抜かれるオブジェクト(立方体)を配置しておきましょう。

f:id:nn_hokuson:20170601215727j:plain

続いてシェーダとマテリアルを作成します。プロジェクトビューで右クリックして「Cutout.shader」そのシェーダをアタッチしたマテリアル「Custom_Cutout」を作成します。「Cutout.shader」には次のプログラムを入力してください。

Shader "Custom/Cutout" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
    }

    SubShader {
        Tags {"Queue" = "Geometry-1"}

        Pass{
            Zwrite On
            ColorMask 0
        }
    }
}

シェーダプログラムが作成できたら、球にアタッチしてください。球が透明になったと思います。

f:id:nn_hokuson:20170601220036j:plain:w500

床は透明にせずに残したい

この方法では球と重なったオブジェクトが全てくり抜かれることになります。例えば、くり抜いた立方体の下側に床を表示したい場合はどうすればよいでしょうか。普通に床を描画すると床までくり抜かれてしまいます。

f:id:nn_hokuson:20170601220153j:plain

球の情報がデプスバッファに書かれることで、それ以降に描画するオブジェクトは描画されなくなるのでした。ということは、球の情報をデプスバッファに書き込む前に床を描画すれば良さそうです。

描画する順番はシェーダのRenderQueueで指定できます。床用のシェーダファイルとマテリアルを作成しましょう。床のシェーダファイルはプロジェクトビューで右クリックし、「Create」→「Shader」→「Standard Surf Shader」を選択して作成後、次のようにTagを書き換えてください。

	Tags { "Queue"="Geometry-2" }

これにより、Render Queueの値は次のようになり、床→球→立方体の順序で描画される様になります。

オブジェクト Render Queue
背景画像 1998
1999
立方体 2000

作成した床用のマテリアルを床オブジェクトにアタッチして実行すると、実行結果は次のようになります。

f:id:nn_hokuson:20170601215112j:plain

動かしてみるとこんな感じです!

f:id:nn_hokuson:20170601220240g:plain