5
\$\begingroup\$

I have been trying to get my shader code (HLSL) to draw a simple circle but after a day and a half I am getting nowhere. It seems people are using $$x^2 + y^2 = r^2$$ and remap texcoords but I only get a white quad.

    struct VertexShaderStruct
{
    float4 Position : POSITION0;
    float2 Tex0 : TEXCOORD0;
};

VertexShaderStruct VertexShaderFunction(VertexShaderStruct input)
{
    VertexShaderStruct output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);
    output.Tex0 = input.Tex0;

    return output;
}

float4 PixelShaderFunction(VertexShaderStruct input) : COLOR0
{
    float dx = 2 * input.Tex0.x - 1;
    float dy = 2 * input.Tex0.y - 1;
    float hyp = (dx * dx + dy * dy);

    return (hyp == 1)? circleColor : otherColor;
}

I define circleColor as blue and otherColor as white, so it seems hyp==1 always fails.

\$\endgroup\$
1
  • \$\begingroup\$ I have having this exact same problem. It sounds like your code is now working. Could you post the entire HLSL file contents? It would really help me. \$\endgroup\$
    – Justin R.
    Jan 23, 2013 at 22:48

1 Answer 1

7
\$\begingroup\$

The fragment shader is executed for each fragment with a single uv for this fragment which will probably never fall perfectly on 1.

You could map the target area roughly to the width of a render target fragment.

Eg something like:

abs(hyp - 1) * CircleRadiusInPixel < BorderWidthInPixel*0.5

Further explanation:

Your gpu rasterizes the triangles and executes the fragment shader for each fragment. A fragment is basically a pixel on your screen when MSAA is not active. For each of these fragments the input.Tex0 is filled by interpolating the values from the vertices. As the vertex values for Tex0 range from (0,0) to (1,1) the fragments get values between (0,0) and (1,1). Each fragment only gets one Tex0 representing the value at the center of the current fragment. So it is very unlikely that the fragment centers lie EXACTLY at distance 1 from the center of the circle. If you align everything perfectly, you could probably get 4 pixels (left-middle, right-middle, top-center and button-center) to get correctly colored but never the whole circle and it will probably look different on different vga's.

Even if you somehow could be sure that all pixels are aligned, never compare floats you calculated to an exact value. Floats are never exact as they have limited precision and are adjusted to it after each computation. Compare ranges instead.

You can get an even better looking circle adding some kind of fade out:

float nonBorder = saturate( abs(hyp - 1) * CircleRadiusInPixel / BorderWidthInPixel*0.5 );
nonBorder = pow( nonBorder, 2.0f );
float4 outColor = lerp( circleColor, otherColor, nonBorder );
return pow( outColor, 1.0f / 2.2f ); // gamma correction
\$\endgroup\$
6
  • \$\begingroup\$ Thank you very much your answer has solved my problem. Id like to understand how you figured out the math or why it works. Or why mine did not. I should do some research but at least its solved. Thanks. \$\endgroup\$
    – Michael
    Jan 23, 2013 at 0:29
  • \$\begingroup\$ Anytime, added some additional information! \$\endgroup\$
    – Archy
    Jan 23, 2013 at 1:01
  • 1
    \$\begingroup\$ You have answered my questions amazingly, and shown me how to improve the circle, which works great. Ive learned most importantly how my calculated floats will most likely not land exactly where I expect and to account for this with ranges. I will continue to study this until I have it fully cemented. Thanks a lot for all your help, and I hope others will find this and learn too. \$\endgroup\$
    – Michael
    Jan 23, 2013 at 1:52
  • \$\begingroup\$ Kind of a n00b question, but how are you getting CircleRadiusInPixel and BorderWidthInPixel into your shader function? -- Are they part of your VertexShaderStruct? If so, what are they declared as semantically? \$\endgroup\$ May 1, 2014 at 5:26
  • \$\begingroup\$ Figured it out, I was able to pass in the extra information as a TEXCOORD. \$\endgroup\$ May 2, 2014 at 6:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .