summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-04-11 15:54:01 -0700
committeryum <yum.food.vr@gmail.com>2026-04-11 15:54:01 -0700
commit30008343bafccd813b5432bb09f3f2af2ee2785b (patch)
tree64a659c89f3c7886a082c02e0f8e82d4e729f07a
parentf2ceb26af143f2e929e4f23ccb1fc86fa9e5307b (diff)
aperiodic: improve aa
Calculate colors after accumulating raw data and use standard fwidth trick to anti-alias edges. The cells themselves are not yet anti aliased.
-rw-r--r--aperiodic_tiling.cginc101
1 files changed, 57 insertions, 44 deletions
diff --git a/aperiodic_tiling.cginc b/aperiodic_tiling.cginc
index 5e12ee0..142a3de 100644
--- a/aperiodic_tiling.cginc
+++ b/aperiodic_tiling.cginc
@@ -43,11 +43,6 @@ float2x2 inv2x2(float2x2 m) {
return float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / d;
}
-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);
@@ -61,13 +56,6 @@ float tile5_distance_from_barycentric(float2 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);
-}
-
#if defined(_APERIODIC_TILING_NORMALS)
float3 aperiodic_tiling_normal(float2 barycentric) {
float bevel_width = min(_Aperiodic_Tiling_Normal_Thickness, 0.5);
@@ -85,13 +73,18 @@ float3 aperiodic_tiling_normal(float2 barycentric) {
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;
- }
+ bool better = (candidate_distance > distance_to_edge);
+ distance_to_edge = better ? candidate_distance : distance_to_edge;
+ best_barycentric = better ? barycentric : best_barycentric;
}
-AperiodicTileSample sample_aperiodic_orientation(
+struct AperiodicTileSample {
+ float distance_to_edge;
+ float2 barycentric;
+ uint face_id;
+};
+
+AperiodicTileSample sample_lattice(
float4 p03, float p44, float4 a03, float a44, float4 b03, float b44) {
float2 pa = proj5(a03, a44);
float2 pb = proj5(b03, b44);
@@ -112,22 +105,17 @@ AperiodicTileSample sample_aperiodic_orientation(
distance_to_edge, best_barycentric);
AperiodicTileSample sample;
- sample.coverage = aperiodic_edge_coverage(distance_to_edge);
+ sample.distance_to_edge = 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
+void accumulate_best(AperiodicTileSample candidate, uint face_id,
+ inout AperiodicTileSample best) {
+ bool better = (candidate.distance_to_edge > best.distance_to_edge);
+ best.distance_to_edge = better ? candidate.distance_to_edge : best.distance_to_edge;
+ best.barycentric = better ? candidate.barycentric : best.barycentric;
+ best.face_id = better ? face_id : best.face_id;
}
void sample_aperiodic_tiling(float2 uv, out float3 albedo
@@ -137,24 +125,49 @@ void sample_aperiodic_tiling(float2 uv, out float3 albedo
float p44 = uv.x * basis_u5_44 + uv.y * basis_v5_44;
float2 u = float2(0, 1);
+
+ // Accumulate best sample across all 10 face orientations = C(5,2) pairs
+ AperiodicTileSample best;
+ best.distance_to_edge = -1e10;
+ best.barycentric = 0;
+ best.face_id = 0;
+
+ accumulate_best(sample_lattice(p03, p44, u.yxxx, u.x, u.xyxx, u.x), 0, best);
+ accumulate_best(sample_lattice(p03, p44, u.yxxx, u.x, u.xxyx, u.x), 1, best);
+ accumulate_best(sample_lattice(p03, p44, u.yxxx, u.x, u.xxxy, u.x), 2, best);
+ accumulate_best(sample_lattice(p03, p44, u.yxxx, u.x, u.xxxx, u.y), 3, best);
+ accumulate_best(sample_lattice(p03, p44, u.xyxx, u.x, u.xxyx, u.x), 4, best);
+ accumulate_best(sample_lattice(p03, p44, u.xyxx, u.x, u.xxxy, u.x), 5, best);
+ accumulate_best(sample_lattice(p03, p44, u.xyxx, u.x, u.xxxx, u.y), 6, best);
+ accumulate_best(sample_lattice(p03, p44, u.xxyx, u.x, u.xxxy, u.x), 7, best);
+ accumulate_best(sample_lattice(p03, p44, u.xxyx, u.x, u.xxxx, u.y), 8, best);
+ accumulate_best(sample_lattice(p03, p44, u.xxxy, u.x, u.xxxx, u.y), 9, best);
+
+ // Compute edge coverage from distance
+ float edge_width = saturate(_Aperiodic_Tiling_Edge_Thickness * 2.0) * 0.5;
+ float edge_sd = best.distance_to_edge - edge_width;
+ float edge_sd_aa = max(abs(fwidth(edge_sd)), 1e-4);
+ float edge_mask = smoothstep(-edge_sd_aa * 0.5, edge_sd_aa * 0.5, edge_sd);
+
+ // Select face color and composite
+ float3 face_colors[10];
+ face_colors[0] = _Aperiodic_Tiling_Color_0.rgb;
+ face_colors[1] = _Aperiodic_Tiling_Color_1.rgb;
+ face_colors[2] = _Aperiodic_Tiling_Color_2.rgb;
+ face_colors[3] = _Aperiodic_Tiling_Color_3.rgb;
+ face_colors[4] = _Aperiodic_Tiling_Color_4.rgb;
+ face_colors[5] = _Aperiodic_Tiling_Color_5.rgb;
+ face_colors[6] = _Aperiodic_Tiling_Color_6.rgb;
+ face_colors[7] = _Aperiodic_Tiling_Color_7.rgb;
+ face_colors[8] = _Aperiodic_Tiling_Color_8.rgb;
+ face_colors[9] = _Aperiodic_Tiling_Color_9.rgb;
+
float3 edge = _Aperiodic_Tiling_Edge_Color.rgb;
- albedo = edge;
- float2 normal_xy_accum = 0;
-
- // 10 face orientations = C(5,2) pairs of 5D axes
- 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);
+ albedo = lerp(edge, face_colors[best.face_id], edge_mask);
#if defined(_APERIODIC_TILING_NORMALS)
- tiling_normal_tangent = normalize(float3(normal_xy_accum, 1.0));
+ float3 tile_normal = aperiodic_tiling_normal(best.barycentric);
+ tiling_normal_tangent = normalize(float3(tile_normal.xy * edge_mask, 1.0));
#else
tiling_normal_tangent = 0;
#endif