Skip to content

Commit d8abcff

Browse files
committed
wip segmentation mesh shader
wip segment properties in shader segment color shader wip segment color shader mvp skeleton working w/o segment id info
1 parent e5371c4 commit d8abcff

File tree

19 files changed

+552
-54
lines changed

19 files changed

+552
-54
lines changed

src/datasource/graphene/backend.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ async function decodeDracoFragmentChunk(
121121
response: Uint8Array,
122122
) {
123123
const rawMesh = await decodeDraco(response);
124+
// console.log("decodeDracoFragmentChunk", chunk.key, chunk.fragmentId);
124125
assignMeshFragmentData(chunk, rawMesh);
125126
}
126127

src/layer/annotation/index.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -854,20 +854,23 @@ class RenderingOptionsTab extends Tab {
854854
href: "https://github.com/google/neuroglancer/blob/master/src/annotation/rendering.md",
855855
},
856856
"neuroglancer-annotation-dropdown-shader-top-row",
857+
"anno",
857858
),
858859
);
859860

861+
ShaderControls;
862+
860863
element.appendChild(this.codeWidget.element);
861-
element.appendChild(
862-
this.registerDisposer(
863-
new ShaderControls(
864-
layer.annotationDisplayState.shaderControls,
865-
this.layer.manager.root.display,
866-
this.layer,
867-
{ visibility: this.visibility },
868-
),
869-
).element,
870-
);
864+
// element.appendChild(
865+
// this.registerDisposer(
866+
// new ShaderControls(
867+
// layer.annotationDisplayState.shaderControls,
868+
// this.layer.manager.root.display,
869+
// this.layer,
870+
// { visibility: this.visibility },
871+
// ),
872+
// ).element,
873+
// );
871874

872875
element.appendChild(
873876
addLayerControlToOptionsTab(

src/layer/image/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ class RenderingOptionsTab extends Tab {
551551
href: "https://github.com/google/neuroglancer/blob/master/src/sliceview/image_layer_rendering.md",
552552
},
553553
"neuroglancer-image-dropdown-top-row",
554+
"fin",
554555
),
555556
);
556557
element.appendChild(

src/layer/segmentation/index.ts

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,21 @@ import {
129129
verifyString,
130130
} from "#src/util/json.js";
131131
import { Signal } from "#src/util/signal.js";
132-
import { makeWatchableShaderError } from "#src/webgl/dynamic_shader.js";
132+
import {
133+
makeTrackableFragmentMain,
134+
makeWatchableShaderError,
135+
parameterizedEmitterDependentShaderGetter,
136+
} from "#src/webgl/dynamic_shader.js";
133137
import type { DependentViewContext } from "#src/widget/dependent_view_widget.js";
134138
import { registerLayerShaderControlsTool } from "#src/widget/shader_controls.js";
139+
import { ShaderControlState } from "#src/webgl/shader_ui_controls.js";
140+
import { initializeWebGL } from "#src/webgl/context.js";
141+
import {
142+
bigIntPreprocessing,
143+
glsl_equalUint64,
144+
glsl_uint64,
145+
} from "#src/webgl/shader_lib.js";
146+
import { GLBuffer } from "#src/webgl/buffer.js";
135147

136148
const MAX_LAYER_BAR_UI_INDICATOR_COLORS = 6;
137149

@@ -410,7 +422,15 @@ class LinkedSegmentationGroupState<
410422
}
411423
}
412424

425+
const DEFAULT_FRAGMENT_MAIN = `
426+
vec4 segmentColor(vec4 color, uint64_t valueForColor) {
427+
return color;
428+
}
429+
`;
430+
413431
class SegmentationUserLayerDisplayState implements SegmentationDisplayState {
432+
private getShader;
433+
414434
constructor(public layer: SegmentationUserLayer) {
415435
// Even though `SegmentationUserLayer` assigns this to its `displayState` property, redundantly
416436
// assign it here first in order to allow it to be accessed by `segmentationGroupState`.
@@ -520,6 +540,9 @@ class SegmentationUserLayerDisplayState implements SegmentationDisplayState {
520540
(group) => group.segmentPropertyMap,
521541
),
522542
);
543+
// end constructor
544+
545+
this.getShader = this.makeGetter();
523546
}
524547

525548
segmentSelectionState = new SegmentSelectionState();
@@ -536,6 +559,8 @@ class SegmentationUserLayerDisplayState implements SegmentationDisplayState {
536559
ignoreNullVisibleSet = new TrackableBoolean(true, true);
537560
skeletonRenderingOptions = new SkeletonRenderingOptions();
538561
shaderError = makeWatchableShaderError();
562+
fragmentMain = makeTrackableFragmentMain(DEFAULT_FRAGMENT_MAIN);
563+
shaderControlState = new ShaderControlState(this.fragmentMain);
539564
renderScaleHistogram = new RenderScaleHistogram();
540565
renderScaleTarget = trackableRenderScaleTarget(1);
541566
selectSegment: (id: bigint, pin: boolean | "toggle") => void;
@@ -551,6 +576,77 @@ class SegmentationUserLayerDisplayState implements SegmentationDisplayState {
551576
this.layer.moveToSegment(id);
552577
};
553578

579+
makeGetter = () => {
580+
const gl = initializeWebGL(new OffscreenCanvas(1, 1));
581+
const parameters = this.shaderControlState.builderState;
582+
return parameterizedEmitterDependentShaderGetter(this.layer, gl, {
583+
memoizeKey: `segmentColorShaderTODO`,
584+
parameters,
585+
encodeParameters: (p) => {
586+
return `${p.parseResult.code}`;
587+
},
588+
shaderError: this.layer.displayState.shaderError, // TODO can I reuse this?
589+
defineShader: (builder, shaderBuilderState) => {
590+
builder.addAttribute("highp vec4", "aVertexPosition");
591+
builder.addUniform("highp vec4", "uColor");
592+
builder.addUniform("highp uvec2", "uID");
593+
builder.addVarying("highp vec4", "vColor");
594+
builder.addVertexCode(glsl_uint64);
595+
builder.addVertexCode(glsl_equalUint64);
596+
builder.addVertexCode(
597+
bigIntPreprocessing(shaderBuilderState.parseResult.code),
598+
);
599+
builder.addVertexMain(`
600+
gl_Position = aVertexPosition;
601+
vColor = segmentColor(uColor, uint64_t(uID));
602+
`);
603+
builder.addOutputBuffer("vec4", "out_fragColor", 0);
604+
builder.setFragmentMain("out_fragColor = vColor;");
605+
},
606+
});
607+
};
608+
609+
context = () => {}; // TEMP
610+
611+
getShaderSegmentColor = (id: bigint, color: Float32Array) => {
612+
const { shader, parameters } = this.getShader(this.context);
613+
if (shader === null) return color;
614+
parameters;
615+
shader.bind();
616+
const { gl } = shader;
617+
{
618+
const positionBuffer = GLBuffer.fromData(
619+
gl,
620+
new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]),
621+
);
622+
positionBuffer.bindToVertexAttrib(shader.attribute("aVertexPosition"), 2);
623+
}
624+
{
625+
gl.uniform4fv(shader.uniform("uColor"), color);
626+
gl.uniform2ui(
627+
shader.uniform(`uID`),
628+
Number(id & 0xffffffffn),
629+
Number(id >> 32n),
630+
);
631+
}
632+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
633+
const data = new Uint8Array(4);
634+
// TODO can I read straight to float?
635+
gl.readPixels(
636+
0,
637+
0,
638+
1,
639+
1,
640+
WebGL2RenderingContext.RGBA,
641+
WebGL2RenderingContext.UNSIGNED_BYTE,
642+
data,
643+
);
644+
for (let i = 0; i < data.length; i++) {
645+
color[i] = data[i] / 255.0;
646+
}
647+
return color;
648+
};
649+
554650
linkedSegmentationGroup: LinkedLayerGroup;
555651
linkedSegmentationColorGroup: LinkedLayerGroup;
556652
originalSegmentationGroupState: SegmentationUserLayerGroupState;
@@ -689,6 +785,9 @@ export class SegmentationUserLayer extends Base {
689785
this.displayState.linkedSegmentationGroup.changed.add(() =>
690786
this.updateDataSubsourceActivations(),
691787
);
788+
this.displayState.fragmentMain.changed.add(
789+
this.specificationChanged.dispatch,
790+
);
692791
this.tabs.add("rendering", {
693792
label: "Render",
694793
order: -100,
@@ -996,6 +1095,9 @@ export class SegmentationUserLayer extends Base {
9961095
this.displayState.ignoreNullVisibleSet.restoreState(
9971096
specification[json_keys.IGNORE_NULL_VISIBLE_SET_JSON_KEY],
9981097
);
1098+
this.displayState.fragmentMain.restoreState(
1099+
specification[json_keys.SHADER_JSON_KEY],
1100+
);
9991101

10001102
const { skeletonRenderingOptions } = this.displayState;
10011103
skeletonRenderingOptions.restoreState(
@@ -1066,6 +1168,7 @@ export class SegmentationUserLayer extends Base {
10661168
this.displayState.renderScaleTarget.toJSON();
10671169
x[json_keys.CROSS_SECTION_RENDER_SCALE_JSON_KEY] =
10681170
this.sliceViewRenderScaleTarget.toJSON();
1171+
x[json_keys.SHADER_JSON_KEY] = this.displayState.fragmentMain.toJSON();
10691172

10701173
const { linkedSegmentationGroup, linkedSegmentationColorGroup } =
10711174
this.displayState;
@@ -1365,6 +1468,7 @@ export class SegmentationUserLayer extends Base {
13651468

13661469
const visibleSegments = [...visibleSegmentsSet];
13671470
const colors = visibleSegments.map((id) => {
1471+
// here we can do a batch get of colors using the segment color shader instead of one at a time
13681472
const color = getCssColor(getBaseObjectColor(displayState, id));
13691473
return { color, id };
13701474
});
@@ -1401,6 +1505,10 @@ registerLayerTypeDetector((subsource) => {
14011505
return undefined;
14021506
});
14031507

1508+
registerLayerShaderControlsTool(SegmentationUserLayer, (layer) => ({
1509+
shaderControlState: layer.displayState.shaderControlState,
1510+
}));
1511+
14041512
registerLayerShaderControlsTool(
14051513
SegmentationUserLayer,
14061514
(layer) => ({

src/layer/segmentation/json_keys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const COLOR_SEED_JSON_KEY = "colorSeed";
1414
export const SEGMENT_STATED_COLORS_JSON_KEY = "segmentColors";
1515
export const MESH_RENDER_SCALE_JSON_KEY = "meshRenderScale";
1616
export const CROSS_SECTION_RENDER_SCALE_JSON_KEY = "crossSectionRenderScale";
17+
export const SHADER_JSON_KEY = "shader";
1718
export const SKELETON_RENDERING_JSON_KEY = "skeletonRendering";
1819
export const SKELETON_SHADER_JSON_KEY = "skeletonShader";
1920
export const SKELETON_CODE_VISIBLE_KEY = "codeVisible";

src/layer/segmentation/style.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
.neuroglancer-segmentation-rendering-tab .neuroglancer-shader-code-widget {
2424
height: 6em;
25+
resize: vertical;
2526
}
2627

2728
.neuroglancer-segmentation-dropdown-skeleton-shader-header {

src/layer/single_mesh/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class DisplayOptionsTab extends Tab {
222222
href: "https://github.com/google/neuroglancer/blob/master/src/sliceview/image_layer_rendering.md",
223223
},
224224
"neuroglancer-single-mesh-dropdown-top-row",
225+
"foop",
225226
),
226227
);
227228
element.appendChild(this.attributeWidget.element);

src/mesh/backend.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ function convertMeshData(
802802
} else {
803803
encodedVertexPositions = data.vertexPositions as Float32Array;
804804
}
805+
// TODO, add attributes here? Or can we change a uniform for every fragment draw request?
805806
return {
806807
vertexPositions: encodedVertexPositions,
807808
vertexNormals: encodedNormals,

0 commit comments

Comments
 (0)