Skip to content

Instantly share code, notes, and snippets.

@sebbbi
Created February 18, 2018 19:31
Show Gist options
  • Star 47 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save sebbbi/a599d7896aa3ad36642145d54459f32b to your computer and use it in GitHub Desktop.
Save sebbbi/a599d7896aa3ad36642145d54459f32b to your computer and use it in GitHub Desktop.
Fast way to render lots of spheres
Setup:
1. Index buffer containing N quads (each 2 triangles), where N is the max amount of spheres. Repeating pattern of {0,1,2,1,3,2} + K*4.
2. No vertex buffer.
Render N*2 triangles, where N is the number of spheres you have.
Vertex shader:
1. Sphere index = N/4 (N = SV_VertexId)
2. Quad coord: Q = float2(N%2, (N%4)/2) * 2.0 - 1.0
3. Transform sphere center -> pos
4. Calculate the optimal oriented bounding box of the sphere. See: http://www.iquilezles.org/www/articles/sphereproj/sphereproj.htm
5. Output bounding box vertex (xy): pos + bbox_xaxis * Q.x + bbox_yaxis * Q.y
6. Bias depth output by sphere radius. (we want front of the sphere)
Pixel shader:
1. Calculate ray-sphere intersection: https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection
2. If ray misses sphere, discard the pixel.
3. Calculate surface position and normal using the ray-sphere intersection result.
4. Calculate all g-buffer outputs, shading, etc that you need.
5. Output depth calculated with ray-sphere intersection.
6. Use SV_DepthGreaterEqual conservative depth output. This way you get HiZ culling (measured up to 6x speedup vs SV_Depth)
Preferably sort spheres front to back, if you have lots of overdraw.
If you have HUGE amount of overdraw, use the two-phase occlusion cull described in page 53 of this SIGGRAPH 2015 presentation:
http://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf
@stevesan
Copy link

hello! so where do you get the sphere centers from?

@sebbbi
Copy link
Author

sebbbi commented Feb 19, 2018

In my case I have a raw buffer written by my GPGPU simulators. I use this technique for debug views of SPH fluids and PBD physics simulation.

In DirectX, you can use one of the following:

Buffer<float4> spheres;
ByteAddressBuffer spheres;
StructuredBuffer<float4> spheres;

Store sphere position to xyz and radius to w. SV_VertexId % 4 gives you the index to address the sphere buffer.

@alexsr
Copy link

alexsr commented May 12, 2018

Hello. Could you elaborate on the way you calculate the rays and possibly the ray origin? I get the vertex shader to work to the point where I can render oriented quads, but I'm struggling with implementing the pixel shader. Thank you for compiling this guide btw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment