Skip to main content
GameDev.net gamedev.net
🔒 Locked

Drawing an Ellipse via its implicit equation in a PIxel Shader

Started by AvengerDr Aug 17, 2008 at 7:29 PM 1 replies 10.3k views
Original Post
AvengerDr
AvengerDr
In this thread we were discussing the possibility of drawing an ellipse in a pixel shader through its implicit equation. I went ahead and tried it but it is not as easy as it seems. In this particular case, I'm trying to generate the outline of an ellipse, so I have two parameters: an outline "width" and a "fade to black" distance, which generates a gradient from the outline color and the transparent background (for no particular reason, I just wanted to smooth the edges). This is the image generated by the pixel shader: As you may have noticed, the width of the outline is wider at the points where its curve changes orientation (ie at the full extents of its semimajor axis in this case) and thinner at its semiminor axis. This is due to the code that I'm using to generate it, I guess. Here follows the pixel shader code:

float a; // Semimajor Axis
float b; // Semiminor Axis

float fOutlineWidth = 0.05;
float fFadeWidth = 0.25;

float4 circleColor = float4(1,0,0,0);
float4 cBlack = float4(0,0,0,0);

float h = 0; // Center X coordinate
float k = 0; // Center Y coordinate

float4 ps_main( float2 texCoord  : TEXCOORD0 ) : COLOR
{

   float x = texCoord.x;
   float y = texCoord.y;

   float fEllipse = pow(x-h,2) / (a*a) + pow(y-k,2) / (b*b);
   float fDistance = abs(1-fEllipse);
   
   float4 color;
   
   if (fDistance <= fOutlineWidth)
      color = circleColor;
   else if (fDistance <= fOutlineWidth + fFadeWidth)
      color = lerp(circleColor,cBlack, (fDistance-fOutlineWidth)/fFadeWidth);
   else
      color = cBlack;
      
   return color;
}

It's very simple. Just compute the ellipse's implicit equation. When it's very close to 1, if it's under a certain value (fOutlineWidth or fOutlineWidth < x < fOutlineWidth + fFadeWidth) apply a certain color. But it provokes the above effect, which is due to these distances not being as "linear" as say, in the case of a circle. So what should I do in order to make it render a "perfect" ellipse? Maybe using two ellipses? With the semimajor/minor axis slightly larger and compute the distance between these two ellipses, and use that value to see which color to apply? Or is there a more elegant way? Thanks in advance!
Ebola0001
Ebola0001
this is the best I could do tonight, I will see if i can refine it later if I feel like it.
Time1 advances 0.005f per frame in the program


   float a = (sin(Time1)+1)/6+0.05; // Semimajor Axis   float b = (cos(Time1)+1)/6+0.05; // Semiminor Axis   float h = 0.5; // Center X coordinate   float k = 0.5; // Center Y coordinate	   float x = texCoord.x;   float y = texCoord.y;   float theta = acos((x-h)/a);   if (y < k)     theta = Pi - theta + Pi;   float x2 = h + a * cos(theta);   float y2 = k + b * sin(theta);   float fEllipse = pow(x-h,2) / (a*a) + pow(y-k,2) / (b*b);   float fDistance = abs(1-fEllipse);   float fDistance2 = sqrt((x2 - x)*(x2 - x) + (y2-y)*(y2-y));         float4 color;    if (fDistance2 <= fOutlineWidth/10)      color.x = circleColor.x;    else if (fDistance <= fOutlineWidth)      color.y = circleColor2.y;    else      color = cBlack;    return color;


the green color is your original function, the red addition is my new function, both of them overlapping make a fairly decent ellipse, but the smoothing function as you wrote it doesn't work on my addition because the coordinates go screwy on the left and right extremes of the ellipse.

program and fx file

anyway hope this helps
Quando Omni Flunkus MoritatiWhen All Else Fails, Play Dead!
RDragon1
RDragon1
Can you maybe for a given pixel position, compute a vector that is perpendicular to the closest point on the ellipse, and then project the pixel position onto that vector, telling you how far off the curve you are, to give a uniform width around the whole ellipse?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.