Original Post
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: 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!
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;
}
