diff options
| -rwxr-xr-x | 3ner.shader | 20 | ||||
| -rw-r--r-- | aperiodic_tiling.cginc | 140 | ||||
| -rwxr-xr-x | features.cginc | 4 | ||||
| -rwxr-xr-x | globals.cginc | 17 | ||||
| -rwxr-xr-x | pbr.cginc | 2 |
5 files changed, 150 insertions, 33 deletions
diff --git a/3ner.shader b/3ner.shader index 1dc06cf..7c71bac 100755 --- a/3ner.shader +++ b/3ner.shader @@ -939,6 +939,26 @@ Shader "yum_food/3ner" [HideInInspector] m_start_Aperiodic_Tiling("Aperiodic Tiling", Float) = 0 [ThryToggle(_APERIODIC_TILING)] _Aperiodic_Tiling_Enabled("Enable", Float) = 0 _Aperiodic_Tiling_Scale("Scale", Float) = 1 + _Aperiodic_Tiling_Edge_Thickness("Edge Thickness", Range(0, 0.5)) = 0.04 + [HDR] _Aperiodic_Tiling_Edge_Color("Edge Color", Color) = (0.04, 0.1, 0.04, 1) + [HDR] _Aperiodic_Tiling_Color_0("Face 0-1", Color) = (0.4, 0.9, 0.4, 1) + [HDR] _Aperiodic_Tiling_Color_1("Face 0-2", Color) = (0.6, 0.7, 0.2, 1) + [HDR] _Aperiodic_Tiling_Color_2("Face 0-3", Color) = (0.3, 0.5, 0.0, 1) + [HDR] _Aperiodic_Tiling_Color_3("Face 0-4", Color) = (0.2, 0.3, 0.0, 1) + [HDR] _Aperiodic_Tiling_Color_4("Face 1-2", Color) = (0.0, 0.3, 0.2, 1) + [HDR] _Aperiodic_Tiling_Color_5("Face 1-3", Color) = (0.0, 0.5, 0.4, 1) + [HDR] _Aperiodic_Tiling_Color_6("Face 1-4", Color) = (0.2, 0.7, 0.6, 1) + [HDR] _Aperiodic_Tiling_Color_7("Face 2-3", Color) = (0.3, 0.6, 0.0, 1) + [HDR] _Aperiodic_Tiling_Color_8("Face 2-4", Color) = (0.0, 0.4, 0.0, 1) + [HDR] _Aperiodic_Tiling_Color_9("Face 3-4", Color) = (0.0, 0.6, 0.3, 1) + + //ifex _Aperiodic_Tiling_Normals_Enabled==0 + [HideInInspector] m_start_Aperiodic_Tiling_Normals("Normals", Float) = 0 + [ThryToggle(_APERIODIC_TILING_NORMALS)] _Aperiodic_Tiling_Normals_Enabled("Enable", Float) = 0 + _Aperiodic_Tiling_Normal_Strength("Strength", Range(0, 4)) = 1 + _Aperiodic_Tiling_Normal_Thickness("Thickness", Range(0, 0.5)) = 0.08 + [HideInInspector] m_end_Aperiodic_Tiling_Normals("Normals", Float) = 0 + //endex [HideInInspector] m_end_Aperiodic_Tiling("Aperiodic Tiling", Float) = 0 //endex diff --git a/aperiodic_tiling.cginc b/aperiodic_tiling.cginc index 78c911d..5e12ee0 100644 --- a/aperiodic_tiling.cginc +++ b/aperiodic_tiling.cginc @@ -10,6 +10,8 @@ #include "globals.cginc" #include "math.cginc" +#if defined(_APERIODIC_TILING) + static const float M5 = sqrt(2.0 / 5.0); static const float4 basis_u5_03 = M5 * float4( @@ -41,60 +43,134 @@ float2x2 inv2x2(float2x2 m) { return float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / d; } -// Test if point p lies in one candidate tile. -// m: inverse of the forward (barycentric -> projected) matrix. -// s: barycentric center of the candidate tile. -// a, b: axis selectors for this face orientation. -float tile5(float4 p03, float p44, float2x2 m, float2 s, - float4 a03, float a44, float4 b03, float b44) { +struct AperiodicTileSample { + float coverage; + float2 barycentric; +}; + +float2 tile5_barycentric(float4 p03, float p44, float2x2 m, float2 s, + float4 a03, float a44, float4 b03, float b44) { float2 q = mul(s, m); p03 -= (1.0 - a03 - b03) * round(q.x * basis_u5_03 + q.y * basis_v5_03); p44 -= (1.0 - a44 - b44) * round(q.x * basis_u5_44 + q.y * basis_v5_44); - float2 f = abs(mul(m, proj5(p03, p44)) - s); - return max(0.0, 0.5 - max(f.x, f.y)); + return mul(m, proj5(p03, p44)) - s; +} + +float tile5_distance_from_barycentric(float2 barycentric) { + float2 f = abs(barycentric); + return 0.5 - max(f.x, f.y); +} + +float aperiodic_edge_coverage(float distance_to_edge) { + float edge_width = saturate(_Aperiodic_Tiling_Edge_Thickness * 2.0) * 0.5; + float signed_distance = distance_to_edge - edge_width; + float aa_width = max(fwidth(signed_distance), 1e-4); + return smoothstep(-aa_width, aa_width, signed_distance); } -// Test all 4 candidate tiles for one face orientation. -// Returns barycentric distance to nearest edge (positive inside, zero outside). -float t5(float4 p03, float p44, float4 a03, float a44, float4 b03, float b44) { +#if defined(_APERIODIC_TILING_NORMALS) +float3 aperiodic_tiling_normal(float2 barycentric) { + float bevel_width = min(_Aperiodic_Tiling_Normal_Thickness, 0.5); + if (bevel_width <= 1e-5) { + return float3(0.0, 0.0, 1.0); + } + + float flat_limit = 0.5 - bevel_width; + float2 edge_factor = smoothstep(flat_limit, 0.5, abs(barycentric)); + float2 xy = sign(barycentric) * edge_factor * _Aperiodic_Tiling_Normal_Strength; + return normalize(float3(xy, 1.0)); +} +#endif // _APERIODIC_TILING_NORMALS + +void choose_aperiodic_candidate(float2 barycentric, inout float distance_to_edge, + inout float2 best_barycentric) { + float candidate_distance = tile5_distance_from_barycentric(barycentric); + if (candidate_distance > distance_to_edge) { + distance_to_edge = candidate_distance; + best_barycentric = barycentric; + } +} + +AperiodicTileSample sample_aperiodic_orientation( + float4 p03, float p44, float4 a03, float a44, float4 b03, float b44) { float2 pa = proj5(a03, a44); float2 pb = proj5(b03, b44); float2x2 m = inv2x2(float2x2(pa.x, pb.x, pa.y, pb.y)); float2 r = round(float2(dot5(p03, p44, a03, a44), dot5(p03, p44, b03, b44))); float2 s = float2(0.5, -0.5); - return tile5(p03, p44, m, r + s.xx, a03, a44, b03, b44) + - tile5(p03, p44, m, r + s.xy, a03, a44, b03, b44) + - tile5(p03, p44, m, r + s.yx, a03, a44, b03, b44) + - tile5(p03, p44, m, r + s.yy, a03, a44, b03, b44); + + float2 best_barycentric = tile5_barycentric(p03, p44, m, r + s.xx, a03, a44, b03, b44); + float distance_to_edge = tile5_distance_from_barycentric(best_barycentric); + choose_aperiodic_candidate( + tile5_barycentric(p03, p44, m, r + s.xy, a03, a44, b03, b44), + distance_to_edge, best_barycentric); + choose_aperiodic_candidate( + tile5_barycentric(p03, p44, m, r + s.yx, a03, a44, b03, b44), + distance_to_edge, best_barycentric); + choose_aperiodic_candidate( + tile5_barycentric(p03, p44, m, r + s.yy, a03, a44, b03, b44), + distance_to_edge, best_barycentric); + + AperiodicTileSample sample; + sample.coverage = aperiodic_edge_coverage(distance_to_edge); + sample.barycentric = best_barycentric; + return sample; +} + +void apply_aperiodic_orientation(float3 face_color, + float4 p03, float p44, + float4 a03, float a44, float4 b03, float b44, + float3 edge_color, + inout float3 albedo, inout float2 normal_xy_acc) { + AperiodicTileSample sample = + sample_aperiodic_orientation(p03, p44, a03, a44, b03, b44); + albedo += (face_color - edge_color) * sample.coverage; +#if defined(_APERIODIC_TILING_NORMALS) + normal_xy_acc += aperiodic_tiling_normal(sample.barycentric).xy * sample.coverage; +#endif } -float3 dim5(float2 uv) { +void sample_aperiodic_tiling(float2 uv, out float3 albedo + , out float3 tiling_normal_tangent + ) { float4 p03 = uv.x * basis_u5_03 + uv.y * basis_v5_03; float p44 = uv.x * basis_u5_44 + uv.y * basis_v5_44; float2 u = float2(0, 1); - float3 edge = float3(0.04, 0.1, 0.04); - float3 c = edge; + float3 edge = _Aperiodic_Tiling_Edge_Color.rgb; + albedo = edge; + float2 normal_xy_accum = 0; // 10 face orientations = C(5,2) pairs of 5D axes - c += (float3(0.4, 0.9, 0.4) - edge) * t5(p03, p44, u.yxxx, u.x, u.xyxx, u.x); - c += (float3(0.6, 0.7, 0.2) - edge) * t5(p03, p44, u.yxxx, u.x, u.xxyx, u.x); - c += (float3(0.3, 0.5, 0.0) - edge) * t5(p03, p44, u.yxxx, u.x, u.xxxy, u.x); - c += (float3(0.2, 0.3, 0.0) - edge) * t5(p03, p44, u.yxxx, u.x, u.xxxx, u.y); - c += (float3(0.0, 0.3, 0.2) - edge) * t5(p03, p44, u.xyxx, u.x, u.xxyx, u.x); - c += (float3(0.0, 0.5, 0.4) - edge) * t5(p03, p44, u.xyxx, u.x, u.xxxy, u.x); - c += (float3(0.2, 0.7, 0.6) - edge) * t5(p03, p44, u.xyxx, u.x, u.xxxx, u.y); - c += (float3(0.3, 0.6, 0.0) - edge) * t5(p03, p44, u.xxyx, u.x, u.xxxy, u.x); - c += (float3(0.0, 0.4, 0.0) - edge) * t5(p03, p44, u.xxyx, u.x, u.xxxx, u.y); - c += (float3(0.0, 0.6, 0.3) - edge) * t5(p03, p44, u.xxxy, u.x, u.xxxx, u.y); - - return c; + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_0.rgb, p03, p44, u.yxxx, u.x, u.xyxx, u.x, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_1.rgb, p03, p44, u.yxxx, u.x, u.xxyx, u.x, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_2.rgb, p03, p44, u.yxxx, u.x, u.xxxy, u.x, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_3.rgb, p03, p44, u.yxxx, u.x, u.xxxx, u.y, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_4.rgb, p03, p44, u.xyxx, u.x, u.xxyx, u.x, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_5.rgb, p03, p44, u.xyxx, u.x, u.xxxy, u.x, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_6.rgb, p03, p44, u.xyxx, u.x, u.xxxx, u.y, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_7.rgb, p03, p44, u.xxyx, u.x, u.xxxy, u.x, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_8.rgb, p03, p44, u.xxyx, u.x, u.xxxx, u.y, edge, albedo, normal_xy_accum); + apply_aperiodic_orientation(_Aperiodic_Tiling_Color_9.rgb, p03, p44, u.xxxy, u.x, u.xxxx, u.y, edge, albedo, normal_xy_accum); + +#if defined(_APERIODIC_TILING_NORMALS) + tiling_normal_tangent = normalize(float3(normal_xy_accum, 1.0)); +#else + tiling_normal_tangent = 0; +#endif } +#endif // defined(_APERIODIC_TILING) -void apply_aperiodic_tiling(float2 uv, inout float3 albedo) { +void apply_aperiodic_tiling(float2 uv, inout float3 albedo, inout float3 normal_tangent) { #if defined(_APERIODIC_TILING) uv *= _Aperiodic_Tiling_Scale; - albedo = dim5(uv); + float3 tiling_normal_tangent; + sample_aperiodic_tiling(uv, albedo + , tiling_normal_tangent + ); +#if defined(_APERIODIC_TILING_NORMALS) + normal_tangent = blendNormalsHill12(normal_tangent, tiling_normal_tangent); +#endif #endif // _APERIODIC_TILING } diff --git a/features.cginc b/features.cginc index 283946b..793ac08 100755 --- a/features.cginc +++ b/features.cginc @@ -138,6 +138,10 @@ #pragma shader_feature_local _APERIODIC_TILING //endex +//ifex _Aperiodic_Tiling_Normals_Enabled==0 +#pragma shader_feature_local _APERIODIC_TILING_NORMALS +//endex + //ifex _Custom31_World_Enabled==0 #pragma shader_feature_local _CUSTOM31_WORLD #pragma shader_feature_local _CUSTOM31_WORLD_HEXAGONS diff --git a/globals.cginc b/globals.cginc index e186f0d..098988e 100755 --- a/globals.cginc +++ b/globals.cginc @@ -186,8 +186,25 @@ float _Logical_Time; #if defined(_APERIODIC_TILING) float _Aperiodic_Tiling_Scale; +float _Aperiodic_Tiling_Edge_Thickness; +float4 _Aperiodic_Tiling_Edge_Color; +float4 _Aperiodic_Tiling_Color_0; +float4 _Aperiodic_Tiling_Color_1; +float4 _Aperiodic_Tiling_Color_2; +float4 _Aperiodic_Tiling_Color_3; +float4 _Aperiodic_Tiling_Color_4; +float4 _Aperiodic_Tiling_Color_5; +float4 _Aperiodic_Tiling_Color_6; +float4 _Aperiodic_Tiling_Color_7; +float4 _Aperiodic_Tiling_Color_8; +float4 _Aperiodic_Tiling_Color_9; #endif // _APERIODIC_TILING +#if defined(_APERIODIC_TILING_NORMALS) +float _Aperiodic_Tiling_Normal_Strength; +float _Aperiodic_Tiling_Normal_Thickness; +#endif // _APERIODIC_TILING_NORMALS + #if defined(_CUSTOM31_WORLD) int _Custom31_World_Ray_March_Steps; float _Custom31_World_Ray_March_Min_Dist; @@ -287,7 +287,7 @@ Pbr getPbr(v2f i) { apply_burley_tiling(pbr, normal_tangent); apply_triplanar_layers(i.worldPos, i.normal, pbr, normal_tangent); apply_custom31_world(i, pbr, normal_tangent); - apply_aperiodic_tiling(i.uv01.xy, pbr.albedo.xyz); + apply_aperiodic_tiling(i.uv01.xy, pbr.albedo.xyz, normal_tangent); applyDecals(i, pbr, normal_tangent); |
