// Netting for the goal pocket. // // Applied to a box viewed from the inside (cull_front), so one mesh gives a // five-sided pocket of netting rather than a flat panel across the back. The // strand pattern is driven from model-space position rather than UV so spacing // stays physical and continuous across all five faces — a box's UV layout // would stretch it differently on each. // // Cut with discard rather than alpha blending on purpose: an alpha-scissor net // still writes depth, so it sorts against the pocket, the frame and the // arena's containment field like ordinary solid geometry. A blended net would // join the transparent queue and sort per-object against the boundary shell, // which is the class of artefact this whole pass removed. shader_type spatial; render_mode cull_front, diffuse_burley; uniform vec3 net_color : source_color = vec3(0.65, 0.78, 1.0); uniform float cell_size = 0.13; uniform float strand_width = 0.011; uniform float emission_strength : hint_range(0.0, 4.0) = 0.35; varying vec3 v_local; varying vec3 v_local_normal; void vertex() { v_local = VERTEX; v_local_normal = NORMAL; } // Distance to the nearest strand centre line of a square lattice. float strand(vec2 p) { vec2 d = abs(fract(p / cell_size) - 0.5) * cell_size; return min(d.x, d.y); } void fragment() { vec3 n = abs(normalize(v_local_normal)); // Project onto whichever plane this face lies in. float d = n.x > max(n.y, n.z) ? strand(v_local.zy) : (n.y > n.z ? strand(v_local.xz) : strand(v_local.xy)); if (d > strand_width) { discard; } // Only back faces survive cull_front, and their normals point out of the // pocket rather than into it, so flip them or the netting lights from // behind and reads flat black. if (!FRONT_FACING) { NORMAL = -NORMAL; } ALBEDO = net_color * 0.25; EMISSION = net_color * emission_strength; ROUGHNESS = 0.65; METALLIC = 0.1; }