Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Approximate Distance Field computation extension to irr::ext #229

Open
devshgraphicsprogramming opened this issue Feb 23, 2019 · 5 comments

Comments

@devshgraphicsprogramming
Copy link
Collaborator

devshgraphicsprogramming commented Feb 23, 2019

Result will be used for Sphere Tracing (SDF Shadows) - but those uses are outside the scope of the extension.
http://jamie-wong.com/2016/07/15/ray-marching-signed-distance-functions/

Use Compute Shader, but make the extension a CGLSLFunctionGenerator function only for processing input that is already a distance field along an axis.

Marching parabolas algorithm can be implemented in shared memory, much like the Blur function.
https://prideout.net/blog/distance_fields/

Flow:

  1. Input is 2D or 3D texture that has already been swept in the X direction
  2. Sweep along Y with extension compute shader
  3. Memory Barrier
  4. Sweep along Z
  5. Done

The distance field should accept a quantization factor (rescaling factor) so that the EDF does not need floating point storage.

@devshgraphicsprogramming devshgraphicsprogramming changed the title Add a Signed Distance Field computation extension to irr::ext Add a Approximate Distance Field computation extension to irr::ext Feb 23, 2019
@devshgraphicsprogramming
Copy link
Collaborator Author

devshgraphicsprogramming commented Feb 23, 2019

Pseudo code for a non optimal version (apparently one can use a prefix sum for this)

uint _out = uint(input*QUANITZATION_FACTOR); // values > EDF_RANGE*EDF_RANGE indicate "infinity"
sharedMem[rowInvocationID] = _out ;
BARRIER();
for (int i=-EDF_RANGE; i<EDF_RANGE; i++) // could optimize by splitting into two loops and not processing i==0
{
    int newCoordinate = coordinateWrapAround(rowInvocationID+i); // usually just a x%ROW_LENGTH
    int distanceBetween = rowInvocationID-newCoordinate;
    _out = min(_out ,sharedMem[newCoordinate]+distanceBetween*distanceBetween );
}
return float(_out )*QUANITZATION_FACTOR_RCP;

EDF_RANGE is max quantizable distance, if storing to a UNORM_R8 texture then it will be 255, if storing to SNORM_R8 then it will be 127.
Naturally the intermediate result texture will have to have 2ce the bits.

@devshgraphicsprogramming
Copy link
Collaborator Author

For rows longer than LOCAL_WORKGROUP_SIZE_X (which should be 256 because of mobile devices), then sharedMem would have to be pre-loaded with LOCAL_WORKGROUP_SIZE_X+2*EDF_RANGE samples.

If performance for example 13.SphereTracing is acceptable then the non-optimal (no prefix-sum/scan version can stay)

@devshgraphicsprogramming
Copy link
Collaborator Author

Perf bound on a 320GB/s GDDR5 desktop GPU will be around 6ms for SDF computation.

I expect the non-optimal (non-scan) algorithm to take between 1000-500ms assuming 2TB/s shared memory speed and EDF_RANGE=255.

So to optimize either use prefix-sum/scan or implement the exchange of shared memory within a warp via NV_shuffle (and similar)

@devshgraphicsprogramming
Copy link
Collaborator Author

Reading Resources about rendering those
http://advances.realtimerendering.com/s2015/AlexEvans_SIGGRAPH-2015-sml.pdf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant