summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-04-10 18:40:47 -0700
committeryum <yum.food.vr@gmail.com>2026-04-10 18:40:47 -0700
commitf2ceb26af143f2e929e4f23ccb1fc86fa9e5307b (patch)
treea4b391469ab805a8361a28c74b9daa24a85dbe69
parent283b8f253cff4a0e39005ba675d7c2cd7ef3c123 (diff)
aperiodic: let user specify colors, add normals
-rwxr-xr-x3ner.shader20
-rw-r--r--aperiodic_tiling.cginc140
-rwxr-xr-xfeatures.cginc4
-rwxr-xr-xglobals.cginc17
-rwxr-xr-xpbr.cginc2
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;
diff --git a/pbr.cginc b/pbr.cginc
index 8326ccf..2d01472 100755
--- a/pbr.cginc
+++ b/pbr.cginc
@@ -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);