5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Unity】StencilをImageEffectで利用するためにCommandBufferを使う

Last updated at Posted at 2018-06-09

以下の記事のCommandBuffer使う版対応です。
[Unity] ステンシルバッファをImageEffectで利用する方法

Stencil情報が破棄される前にCommandBufferで使いましょう
MSAA処理前なのでMSAAを有効にしていても大丈夫です
Unity2017.2.0f3 と Unity2018.1.1f1で確認しています

適用前
SnapCrab_NoName_2018-6-10_1-18-17_No-00.png
適用後
SnapCrab_NoName_2018-6-10_1-18-19_No-00.png

CubeとSphereに貼ってあるShader
ただのStencil描きこんでいるだけのUnlitです

Shader "Unlit/StencilUnlitShader"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
        _Stencil("Stencil", Int) = 32
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
            Stencil{
                Ref [_Stencil]
                Comp Always
                Pass Replace
            }		
		
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				fixed4 col = tex2D(_MainTex, i.uv);
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}

Cameraに張り付けているComponentで、
camera.AddCommandBuffer(CameraEvent.AfterForwardAlpha, buffer);
としているのでStencil情報が破棄される前に描きこめます

[ExecuteInEditMode, RequireComponent(typeof(Camera))]
public class StencilEffect : MonoBehaviour {
    public byte stencil = 32;
    private Material material;
    private new Camera camera;

    private CommandBuffer buffer;
    private int cachedScreenImageID;
    
    private void OnEnable() {
        Init();
        camera.AddCommandBuffer(CameraEvent.AfterForwardAlpha, buffer);        
    }

    private void OnDisable() {
        camera.RemoveCommandBuffer(CameraEvent.AfterForwardAlpha, buffer);
    }
    private void Init() {
        if (cachedScreenImageID == 0) { cachedScreenImageID = Shader.PropertyToID("_tempTex"); }
        
        camera = GetComponent<Camera>();
        
        if (material == null) {
            material = new Material(Shader.Find("Hidden/StencilEffect")) {
                hideFlags = HideFlags.DontSave
            };
        }
        material.SetInt("_StencilRef",(int)stencil);

        
        if (buffer == null){
            buffer = new CommandBuffer {name = "commandBuffer"};

            buffer.GetTemporaryRT(cachedScreenImageID, -1, -1, 0);

            buffer.Blit(BuiltinRenderTextureType.CameraTarget, cachedScreenImageID);
            buffer.Blit(cachedScreenImageID, BuiltinRenderTextureType.CameraTarget, material);
        }
    }    
}

StencilEffect.csで使っているShader
ステンシルテストが通ったところを赤っぽくしているだけです

Shader "Hidden/StencilEffect"
{
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Stencil("Stencil", Int) = 32
    }
    SubShader {

        Cull Off
        ZWrite Off
        ZTest Always



        Pass {
            Stencil{
                Ref [_Stencil]
                Comp Equal
            }
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            float4 frag (v2f i) : SV_Target {
                float4 col = tex2D(_MainTex, i.uv);
                col.r = 1;
                col.gb *= 0.5; 
                return col;
            }
            ENDCG
        }
    }
}

Windowsマシンから映像を出す目的のための調査だったので、モバイルなどでの動作の確認はしてません。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?