Skip to content

Instantly share code, notes, and snippets.

@zawazawagh
Created January 16, 2022 11:53
Show Gist options
  • Save zawazawagh/1295e2de491a1375762dc60da038a81f to your computer and use it in GitHub Desktop.
Save zawazawagh/1295e2de491a1375762dc60da038a81f to your computer and use it in GitHub Desktop.
FineTextureTiling

【Unity】テクスチャタイリングのパターンが気にならなくなるshader

これはなに

FineTextureTiling.mp4

Unityでテクスチャをタイリングするとパターンが目立つのがずっと前から気になっていたので、それが気にならなくなるshaderです。
ノイズテクスチャから取得した値をもとに複数のインデックスを生成します(コードでは8個)。
それをもとにfetchするテクスチャのuvにオフセットを加えつつ自然に他インデックスのグループの色を補完します。
位置にオフセットを加えただけではまだパターンが気になったので回転も加えるオプション(_RotateUV)もつけました(インデックスが変化する境界で模様が途切れる副作用アリ)。
ノイズの乗り方を確認するためのオプション(_ShowIndex)があります。_NoiseScaleでテクスチャに合ったサイズに調整しやすくなります。

もともとのタイリングと比較したいときは_FineTilingを有効にしてください。

デバッグ目的のコードがたくさん入っているので、好きに編集してください。

The MIT License
Copyright © 2022 zawazawa

参考資料

https://www.iquilezles.org/www/articles/texturerepetition/texturerepetition.htm

Shader "Unlit/FineTextureTiling"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_NoiseTex ("Noise Texture", 2D) = "white" {}
_NoiseScale("Noise Scale", float) = 0.005
_SmoothingPower("Smoothing Power", Range(0.001, 2)) = 1
[Toggle]_ShowIndex("Show Index", int) = 0
[Toggle]_FineTiling("Fine Tiling", int) = 0
[Toggle]_RotateUV("Rotate UV", int) = 0
}
SubShader
{
Tags
{
"RenderType"="Opaque"
}
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#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;
sampler2D _NoiseTex;
float4 _MainTex_ST;
float _NoiseScale;
float _SmoothingPower;
int _ShowIndex;
int _FineTiling;
int _RotateUV;
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;
}
float random(float2 input)
{
return frac(sin(dot(input.xy, float2(12.9898, 78.233))) * 43758.5453123);
}
float2 Rotate(float2 UV, float2 Center, float degrees)
{
float radian = degrees * (3.1415926f / 180.0f);
UV -= Center;
float s = sin(radian);
float c = cos(radian);
float2x2 rMatrix = float2x2(c, -s, s, c);
rMatrix *= 0.5;
rMatrix += 0.5;
rMatrix = rMatrix * 2 - 1;
UV.xy = mul(UV.xy, rMatrix);
UV += Center;
return UV;
}
fixed4 frag(v2f input) : SV_Target
{
//indexを生成
float k = tex2D(_NoiseTex, input.uv * _NoiseScale).x;
float index = k * 8.0;
float l = floor(index);
float f = frac(index);
float rotationOffset = 30 * l;
float2 uv = _FineTiling && _RotateUV ? Rotate(input.uv, float2(0.5, 0.5), rotationOffset) : input.uv;
//オフセットパターン生成。任意のハッシュ関数に置き換えてもよい。
float2 offa = sin(float2(3.0, 7.0) * l);
float2 offb = sin(float2(3.0, 7.0) * (l + 1.0));
//偏微分値を求める。mipmapが破綻しないようにするために使う。
float2 dx = ddx(uv);
float2 dy = ddy(uv);
//色を取得
float3 cola = tex2Dgrad(_MainTex, uv + offa, dx, dy).xyz;
float3 colb = tex2Dgrad(_MainTex, uv + offb, dx, dy).xyz;
//補完
float3 col = lerp(cola, colb, pow(smoothstep(0.2, 0.8, f - 0.1 * length(cola - colb)),
_SmoothingPower));
if (_FineTiling == 0)
{
col = tex2D(_MainTex, uv);
}
UNITY_APPLY_FOG(i.fogCoord, col);
if (_ShowIndex == 0)
{
return float4(col, 1);
}
else
{
float3 randomColA = float3(
random(offa + float2(l, 0)),
random(offa + float2(l, 0.5)),
random(offa + float2(l, 1))
);
float3 randomColB = float3(
random(offb + float2(l, 0)),
random(offb + float2(l, 0.5)),
random(offb + float2(l, 1))
);
col = lerp(randomColA, randomColB,
pow(smoothstep(0.2, 0.8, f - 0.1 * length(cola - colb)), _SmoothingPower));
return float4(col, 1);
}
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment