Commit d1d5e902 authored by Philip Trettner's avatar Philip Trettner
Browse files

Reduced number of cells visited

parent 6985ed47
......@@ -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();
......
......@@ -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);
......
......@@ -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);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment