diff --git a/samples/distancefield/DistanceFieldApp.cc b/samples/distancefield/DistanceFieldApp.cc
index ab87b8d55731786d4e105d28247ed00bd8f1d48d..7aac68f5c331509e0275aa7810404b40c2560cc5 100644
--- a/samples/distancefield/DistanceFieldApp.cc
+++ b/samples/distancefield/DistanceFieldApp.cc
@@ -101,13 +101,14 @@ void DistanceFieldApp::init()
     mGpuTimer = TimerQuery::create();
 
     // bunny
+    if (!false)
     {
         std::ifstream file(util::pathOf(__FILE__) + "/../../data/bunny.obj");
 
         glm::vec3 amin{std::numeric_limits<float>::max()};
         glm::vec3 amax{-std::numeric_limits<float>::max()};
         std::string line;
-		std::vector<glm::vec3> pts;
+        std::vector<glm::vec3> pts;
         while (std::getline(file, line))
         {
             std::istringstream iss(line);
@@ -120,26 +121,28 @@ void DistanceFieldApp::init()
                 glm::vec3 v = {x, y, z};
                 amin = min(amin, v);
                 amax = max(amax, v);
-				pts.push_back(v);
+                pts.push_back(v);
             }
         }
 
-		auto s = amax - amin;
-		amin -= s * 0.1f;
-		amin += s * 0.1f;
-		auto ms = glm::max(s.x, glm::max(s.y, s.z));
-		for (auto v : pts)
-		{
-			v = (v - amin) / ms * Size;
-			v.x += (ms - s.x) / 2.0f;
-			v.y += (ms - s.y) / 2.0f;
-			v.z += (ms - s.z) / 2.0f;
-			mPoints.push_back(glm::vec4(v, 1.0f));
-		}
+        auto s = amax - amin;
+        amin -= s * 0.1f;
+        amin += s * 0.1f;
+        auto ms = glm::max(s.x, glm::max(s.y, s.z));
+        for (auto v : pts)
+        {
+            v = (v - amin) / ms * Size;
+            v.x += (ms - s.x) / 2.0f;
+            v.y += (ms - s.y) / 2.0f;
+            v.z += (ms - s.z) / 2.0f;
+            mPoints.push_back(glm::vec4(v, 1.0f));
+        }
     }
 
+    // mPoints.push_back(glm::vec4(Size / 2));
+
     // data
-    if (false)
+    if (!!false)
     {
         // mPoints.push_back(glm::vec4(Size / 2.0f));
         for (auto i = 0; i < 1000; ++i) // DEBUG
@@ -170,7 +173,7 @@ void DistanceFieldApp::init()
     mTexIteration = Texture3D::createStorageImmutable(Size, Size, Size, GL_R32UI, 1);
     mTexNearestPoint = Texture3D::createStorageImmutable(Size, Size, Size, GL_R32UI, 1);
 
-    for (auto const& tex : { mTexIteration, mTexNearestPoint})
+    for (auto const& tex : {mTexIteration, mTexNearestPoint})
     {
         auto t = tex->bind();
         t.setMinFilter(GL_NEAREST);
@@ -214,10 +217,10 @@ void DistanceFieldApp::init()
     mMarchShader->configureTransformFeedback({"gPosition"});
 
     // tweakbar
-	TwAddVarRW(tweakbar(), "Crust Size", TW_TYPE_FLOAT, &mCrustSize, "group=algorithm step=0.1");
+    TwAddVarRW(tweakbar(), "Crust Size", TW_TYPE_FLOAT, &mCrustSize, "group=algorithm step=0.1");
 
-	TwAddVarRW(tweakbar(), "Cut Y", TW_TYPE_FLOAT, &mCutY, "group=rendering step=0.002");
-	TwAddVarRW(tweakbar(), "Y Anim", TW_TYPE_FLOAT, &mYAnim, "group=rendering step=0.002");
+    TwAddVarRW(tweakbar(), "Cut Y", TW_TYPE_FLOAT, &mCutY, "group=rendering step=0.002");
+    TwAddVarRW(tweakbar(), "Y Anim", TW_TYPE_FLOAT, &mYAnim, "group=rendering step=0.002");
     TwAddVarRW(tweakbar(), "Show Slice", TW_TYPE_BOOLCPP, &mShowSlice, "group=rendering");
 
     TwAddVarRW(tweakbar(), "Auto Recalc", TW_TYPE_BOOLCPP, &mRecalcEveryFrame, "group=actions");
@@ -253,16 +256,16 @@ void DistanceFieldApp::recompute()
     mGpuTimerStart->saveTimestamp();
     // clear
     mClearShader->use().compute(Size / CLEAR_SHADER_SIZE, Size / CLEAR_SHADER_SIZE, Size / CLEAR_SHADER_SIZE);
-	glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
+    glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
 
-	auto nextIteration = 1u;
+    auto nextIteration = 1u;
 
     // init
     {
         mFeedbackQuery->begin();
         mGpuTimer->begin();
         auto shader = mInitShader->use();
-		shader.setUniform("uNextIteration", nextIteration++);
+        shader.setUniform("uNextIteration", nextIteration++);
 
         auto vao = mPointVAO->bind();
         vao.negotiateBindings(); // must be done before transform feedback
@@ -271,20 +274,21 @@ void DistanceFieldApp::recompute()
         fb.begin(GL_POINTS);
         vao.draw();
         fb.end();
+        glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
+
         mFeedbackQuery->end();
         mGpuTimer->end();
         auto time = TimerQuery::toSeconds(mGpuTimer->getResult64());
         auto pts = mFeedbackQuery->getResult64();
         glow::info() << "Seeds: " << pts << " (" << time * 1000 << " ms, " << (time / pts * 1000 * 1000 * 1000) << " ns/pt)";
     }
-    glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
 
     // march
     {
         auto outputA = false;
 
         auto shader = mMarchShader->use();
-		shader.setUniform("uCrustSize", mCrustSize);
+        shader.setUniform("uCrustSize", mCrustSize);
         mVAOQueueA->bind().negotiateBindings(); // must be done before transform feedback
         mVAOQueueB->bind().negotiateBindings(); // must be done before transform feedback
 
@@ -300,13 +304,13 @@ void DistanceFieldApp::recompute()
             }
 
             {
-				shader.setUniform("uNextIteration", nextIteration++);
+                shader.setUniform("uNextIteration", nextIteration++);
                 auto fb = (outputA ? mFeedbackA : mFeedbackB)->bind();
                 fb.begin(GL_POINTS);
                 (outputA ? mVAOQueueB : mVAOQueueA)->bind().drawTransformFeedback(outputA ? mFeedbackB : mFeedbackA);
                 fb.end();
+                glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
             }
-            glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
 
             if (shouldQuery)
             {
@@ -320,8 +324,8 @@ void DistanceFieldApp::recompute()
                 shouldQuery = true;
                 auto pts = mFeedbackQuery->getResult64();
                 auto time = TimerQuery::toSeconds(mGpuTimer->getResult64());
-                glow::info() << "Got " << pts << " indices at iteration " << nextIteration << " (" << time * 1000 << " ms, "
-                             << (time / pts * 1000 * 1000 * 1000) << " ns/pt)";
+                glow::info() << "Got " << pts << " indices at iteration " << nextIteration << " (" << time * 1000
+                             << " ms, " << (time / pts * 1000 * 1000 * 1000) << " ns/pt)";
 
                 forceSync = maxSync;
                 (void)forceSync;
@@ -332,8 +336,11 @@ void DistanceFieldApp::recompute()
 
             outputA = !outputA;
 
-			if (nextIteration > Size * 4)
-				break; // DEBUG
+            if (nextIteration > Size * 4)
+            {
+                glow::error() << "Too many iterations, aborting.";
+                break; // DEBUG
+            }
         }
     }
     mGpuTimerEnd->saveTimestamp();
@@ -353,7 +360,7 @@ void DistanceFieldApp::update(float elapsedSeconds)
     // IMPORTANT: call base function
     glfw::GlfwApp::update(elapsedSeconds);
 
-	mCutY += mYAnim * elapsedSeconds;
+    mCutY += mYAnim * elapsedSeconds;
 }
 
 void DistanceFieldApp::renderPass(const glow::pipeline::RenderPass& pass, float elapsedSeconds)
@@ -375,8 +382,8 @@ void DistanceFieldApp::renderPass(const glow::pipeline::RenderPass& pass, float
 
             auto shader = mSliceShader->use();
             shader.setUniform("uCutY", mCutY);
-			shader.setUniform("uCrustSize", mCrustSize);
-			shader.setUniform("uView", cam->getViewMatrix());
+            shader.setUniform("uCrustSize", mCrustSize);
+            shader.setUniform("uView", cam->getViewMatrix());
             shader.setUniform("uProj", cam->getProjectionMatrix());
 
             mQuadVAO->bind().draw();
diff --git a/samples/distancefield/gs-header.glsl b/samples/distancefield/gs-header.glsl
index 236fcbf6fc02b8bae83e2c3e94a2dfb69b8859c9..e995e816e761dddcdb687b56585206240eb515d5 100644
--- a/samples/distancefield/gs-header.glsl
+++ b/samples/distancefield/gs-header.glsl
@@ -10,6 +10,18 @@ void notifyNeighbor(int x, int y, int z, int w, int h)
     EmitVertex();
 }
 
+void notifyNeighbor(ivec3 ip, ivec3 is)
+{
+    if (any(lessThan(ip, ivec3(0))) || any(greaterThanEqual(ip, is)))
+        return; // out of bounds
+
+    if (imageAtomicMax(uTexIteration, ip, uNextIteration) == uNextIteration)
+        return; // already emitted
+
+    gPosition = (ip.z * is.y + ip.y) * is.x + ip.x;
+    EmitVertex();
+}
+
 void notifyNeighbors(ivec3 ip)
 {
     ivec3 is = imageSize(uTexNearestPoint);
diff --git a/samples/distancefield/march-shader.gsh b/samples/distancefield/march-shader.gsh
index f535b645eb2b2addb21d7b122584babb2e58c60b..aaace3e5f8fd4b053a3612b75eeaaa60d370d3c7 100644
--- a/samples/distancefield/march-shader.gsh
+++ b/samples/distancefield/march-shader.gsh
@@ -10,7 +10,17 @@ layout(points, max_vertices = 6) out;
 
 in uint vPosition[1];
 
-ivec3 is = imageSize(uTexNearestPoint);
+const ivec3 is = imageSize(uTexNearestPoint);
+const float maxDistance = is.x + is.y + is.z;
+
+const ivec3 dirs[6] = ivec3[6](
+    ivec3(-1, 0, 0),
+    ivec3(+1, 0, 0),
+    ivec3(0, -1, 0),
+    ivec3(0, +1, 0),
+    ivec3(0, 0, -1),
+    ivec3(0, 0, +1)
+);
 
 void checkNeighbor(ivec3 ip, int dx, int dy, int dz, inout float refDis, inout uint ptIdx)
 {
@@ -40,31 +50,51 @@ void main()
         idx / (is.x * is.y)
     );
 
-    //if (imageLoad(uTexDistanceField, ip).r != dis)
-    //    return; // wrong distance
-
     uint ptIdx = imageLoad(uTexNearestPoint, ip).r;
     uint origIdx = ptIdx;
 
-    float dis = is.x + is.y + is.z;
+    float refDis = maxDistance;
+    vec3 refP = vec3(0);
+
+    // collect candidates
+    float nDistances[6];
 
     // initial dis
     if (origIdx < points.length())
     {
-        vec3 currP = points[ptIdx].xyz;
-        dis = primitiveDistance(ip, currP);
+        refP = points[ptIdx].xyz;
+        refDis = primitiveDistance(ip, refP);
     }
 
-    // check nearest
-    checkNeighbor(ip, +1, 0, 0, dis, ptIdx);
-    checkNeighbor(ip, -1, 0, 0, dis, ptIdx);
-    checkNeighbor(ip, 0, +1, 0, dis, ptIdx);
-    checkNeighbor(ip, 0, -1, 0, dis, ptIdx);
-    checkNeighbor(ip, 0, 0, +1, dis, ptIdx);
-    checkNeighbor(ip, 0, 0, -1, dis, ptIdx);
+    // check neighbors
+    for (int i = 0; i < 6; ++i)
+    {
+        ivec3 np = ip + dirs[i];
+        uint nIdx = imageLoad(uTexNearestPoint, np).x;
+
+        // no change possible
+        if (nIdx == INVALID_POINT)
+        {
+            nDistances[i] = maxDistance;
+        }
+        else
+        {
+            vec3 nPos = points[nIdx].xyz;
+            float nDis = primitiveDistance(ip, nPos); // distance to ip!
+
+            nDistances[i] = primitiveDistance(np, nPos); // distance to np!
+
+            if (nDis < refDis) // update
+            {
+                refDis = nDis;
+                refP = nPos;
+                ptIdx = nIdx;
+            }
+        }
+    }
 
     // crust
-    if (dis > uCrustSize)
+    if (refDis > uCrustSize)
         return;
 
     // notify neighbors if changed
@@ -74,6 +104,14 @@ void main()
         imageStore(uTexNearestPoint, ip, uvec4(ptIdx));
 
         // notify
-        notifyNeighbors(ip);
+        for (int i = 0; i < 6; ++i)
+        {
+            ivec3 np = ip + dirs[i];
+
+            // only if update expected
+            float newDis = primitiveDistance(np, refP);
+            if (newDis < nDistances[i])
+                notifyNeighbor(np, is);
+        }
     }
 }