0.シェーダーを書いた経緯
このアセットをURPで使おうとしたところ、シェーダーが対応していなかったので...頑張った。
1.シェーダーの最低限仕様
- 用意されている3DモデルがPlaneみたいに裏面非描画になっていたので、描画させる
- 表面と裏面で違うテクスチャを貼る
- 基本的にテクスチャの白成分が高いので、重なってもわかるようにアウトラインを付与する
2.作ったシェーダー
Custom/Outline and Double-sided.shader
Shader "Custom/Outline and Double-sided"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_BackTex ("Back Texture", 2D) = "white" {}
_OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)
_OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.02
}
SubShader
{
Cull Off
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" }
LOD 100
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// マクロで定数化
#define MIN 0.0001
struct appdata
{
half4 vertex : POSITION;
half2 uv : TEXCOORD0;
};
struct v2f
{
half4 vertex : SV_POSITION;
half2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex);
TEXTURE2D(_BackTex);
SAMPLER(sampler_MainTex);
SAMPLER(sampler_BackTex);
CBUFFER_START(UnityPerMaterial)
half4 _MainTex_ST;
half4 _BackTex_ST;
half4 _OutlineColor;
half _OutlineWidth;
CBUFFER_END
ENDHLSL
// 裏面も描画する
Pass
{
// LightModeはマルチパス実行のために必須
Tags{ "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
v2f vert (appdata v)
{
v2f o;
o.vertex = TransformObjectToHClip(v.vertex);
o.vertex.z += MIN;
o.uv = v.uv;
return o;
}
half4 frag (v2f i, half facing : VFACE) : SV_Target
{
// カメラに向いている面によって表裏のテクスチャを切り替え
return facing > 0 ? SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv) : SAMPLE_TEXTURE2D(_BackTex, sampler_BackTex, i.uv);
}
ENDHLSL
}
// アウトラインの描画
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert (appdata v)
{
v2f o;
// アウトラインの分だけ拡大
o.vertex = TransformObjectToHClip(v.vertex * (1 +_OutlineWidth));
return o;
}
half4 frag(v2f i) : SV_Target
{
return _OutlineColor;
}
ENDHLSL
}
}
}
3.課題点
- アウトラインが太さ統一ではなく、あくまでモデルの形を拡大したのを用意しているだけなので、ちょっと気持ち悪いなとは思ってる。まあ、妥協できるかな...
4.感想
正直、自力のシェーダーコーディングは初めてだったので、URPの仕様に苦戦したりShader Graphに浮気したりとまあいろいろ大変だった...。