"""Region agreement: does the 3D pane paint exactly the 2D island? The user-visible claim this file checks: the set of fragments the 3D surface paints as *valid* must be the 2D island's inverse image under the mesh's UV map, to within one texel of the field domain, with **no** disagreement in the island's interior. Before the texture-first path it was not. The colour came from a per-vertex gather (``sampling.SurfaceSampler``), one invalid tap made a vertex ``NaN``, the shader's ``isnan`` rule painted every triangle touching it grey, and on the shipped finger asset that measured as 5763 of the 27227 mesh-covered island texels painted grey (**21.17 %**), 5476 of them strictly *inside* the island, with 26840 wrong pixels on screen. The same measurement after the change is 0, 0 and 0. How it is measured, and why this is not a tautology --------------------------------------------------- The pane is drawn by a real GL context and the framebuffer is read back. The *reference* is computed on the CPU from the same camera matrices, viewport, vertex positions and UVs: every triangle is rasterised, ``a_uv`` is interpolated perspective-correctly exactly as a GPU varying is, and the texel it addresses is the one the fragment shader's ``floor(v_uv + 0.5)`` selects. So the comparison is between the GPU's answer and an independent CPU derivation of the same UV map. A wrong UV convention, a wrong v flip, an off-by-one texel, a stale ``a_scalar`` attribute or a leftover per-vertex path all show up as a large difference — which is exactly how the numbers above were produced. The tolerance is the design's, and it is asserted in *domain* space, which is where "one texel of the 300x280 domain" is defined: * every island texel the mesh covers is painted valid, and no texel outside the island's one-texel dilation is (``residual <= 1 texel``); * the island's one-texel *erosion* is painted valid everywhere and invalid nowhere (``zero interior disagreement``); * no texel is painted both ways (a fragment-level disagreement). The mesh's UV footprint is a sub-rectangle of the domain (the shipped finger mesh spans x 0.03..279.0, y 42.6..256.4 of a 300x280 grid), so 5710 island texels have no triangle over them at all. "The island's inverse image under the mesh UV map" is therefore *island ∩ covered*, and every interior/outside assertion is restricted to that set: a texel no triangle reaches cannot be evidence about the shader. There is deliberately no ``pytest.skip`` for a missing context once a real platform is in use: this is the only coverage of this property on actual hardware, and a silent skip is how it stayed broken. The module is not collected under the offscreen plugin because that plugin cannot create a platform GL context *at all* — a property of the plugin, not of the machine — which is the same rule ``test_scene3d_gl_smoke.py`` follows. """ from __future__ import annotations import os import numpy as np import pytest os.environ.setdefault("QT_OPENGL", "desktop") os.environ.setdefault("PYQTGRAPH_QT_LIB", "PySide6") pytestmark = pytest.mark.skipif( os.environ.get("QT_QPA_PLATFORM", "").lower() in ("offscreen", "minimal"), reason="the offscreen/minimal plugin cannot create a platform GL context", ) #: The 2D canvas's clear colour and the round-trip sentinels, in 8-bit. BACKGROUND_RGB = (15, 18, 23) INVALID_SENTINEL = (0, 255, 0) # patches gl_backend.INVALID_COLOR #: The shipped domain, when the real package is the subject. REAL_VIEWPORT = (900, 900) #: A dense synthetic domain: one vertex per texel over a 320x240 viewport, so a texel is #: about five pixels and a per-vertex path cannot look like a per-fragment one by luck. DENSE_DOMAIN_HW = (40, 48) DENSE_VIEWPORT = (320, 240) DENSE_PLATE_M = 0.06 # ------------------------------------------------------------------------ helpers def adjacent_to(mask: np.ndarray) -> np.ndarray: """Everything 8-adjacent to ``mask``: its one-texel dilation, without itself.""" out = np.zeros_like(mask) for dy in (-1, 0, 1): for dx in (-1, 0, 1): if dy == 0 and dx == 0: continue out |= np.roll(np.roll(mask, dy, axis=0), dx, axis=1) return out def dilate1(mask: np.ndarray) -> np.ndarray: return mask | adjacent_to(mask) def erode1(mask: np.ndarray) -> np.ndarray: return mask & ~adjacent_to(~mask) def reference_texels(positions, uvs, triangles, camera, viewport): """Which texel every framebuffer pixel reads, derived independently of the GPU.""" view = np.asarray(camera.view, dtype=np.float64).reshape(4, 4) projection = np.asarray(camera.projection, dtype=np.float64).reshape(4, 4) width, height = int(viewport[0]), int(viewport[1]) homo = np.hstack([np.asarray(positions, dtype=np.float64), np.ones((len(positions), 1))]) clip = (projection @ view @ homo.T).T w = clip[:, 3] ndc = clip[:, :3] / w[:, None] x = (ndc[:, 0] * 0.5 + 0.5) * width y = (ndc[:, 1] * 0.5 + 0.5) * height depth = np.full((height, width), np.inf) texel = np.full((height, width, 2), -1, dtype=np.int64) for tri in np.asarray(triangles, dtype=np.int64): i0, i1, i2 = int(tri[0]), int(tri[1]), int(tri[2]) xs = np.array([x[i0], x[i1], x[i2]]) ys = np.array([y[i0], y[i1], y[i2]]) area = (xs[1] - xs[0]) * (ys[2] - ys[0]) - (xs[2] - xs[0]) * (ys[1] - ys[0]) if area == 0.0: continue min_x = max(int(np.floor(xs.min() - 0.5)), 0) max_x = min(int(np.ceil(xs.max() + 0.5)), width) min_y = max(int(np.floor(ys.min() - 0.5)), 0) max_y = min(int(np.ceil(ys.max() + 0.5)), height) if min_x >= max_x or min_y >= max_y: continue gx, gy = np.meshgrid( np.arange(min_x, max_x) + 0.5, np.arange(min_y, max_y) + 0.5 ) l0 = ((xs[1] - gx) * (ys[2] - gy) - (xs[2] - gx) * (ys[1] - gy)) / area l1 = ((xs[2] - gx) * (ys[0] - gy) - (xs[0] - gx) * (ys[2] - gy)) / area l2 = 1.0 - l0 - l1 inside = (l0 >= 0.0) & (l1 >= 0.0) & (l2 >= 0.0) if not inside.any(): continue zs = np.array([ndc[i0, 2], ndc[i1, 2], ndc[i2, 2]]) ws = np.array([w[i0], w[i1], w[i2]]) zi = l0 * zs[0] + l1 * zs[1] + l2 * zs[2] window = depth[min_y:max_y, min_x:max_x] take = inside & (zi < window) if not take.any(): continue inv_w = l0 / ws[0] + l1 / ws[1] + l2 / ws[2] uu = ( l0 * uvs[i0, 0] / ws[0] + l1 * uvs[i1, 0] / ws[1] + l2 * uvs[i2, 0] / ws[2] ) / inv_w vv = ( l0 * uvs[i0, 1] / ws[0] + l1 * uvs[i1, 1] / ws[1] + l2 * uvs[i2, 1] / ws[2] ) / inv_w window[take] = zi[take] rows, cols = np.nonzero(take) view_x = texel[min_y:max_y, min_x:max_x, 0] view_y = texel[min_y:max_y, min_x:max_x, 1] view_x[rows, cols] = np.floor(uu[take] + 0.5) view_y[rows, cols] = np.floor(vv[take] + 0.5) return texel, np.isfinite(depth) def classify(pixels, target, tolerance): flat = pixels.reshape(-1, 3).astype(np.int16) return ( np.abs(flat - np.asarray(target, dtype=np.int16)).max(axis=1) <= tolerance ).reshape(pixels.shape[:2]) def measure(island, texel, covered, painted_valid, painted_invalid): """The domain-space numbers, and the assertions, in one place.""" shape = island.shape # The GPU's own coverage, not this rasteriser's: the reference's barycentric test # includes triangle and silhhouette edge pixels that GL's fill rule rejects, and a # texel only this reference reaches would otherwise read as "the pane failed to paint # it". A texel is covered when a pixel the pane *did* paint resolves to it. painted = painted_valid | painted_invalid covered = covered & painted height, width = int(shape[0]), int(shape[1]) flat = texel[..., 1] * width + texel[..., 0] valid_texel = np.zeros(shape[0] * shape[1], dtype=bool) invalid_texel = np.zeros(shape[0] * shape[1], dtype=bool) covered_texel = np.zeros(shape[0] * shape[1], dtype=bool) covered_texel[flat[covered]] = True valid_texel[flat[covered & painted_valid]] = True invalid_texel[flat[covered & painted_invalid]] = True valid_texel = valid_texel.reshape(shape) invalid_texel = invalid_texel.reshape(shape) covered_texel = covered_texel.reshape(shape) island_covered = island & covered_texel grey = island_covered & ~valid_texel extra = valid_texel & ~island interior = erode1(island) & covered_texel outside = ~dilate1(island) & covered_texel mixed = valid_texel & invalid_texel # The one-texel rim of the island, in screen terms: a pixel is in the band when its # own texel has a 4-neighbour with the opposite validity. tx = np.clip(texel[..., 0], 0, width - 1) ty = np.clip(texel[..., 1], 0, height - 1) here = island[ty, tx] band = np.zeros_like(here) for dy, dx in ((-1, 0), (1, 0), (0, -1), (0, 1)): band |= island[np.clip(ty + dy, 0, height - 1), np.clip(tx + dx, 0, width - 1)] != here band &= covered expected = np.zeros(here.shape, dtype=bool) expected[covered] = here[covered] missing_pixels = expected & ~painted_valid extra_pixels = painted_valid & covered & ~expected return { "island_texels": int(island.sum()), "rim_texels": int((island & adjacent_to(~island)).sum()), "island_covered_texels": int(island_covered.sum()), "island_uncovered_texels": int((island & ~covered_texel).sum()), "painted_valid_texels": int(valid_texel.sum()), "island_grey_texels": int(grey.sum()), "island_grey_percent": round( 100.0 * float(grey.sum()) / max(int(island_covered.sum()), 1), 4 ), "extra_valid_texels": int(extra.sum()), "mixed_texels": int(mixed.sum()), "mixed_inside_interior": int((mixed & erode1(island)).sum()), "covered_pixels": int(covered.sum()), "interior_texels": int(interior.sum()), "interior_not_painted_valid": int((interior & ~valid_texel).sum()), "interior_painted_invalid": int((interior & invalid_texel).sum()), "outside_dilated_painted_valid": int((outside & valid_texel).sum()), "grey_more_than_one_texel_inside": int((grey & erode1(island)).sum()), "grey_more_than_two_texels_inside": int((grey & erode1(erode1(island))).sum()), "extra_more_than_one_texel_outside": int((extra & ~dilate1(island)).sum()), "extra_more_than_two_texels_outside": int( (extra & ~dilate1(dilate1(island))).sum() ), "band_pixels": int(band.sum()), "missing_pixels": int(missing_pixels.sum()), "extra_pixels": int(extra_pixels.sum()), "missing_pixels_outside_band": int((missing_pixels & ~band).sum()), "extra_pixels_outside_band": int((extra_pixels & ~band).sum()), } def assert_agreement(numbers: dict, label: str) -> None: """Every assertion, with the label so a failure says which subject it was.""" assert numbers["covered_pixels"] > 5000, (label, numbers) # A render that covers almost none of the island would make the rest vacuous. assert numbers["island_covered_texels"] > 0.5 * numbers["island_texels"], (label, numbers) # The island's inverse image: every covered island texel is a measurement. # # Two residues are bounded here rather than waved at, because they have different # causes and only one of them is avoidable: # # * a *rim* texel can be missed when a fragment's interpolated UV sits within float32 # rounding of the neighbouring texel and the GPU rounds the other way — the # "residual <= 1 texel" of the acceptance, and it may not reach deeper than the rim; # * a texel can be *skipped entirely* when the plate is minified: NEAREST sampling of a # 300x280 domain onto a plate of roughly half that many pixels cannot show every # texel, and a validity channel deliberately cannot be averaged (a blended validity # is the partly-valid triangle this change removed). One texel two steps inside the # rim is the measured worst case at the shipped asset's own default view, so the # band is bounded at two texels and the *fraction* at 0.05 %. assert numbers["grey_more_than_one_texel_inside"] <= numbers["rim_texels"], ( f"{label}: the unpainted residue is deeper than the island's rim" ) assert numbers["grey_more_than_two_texels_inside"] == 0, (label, numbers) assert numbers["island_grey_percent"] <= 0.05, ( f"{label}: {numbers['island_grey_percent']} % of the island is painted as no " "measurement; at most a hairline of the rim may be" ) # The same tolerance in the other direction: a texel just outside the island may be # resolved as valid when a fragment's UV rounds the other way, but never deeper than # the rim and never in a way that grows with the island. assert numbers["extra_valid_texels"] <= numbers["rim_texels"], (label, numbers) assert numbers["extra_more_than_one_texel_outside"] == 0, (label, numbers) # Zero interior disagreement, and no disagreement more than one texel out. assert numbers["interior_not_painted_valid"] == 0, (label, numbers) assert numbers["interior_painted_invalid"] == 0, (label, numbers) assert numbers["outside_dilated_painted_valid"] == 0, (label, numbers) assert numbers["grey_more_than_two_texels_inside"] == 0, (label, numbers) assert numbers["extra_more_than_two_texels_outside"] == 0, (label, numbers) # A texel painted both ways can only be a half-texel rounding tie at the rim: a # fragment whose interpolated UV sits within float32 rounding of a texel boundary is # rounded to a different texel by the GPU than by this float64 reference. That is the # residue the one-texel tolerance exists for, and it may never reach the interior. assert numbers["mixed_inside_interior"] == 0, (label, numbers) # ...and every pixel that disagrees is inside that one-texel band. assert numbers["missing_pixels_outside_band"] == 0, (label, numbers) assert numbers["extra_pixels_outside_band"] == 0, (label, numbers) # ---------------------------------------------------------------------- subjects def _dense_scene(): """A flat plate with one vertex per texel, and its island: the controlled case.""" from orisys_app_shared.scene3d.contracts import ( CameraPreset, Material, MeshPart, SceneAssets, SurfaceBinding, freeze, ) from orisys_app_shared.scene3d.digest import field_domain_id, geometry_id height, width = DENSE_DOMAIN_HW step = DENSE_PLATE_M / (max(height, width) - 1) rows, cols = np.meshgrid(np.arange(height), np.arange(width), indexing="ij") positions = np.stack( [ (cols - (width - 1) / 2.0) * step, -(rows - (height - 1) / 2.0) * step, np.zeros_like(rows, dtype=np.float64), ], axis=-1, ).astype(np.float32) flat = positions.reshape(-1, 3) index = (rows * width + cols).astype(np.int64) a = index[:-1, :-1].reshape(-1) b = index[:-1, 1:].reshape(-1) c = index[1:, :-1].reshape(-1) d = index[1:, 1:].reshape(-1) triangles = np.concatenate( [np.stack([a, b, d], axis=1), np.stack([a, d, c], axis=1)], axis=0 ).astype(np.uint32) part = MeshPart( part_id="sensing_surface", role="sensing", positions_sensor_m=freeze(flat, dtype=np.float32), normals_sensor=freeze( np.tile(np.array([0.0, 0.0, 1.0], dtype=np.float32), (len(flat), 1)), dtype=np.float32, ), triangles=freeze(triangles, dtype=np.uint32), material=Material((0.85, 0.85, 0.88, 1.0), "unlit_scalar", True), lod_id="region", ) geom = geometry_id([part]) domain = field_domain_id(shape_hw=DENSE_DOMAIN_HW, flip_v=False) uvs = np.stack( [cols.reshape(-1).astype(np.float32), rows.reshape(-1).astype(np.float32)], axis=1 ) count = len(flat) indices = np.full((count, 4), -1, dtype=np.int32) weights = np.zeros((count, 4), dtype=np.float32) indices[:, 0] = np.arange(count, dtype=np.int32) weights[:, 0] = 1.0 assets = SceneAssets( asset_id="region-dense", asset_version="0.0.0", asset_hash="region-hash", geometry_id=geom, parts=(part,), binding=SurfaceBinding( part_id="sensing_surface", geometry_id=geom, field_domain_id=domain, shape_hw=DENSE_DOMAIN_HW, uvs=freeze(uvs, dtype=np.float32), sample_indices=freeze(indices, dtype=np.int32), sample_weights=freeze(weights, dtype=np.float32), ), camera_presets=( CameraPreset( "front", (0.0, 0.0, DENSE_PLATE_M * 2.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0), 0.6 ), ), bounds_sensor_m=freeze( np.stack([flat.min(axis=0), flat.max(axis=0)]).astype(np.float32), dtype=np.float32, ), field_domain_id=domain, shape_hw=DENSE_DOMAIN_HW, ) island = np.zeros(DENSE_DOMAIN_HW, dtype=bool) island[6:34, 8:40] = True island[12:20, 20:26] = False # a hole: an interior the shader must still colour island[24:30, 30:36] = False # a notch: a concave corner on the boundary return assets, island, uvs, "front" def _shipped_scene(preset_name: str = "front"): """The real finger package, with the island it carries. ``surface_valid.npy`` is byte-identical to the unroll map's ``valid_mask`` (measured: 32937 texels, 0 differing), so the island is the 2D canvas's own island and no path outside this repository is needed to state it. """ from pathlib import Path from orisys_app_shared.scene3d.package import read_package, scene_from_contents package = ( Path(__file__).resolve().parents[1] / "config" / "sensors" / "finger" / "scene" / "finger-display-1.0.0.oryscene" ) assert package.is_file(), f"the shipped scene package is missing: {package}" assets = scene_from_contents(read_package(package), None) mapping = assets.surface_mapping assert mapping is not None, "the shipped package carries no surface mapping" names = {preset.name for preset in assets.camera_presets} assert preset_name in names, f"the shipped package has no {preset_name!r} preset: {names}" return ( assets, np.asarray(mapping.valid, dtype=bool), np.asarray(assets.binding.uvs, dtype=np.float32), preset_name, ) def _render_region(qt_app, assets, island, uvs, preset_name, viewport): """Draw the island through the real GL path and measure the painted region.""" from orisys_app_shared.scene3d.contracts import ( ColorScale, DisplayField, DisplaySettings, FieldDescriptor, FrameIdentity, RenderFrame, freeze, ) from orisys_studio.scene3d import gl_backend from orisys_studio.scene3d.camera import OrbitCamera from orisys_studio.scene3d.gl_backend import ( GLDispatch, GLRenderer, configure_surface_format, lut_rgba, ) from orisys_studio.scene3d.widget import Sensor3DWidget from PySide6.QtGui import QImage configure_surface_format("desktop33") renderer = GLRenderer() widget = Sensor3DWidget(renderer, OrbitCamera(), dispatch=GLDispatch()) seen: list = [] widget.diagnosticRaised.connect(seen.append) widget.resize(*viewport) widget.show() widget.set_scene(assets) def pump(predicate, timeout_s=12.0): import time deadline = time.perf_counter() + timeout_s while time.perf_counter() < deadline: widget.repaint() qt_app.processEvents() if predicate(): return True time.sleep(0.01) return False if not pump(lambda: bool(renderer.part_ids)): widget.release_resources() widget.close() pytest.fail( "no usable OpenGL context on a real platform: " f"{widget.diagnostic() or seen or 'the widget never initialized'}" ) preset = next(item for item in assets.camera_presets if item.name == preset_name) widget.camera().set_preset(preset) widget.camera().fit(assets.bounds_sensor_m, viewport[0] / max(viewport[1], 1)) widget.repaint() qt_app.processEvents() descriptor = FieldDescriptor("flow_magnitude", "px", "approximate", False) frame = RenderFrame( identity=FrameIdentity("region", 1, 1, 0.0, generation=1), asset_hash=assets.asset_hash, geometry_id=assets.geometry_id, sensing_part_id=assets.sensing_part().part_id, positions_sensor_m=assets.sensing_part().positions_sensor_m, normals_sensor=assets.sensing_part().normals_sensor, field=DisplayField( domain_id=assets.field_domain_id, shape_hw=(int(island.shape[0]), int(island.shape[1])), scalar=freeze( np.where(island, 1.0, 0.0).astype(np.float32), dtype=np.float32 ), valid=freeze(np.array(island, dtype=bool), dtype=np.bool_), descriptor=descriptor, ), ) widget.set_settings( DisplaySettings( housing_visible=False, color_scale=ColorScale( descriptor=descriptor, lower=0.0, upper=1.0, lut_id="sequential" ), ) ) # The invalid colour is the sentinel the readback is classified by. ``draw`` reads it # from the module, so patching the module is what the shader is given. gl_backend.INVALID_COLOR = (0.0, 1.0, 0.0, 1.0) # The colour a *valid* fragment gets comes from the tree's own lookup table, not from # a hard-coded constant: the 2D canvas and the 3D surface must be coloured by one # table, and a test that hard-coded the colour would stop noticing if they diverged. valid_rgb = tuple(int(v) for v in lut_rgba("sequential")[-1, 0, :3]) widget.present(frame) try: assert pump( lambda: getattr(renderer, "field_shape", None) == (int(island.shape[0]), int(island.shape[1])) ), "the field texture was never uploaded" for _ in range(8): widget.repaint() qt_app.processEvents() image = widget.grabFramebuffer() assert not image.isNull(), "Qt returned no framebuffer" image = image.convertToFormat(QImage.Format.Format_RGB888) width, height = image.width(), image.height() buffer = np.frombuffer(image.constBits(), dtype=np.uint8) pixels = ( np.frombuffer(buffer, dtype=np.uint8) .reshape(height, image.bytesPerLine())[:, : width * 3] .reshape(height, width, 3) .copy() ) background = classify(pixels, BACKGROUND_RGB, 6) painted_valid = classify(pixels, valid_rgb, 14) & ~background painted_invalid = classify(pixels, INVALID_SENTINEL, 14) & ~background texel, covered = reference_texels( np.asarray(frame.positions_sensor_m, dtype=np.float64), uvs, assets.sensing_part().triangles, widget.camera().matrices(widget.viewport_pixels()), widget.viewport_pixels(), ) # The reference is built in GL window coordinates (y up); the grab is top-down. return ( measure( island, texel[::-1], covered[::-1], painted_valid, painted_invalid, ), renderer, ) finally: widget.release_resources() widget.close() # ------------------------------------------------------------------------ the test @pytest.fixture(scope="module") def dense_region(qt_app): assets, island, uvs, preset = _dense_scene() numbers, _ = _render_region( qt_app, assets, island, uvs, preset, DENSE_VIEWPORT ) return numbers @pytest.fixture(scope="module") def shipped_region(qt_app): """The shipped asset, seen face-on and magnified: the exact case.""" assets, island, uvs, preset = _shipped_scene("front") numbers, _ = _render_region(qt_app, assets, island, uvs, preset, REAL_VIEWPORT) return numbers @pytest.fixture(scope="module") def shipped_default_region(qt_app): """The shipped asset at *its own* default preset: a three-quarter, minified view.""" assets, island, uvs, _ = _shipped_scene("front") default = assets.camera_presets[0].name numbers, _ = _render_region(qt_app, assets, island, uvs, default, REAL_VIEWPORT) return numbers def test_the_dense_scene_paints_exactly_the_island(dense_region): """The controlled case: one vertex per texel, a hole and a notch in the island. Nothing is tolerated here. The plate is seen face-on and every texel is magnified, so neither a rounding tie nor a skipped texel can arise: the painted region must be the island exactly. """ assert_agreement(dense_region, "dense") assert dense_region["island_grey_texels"] == 0, dense_region assert dense_region["extra_valid_texels"] == 0, dense_region assert dense_region["grey_more_than_one_texel_inside"] == 0, dense_region assert dense_region["mixed_texels"] == 0, dense_region assert dense_region["missing_pixels"] == 0, dense_region assert dense_region["extra_pixels"] == 0, dense_region # Nothing may be left uncovered here: the mesh spans the whole domain. assert dense_region["island_uncovered_texels"] == 0, dense_region assert dense_region["painted_valid_texels"] == dense_region["island_texels"] def test_the_shipped_package_paints_exactly_the_island(shipped_region): """The real acceptance: the shipped asset, face-on, every texel magnified. Zero tolerance, as the design asks: no island texel is grey, no texel outside the island is painted as a measurement, and no pixel disagrees at all. Before the change the same measurement was 5763 grey island texels — 5476 of them strictly inside the island — and 26840 wrong pixels. """ numbers = shipped_region assert_agreement(numbers, "shipped") assert numbers["island_grey_texels"] == 0, numbers assert numbers["extra_valid_texels"] == 0, numbers assert numbers["mixed_texels"] == 0, numbers assert numbers["missing_pixels"] == 0, numbers assert numbers["extra_pixels"] == 0, numbers assert numbers["painted_valid_texels"] == numbers["island_covered_texels"], numbers # Reported, not asserted: the mesh's UV footprint is a sub-rectangle of the domain, # so these island texels have no triangle over them at all. assert numbers["island_uncovered_texels"] > 0, numbers def test_the_shipped_default_view_keeps_the_residue_on_the_rim(shipped_default_region): """The view an operator actually opens: three-quarter, and minified. Nothing may be grey except within two texels of the island's rim, and almost nothing may be: measured as 1 texel of 25539 (0.0039 %) — the one texel the GPU never resolved as itself, because NEAREST sampling of a 300x280 domain onto a plate of about half that many pixels cannot show every texel, and a validity channel may not be averaged. (The old per-vertex path, on this same view, left 5763 texels grey with 5476 of them strictly inside the island.) """ numbers = shipped_default_region assert_agreement(numbers, "shipped-default") assert numbers["island_grey_percent"] < 0.05, numbers assert numbers["interior_painted_invalid"] == 0, numbers # The residual at this view is a rim rounding tie and nothing more: at most one texel # of the island missed and at most one texel just outside it claimed, both adjacent to # the boundary, and no disagreement anywhere but the one-texel band. assert numbers["island_grey_texels"] <= 1, numbers assert numbers["extra_valid_texels"] <= 1, numbers assert numbers["grey_more_than_one_texel_inside"] == 0, numbers assert numbers["extra_more_than_one_texel_outside"] == 0, numbers