[Unity] Standard.shaderを改良して裏面描画

UnityのStandard.shaderを改良する機会があったのでメモ

Unityのマテリアルは、デフォルトでStandard.shaderというUnity本体のビルトインシェーダーが設定されます。
このシェーダーは汎用的な事が色々できて便利なのですが、裏面が描画されません。

このようにCubeのようなオブジェクトに対して、VRで中を覗き込まれたりすると透けて見えてしまいます。

コメント 2020-02-01 122301

今回はこのStandard.shaderを改良して、裏面描画する方法を解説します。

[環境] Unity 2017.4.28f1

Standard.shaderの入手

まずは改良元のStandard Shaderを入手します。

こちらのダウンロードから好きなバージョンのビルトインシェーダーを入手可能です。
buildin_shaders-2017.4.18f.1/DefaultResourcesExtra/Standard.shader が改良元となるシェーダーです。

単純に裏面描画してみる

単純に裏面描画したい場合はCull OFFオプションを追加するだけです。

コメント 2020-02-01 125134

こうすると裏面は描画されたのですが、裏面もライトの影響を受けて不自然な影ができてしまいました。

コメント 2020-02-01 122541

これは単純にカリングをオフにしただけなので、裏面も表面と全く同じ描画がされていることが原因だと思います。

ライトの影響を受けないよう裏面を描画する

今回は裏面はライトの影響を受けないテクスチャの描画をしたかったので、もう少し改良を加えました。
まず先ほどのCull OFFオプションはパフォーマンス負荷が上がるのでもとに戻します。

裏面描画用に以下のPassを記述します。

Pass
{
	Cull Front // 裏面のみ描画

	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;
	};

	sampler2D _MainTex;
	float4 _MainTex_ST;
	
	v2f vert (appdata v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
		o.uv = TRANSFORM_TEX(v.uv, _MainTex);
		return o;
	}
	
	fixed4 frag (v2f i) : SV_Target
	{
		float brightness = 0.1; // 裏面の明るさ
		return tex2D(_MainTex, i.uv) * brightness;
	}
	ENDCG
}


このシェーダーは単純に裏面だけに明るさを固定したテクスチャを表示するもので、このPassをBase forward passAdditive forward passの間に追加します。

こうすることで無事にライトの影響を受けずに裏面の描画ができました!

コメント 2020-02-01 122648

brightnessの値を変更することで裏面の明るさを変えることも可能です。
(ちなみに自己流の方法なので、もっと良い裏面描画の方法知ってる人が居たら教えて欲しいです。)


いいなと思ったら応援しよう!