The pick and depth shaders in cortex/webgl/resources/js/shaderlib.js hardcode the old thickness-based cortical-sheet displacement and know nothing about bumpyflat, so the geometry they test against drifts away from the geometry that is actually rendered.
What is inconsistent
surface_pixel and surface_vertex both do this:
"#ifdef CORTSHEET",
"#ifdef HASFLAT",
"pos += clamp(surfmix*2., 0., 1.) * normalize(norm) * mix(1., 0., use_thickmix) * flatheight * f_bumpyflat;",
"#else",
"pos += clamp(surfmix*2., 0., 1.) * normalize(norm) * .62 * distance(position, wm.xyz) * mix(1., 0., use_thickmix);",
"#endif",
"#endif",
pick and depth only ever do the #else branch — there is no HASFLAT define and no bumpyflat uniform in either. So whenever the subject has a flatmap (HASFLAT defined, i.e. essentially every real subject), the two disagree:
bumpy_flatmap |
rendered surface |
pick / depth |
| on |
flatheight bump |
.62 * thickness |
| off |
no displacement at all |
.62 * thickness |
pick backs the click-to-select-a-vertex picker (facepick.js:51); depth backs the occlusion test that hides ROI labels and paths behind the surface (svgoverlay.js:42).
Measured impact
Measured on S1 by projecting both the rendered and the pick-shader vertex positions through the live camera matrices, 1800x1400 drawing buffer, depth slider at its 0.5 default, ~4.1k sampled vertices:
- Bumpy flatmap on, viewed head-on: mean 0.20 px, max 1.59 px. Negligible — the bump displaces along the surface normal, which points nearly at the camera in this view, so almost all of it is lost to the projection. Expect this to grow as the flatmap is tilted.
- Inflated surface (
unfold 0.5), bumpy flatmap off: mean 3.08 px, max 7.89 px, with 51% of sampled vertices off by more than 3 px. This is the worse case, and it is not about bumpy flatmaps at all — it is the f_bumpyflat = 0 row of the table above, where the surface renders undisplaced but the picker still pushes vertices 0.62 * thickness along their normals.
So the practical symptom is picking that is a few pixels off on inflated/partially-unfolded surfaces, worst near silhouette edges where the normal is perpendicular to the view direction, plus label occlusion that is judged against slightly the wrong surface.
This mismatch has existed for volume data ever since the HASFLAT branch was added to surface_pixel. #679 ports that branch into surface_vertex so vertex and volume data finally shade flatmaps identically — but as a side effect it propagates this same pick/depth mismatch to vertex data, which previously matched pick exactly because both used the .62 * distance formula. Making the two data paths consistent was the point; this issue is the leftover.
Suggested fix
Give pick and depth the same HASFLAT / bumpyflat treatment as the surface shaders — they need the hasflat opt threaded through from mriview_surface.js, the flatheight attribute bound, and the bumpyflat uniform declared. The displacement expression can then be shared rather than copy-pasted a fourth time, which is what let the four copies drift apart in the first place.
The
pickanddepthshaders incortex/webgl/resources/js/shaderlib.jshardcode the old thickness-based cortical-sheet displacement and know nothing aboutbumpyflat, so the geometry they test against drifts away from the geometry that is actually rendered.What is inconsistent
surface_pixelandsurface_vertexboth do this:pickanddepthonly ever do the#elsebranch — there is noHASFLATdefine and nobumpyflatuniform in either. So whenever the subject has a flatmap (HASFLATdefined, i.e. essentially every real subject), the two disagree:bumpy_flatmappick/depthflatheightbump.62 * thickness.62 * thicknesspickbacks the click-to-select-a-vertex picker (facepick.js:51);depthbacks the occlusion test that hides ROI labels and paths behind the surface (svgoverlay.js:42).Measured impact
Measured on S1 by projecting both the rendered and the pick-shader vertex positions through the live camera matrices, 1800x1400 drawing buffer,
depthslider at its 0.5 default, ~4.1k sampled vertices:unfold0.5), bumpy flatmap off: mean 3.08 px, max 7.89 px, with 51% of sampled vertices off by more than 3 px. This is the worse case, and it is not about bumpy flatmaps at all — it is thef_bumpyflat = 0row of the table above, where the surface renders undisplaced but the picker still pushes vertices 0.62 * thickness along their normals.So the practical symptom is picking that is a few pixels off on inflated/partially-unfolded surfaces, worst near silhouette edges where the normal is perpendicular to the view direction, plus label occlusion that is judged against slightly the wrong surface.
Note on #679
This mismatch has existed for volume data ever since the
HASFLATbranch was added tosurface_pixel. #679 ports that branch intosurface_vertexso vertex and volume data finally shade flatmaps identically — but as a side effect it propagates this same pick/depth mismatch to vertex data, which previously matchedpickexactly because both used the.62 * distanceformula. Making the two data paths consistent was the point; this issue is the leftover.Suggested fix
Give
pickanddepththe sameHASFLAT/bumpyflattreatment as the surface shaders — they need thehasflatopt threaded through frommriview_surface.js, theflatheightattribute bound, and thebumpyflatuniform declared. The displacement expression can then be shared rather than copy-pasted a fourth time, which is what let the four copies drift apart in the first place.