Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8546453
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T13:01:34+00:00 2026-06-11T13:01:34+00:00

I am writing a shader to render spheres on point sprites, by drawing shaded

  • 0

I am writing a shader to render spheres on point sprites, by drawing shaded circles, and need to write a depth component as well as colour in order that spheres near each other will intersect correctly.

I am using code similar to that written by Johna Holwerda:

void PS_ShowDepth(VS_OUTPUT input, out float4 color: COLOR0,out float depth : DEPTH)
{
   float dist = length (input.uv - float2 (0.5f, 0.5f)); //get the distance form the center of the point-sprite
   float alpha = saturate(sign (0.5f - dist));
   sphereDepth = cos (dist * 3.14159) * sphereThickness * particleSize; //calculate how thick the sphere should be; sphereThickness is a variable.

   depth = saturate (sphereDepth + input.color.w); //input.color.w represents the depth value of the pixel on the point-sprite
   color = float4 (depth.xxx ,alpha ); //or anything else you might need in future passes
}

The video at that link gives a good idea of the effect I’m after: those spheres drawn on point sprites intersect correctly. I’ve added images below to illustrate too.

I can calculate the depth of the point sprite itself fine. However, I am not sure show to calculate the thickness of the sphere at a pixel in order to add it to the sprite’s depth, to give a final depth value. (The above code uses a variable rather than calculating it.)

I’ve been working on this on and off for several weeks but haven’t figured it out – I’m sure it’s simple, but it’s something my brain hasn’t twigged.

Direct3D 9’s point sprite sizes are calculated in pixels, and my sprites have several sizes – both by falloff due to distance (I implemented the same algorithm the old fixed-function pipeline used for point size computations in my vertex shader) and also due to what the sprite represents.

How do I go from the data I have in a pixel shader (sprite location, sprite depth, original world-space radius, radius in pixels onscreen, normalised distance of the pixel in question from the centre of the sprite) to a depth value? A partial solution simply of sprite size to sphere thickness in depth coordinates would be fine – that can be scaled by the normalised distance from the centre to get the thickness of the sphere at a pixel.

I am using Direct3D 9 and HLSL with shader model 3 as the upper SM limit.

In pictures

To demonstrate the technique, and the point at which I’m having trouble:

Start with two point sprites, and in the pixel shader draw a circle on each, using clip to remove fragments outside the circle’s boundary:

enter image description here

One will render above the other, since after all they are flat surfaces.

Now, make the shader more advanced, and draw the circle as though it was a sphere, with lighting. Note that even though the flat sprites look 3D, they still draw with one fully in front of the other since it’s an illusion: they are still flat.

enter image description here

(The above is easy; it’s the final step I am having trouble with and am asking how to achieve.)

Now, instead of the pixel shader writing only colour values, it should write the depth as well:

void SpherePS (...any parameters...
    out float4 oBackBuffer : COLOR0,
    out float oDepth : DEPTH0 <- now also writing depth
   )
{

Note that now the spheres intersect when the distance between them is smaller than their radiuses:

enter image description here

How do I calculate the correct depth value in order to achieve this final step?

Edit / Notes

Several people have commented that a real sphere will distort due to perspective, which may be especially visible at the edges of the screen, and so I should use a different technique. First, thanks for pointing that out, it’s not necessarily obvious and is good for future readers! Second, my aim is not to render a perspective-correct sphere, but to render millions of data points fast, and visually I think a sphere-like object looks nicer than a flat sprite, and shows the spatial position better too. Slight distortion or lack of distortion does not matter. If you watch the demo video, you can see how it is a useful visual tool. I don’t want to render actual sphere meshes because of the large number of triangles compared to a simple hardware-generated point sprite. I really do want to use the technique of point sprites, and I simply want to extend the extant demo technique in order to calculate the correct depth value, which in the demo was passed in as a variable with no source for how it was derived.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T13:01:36+00:00Added an answer on June 11, 2026 at 1:01 pm

    I came up with a solution yesterday, which which works well and and produces the desired result of a sphere drawn on the sprite, with a correct depth value which intersects with other objects and spheres in the scene. It may be less efficient than it needs to be (it calculates and projects two vertices per sprite, for example) and is probably not fully correct mathematically (it takes shortcuts), but it produces visually good results.

    The technique

    In order to write out the depth of the ‘sphere’, you need to calculate the radius of the sphere in depth coordinates – i.e., how thick half the sphere is. This amount can then be scaled as you write out each pixel on the sphere by how far from the centre of the sphere you are.

    To calculate the radius in depth coordinates:

    • Vertex shader: in unprojected scene coordinates cast a ray from the eye through the sphere centre (that is, the vertex that represents the point sprite) and add the radius of the sphere. This gives you a point lying on the surface of the sphere. Project both the sprite vertex and your new sphere surface vertex, and calculate depth (z/w) for each. The different is the depth value you need.

    • Pixel Shader: to draw a circle you already calculate a normalised distance from the centre of the sprite, using clip to not draw pixels outside the circle. Since it’s normalised (0-1), multiply this by the sphere depth (which is the depth value of the radius, i.e. the pixel at the centre of the sphere) and add to the depth of the flat sprite itself. This gives a depth thickest at the sphere centre to 0 and the edge, following the surface of the sphere. (Depending on how accurate you need it, use a cosine to get a curved thickness. I found linear gave perfectly fine-looking results.)

    Code

    This is not full code since my effects are for my company, but the code here is rewritten from my actual effect file omitting unnecessary / proprietary stuff, and should be complete enough to demonstrate the technique.

    Vertex shader

    void SphereVS(float4 vPos // Input vertex,
       float fPointRadius, // Radius of circle / sphere in world coords
       out float fDXScale, // Result of DirectX algorithm to scale the sprite size
       out float fDepth, // Flat sprite depth
       out float4 oPos : POSITION0, // Projected sprite position
       out float fDiameter : PSIZE, // Sprite size in pixels (DX point sprites are sized in px)
       out float fSphereRadiusDepth : TEXCOORDn // Radius of the sphere in depth coords
    {
        ...
       // Normal projection
       oPos = mul(vPos, g_mWorldViewProj);
    
       // DX depth (of the flat billboarded point sprite)
       fDepth = oPos.z / oPos.w;
    
       // Also scale the sprite size - DX specifies a point sprite's size in pixels.
       // One (old) algorithm is in http://msdn.microsoft.com/en-us/library/windows/desktop/bb147281(v=vs.85).aspx
       fDXScale = ...;
       fDiameter = fDXScale * fPointRadius;
    
       // Finally, the key: what's the depth coord to use for the thickness of the sphere?
       fSphereRadiusDepth = CalculateSphereDepth(vPos, fPointRadius, fDepth, fDXScale);
    
       ...
    }
    

    All standard stuff, but I include it to show how it’s used.

    The key method and the answer to the question is:

    float CalculateSphereDepth(float4 vPos, float fPointRadius, float fSphereCenterDepth, float fDXScale) {
       // Calculate sphere depth.  Do this by calculating a point on the
       // far side of the sphere, ie cast a ray from the eye, through the
       // point sprite vertex (the sphere center) and extend it by the radius
       // of the sphere
       // The difference in depths between the sphere center and the sphere
       // edge is then used to write out sphere 'depth' on the sprite.
       float4 vRayDir = vPos - g_vecEyePos;
       float fLength = length(vRayDir);
       vRayDir = normalize(vRayDir);
       fLength = fLength + vPointRadius; // Distance from eye through sphere center to edge of sphere
    
       float4 oSphereEdgePos = g_vecEyePos + (fLength * vRayDir); // Point on the edge of the sphere
       oSphereEdgePos.w = 1.0;
       oSphereEdgePos = mul(oSphereEdgePos, g_mWorldViewProj); // Project it
    
       // DX depth calculation of the projected sphere-edge point
       const float fSphereEdgeDepth = oSphereEdgePos.z / oSphereEdgePos.w;
       float fSphereRadiusDepth = fSphereCenterDepth - fSphereEdgeDepth; // Difference between center and edge of sphere
       fSphereRadiusDepth *= fDXScale; // Account for sphere scaling
    
       return fSphereRadiusDepth;
    }
    

    Pixel shader

    void SpherePS(
       ...
        float fSpriteDepth : TEXCOORD0,
        float fSphereRadiusDepth : TEXCOORD1,
        out float4 oFragment : COLOR0,
        out float fSphereDepth : DEPTH0
       )
    {
       float fCircleDist = ...; // See example code in the question
       // 0-1 value from the center of the sprite, use clip to form the sprite into a circle
       clip(fCircleDist);    
    
       fSphereDepth = fSpriteDepth + (fCircleDist * fSphereRadiusDepth);
    
       // And calculate a pixel color
       oFragment = ...; // Add lighting etc here
    }
    

    This code omits lighting etc. To calculate how far the pixel is from the centre of the sprite (to get fCircleDist) see the example code in the question (calculates ‘float dist = ...‘) which already drew a circle.

    The end result is…

    Result

    Intersecting spheres using point sprites

    Voila, point sprites drawing spheres.

    Notes

    • The scaling algorithm for the sprites may require the depth to be
      scaled, too. I am not sure that line is correct.
    • It is not fully mathematically correct (takes shortcuts)
      but as you can see the result is visually correct
    • When using millions of sprites, I still get a good rendering speed (<10ms per frame for 3 million sprites, on a VMWare Fusion emulated Direct3D device)
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am writing a shader for OpenGL and I need to be able to
I'm writing a vertex shader at the moment, and I need some random numbers.
I'm writing graphic shader program. I wrote everything I need except the color changing.
I'm writing a simplistic shader manager so I don't have to write repeditive code
I'm writing a shader in GLSL and I need to pass it a certain
I need to write to the depth buffer on an android device (OpenGL ES
I am writing a GLSL shader that simulates chromatic aberration for simple objects. I
I am writing a GLSL geometry shader and I am trying to use the
I am working on a project writing a GLSL fragment shader, and it just
I am writing a basic toon shader in OpenGL. I am using MSVC 2008.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.