Repository navigation
Fix shader problem that broke 2-D vertex data - #715
Merged
Merged
Conversation
Contributor
|
This fixes Vertex2D in Chromium. I was hoping it would also fix it in Firefox (#375), since the root cause was the same from my investigation, but apparently not. |
Contributor
|
I also don't like that this test duplicates a chunk of the shader code (mainly definitions). I think we should test for general OpenGL errors in one of the basic rendering tests, or even |
Nothing caught gh-714: the shader that failed to link compiled fine, no javascript error was raised, and the screenshot was written -- it was just empty. test_webgl_shaders links every combination of options the viewer builds surface, pick and depth shaders with, through THREE.ShaderMaterial (the same path DataView.getShader() uses) in a real SwiftShader GL context. Needs Chromium but no subject database, so it runs in a couple of seconds and covers variants no render test puts on screen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013wiUP7TLgDqSfnv4n9ySZj
The surface shaders sit right up against the 16 vertex attribute slots WebGL guarantees, and #679 added two more of them (flatheight and flatBumpNorms) to the vertex data shader so that bumpy_flatmap would work for Vertex dataviews. 2D vertex data needs four data attributes rather than two, which pushed surface_vertex to 17: it still compiles, but it fails to link with "Too many attributes", and three.js only reports that on the browser console, so the viewer just draws a black screen. The same overflow hits plain Vertex data as soon as equivolume sampling is on. Rather than giving these values slots of their own, pack them into the spare components of attributes that are already bound: - the white matter and pial vertex areas, which only the equivolume depth sampling reads, move into auxdat.zw (auxdat.x is the medial wall mask and .y the curvature; z and w were left at zero by brainctm) - the flatmap bump height moves into the fourth component of the bumped flatmap normals, so the two become a single vec4 flatbump attribute Every shader variant now links: the worst case, 2D vertex data on a subject with a flatmap, goes from 19 attributes to 16. Renders of the paths that did work before -- volume data with equivolume sampling, and the bumpy flatmap -- are pixel-identical to what they were. Fixes gh-714. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013wiUP7TLgDqSfnv4n9ySZj
Regenerated the visual-regression references with the same pinned chromium/playwright/matplotlib as the rest of the reference set; no existing reference image changed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Drop the dead compiled/attributes/max_attributes diagnostics from the assert: a compile failure always fails the subsequent link too (its error text already lands in the joined log). - Add test to ensure we catch compile failures.
kroq-gar78
force-pushed
the
claude/issue-714-irf5g0
branch
from
September 21, 2026 08:21
f534196 to
8a03351
Compare
kroq-gar78
approved these changes
Sep 21, 2026
mvdoc
pushed a commit
that referenced
this pull request
Sep 21, 2026
#715 landed the same fix on main, and did it better. Both pack the bumpy flatmap's height into the fourth component of its normals, but #715 also moves the white matter and pial vertex areas into the two unused components of `auxdat`, which brings the worst case (2D vertex data on a subject with a flatmap) from 19 attributes down to 16 rather than to 17. That extra headroom matters: at 17, plain `Vertex` data still overflows as soon as equivolume sampling is on, which our fix left broken. #715 also names the packed attribute `flatbump`, factors its declaration into `utils.flatbump_attr`, and adds test_webgl_shaders.py, which links every shader variant the viewer can build and would have caught gh-714 in the first place. Dropping our version of the JS here so the merge of main takes #715's wholesale rather than resolving two equivalent edits line by line. The xfail removals and the reference-image bookkeeping are reconciled in the merge commit that follows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015yNgwu9miNKAuv79yPMqU8
mvdoc
pushed a commit
that referenced
this pull request
Sep 21, 2026
main gained #715, which fixes gh-714 the same way this branch had just tried to and then some, so the JS took main's side wholesale (see the revert commit before this one). The two conflicts were both in the bookkeeping that fix came with: - test_visual_regression.py: the comment explaining why Vertex2D was xfailed. Both sides dropped the xfail; main's side wins, since #715 is what fixed it, not this branch. - reference_images/README.md: same, plus provenance. Took main's account of the four Vertex2D images and kept this branch's note that the flatmap references still need regenerating for the NaN/alpha changes. Left this branch's correction to the webgl/quickflat reference counts (18/14, not 16/12): #715 added four images without updating that line. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015yNgwu9miNKAuv79yPMqU8
mvdoc
pushed a commit
that referenced
this pull request
Sep 21, 2026
Three gaps this branch's own changes left uncovered. test_webgl_shaders.py: #715's matrix already covers this branch's extra `nanmask` attribute -- all 27 variants still link, worst case included -- but not the options this branch adds to the volume-sampling shader. _nan_alpha_variants adds 20 surface_pixel variants over dataalpha x nanmean x layers (1 and 32) x the cmap/2d/rgb branches, hasflat and equivolume pinned on. 47 variants, still under seven seconds, and no subject database needed. test_visual_regression.py, the alpha map on 2D dataviews: _dataview grew a `twod_alpha` switch and NAN_ALPHA_DATAVIEW_NAMES now lists all four classes that take an explicit `alpha=`, not just the two RGB ones. Volume2D and Vertex2D accepted the argument before this branch as well, but it went into `attrs` as a bare ndarray, so quickflat mishandled it and the viewer failed to load the dataview -- that is the first fix in this PR and nothing in the visual suite could see it. _build_nan_dataview passes it too, which finally makes that builder do what its own comment says: NaN every place the rule names, the alpha map included. test_visual_regression.py, averaging across depth: a new multilayer_nan_dataviews suite, the three volumetric classes at both values of `nanmean`, with quickflat's `thick` and the viewer's `layers` both set to 32 and NaNs in diagonal slabs two voxels thick, so most surface points have both NaN and valid samples under them. The other suites NaN whole columns and leave depth sampling alone -- at their defaults the renderers do not even sample the same number of depths (quickflat 32, the viewer 1) -- so none of them can see the change this PR makes to how a column of samples is combined. Measured on renders from the regenerate path, the scenario separates cleanly and the renderers agree: data covers 0.797 of the flatmap with nanmean on and 0.196 with it off in quickflat, 0.815 and 0.185 in the viewer. The Volume2D case of that suite is flaky, and not because of anything here. Setting `layers` above 1 intermittently leaves the viewer's RPC proxy answering `{}` to every later query, so save_3d_views dies on the next parameter it sets; it never recovers and the browser reports no error. Building the same dataview inline and running the same sequence reproduces it on main at about the same rate, roughly one run in four, so it is a pre-existing viewer/JSProxy bug rather than a gh-695 regression -- this is just the first test to drive `layers` above 1 on a 2D dataview. Documented in the test and left in. References for all of this still have to be generated; see reference_images/README.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015yNgwu9miNKAuv79yPMqU8
AgarwalNilay
pushed a commit
that referenced
this pull request
Sep 22, 2026
The bumpy flatmap gives a flatmap relief that survives full data coverage. It was computed in javascript, at viewer load time, and it was noisy enough that the result was treated with iterated Laplacian smoothing. Reading the shipped code, two things stood out. The height was `computeFlatVolumeHeight(wmareas, vertexvolumes)` -- the denominator was the *folded* white matter vertex area, not the flattened one -- so with `A_pial = r**2 * A_wm` it collapsed to `thickness * (1 + r + r**2) / 3` and never looked at the flatmap at all. The version that does use flat areas was commented out, because it spikes: `V / A_flat` has a denominator that goes to zero wherever flattening crushed a triangle, and smoothing a field of ratios afterwards is dominated by exactly those outliers. Replace it with a physical model, computed in python and cached. cortex.polyutils.FlatSlab treats the tissue between the white matter and pial surfaces as a soft elastic solid, pins the white matter side to the flatmap and lets the pial side settle, minimising a stable Neo-Hookean energy (Smith, De Goes & Kim 2018) over wedge elements cut into tetrahedra. What keeps real tissue from spiking is not gravity -- over a 3mm slab `rho*g*t/mu` is about 0.026, a couple of percent -- but shear: a tall narrow column is expensive because it shears against its neighbours and relieves that by spreading sideways. So the pial vertices get three degrees of freedom rather than one, gyral crowns end up wider at the top than at the bottom and sulcal fundi narrower, and the relief comes out smooth without anything being smoothed. With no body force and a uniform material the shear modulus factors out of the minimiser entirely, so Poisson's ratio is the only material parameter that affects the result and it is the only one the API takes. On S1's left hemisphere this drops the height's p99.9-to-median ratio from 2.4 (naive) and 3.8 (the old javascript) to 1.9, with the tallest point at 5.9mm rather than 13.9mm, and the height correlates with mean curvature at +0.52. Also move the equivolume depth sampling's vertex areas out of javascript, which lets them use the cotangent-weighted operator in Surface.smooth rather than a uniform umbrella, and removes the last of the per-load numeric kernels. Plumbing: - surfinfo.bumpy_flatmap and surfinfo.equivolume_areas cache the results. Both store more than one value per vertex, so they avoid the `left`/`right` keys that get_surfinfo turns into a Vertex by concatenation. - get_surfinfo takes `generate=False` for info too expensive to compute behind someone's back. The bumpy flatmap uses it: it is generated when a flatmap is imported, and a subject imported before this existed gets a flat flatmap and a message saying how to fill it in, rather than a viewer that disappears for a quarter of an hour. - import_flat generates it, and now also clears the surface info derived from the flatmap it just replaced -- clear_cache only empties cache/, so distortion and flat_border could go stale there too. - The offsets ride to the viewer in a `flatoffset` ctm attribute. The surface shaders use all 16 of the vertex attribute slots webgl guarantees (see #715), so javascript unpacks them into `flatbump.w` and the unused `w` of `wm` and of the flat morph target rather than adding a seventeenth. - bumpy_flatmap_scale exaggerates the relief for display without touching the cached geometry. - The ctm cache token goes to v4, since older packs have neither attribute. Tests check the relaxation against cases with known answers rather than against stored output: an identity flat map has to leave the slab exactly alone, a uniformly stretched thin slab has to reproduce the homogeneous solution in its interior, and the requested Poisson ratio has to come back out of the small strain elasticity tensor. A headless test renders the flatmap with and without the relief and fails if the two images match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JG9XE4ZAitPgsQYRDwtwVT
kroq-gar78
added a commit
that referenced
this pull request
Sep 30, 2026
…views (#695) * WebGL viewer: make opacity slider and `o` toggle work for Vertex data (#684) The dat.GUI opacity slider and the `o` shortcut both drive the `dataAlpha` uniform. The volume shaders apply it (`vColor *= dataAlpha`), but the `surface_vertex` fragment shader only declared it and never read it, so opacity was a silent no-op for Vertex, Vertex2D and VertexRGB data. - shaderlib.js: scale the per-vertex data colour by `dataAlpha` before compositing over the curvature. `vColor` is a varying, so scale into a local `dColor`. Scaling all four channels keeps the premultiplied-alpha convention of the volume path, so opacity 0 shows curvature only. - mriview_surface.js: `toggleOpacity` now remembers the last visible opacity instead of rounding it (0.7 -> 0 -> 0.7, not 0.7 -> 0 -> 1), and no longer leaks an implicit global. - test_webgl_headless.py: regression test rendering a saturated Vertex at opacity 1 -> 0 -> 1 and counting coloured pixels. Fails on main (53,760 red pixels at opacity 0) and passes with the fix. Closes #684 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8oA4mUvTLd7sbs9iFaqM8 * test: replace magic-number thresholds in vertex opacity test with named, image-relative quantities Address review on #685: the 1000 / 50 / 1000 pixel-count thresholds were unexplained. The assertions now use named constants derived from the measured renders and related to the image size or to each other: - opacity 1: red-dominant pixels must cover >= 10% of the frame (measured ~27% at this view; curvature-only renders give 0%). - opacity 0: at most 1% of the opacity-1 count (measured 0). - opacity restored to 1: within 5% of the original count, which is a stronger check of the round trip than the previous "> 1000". Re-verified: fails against the pre-fix shader (53,760 red pixels remain at opacity 0), passes with the fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8oA4mUvTLd7sbs9iFaqM8 * FIX unify NaN and alpha handling across quickflat, WebGL and RGB dataviews Rule: a NaN anywhere at a voxel/vertex (data, either 2D dimension, any RGB channel, or the alpha map) renders fully transparent in both renderers; otherwise the alpha (2D colormap, alpha= kwarg, RGB alpha channel) is honored. - Volume2D/Vertex2D: alpha= is a real attribute (not an ndarray in attrs, which crashed the WebGL viewer with a 500); multiplied into the colormap alpha in quickflat for both classes, shipped to WebGL as a normalized float brain and applied in the shaders (folded into the nanmask attribute for vertex data: 2D vertex views already use 15 of the 16 guaranteed vertex attributes and adding more made the program fail to link silently). Saved/restored in HDF. - VolumeRGB/VertexRGB: NaN mask is applied without writing into the temporary returned by .volume for masked (linear) alpha Volumes; single- frame alpha is broadcast against multi-frame NaN masks (closes #629); NaN inside the alpha map -> 0 explicitly; color_voxels no longer mutates the caller's alpha array. - quickflat: RGBA is averaged across thickness in premultiplied space (no dark halos around transparent voxels, matching the WebGL compositor); make_svg no longer indexes arr[..., 3] on 2-D scalar images. - Dataview2D.to_json keeps vmin/vmax of exactly 0. - Package deduplicates byte-identical brains (Vertex2D(x, x) / VertexRGB(r, r, r) used to be reordered twice and crash the viewer). - WebGL hover/click readout shows NaN for masked vertices instead of 0. - Tests: browser-free NaN/alpha unit tests, quickflat-vs-WebGL parity tests, and dataset-switching tests checking that NaN masks and alpha never leak between datasets (setData and addData). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdjyZMFXsn6mRMJu9i8ige * ENH nanmean across layers in the WebGL viewer; quickflat nanmean=True by default The WebGL multi-layer sampling summed the layer samples, so one NaN voxel at any depth made the whole fragment transparent (quickflat's nanmean=False). surface_pixel now averages only the valid (non-NaN) layer samples and is transparent only when none is valid, matching quickflat's nanmean=True. A `nanmean` toggle in the surface controls (on by default) restores the old any-NaN-is-transparent behavior, and quickflat's make_figure / make_flatmap_image / add_data default to nanmean=True so both renderers agree. NaN-free data renders identically either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdjyZMFXsn6mRMJu9i8ige * DOC describe the vmin/vmax defaults of Volume2D/Vertex2D Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdjyZMFXsn6mRMJu9i8ige * FIX address review: nanmean for RGBA paths, movie masks, uint8 alpha, package dedup - quickflat: nanmean now applies to dataviews that reach the RGBA branch. 2D/raw conversions carry their NaN mask, so nanmean=True averages the valid voxels only and nanmean=False hides any pixel touched by a NaN voxel; native RGB (NaN already alpha 0) treats fully transparent voxels as missing, like the WebGL RGB textures. - WebGL surface_pixel: NANMEAN also applies to RGB textures (fully transparent layer samples are skipped; validity from the current frame since an unbound next-frame sampler reads as opaque black). - WebGL vertex data: the nanmask combines the masks of both frames being blended (next frame only while framemix > 0), so a NaN in the next frame no longer interpolates towards a fake 0. - _mask_alpha: uint8 alpha maps are filled with byte 0 (their inferred vmin is a percentile of the bytes, 255 for a constant map). - Package: same-name brains are deduplicated only when their class, subject, transform, shape, dtype and mask match; otherwise raise a clear ValueError instead of serving one brain with another's metadata. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdjyZMFXsn6mRMJu9i8ige * FIX gh-714: pack the flat bump attributes so the 2D vertex shader links #679 added two vertex attributes to the surface shaders, `flatBumpNorms` (vec3) and `flatheight` (float), for the bumpy flatmap. That put the 2D vertex program one over MAX_VERTEX_ATTRIBS, so it failed to link: THREE.WebGLProgram: gl.getProgramInfoLog() Too many attributes (mixNorms1) THREE.WebGLProgram: Could not initialise shader. WebGL: INVALID_OPERATION: drawElements: no valid shader program in use Vertex2D flatmaps then rendered blank and `save_3d_views` raised, which is gh-714. This branch had already spent the last free slot on `nanmask`, and folds the per-vertex alpha map into it for the same reason. Both of #679's attributes are static per-vertex geometry, computed together in one block of mriview_surface.js, so they pack into a single vec4 (.xyz the bump normal, .w the bump height) with no behavioural change and no per-dataset buffer churn. That returns one slot, which is all that was needed. `auxdat` has two free components but is deliberately left alone: it is static geometry, and per-dataset state there would mean rewriting the buffer on every setData. Verified on the headless viewer: a Vertex2D flatmap went from a link failure plus ~140 `no valid shader program in use` errors to none, and the three `vertex2d_*` cases in test_webgl_nan_alpha_parity.py plus the two Vertex2D cases in test_webgl_switching.py pass again. Those five passed before this branch merged main and regressed on the merge. The strict xfail #672 put on Vertex2D is removed: it was marked `raises=RuntimeError, strict=True` precisely so that a render which starts working reports rather than passing silently. Its reference images still have to be generated, along with a regeneration of the whole stored set for this branch's NaN/alpha changes; reference_images/README.md now says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015yNgwu9miNKAuv79yPMqU8 * Revert our gh-714 shader fix in favour of #715 #715 landed the same fix on main, and did it better. Both pack the bumpy flatmap's height into the fourth component of its normals, but #715 also moves the white matter and pial vertex areas into the two unused components of `auxdat`, which brings the worst case (2D vertex data on a subject with a flatmap) from 19 attributes down to 16 rather than to 17. That extra headroom matters: at 17, plain `Vertex` data still overflows as soon as equivolume sampling is on, which our fix left broken. #715 also names the packed attribute `flatbump`, factors its declaration into `utils.flatbump_attr`, and adds test_webgl_shaders.py, which links every shader variant the viewer can build and would have caught gh-714 in the first place. Dropping our version of the JS here so the merge of main takes #715's wholesale rather than resolving two equivalent edits line by line. The xfail removals and the reference-image bookkeeping are reconciled in the merge commit that follows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015yNgwu9miNKAuv79yPMqU8 * TST cover the 2D alpha map and across-depth NaN averaging Three gaps this branch's own changes left uncovered. test_webgl_shaders.py: #715's matrix already covers this branch's extra `nanmask` attribute -- all 27 variants still link, worst case included -- but not the options this branch adds to the volume-sampling shader. _nan_alpha_variants adds 20 surface_pixel variants over dataalpha x nanmean x layers (1 and 32) x the cmap/2d/rgb branches, hasflat and equivolume pinned on. 47 variants, still under seven seconds, and no subject database needed. test_visual_regression.py, the alpha map on 2D dataviews: _dataview grew a `twod_alpha` switch and NAN_ALPHA_DATAVIEW_NAMES now lists all four classes that take an explicit `alpha=`, not just the two RGB ones. Volume2D and Vertex2D accepted the argument before this branch as well, but it went into `attrs` as a bare ndarray, so quickflat mishandled it and the viewer failed to load the dataview -- that is the first fix in this PR and nothing in the visual suite could see it. _build_nan_dataview passes it too, which finally makes that builder do what its own comment says: NaN every place the rule names, the alpha map included. test_visual_regression.py, averaging across depth: a new multilayer_nan_dataviews suite, the three volumetric classes at both values of `nanmean`, with quickflat's `thick` and the viewer's `layers` both set to 32 and NaNs in diagonal slabs two voxels thick, so most surface points have both NaN and valid samples under them. The other suites NaN whole columns and leave depth sampling alone -- at their defaults the renderers do not even sample the same number of depths (quickflat 32, the viewer 1) -- so none of them can see the change this PR makes to how a column of samples is combined. Measured on renders from the regenerate path, the scenario separates cleanly and the renderers agree: data covers 0.797 of the flatmap with nanmean on and 0.196 with it off in quickflat, 0.815 and 0.185 in the viewer. The Volume2D case of that suite is flaky, and not because of anything here. Setting `layers` above 1 intermittently leaves the viewer's RPC proxy answering `{}` to every later query, so save_3d_views dies on the next parameter it sets; it never recovers and the browser reports no error. Building the same dataview inline and running the same sequence reproduces it on main at about the same rate, roughly one run in four, so it is a pre-existing viewer/JSProxy bug rather than a gh-695 regression -- this is just the first test to drive `layers` above 1 on a 2D dataview. Documented in the test and left in. References for all of this still have to be generated; see reference_images/README.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015yNgwu9miNKAuv79yPMqU8 * TST regenerate the visual-regression reference images 236e8c9 added the multilayer and nan_alpha 2D cases but none of their reference images, so those suites could not run: _render_and_check_dataview fails outright on a missing reference. Adds the 16 that were absent (the 12 multilayer_nan_dataviews/ renders, and the four nan_alpha_dataviews/ ones for Volume2D and Vertex2D) and refreshes the 18 that had drifted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5AMBzUzPKfDfVdjLvxqri * TST xfail the multilayer suite's cross-renderer leg (gh-749) quickflat and the WebGL viewer average over the same number of depth samples here, but not at the same depths: quickflat takes the interior fractions linspace(0, 1, thick+2)[1:-1] while the shader takes i/(layers-1), which reaches both the white-matter and pial surfaces. On smooth data that is invisible -- every cross check outside this suite passes at mean|diff| 1.3-1.9 of 255 -- but the multilayer suite's NaN slabs are two voxels thick, at the sampling limit, so the offset flips which samples are NaN and the two renders disagree pixel by pixel. Five of its six parameter sets breach the tolerance. The disagreement is phase noise rather than a difference in what is drawn: signed bias within +-2, transparency agreeing to the same 1.19% outline as the passing suites, and mean|diff| dropping to 1.3 under a sigma=4 blur against a 1.18 floor. Both renderers also respond to nanmean the same way, which is what the suite exists to cover. Aligning the two grids would shift every render and invalidate both reference sets, so that is left to gh-749. Only the cross-renderer leg is conceded: the reference legs stay strict, and are asserted before the xfail so a real regression cannot hide behind it. Uses the imperative pytest.xfail rather than a mark, so the sixth parameter set -- which stays inside the tolerance -- simply passes, and all six will go green on their own once gh-749 is fixed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5AMBzUzPKfDfVdjLvxqri * TST stop the nan suite's vertex masks from covering the whole surface _build_nan_dataview NaN'd the vertex channels over three disjoint index ranges -- idx >= total/2, idx < total/4, and the quarter between -- which tile the surface exactly. A NaN in any channel renders an element transparent, so with no vertex left clean the two classes drawing on all three (Vertex2D, and VertexRGB through red/green/alpha) came out as bare curvature: 0% of their opaque pixels carried any color, against 10-100% everywhere else. The four nan_dataviews references for them pinned an empty flatmap, so they covered nothing -- a regression in 2D or RGB vertex NaN handling would still render blank and still pass, and the cross-renderer leg compared one blank flatmap against another. The volume regions never had this problem because they are three overlapping halves on independent axes (x>=50, y>=50, z>=15), whose union is 7/8 and leaves 37500 clean voxels. Splits the vertex regions on the vertex coordinates the same way, at the median of each axis so the masks stay at half the surface exactly. That leaves 39784 vertices (13.1%) clean, against 12.1% of the volume, and Vertex2D and VertexRGB now retain 13.07% all-finite elements rather than none. Volume regions are untouched, so only the four nan_dataviews vertex references need regenerating. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5AMBzUzPKfDfVdjLvxqri * TST put the nan suite's clean remainder where the data is visible, and guard it Two follow-ups to the vertex masks. Leaving a remainder is not sufficient on its own: it also has to land somewhere the data can be seen. Vertex2D's visibility is governed by the alpha its 2D colormap derives from dim2, which is the accuracy bump, and >= on all three axes put the survivors off it -- mean accuracy 0.23, 3.5% of them above 0.5, and a render with 1.2% of its opaque pixels colored against Volume2D's 9.9%. Flipping the z comparison moves the remainder onto the bump (mean accuracy 0.62, 70% above 0.5) for the same 12% of the surface. VertexRGB improves with it; Vertex is unaffected, since it reads only the primary mask. Adds test_nan_builders_leave_clean_elements, asserting on the dataviews themselves that each NaN suite leaves at least 5% of elements free of NaNs in every channel -- the suites sit at 12% and above, so the floor is not tuned. Nothing could catch the original fault, because a blank render matches a blank reference exactly and agrees with the other renderer's blank render exactly as well; the failure is only visible before rendering. Checked against the masks as they were: it fails on Vertex2D and VertexRGB at 0.00% and passes the rest. The check needs no browser, so the playwright skip moves off pytestmark and onto the five render tests individually. Without playwright this file used to collect 39 skips and assert nothing; it now runs the 13 builder checks and skips the 26 renders. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5AMBzUzPKfDfVdjLvxqri * Update test images Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AGP6ytTVeCU29FbmuLNBza --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Aditya Vaidya <kroq-gar78@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pr fixes the recently introduced shader bug that broke 2-D vertex data displays (see issue #714). The core issue is that we are hitting the upper limit on the number of vertex attributes that we can pass to the shaders, and this causes threejs to silently choke. It also adds some tests that look for blank rendered images. This is not a real visual regression test — that would supersede this test.