Skip to content

Instantly share code, notes, and snippets.

@yukatayu
Created June 12, 2019 05:15
Show Gist options
  • Save yukatayu/70764be655da422f006aec3434d1ef2d to your computer and use it in GitHub Desktop.
Save yukatayu/70764be655da422f006aec3434d1ef2d to your computer and use it in GitHub Desktop.
ステンドグラス (後ろを歪ませるだけ)
Shader "Yukatayu/Stend Grass" {
Properties {
[Header(Stend Glass)] [Space(7)]
_MainTex ("テクスチャ", 2D) = "white" {}
_Division ("分割数", Int) = 60
_Threshold ("枠線の太さ", Range(0,1)) = 0.08
_Height("盛り上がり", Range(-4, 4)) = 0.5
_Opacity("ガラス全体の不透明度", Range(0, 1)) = 0.5
_EdgeOpacity("枠線の不透明度", Range(0, 1)) = 0.85
[Space(7)] [Header(Advanced)] [Space(7)]
_PerinNoiseStrength("歪みの強さ", Float) = 0.1
_PerinNoiseStrengthBack("背景の歪みの強さ", Float) = 0.1
_PerinNoiseColor("歪みによる黒ずみ", Float) = 10
}
SubShader {
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 100
ZWrite Off
Cull Off
Blend SrcAlpha OneMinusSrcAlpha
GrabPass { "_GrabTexture"}
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
//
// 乱数
//
float rand(float2 xy) {
return frac(sin(dot(xy, fixed2(12.9898,78.233))) * 43758.5453);
}
//
// セルラーノイズ
//
float3x3 cellularNoise(float2 uv){
float2 resPos = 0; // 最近傍の位置
float nearest = 1e7; // 最近傍からの距離
float nearest2 = 1e7; // 二番目の近傍からの距離
for (int y = -1; y <= 1; ++y){
for (int x = -1; x <= 1; ++x){
float2 base_pos = floor(uv) + float2(x, y);
float2 rand_pos = base_pos + rand(base_pos) * 0.8 + 0.2;
float dist = length(rand_pos - uv);
if (dist < nearest){
// 最近傍を更新
nearest2 = nearest;
nearest = dist;
resPos = rand_pos;
} else{
// 二番目の近傍を更新
nearest2 = min(nearest2, dist);
}
}
}
float height = pow(saturate(nearest - 0.2), 1.5);
float2 normal = float2(ddx(height), ddy(height));
//normal = height;
return float3x3(resPos, 0, normal, 0, nearest2 - nearest, 0, 0);
}
//
// パーリンノイズ
//
fixed2 random2(fixed2 st) {
st = fixed2( dot(st,fixed2(127.1,311.7)),
dot(st,fixed2(269.5,183.3)) );
return -1.0 + 2.0*frac(sin(st)*43758.5453123);
}
float perlinNoise(fixed2 st) {
fixed2 p = floor(st);
fixed2 f = frac(st);
fixed2 u = f*f*(3.0-2.0*f);
float v00 = random2(p+fixed2(0,0));
float v10 = random2(p+fixed2(1,0));
float v01 = random2(p+fixed2(0,1));
float v11 = random2(p+fixed2(1,1));
return lerp( lerp( dot( v00, f - fixed2(0,0) ), dot( v10, f - fixed2(1,0) ), u.x ),
lerp( dot( v01, f - fixed2(0,1) ), dot( v11, f - fixed2(1,1) ), u.x ),
u.y)+0.5f;
}
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 uv_screen : TEXCOORD1;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D _GrabTexture;
float4 _MainTex_ST;
int _Division;
half _Threshold;
half _Height;
float _PerinNoiseColor;
float _PerinNoiseStrength;
float _PerinNoiseStrengthBack;
float _Opacity;
float _EdgeOpacity;
v2f vert (appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv_screen = ComputeGrabScreenPos(o.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
half alpha = _Opacity;
clip(tex2D (_MainTex, i.uv).a - 0.01);
// ガラスの歪み
float perin = perlinNoise(i.uv * 26);
float2 perlinNormal = float2(ddx(perin), ddy(perin));
// セルラーノイズの最近傍のテクスチャを取得、代表点とする
float3x3 cn = cellularNoise((i.uv + perlinNormal * _PerinNoiseStrength) * _Division);
fixed4 mainCol = tex2D (_MainTex, cn[0].xy / _Division);
mainCol.a = 1;
float2 cellularNormal = cn[1].xy;
// 背景の歪みの計算
float2 uv_screen = i.uv_screen.xy / i.uv_screen.w;
uv_screen += (cellularNormal + perlinNormal * _PerinNoiseStrengthBack) * _Height * alpha * 2;
fixed4 grabCol = tex2D (_GrabTexture, uv_screen);
fixed4 col = lerp(grabCol, mainCol, alpha);
// 歪みによる黒ずみの計算
// 歪みによる法線が下を向いているところを黒くする
float perlinShadow = saturate(-perlinNormal.y);
col.rgb *= 1-perlinShadow * _PerinNoiseColor;
// ついでに不透明度も落とす
col = lerp(col, mainCol, perlinShadow);
//col.a = 1 - (1-col.a)*(1-perlinShadow) * 0.4;
// 最近傍の二つの点の距離の差が一定以下 → ボロノイ境界付近にいるので黒
col = lerp(col, fixed4(0, 0, 0, _EdgeOpacity), step(cn[2][0], _Threshold));
//alpha *= col.a;
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment