diff options
| author | yum <yum.food.vr@gmail.com> | 2026-01-21 16:03:52 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-01-21 16:03:52 -0800 |
| commit | 97ee1dcf26b62f48e351b6392c11a30775619442 (patch) | |
| tree | 034c7d64461fa5766deb7df6a0f4737f58eaec8c | |
| parent | e54c87201b97fb36ef9c0e63f9e0012ac59f2f0b (diff) | |
Fur: add domain warping
| -rw-r--r-- | 2ner.cginc | 18 | ||||
| -rw-r--r-- | 2ner.shader | 6 | ||||
| -rw-r--r-- | features.cginc | 1 | ||||
| -rw-r--r-- | globals.cginc | 5 | ||||
| -rw-r--r-- | interpolators.cginc | 1 | ||||
| -rw-r--r-- | math.cginc | 54 | ||||
| -rw-r--r-- | ssao.cginc | 4 | ||||
| -rw-r--r-- | yum_pbr.cginc | 11 |
8 files changed, 84 insertions, 16 deletions
@@ -257,7 +257,7 @@ void geom(triangle v2f input[3], inout TriangleStream<v2f> stream) { o.vertexLight.w = t;
stream.Append(o);
}
- stream.RestartStrip();
+ // We do not restart strips. Looks a little nicer.
}
#else
stream.Append(input[0]);
@@ -294,6 +294,11 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace f.binormal = cross(i.tangent, i.normal);
f.eyeVec = i.worldPos - _WorldSpaceCameraPos;
f.viewDir = normalize(f.eyeVec);
+ f.tbn = float3x3(
+ i.tangent,
+ f.binormal,
+ i.normal
+ );
#if defined(_RAYMARCHED_FOG)
{
@@ -429,19 +434,12 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace #endif
#endif
- float4x4 tangentToWorld = float4x4(
- float4(i.tangent, 0),
- float4(f.binormal, 0),
- float4(i.normal, 0),
- float4(0, 0, 0, 1)
- );
-
float ssao = 1;
#if defined(_SSAO)
float2 debug;
- ssao = get_ssao(i, tangentToWorld, debug);
+ ssao = get_ssao(i, f, debug);
#endif
- YumPbr pbr = GetYumPbr(i, f, tangentToWorld);
+ YumPbr pbr = GetYumPbr(i, f);
pbr.albedo.rgb *= ssao;
#if defined(META_PASS)
diff --git a/2ner.shader b/2ner.shader index 357f372..6cac4f9 100644 --- a/2ner.shader +++ b/2ner.shader @@ -121,6 +121,12 @@ Shader "yum_food/2ner" _Fur_Mask("Mask", 2D) = "white" {} [HideInInspector] m_end_Fur_Mask("Mask", Float) = 0 + [HideInInspector] m_start_Fur_Warping("Warping", Float) = 0 + [ThryToggle(_FUR_WARPING)]_Fur_Warping_Enabled("Enable", Float) = 0 + _Fur_Warping_Strength("Strength", Range(0, 10)) = 1 + _Fur_Warping_Frequency("Frequency", Float) = 1 + [HideInInspector] m_end_Fur_Warping("Warping", Float) = 0 + // Shit for thry [HideInInspector] GeometryShader_Enabled("Enabled", Float) = 1 [HideInInspector] GeometryShader_EnabledForwardBase("Enabled (ForwardBase)", Float) = 1 diff --git a/features.cginc b/features.cginc index c774103..ab45306 100644 --- a/features.cginc +++ b/features.cginc @@ -77,6 +77,7 @@ //ifex _Fur_Enabled==0 #pragma shader_feature_local _FUR #pragma shader_feature_local _FUR_MASK +#pragma shader_feature_local _FUR_WARPING //endex //ifex _Matcap0_Enabled==0 diff --git a/globals.cginc b/globals.cginc index 4bc39b4..00f9a31 100644 --- a/globals.cginc +++ b/globals.cginc @@ -157,6 +157,11 @@ texture2D _Fur_Mask; float4 _Fur_Mask_ST;
#endif
+#if defined(_FUR_WARPING)
+float _Fur_Warping_Strength;
+float _Fur_Warping_Frequency;
+#endif
+
#define MATCAP_MODE_REPLACE 0
#define MATCAP_MODE_ADD 1
#define MATCAP_MODE_MULTIPLY 2
diff --git a/interpolators.cginc b/interpolators.cginc index bb08c4e..020c80f 100644 --- a/interpolators.cginc +++ b/interpolators.cginc @@ -47,6 +47,7 @@ struct f2f { float3 binormal;
float3 eyeVec;
float3 viewDir;
+ float3x3 tbn;
};
#endif // __INTERPOLATORS_INC
@@ -307,7 +307,57 @@ float2 hex_to_cart(float3 cart) { (cart[1] - cart[2]) * SQRT_3_OVER_2);
}
-// Rotate 45 degrees.
-float2 rot45(float2 v) { return float2(v.x - v.y, v.x + v.y) * RCP_SQRT_2; }
+// Rotate 45 degrees. +float2 rot45(float2 v) { return float2(v.x - v.y, v.x + v.y) * RCP_SQRT_2; } + +// p = point to get noise for +float valueNoise2D( + float2 p) { + // quantized part + float2 q = floor(p); + // fractional part + float2 f = frac(p); + + float l00 = rand2(q); + float l01 = rand2(q + float2(0, 1)); + float l10 = rand2(q + float2(1, 0)); + float l11 = rand2(q + float2(1, 1)); + + // Cubic interpolation. + f = f * f * (3.0f - 2.0f * f); + + float l0 = lerp(l00, l01, f.y); + float l1 = lerp(l10, l11, f.y); + return lerp(l0, l1, f.x); +} + +// p = point to get noise for +float valueNoise3D( + float3 p) { + // quantized part
+ float3 q = floor(p);
+ // fractional part
+ float3 f = frac(p);
+
+ float l000 = rand3(q);
+ float l001 = rand3(q + float3(0, 0, 1));
+ float l010 = rand3(q + float3(0, 1, 0));
+ float l011 = rand3(q + float3(0, 1, 1));
+ float l100 = rand3(q + float3(1, 0, 0));
+ float l101 = rand3(q + float3(1, 0, 1));
+ float l110 = rand3(q + float3(1, 1, 0));
+ float l111 = rand3(q + float3(1, 1, 1));
+
+ // Cubic interpolation.
+ f = f * f * (3.0f - 2.0f * f);
+
+ float l00 = lerp(l000, l001, f.z);
+ float l01 = lerp(l010, l011, f.z);
+ float l10 = lerp(l100, l101, f.z);
+ float l11 = lerp(l110, l111, f.z);
+ float l0 = lerp(l00, l01, f.y);
+ float l1 = lerp(l10, l11, f.y);
+ return lerp(l0, l1, f.x);
+}
#endif // __MATH_INC
@@ -6,7 +6,7 @@ #include "interpolators.cginc" #if defined(_SSAO) -float get_ssao(v2f i, float3x3 tangentToWorld, out float2 debug) { +float get_ssao(v2f i, f2f f, out float2 debug) { float3 objPos = mul(unity_WorldToObject, float4(i.worldPos, 1)); float4 clipPos = UnityObjectToClipPos(objPos); float4 screenPos = ComputeScreenPos(clipPos); @@ -47,7 +47,7 @@ float get_ssao(v2f i, float3x3 tangentToWorld, out float2 debug) { sample_point.xy = mul(ssao_rot, sample_point.xy); // Remap to world space. - sample_point = mul(sample_point, tangentToWorld); + sample_point = mul(sample_point, f.tbn); float scale = (ii * 1.0f) / _SSAO_Samples; sample_point *= lerp(0.1f, 1.0f, scale * scale) * _SSAO_Radius; diff --git a/yum_pbr.cginc b/yum_pbr.cginc index f9a29c3..515aef9 100644 --- a/yum_pbr.cginc +++ b/yum_pbr.cginc @@ -142,6 +142,13 @@ float FurClip(v2f i, f2f f, inout YumPbr result) { #if defined(_FUR) float fur_layer = i.vertexLight.w; float2 fur_uv = i.uv01.xy * _Fur_Heightmap_ST.xy; + +#if defined(_FUR_WARPING) + float2 vnoise = valueNoise3D(i.objPos * _Fur_Warping_Frequency); + float3 vnoise_tbn = mul(vnoise, f.tbn); + fur_uv += vnoise_tbn.xy * (_Fur_Warping_Strength / _Fur_Warping_Frequency); +#endif + float fur_thickness = _Fur_Heightmap.SampleBias( trilinear_aniso4_repeat_s, fur_uv, _Fur_Heightmap_Mip_Bias).r; @@ -152,7 +159,7 @@ float FurClip(v2f i, f2f f, inout YumPbr result) { #endif } -YumPbr GetYumPbr(v2f i, f2f f, float3x3 tangentToWorld) { +YumPbr GetYumPbr(v2f i, f2f f) { YumPbr result = (YumPbr)0; float fur_thickness = FurClip(i, f, result); @@ -280,7 +287,7 @@ YumPbr GetYumPbr(v2f i, f2f f, float3x3 tangentToWorld) { result.albedo.rgb = OKLABtoLRGB(lab); #endif - result.normal = normalize(mul(normal_tangent, tangentToWorld)); + result.normal = normalize(mul(normal_tangent, f.tbn)); #if defined(_GRADIENT_NORMALS) applyGradientNormals(i, result); |
