Skip to content

Instantly share code, notes, and snippets.

@tar-bin
Last active December 2, 2019 14:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tar-bin/6d57baada8a7f8852bb0f95cbead3c65 to your computer and use it in GitHub Desktop.
Save tar-bin/6d57baada8a7f8852bb0f95cbead3c65 to your computer and use it in GitHub Desktop.
VRChatのミラーにカスタムシェーダーを適用するサンプル
Shader "Tarbin/MirrorEffect"
{
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
[HideInInspector] _ReflectionTex0("", 2D) = "white" {}
[HideInInspector] _ReflectionTex1("", 2D) = "white" {}
_MirrorModeTex("MirrorMode", 2D) = "white" {}
_OutlineThick ("Outline Thick", int) = 1
_OutlineThreshold ("Outline Threshold", float) = 0.0
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityInstancing.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _ReflectionTex0;
float4 _ReflectionTex0_TexelSize;
sampler2D _ReflectionTex1;
float4 _ReflectionTex1_TexelSize;
sampler2D _MirrorModeTex;
int _OutlineThick;
float _OutlineThreshold;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 refl : TEXCOORD1;
float4 pos : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.refl = ComputeNonStereoScreenPos(o.pos);
return o;
}
float2 getRefUv(v2f i, int2 offsetPix, float4 texelSize) {
float4 fixedRefl = UNITY_PROJ_COORD(i.refl);
return (fixedRefl.xy / fixedRefl.w) + float2(texelSize.x * offsetPix.x, texelSize.y * offsetPix.y);
}
half4 getTex(v2f i, int2 offsetPix) {
half4 tex = tex2D(_MainTex, i.uv);
half4 refl = unity_StereoEyeIndex == 0
? tex2D(_ReflectionTex0, getRefUv(i, offsetPix, _ReflectionTex0_TexelSize))
: tex2D(_ReflectionTex1, getRefUv(i, offsetPix, _ReflectionTex1_TexelSize));
return tex * refl;
}
half4 grayScale(v2f i) {
half4 tex = getTex(i, int2(0, 0));
tex.rgb = Luminance(tex.rgb);
return tex;
}
// 【Unity】【シェーダ】ソーベルフィルタでエッジを抽出する - LIGHT11
// http://light11.hatenadiary.com/entry/2018/05/13/161104
half4 edgeEnhancedSobel(v2f i) {
// 近隣のテクスチャ色をサンプリング
int diffU = 1 * _OutlineThick;
int diffV = 1 * _OutlineThick;
half3 col00 = getTex(i, int2(-diffU, -diffV));
half3 col01 = getTex(i, int2(-diffU, 0));
half3 col02 = getTex(i, int2(-diffU, diffV));
half3 col10 = getTex(i, int2(0, -diffV));
half3 col12 = getTex(i, int2(0, diffV));
half3 col20 = getTex(i, int2(diffU, -diffV));
half3 col21 = getTex(i, int2(diffU, 0));
half3 col22 = getTex(i, int2(diffU, diffV));
// 水平方向のコンボリューション行列適用後の色を求める
half3 horizontalColor = 0;
horizontalColor += col00 * -1.0;
horizontalColor += col01 * -1.0;
horizontalColor += col02 * -1.0;
horizontalColor += col20;
horizontalColor += col21;
horizontalColor += col22;
// 垂直方向のコンボリューション行列適用後の色を求める
half3 verticalColor = 0;
verticalColor += col00;
verticalColor += col10;
verticalColor += col20;
verticalColor += col02 * -1.0;
verticalColor += col12 * -1.0;
verticalColor += col22 * -1.0;
// この値が大きく正の方向を表す部分がアウトライン
half3 outlineValue = horizontalColor * horizontalColor + verticalColor * verticalColor;
return half4(outlineValue - _OutlineThreshold, 1);
}
half4 edgeEnhancedGray(v2f i) {
// 近隣のテクスチャ色をサンプリング
int diffU = 1 * _OutlineThick;
int diffV = 1 * _OutlineThick;
half3 col00 = getTex(i, int2(-diffU, -diffV));
half3 col01 = getTex(i, int2(-diffU, 0));
half3 col02 = getTex(i, int2(-diffU, diffV));
half3 col10 = getTex(i, int2(0, -diffV));
half3 col12 = getTex(i, int2(0, diffV));
half3 col20 = getTex(i, int2(diffU, -diffV));
half3 col21 = getTex(i, int2(diffU, 0));
half3 col22 = getTex(i, int2(diffU, diffV));
// 水平方向のコンボリューション行列適用後の色を求める
half3 horizontalColor = 0;
horizontalColor += col00 * -1.0;
horizontalColor += col01 * -1.0;
horizontalColor += col02 * -1.0;
horizontalColor += col20;
horizontalColor += col21;
horizontalColor += col22;
// 垂直方向のコンボリューション行列適用後の色を求める
half3 verticalColor = 0;
verticalColor += col00;
verticalColor += col10;
verticalColor += col20;
verticalColor += col02 * -1.0;
verticalColor += col12 * -1.0;
verticalColor += col22 * -1.0;
// この値が大きく正の方向を表す部分がアウトライン
half3 outlineValue = horizontalColor * horizontalColor + verticalColor * verticalColor;
half4 col = half4(outlineValue - _OutlineThreshold, 1);
col.rgb = Luminance(col.rgb);
return col;
}
half4 getFilteredTex(v2f i) {
float mode = floor(tex2D(_MirrorModeTex, float2(0.5, 0.5)).r * 255 + 0.5);
if (mode < 25) {
return getTex(i, int2(0, 0));
} else if (mode < 50) {
return grayScale(i);
} else if (mode < 75) {
return edgeEnhancedSobel(i);
} else if (mode < 100) {
return edgeEnhancedGray(i);
} else {
return getTex(i, int2(0, 0));
}
}
half4 frag(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
return getFilteredTex(i);
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment