// Shader for drawing concentric circles
//
// Author: James Closs
// Email: james[at]bitbull.com
// Twitter: @bitbulldotcom
//
// You may use this code for whatever you see fit but please don't pass
// off this work as your own.
//
// I'd appreciate credit where credits' due, more Twitter followers,
// and especially anyone who buys my games!
sampler s0;
// an argb tint that is applied to the supplied texture
float4 tint;
// size of the outer shape with 1.0 being full span of the supplied texture
float size;
// strokewidth of the outer shape as a proportion of texture size
float strokewidth;
// spacing between shapes as a proportion of texture size
float spacing;
// amount by which the spacing between shapes increases with each concentric shape drawn
float spacing_increment;
// amount by which the stroke width of shapes increases with each concentric shape drawn
float strokewidth_increment;
// if 'true' multiplication is used to increase strokewidth/spacing. If false addition is used.
//
// if addition is used the values for spacing_increment and strokewidth_increment are as a
// proportion of total texture size
bool multiply_increments;
// the number of concentric shapes to draw
int repeats;
// Works out whether a point with distance d is within the circles
// defined by radius - note that d has been pre-computed as x*x + y*y.
//
// This is a 'partial pythagorous' calculation, we don't need to
// do the final (and expensive) sqrt calculation for
// pythagorous as we are only comparing relative distances, the actual distance doesn't matter
bool InsideCircle( float d, float radius )
{
return( d<=radius*radius);
}
// Works out whether a point with distance d is within the circles
// defined by inner_radius and outer_radius- note that d has been pre-computed as x*x + y*y.
bool InsideCircle( float d, float outer_radius, float inner_radius )
{
// clip to a circle that's as big as we can get in the texture...
// i've found this looks better in most instances
// 0.25 is the max radius squared (0.5*0.5)
if ( d>0.25 ) return false;
// don't allow values less than zero
outer_radius = max( outer_radius, 0 );
inner_radius = max( inner_radius, 0 );
if ( InsideCircle( d, inner_radius) ) return false;
if ( InsideCircle( d, outer_radius) ) return true;
return false;
}
float4 CircleShaderFunction(float2 coords: TEXCOORD0) : COLOR0
{
// This is the colour that will be returned by the shader
float4 color = tex2D(s0, coords);
// Multiply the colour by the tint parameter (pre-multiplied alpha)
color.r*=tint.r*tint.a;
color.g*=tint.g*tint.a;
color.b*=tint.b*tint.a;
color.a*=tint.a;
// This is here because the compiler barfs if we allow a loop
// with zero iterations
int n_repeats = (repeats<1)?1:repeats;
// Local (mutable) variables for strokewidth and spacing
float _strokewidth = strokewidth;
float _spacing = (spacing<0)?0:spacing;
// horizontal distance from centre to current coordinate
float dx = 0;
// vertical distance from centre to current coordinate
float dy = 0;
// total distance from centre to current coordinate
float d = 0;
// radius of the outer circle.
// default to full radius if a value of zero supplies
float r = (size>0)?0.5+(size-1.0):0.5;
// calculate distance from centre to current coordinate - this is a 'partial pythagorous'
// calculation, we don't need to do the final (and expensive) sqrt calculation for
// pythagorous as we are only comparing relative distances, the actual distance doesn't matter
dx = 0.5-coords.x;
dy = 0.5-coords.y;
d = dx*dx + dy*dy;
// compilers can barf without this modulo here which limits the max amount of iterations
for( int i=0; i