From 6ba559f22903ffc7e860a1bee1216cc30820072e Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 27 Mar 2019 18:30:57 +0100 Subject: [PATCH 1/3] make mappings work with 8 and 16 bit segmentations --- .../model/bucket_data_handling/data_rendering_logic.js | 6 ++++-- .../model/bucket_data_handling/texture_bucket_manager.js | 3 ++- frontend/javascripts/oxalis/shaders/segmentation.glsl.js | 9 +++++++++ .../javascripts/oxalis/shaders/texture_access.glsl.js | 8 ++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/frontend/javascripts/oxalis/model/bucket_data_handling/data_rendering_logic.js b/frontend/javascripts/oxalis/model/bucket_data_handling/data_rendering_logic.js index 0027e881a4..258a58fab7 100644 --- a/frontend/javascripts/oxalis/model/bucket_data_handling/data_rendering_logic.js +++ b/frontend/javascripts/oxalis/model/bucket_data_handling/data_rendering_logic.js @@ -44,8 +44,10 @@ export function validateMinimumRequirements(specs: GpuSpecs): void { export type DataTextureSizeAndCount = { textureSize: number, textureCount: number }; export function getPackingDegree(byteCount: number) { - // If the layer only holds one byte per voxel, we can pack 4 bytes using rgba channels - return byteCount === 1 ? 4 : 1; + // If the layer holds less than 4 byte per voxel, we can pack multiple voxels using rgba channels + if (byteCount === 1) return 4; + if (byteCount === 2) return 2; + return 1; } function getNecessaryVoxelCount() { diff --git a/frontend/javascripts/oxalis/model/bucket_data_handling/texture_bucket_manager.js b/frontend/javascripts/oxalis/model/bucket_data_handling/texture_bucket_manager.js index d51f37e349..2f25c798ea 100644 --- a/frontend/javascripts/oxalis/model/bucket_data_handling/texture_bucket_manager.js +++ b/frontend/javascripts/oxalis/model/bucket_data_handling/texture_bucket_manager.js @@ -6,6 +6,7 @@ import { DataBucket, bucketDebuggingFlags } from "oxalis/model/bucket_data_handl import { createUpdatableTexture } from "oxalis/geometries/materials/plane_material_factory_helpers"; import { getBaseBucketsForFallbackBucket } from "oxalis/model/helpers/position_converter"; import { getMaxZoomStepDiff } from "oxalis/model/bucket_data_handling/loading_strategy_logic"; +import { getPackingDegree } from "oxalis/model/bucket_data_handling/data_rendering_logic"; import { getRenderer } from "oxalis/controller/renderer"; import { getResolutions } from "oxalis/model/accessors/dataset_accessor"; import { waitForCondition } from "libs/utils"; @@ -57,7 +58,7 @@ export default class TextureBucketManager { constructor(textureWidth: number, dataTextureCount: number, bytes: number) { // If there is one byte per voxel, we pack 4 bytes into one texel (packingDegree = 4) // Otherwise, we don't pack bytes together (packingDegree = 1) - this.packingDegree = bytes === 1 ? 4 : 1; + this.packingDegree = getPackingDegree(bytes); this.maximumCapacity = (this.packingDegree * dataTextureCount * textureWidth ** 2) / constants.BUCKET_SIZE; diff --git a/frontend/javascripts/oxalis/shaders/segmentation.glsl.js b/frontend/javascripts/oxalis/shaders/segmentation.glsl.js index cfeb209dae..7e33f0446b 100644 --- a/frontend/javascripts/oxalis/shaders/segmentation.glsl.js +++ b/frontend/javascripts/oxalis/shaders/segmentation.glsl.js @@ -78,6 +78,15 @@ export const getSegmentationId: ShaderModule = { <% if (isMappingSupported) { %> if (isMappingEnabled) { + // Depending on the packing degree, the returned volume color contains extra values + // which would make the binary search fail + + <% if (segmentationPackingDegree === "4.0") { %> + volume_color = vec4(volume_color.r, 0.0, 0.0, 0.0); + <% } else if (segmentationPackingDegree === "2.0") { %> + volume_color = vec4(volume_color.r, volume_color.g, 0.0, 0.0); + <% } %> + float index = binarySearchIndex( <%= segmentationName %>_mapping_lookup_texture, mappingSize, diff --git a/frontend/javascripts/oxalis/shaders/texture_access.glsl.js b/frontend/javascripts/oxalis/shaders/texture_access.glsl.js index 11a1057aea..7b6bf2337d 100644 --- a/frontend/javascripts/oxalis/shaders/texture_access.glsl.js +++ b/frontend/javascripts/oxalis/shaders/texture_access.glsl.js @@ -207,6 +207,14 @@ export const getColorForCoords: ShaderModule = { float rgbaIndex = linearizeVec3ToIndexWithMod(offsetInBucket, bucketWidth, packingDegree); + if (packingDegree == 2.0) { + if (rgbaIndex == 0.0) { + return vec4(bucketColor.r, bucketColor.g, bucketColor.r, bucketColor.g); + } else if (rgbaIndex == 1.0) { + return vec4(bucketColor.b, bucketColor.a, bucketColor.b, bucketColor.a); + } + } + if (rgbaIndex == 0.0) { return vec4(bucketColor.r); } else if (rgbaIndex == 1.0) { From b9f71d4f71ba563dbf55d7a299768f519c14aaca Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 27 Mar 2019 18:42:18 +0100 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f537c82064..5a317737ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md). - webKnossos now comes with a list of sample datasets that can be automatically downloaded and imported from the menu. [#3725](https://github.com/scalableminds/webknossos/pull/3725) - Added a shortcut (Q) and button in the actions dropdown to screenshot the tracing views. The screenshots will contain everything that is visible in the tracing views, so feel free to disable the crosshairs in the settings or toggle the tree visibility using the (1) and (2) shortcuts before triggering the screenshot. [#3834](https://github.com/scalableminds/webknossos/pull/3834) - Neuroglancer precomputed datasets can now be added to webKnossos using the webknossos-connect (wk-connect) service. To setup a wk-connect datastore follow the instructions in the [Readme](https://github.com/scalableminds/webknossos-connect). Afterwards, datasets can be added through "Add Dataset" - "Add Dataset via wk-connect". [#3843](https://github.com/scalableminds/webknossos/pull/3843) +- Added support for mappings for 8-bit and 16-bit segmentation layers. [#3953](https://github.com/scalableminds/webknossos/pull/3953) - The dataset settings within the tracing view allow to select between different loading strategies now ("best quality first" and "progressive quality"). Additionally, the rendering can use different magnifications as a fallback (instead of only one magnification). [#3801](https://github.com/scalableminds/webknossos/pull/3801) - The mapping selection dropbown is now sorted alphabetically. [#3864](https://github.com/scalableminds/webknossos/pull/3864) - Added the possibility to filter datasets in the dashboard according to their availability. By default, datasets which are missing on disk (e.g., when the datastore was deleted) are not shown anymore. This behavior can be configured via the settings icon next to the search box in the dashboard. [#3883](https://github.com/scalableminds/webknossos/pull/3883) From 3be3c599b52a59f6512c2df88d75b9093693622a Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Thu, 28 Mar 2019 13:32:53 +0100 Subject: [PATCH 3/3] apply PR feedback --- .../javascripts/oxalis/shaders/texture_access.glsl.js | 4 ++++ .../oxalis/view/settings/user_settings_view.js | 8 +++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/javascripts/oxalis/shaders/texture_access.glsl.js b/frontend/javascripts/oxalis/shaders/texture_access.glsl.js index 7b6bf2337d..38fdcf6179 100644 --- a/frontend/javascripts/oxalis/shaders/texture_access.glsl.js +++ b/frontend/javascripts/oxalis/shaders/texture_access.glsl.js @@ -208,6 +208,9 @@ export const getColorForCoords: ShaderModule = { float rgbaIndex = linearizeVec3ToIndexWithMod(offsetInBucket, bucketWidth, packingDegree); if (packingDegree == 2.0) { + // It's essentially irrelevant what we return as the 3rd and 4th value here as we only have 2 byte of information. + // The caller needs to unpack this vec4 according to the packingDegree, see getSegmentationId for an example. + // The same goes for the following code where the packingDegree is 4 and we only have 1 byte of information. if (rgbaIndex == 0.0) { return vec4(bucketColor.r, bucketColor.g, bucketColor.r, bucketColor.g); } else if (rgbaIndex == 1.0) { @@ -215,6 +218,7 @@ export const getColorForCoords: ShaderModule = { } } + // The following code deals with packingDegree == 4.0 if (rgbaIndex == 0.0) { return vec4(bucketColor.r); } else if (rgbaIndex == 1.0) { diff --git a/frontend/javascripts/oxalis/view/settings/user_settings_view.js b/frontend/javascripts/oxalis/view/settings/user_settings_view.js index aea38b04fa..5c98c96713 100644 --- a/frontend/javascripts/oxalis/view/settings/user_settings_view.js +++ b/frontend/javascripts/oxalis/view/settings/user_settings_view.js @@ -18,6 +18,7 @@ import { } from "oxalis/view/settings/setting_input_views"; import type { UserConfiguration, OxalisState, Tracing } from "oxalis/store"; import type { APIDataset } from "admin/api_flow_types"; +import { hasSegmentation } from "oxalis/model/accessors/dataset_accessor"; import { enforceSkeletonTracing, getActiveNode, @@ -239,10 +240,7 @@ class UserSettingsView extends PureComponent { const activeNodeRadius = getActiveNode(skeletonTracing) .map(activeNode => activeNode.radius) .getOrElse(0); - const isMergerModeSupported = - (this.props.dataset.dataSource.dataLayers || []).find( - layer => layer.category === "segmentation" && layer.elementClass === "uint32", - ) != null; + const isMergerModeSupported = hasSegmentation(this.props.dataset); panels.push( { disabled={!isMergerModeSupported} tooltipText={ !isMergerModeSupported - ? "The merger mode is only available for datasets with uint32 segmentations." + ? "The merger mode is only available for datasets with a segmentation layer." : null } />