diff options
| -rw-r--r-- | aperiodic_tiling.cginc | 101 |
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 |
