AABB of a sphere's screen space projection

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.

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

Found the correct derivation of the extents on AltDevBlogADay.

• Link's dead :/ Don't suppose there's a copy elsewhere? – ZorbaTHut Aug 12 '15 at 11:45
• Found a copy! gamasutra.com/view/news/164007/… @ZorbaTHut – 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="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
return false;

float d2 = dot(center,center);

/// 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);

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):

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.