Skip to content

Commit a876578

Browse files
committed
Add a UI element for the cluterRemoval
1 parent fea1826 commit a876578

9 files changed

Lines changed: 117 additions & 50 deletions

File tree

DVRViewPlugin/res/shaders/MaterialTransition2D.frag

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ uniform vec3 u_minClippingPlane;
2121
uniform vec3 u_maxClippingPlane;
2222

2323
uniform bool useShading;
24+
uniform bool useClutterRemover;
2425

2526
float getMaterialID(float[5] materials, vec3[5] samplePositions) {
2627
float firstMaterial = materials[0];
@@ -31,7 +32,7 @@ float getMaterialID(float[5] materials, vec3[5] samplePositions) {
3132
float nextMaterial = materials[3];
3233
float lastMaterial = materials[4];
3334

34-
if(firstMaterial == previousMaterial && nextMaterial == lastMaterial && currentMaterial != previousMaterial && currentMaterial != nextMaterial){
35+
if(useClutterRemover && firstMaterial == previousMaterial && nextMaterial == lastMaterial && currentMaterial != previousMaterial && currentMaterial != nextMaterial){
3536
vec3 samplePos = round(samplePositions[2] + vec3(0.5f)) - vec3(0.5f); // Sample the nearest voxel center instead
3637
vec2 sample2DPos = texture(volumeData, samplePos * invDimensions).rg * invTfTexSize;
3738
currentMaterial = texture(tfTexture, sample2DPos).r + 0.5f;

DVRViewPlugin/res/shaders/NNMaterialTransition.frag

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,66 @@ uniform vec3 u_minClippingPlane;
2222
uniform vec3 u_maxClippingPlane;
2323

2424
uniform bool useShading;
25+
uniform bool useClutterRemover;
2526

2627
const float MAX_FLOAT = 3.4028235e34;
2728
const float EPSILON = 0.00001f;
2829

2930
// Sample the volume at a given position and return the material ID
30-
float sampleVolume(vec3 samplePos) {
31+
float sampleVolume(vec3 samplePos){
32+
vec3 voxelPos = floor(samplePos) + 0.5f;
3133
vec3 volPos = samplePos * invDimensions;
3234
return texture(volumeData, volPos).r;
3335
}
3436

35-
// Get the material at a given sample position, with smoothing for transitions
36-
float getNewMaterial(vec3 previousPos, vec3 currentPos) {
37-
vec3 samplePos = floor((previousPos + currentPos) * 0.5 + 0.5) - 0.5;
38-
39-
float voxelMaterial = sampleVolume(samplePos);
40-
// vec3 interVoxelPos = fract(samplePos);
41-
// vec3 voxelSide = sign(interVoxelPos - 0.5);
42-
//
43-
// float materialX = sampleVolume(samplePos + vec3(voxelSide.x, 0.0, 0.0));
44-
// float materialY = sampleVolume(samplePos + vec3(0.0, voxelSide.y, 0.0));
45-
// float materialZ = sampleVolume(samplePos + vec3(0.0, 0.0, voxelSide.z));
46-
//
47-
// if (materialX == materialY && materialX == materialZ && materialX != voxelMaterial) {
48-
// return materialX;
49-
// }
50-
return voxelMaterial;
37+
// Sliding window: update arrays (shift left, insert new at end)
38+
void updateArrays(
39+
inout float[5] materials,
40+
inout vec3[5] samplePositions,
41+
inout vec3[5] normals,
42+
float newMaterial,
43+
vec3 newSamplePos,
44+
vec3 newNormal
45+
) {
46+
for (int j = 0; j < 4; ++j) {
47+
materials[j] = materials[j + 1];
48+
samplePositions[j] = samplePositions[j + 1];
49+
normals[j] = normals[j + 1];
50+
}
51+
materials[4] = newMaterial;
52+
samplePositions[4] = newSamplePos;
53+
normals[4] = newNormal;
54+
}
55+
56+
57+
// Get the current material using the sliding window (like MaterialTransition2D.frag)
58+
// Refinement step: copy previous value instead of re-sampling
59+
float getMaterialID(inout float[5] materials, inout vec3[5] samplePositions) {
60+
float firstMaterial = materials[0];
61+
float previousMaterial = materials[1];
62+
float currentMaterial = materials[2];
63+
float nextMaterial = materials[3];
64+
float lastMaterial = materials[4];
65+
66+
// If a transition is detected, copy the previous value instead of re-sampling
67+
if (currentMaterial != previousMaterial && currentMaterial != nextMaterial
68+
&& useClutterRemover) {
69+
currentMaterial = previousMaterial;
70+
materials[2] = currentMaterial;
71+
}
72+
return currentMaterial;
5173
}
5274

5375
// DDA: Find the next voxel boundary intersection and return the step length
5476
// Returns the step length and sets hitAxis to 0 (x), 1 (y), or 2 (z)
55-
float findNextVoxelIntersection(inout vec3 tNext, vec3 tDelta, vec3 rayDir, float t, out int hitAxis) {
77+
float findNextVoxelIntersection(
78+
inout vec3 tNext,
79+
vec3 tDelta,
80+
vec3 rayDir,
81+
float t,
82+
out int hitAxis,
83+
inout vec3 voxelSampleIndex
84+
) {
5685
float stepLength;
5786
if (tNext.x < tNext.y) {
5887
if (tNext.x < tNext.z) {
@@ -75,10 +104,12 @@ float findNextVoxelIntersection(inout vec3 tNext, vec3 tDelta, vec3 rayDir, floa
75104
hitAxis = 2;
76105
}
77106
}
107+
// Update voxelSampleIndex along the hit axis
108+
float dir = sign(rayDir[hitAxis]);
109+
voxelSampleIndex[hitAxis] += dir;
78110
return stepLength;
79111
}
80112

81-
82113
// Apply Phong shading at a surface position, using the local normal and lighting
83114
vec4 applyShading(
84115
vec3 previousPos,
@@ -128,43 +159,61 @@ void main() {
128159
vec3 samplePos = frontFacesPos;
129160
vec4 color = vec4(0.0);
130161

131-
float previousMaterial = sampleVolume(samplePos);
132-
float currentMaterial = previousMaterial;
133-
134-
vec3 previousPos = samplePos;
135-
vec3 currentPos = samplePos;
162+
// --- Sliding window arrays ---
163+
float[5] materials = float[5](0.0, 0.0, 0.0, 0.0, 0.0);
164+
vec3[5] samplePositions = vec3[5](samplePos, samplePos, samplePos, samplePos, samplePos);
165+
vec3[5] normals = vec3[5](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
136166

137167
// DDA setup
138168
vec3 tDelta = mix(vec3(MAX_FLOAT), 1.0 / abs(rayDir), notEqual(rayDir, vec3(0.0)));
139-
vec3 tNext = abs(step(vec3(0.0), rayDir) * (1.0 - fract(samplePos + 0.5)) + step(rayDir, vec3(0.0)) * fract(samplePos + 0.5)) * tDelta; // The ray length for each axis needed to reach a boundery, with a 0.5 offset since we use MC for smoothing where the center of a cube is the intersection of 8 voxels
169+
vec3 tNext = abs(step(vec3(0.0), rayDir) * (1.0 - fract(samplePos)) + step(rayDir, vec3(0.0)) * fract(samplePos)) * tDelta;
170+
tNext = mix(vec3(0.0001),tNext, notEqual(tNext, vec3(0.0)));
140171

141172
float t = 0.0;
142-
143-
int currentHitAxis = 0;
144-
int nextHitAxis = 0;
173+
int hitAxis = 0;
174+
175+
// Track voxel index for correct sampling
176+
vec3 voxelSampleIndex = floor(samplePos);
177+
178+
179+
// Initialize sliding window with first sample and normal
180+
float newMaterial = sampleVolume(voxelSampleIndex);
181+
vec3 newNormal = vec3(0.0); // No normal for the first sample
182+
for (int i = 0; i < 5; ++i) {
183+
materials[i] = newMaterial;
184+
samplePositions[i] = samplePos;
185+
normals[i] = newNormal;
186+
}
145187

146188
while (lengthRay > 0.0) {
147-
currentHitAxis = nextHitAxis;
148-
float stepLength = findNextVoxelIntersection(tNext, tDelta, rayDir, t, nextHitAxis);
189+
float stepLength = findNextVoxelIntersection(tNext, tDelta, rayDir, t, hitAxis, voxelSampleIndex);
149190
if (stepLength <= 0.0 || lengthRay <= 0.0)
150191
break;
151192

152-
previousPos = currentPos;
153-
currentPos = samplePos + rayDir * stepLength;
154-
previousMaterial = currentMaterial;
155-
currentMaterial = getNewMaterial(previousPos, currentPos);
193+
vec3 previousPos = samplePositions[1];
194+
vec3 currentPos = samplePos + rayDir * stepLength;
195+
196+
// Compute normal for this step
197+
vec3 newNormal = vec3(0.0);
198+
if (hitAxis == 0) newNormal.x = -sign(rayDir.x);
199+
else if (hitAxis == 1) newNormal.y = -sign(rayDir.y);
200+
else if (hitAxis == 2) newNormal.z = -sign(rayDir.z);
201+
202+
// Sample new material and update sliding window (including normals)
203+
newMaterial = sampleVolume(voxelSampleIndex + 0.5f); // + 0.5f to center the sample
204+
updateArrays(materials, samplePositions, normals, newMaterial, currentPos, newNormal);
205+
206+
float previousMaterial = materials[1];
207+
float currentMaterial = getMaterialID(materials, samplePositions);
208+
209+
vec4 sampleColor = texture(materialTexture, vec2(currentMaterial, previousMaterial) * invMatTexSize);
156210

157211
// Only composite if not the very first step
158212
if (t > 0.0) {
159-
vec4 sampleColor = texture(materialTexture, vec2(currentMaterial, previousMaterial) * invMatTexSize);
213+
// Use the normal associated with the current sample (index 2)
214+
vec3 normal = normals[2];
160215

161216
if (useShading && previousMaterial != currentMaterial && sampleColor.a > 0.01) {
162-
// Compute normal based on hit axis and ray direction
163-
vec3 normal = vec3(0.0);
164-
if (currentHitAxis == 0) normal.x = -sign(rayDir.x);
165-
else if (currentHitAxis == 1) normal.y = -sign(rayDir.y);
166-
else if (currentHitAxis == 2) normal.z = -sign(rayDir.z);
167-
168217
sampleColor = applyShading(previousPos, rayDir, sampleColor, currentPos, normal);
169218
}
170219

@@ -185,4 +234,4 @@ void main() {
185234
}
186235

187236
FragColor = color;
188-
}
237+
}

DVRViewPlugin/src/DVRViewPlugin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ void DVRViewPlugin::updateRenderSettings()
237237
_DVRWidget->setStepSize(_settingsAction.getStepSizeAction().getValue());
238238
_DVRWidget->setRenderMode(_settingsAction.getRenderModeAction().getCurrentText());
239239
_DVRWidget->setMIPDimension(_settingsAction.getMIPDimensionPickerAction().getCurrentDimensionIndex());
240+
_DVRWidget->setUseClutterRemover(_settingsAction.getUseClutterRemoverAction().isChecked());
240241
_DVRWidget->setUseShading(_settingsAction.getUseShaderAction().isChecked());
241242
_DVRWidget->setRenderCubeSize(_settingsAction.getRenderCubeSizeAction().getValue());
242243

DVRViewPlugin/src/DVRWidget.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,13 @@ void DVRWidget::setRenderMode(const QString& renderMode)
144144

145145
void DVRWidget::setMIPDimension(int mipDimension)
146146
{
147-
_volumeRenderer.setMIPDimension(mipDimension);}
147+
_volumeRenderer.setMIPDimension(mipDimension);
148+
}
149+
150+
void DVRWidget::setUseClutterRemover(bool useClutterRemover)
151+
{
152+
_volumeRenderer.setUseClutterRemover(useClutterRemover);
153+
}
148154

149155
void DVRWidget::setUseShading(bool useShading)
150156
{

DVRViewPlugin/src/DVRWidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class DVRWidget : public QOpenGLWidget, protected QOpenGLFunctions
4646
void setUseCustomRenderSpace(bool useCustomRenderSpace);
4747
void setRenderMode(const QString& renderMode);
4848
void setMIPDimension(int mipDimension);
49+
void setUseClutterRemover(bool useClutterRemover);
4950
void setUseShading(bool useShading);
5051
void setRenderCubeSize(float renderCubeSize);
5152

DVRViewPlugin/src/SettingsAction.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ SettingsAction::SettingsAction(QObject* parent, const QString& title) :
1717
_renderCubeSizeAction(this, "Render Cube Size", 1, 500, 30),
1818
_stepSizeAction(this, "Step Size", 0.1f, 5.0f, 1.0f),
1919
_useShadingAction(this, "Use Shader"),
20-
_useEmptySpaceSkippingAction(this, "Use Empty Space Skipping"),
20+
_useClutterRemover(this, "Use Clutter Remover"),
2121
_useCustomRenderSpaceAction(this, "Use Custom Render Space"),
2222
_xRenderSizeAction(this, "X Render Size", 0, 500, 50),
2323
_yRenderSizeAction(this, "Y Render Size", 0, 500, 50),
@@ -29,7 +29,7 @@ SettingsAction::SettingsAction(QObject* parent, const QString& title) :
2929

3030
addAction(&_datasetNameAction);
3131

32-
addAction(&_useEmptySpaceSkippingAction);
32+
addAction(&_useClutterRemover);
3333
addAction(&_renderCubeSizeAction);
3434

3535
addAction(&_useShadingAction);
@@ -57,7 +57,7 @@ SettingsAction::SettingsAction(QObject* parent, const QString& title) :
5757

5858
_renderCubeSizeAction.setToolTip("Render cube size");
5959
_useShadingAction.setToolTip("Toggle shading");
60-
_useEmptySpaceSkippingAction.setToolTip("Toggle empty space skipping");
60+
_useClutterRemover.setToolTip("Toggle clutter remover");
6161
_useCustomRenderSpaceAction.setToolTip("Toggle custom render space");
6262

6363
_xRenderSizeAction.setToolTip("X dimension render size");
@@ -88,7 +88,7 @@ SettingsAction::SettingsAction(QObject* parent, const QString& title) :
8888
connect(&_stepSizeAction, &DecimalAction::valueChanged, _DVRViewPlugin, &DVRViewPlugin::updateRenderSettings);
8989

9090
connect(&_useShadingAction, &ToggleAction::toggled, _DVRViewPlugin, &DVRViewPlugin::updateRenderSettings);
91-
connect(&_useEmptySpaceSkippingAction, &ToggleAction::toggled, _DVRViewPlugin, &DVRViewPlugin::updateRenderSettings);
91+
connect(&_useClutterRemover, &ToggleAction::toggled, _DVRViewPlugin, &DVRViewPlugin::updateRenderSettings);
9292
connect(&_useCustomRenderSpaceAction, &ToggleAction::toggled, _DVRViewPlugin, &DVRViewPlugin::updateRenderSettings);
9393

9494
connect(&_xRenderSizeAction, &IntegralAction::valueChanged, _DVRViewPlugin, &DVRViewPlugin::updateRenderSettings);

DVRViewPlugin/src/SettingsAction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class SettingsAction : public GroupAction
4343
IntegralAction& getRenderCubeSizeAction() { return _renderCubeSizeAction; }
4444

4545
ToggleAction& getUseShaderAction() { return _useShadingAction; }
46-
ToggleAction& getUseEmptySpaceSkippingAction() { return _useEmptySpaceSkippingAction; }
46+
ToggleAction& getUseClutterRemoverAction() { return _useClutterRemover; }
4747
ToggleAction& getUseCustomRenderSpaceAction() { return _useCustomRenderSpaceAction; }
4848

4949
DimensionPickerAction& getMIPDimensionPickerAction() { return _mipDimensionPickerAction; }
@@ -66,7 +66,7 @@ class SettingsAction : public GroupAction
6666
IntegralAction _renderCubeSizeAction; /** Sets the size of the cubes used for empty space skipping action */
6767

6868
ToggleAction _useShadingAction; /** Toggle action for using shading when available in the render mode */
69-
ToggleAction _useEmptySpaceSkippingAction; /** Toggle action for using empty space skipping */
69+
ToggleAction _useClutterRemover; /** Toggle action for using isolated voxel remover, which skips rendering of isolated voxels to remve clutter */
7070
ToggleAction _useCustomRenderSpaceAction; /** Toggle action for custom render space */
7171

7272
DimensionPickerAction _mipDimensionPickerAction; /** Dimension picker action */

DVRViewPlugin/src/VolumeRenderer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,11 @@ void VolumeRenderer::setMIPDimension(int mipDimension)
630630
_mipDimension = mipDimension;
631631
}
632632

633+
void VolumeRenderer::setUseClutterRemover(bool ClutterRemoval)
634+
{
635+
_useClutterRemover = ClutterRemoval;
636+
}
637+
633638
void VolumeRenderer::setUseShading(bool useShading)
634639
{
635640
_useShading = useShading;
@@ -1623,6 +1628,7 @@ void VolumeRenderer::renderMaterialTransition2D()
16231628
_materialTransition2DShader.uniform1f("stepSize", _stepSize);
16241629

16251630
_materialTransition2DShader.uniform1i("useShading", _useShading);
1631+
_materialTransition2DShader.uniform1f("useClutterRemover", _useClutterRemover);
16261632
_materialTransition2DShader.uniform3fv("camPos", 1, &_cameraPos);
16271633
_materialTransition2DShader.uniform3fv("lightPos", 1, &_cameraPos);
16281634

@@ -1681,6 +1687,7 @@ void VolumeRenderer::renderNNMaterialTransition()
16811687
_nnMaterialTransitionShader.uniform1i("materialTexture", 3);
16821688

16831689
_nnMaterialTransitionShader.uniform1f("stepSize", _stepSize);
1690+
_nnMaterialTransitionShader.uniform1f("useClutterRemover", _useClutterRemover);
16841691
_nnMaterialTransitionShader.uniform1i("useShading", _useShading);
16851692
_nnMaterialTransitionShader.uniform3fv("camPos", 1, &_cameraPos);
16861693
_nnMaterialTransitionShader.uniform3fv("lightPos", 1, &_cameraPos);

DVRViewPlugin/src/VolumeRenderer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class VolumeRenderer : protected QOpenGLFunctions_4_3_Core
8888

8989
void setRenderMode(const QString& renderMode);
9090
void setMIPDimension(int mipDimension);
91+
void setUseClutterRemover(bool ClutterRemoval);
9192
void setUseShading(bool useShading);
9293

9394
void setRenderCubeSize(float renderCubeSize);
@@ -167,6 +168,7 @@ class VolumeRenderer : protected QOpenGLFunctions_4_3_Core
167168
bool _hasColors = false;
168169
bool _dataSettingsChanged = true;
169170
bool _useCustomRenderSpace = false;
171+
bool _useClutterRemover = false; // only works for a few render modes, such as the NNMaterialTransition renderMode
170172
bool _useShading = false;
171173
bool _ANNAlgorithmTrained = false;
172174

0 commit comments

Comments
 (0)