What is a nice, neat way to get the AABB of a sphere's projection onto the screen? This is to determine simplified geometry for lights in deferred shading.

  • \$\begingroup\$ Axis Alighned Bounding Box... So you want a box around the sphere?? \$\endgroup\$ – Savlon Feb 12 '13 at 18:03
  • \$\begingroup\$ I want to know what screen space rectangle to draw that will touch all of the pixels a specified sphere would touch. \$\endgroup\$ – Promit Feb 12 '13 at 19:26
  • \$\begingroup\$ Have you searched google for AABB of a sphere space projection? \$\endgroup\$ – Savlon Feb 12 '13 at 19:35

Found the correct derivation of the extents on AltDevBlogADay.

|improve this answer|||||
  • \$\begingroup\$ Link's dead :/ Don't suppose there's a copy elsewhere? \$\endgroup\$ – ZorbaTHut Aug 12 '15 at 11:45
  • 1
    \$\begingroup\$ Found a copy! gamasutra.com/view/news/164007/… @ZorbaTHut \$\endgroup\$ – Promit Aug 28 '15 at 21:27

Old question, but here's my version (GLSL):

/// <summary>
/// returns the screen-space (normalized device coordinates) bounds of a projected sphere
/// </summary>
/// <param name="center">view-space center of the sphere</param>
/// <param name="radius">world or view space radius of the sphere</param>
/// <param name="boxMin">minimum (bottom left) projected bounds</param>
/// <param name="boxMax">maximum (top right) projected bounds</param>
bool GetProjectedBounds(vec3 center, float radius, inout vec3 boxMin, inout vec3 boxMax)

    /// frustum culling helper
    if (ShouldCull(center,radius))
        return false;

    float d2 = dot(center,center);

    float a = sqrt(d2 - radius * radius);

    /// view-aligned "right" vector (right angle to the view plane from the center of the sphere. Since  "up" is always (0,n,0), replaced cross product with vec3(-c.z, 0, c.x)
    vec3 right = (radius / a) * vec3(-center.z, 0, center.x);
    vec3 up = vec3(0,radius,0);

    vec4 projectedRight  = Projection * vec4(right,0);
    vec4 projectedUp     = Projection * vec4(up,0);

    vec4 projectedCenter = Projection * vec4(center,1);

    vec4 north  = projectedCenter + projectedUp;
    vec4 east   = projectedCenter + projectedRight;
    vec4 south  = projectedCenter - projectedUp;
    vec4 west   = projectedCenter - projectedRight;

    north /= north.w ;
    east  /= east.w  ;
    west  /= west.w  ;
    south /= south.w ;

    boxMin = min(min(min(east,west),north),south).xyz;
    boxMax = max(max(max(east,west),north),south).xyz;

    return true;

The version I'm using performs frustum culling at the beginning (view space).

And, here's the output (my visualizer adds some padding on the right and left):

screen-space AABB of a sphere

The yellow represents the undistorted bounds of the sphere. Note that the left and right half-widths (relative to the real center of the sphere, at the center of the yellow circle) are different lengths.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.