Sign in to follow this  

Reducing Atan2's operation into fewer instructions

This topic is 3668 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a texture being drawn to the screen with a special pixel shader. Based on two given angles, the pixel shader will output full color of the texture, or no color (Alpha = 0). The problem is that due to the nature of Lerp(blah, blah, texCoord) and Atan2(y, x), this shader only fits into SM3. I am trying to get it to fit into SM2 with little luck so far. I have tried reducing the arithmetic to 4 steps of the atan infinite series but this does not give nearly decent enough precision. Any help on reducing the arithmetic instruction count would be a great help! Here is my code.. The "Sub" version compiles, but doesn't work yet. The double test is a hack because of how messy XNA's SpriteBatch works.
uniform extern texture ScreenTexture;
uniform extern texture AlphaTexture;
    
uniform extern float2 Position;
uniform extern float2 Size;
uniform extern float2 Offset = float2(400,300);

uniform extern float AngleMin;
uniform extern float AngleMax;

sampler ScreenS = sampler_state
{
    Texture = <ScreenTexture>;    
};

sampler AlphaSampler = sampler_state
{
    Texture = <AlphaTexture>;    
};

float4 PixelShader(float2 texCoord: TEXCOORD0) : COLOR
{
    float4 Color = tex2D(ScreenS, texCoord);
    float4 Alpha = tex2D(AlphaSampler, texCoord);
    
    Color.a = Color.a - Alpha.a;
    
    float2 RealPos = lerp(Position, Position + Size, texCoord) - Offset;
    RealPos.y *= -1;
    
    float DoubleTest = -1000;
    if(AngleMax > 3.141593f)
    {
		DoubleTest = AngleMax - 6.283186f;
	}
    
    float angleTest = atan2(RealPos.y, RealPos.x);
    
    if(angleTest < AngleMin || angleTest > AngleMax)
	{	
		if(DoubleTest != -1000)
		{
			if(angleTest > DoubleTest && angleTest < AngleMin)
				Color.a = 0.0f;
		}
		else
			Color.a = 0.0f;
	}
            
    return Color;
}

//float myPows[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23};
float GetAngle(float z)
{
	float angle = z;
	
	int i = 0;
	while(i < 3)
	{
		float b = 2 * i + 1;
		float f = pow(z, b) / b;
		if(i % 2 == 0)
			angle -= f;
		else
			angle += f;
		
		i++;
	}

	
	return angle;
}

float4 PixelShaderSub(float2 texCoord: TEXCOORD0) : COLOR
{
    float4 Color = tex2D(ScreenS, texCoord);
    float4 Alpha = tex2D(AlphaSampler, texCoord);
    
    Color.a = Color.a - Alpha.a;
    
    float2 RealPos = lerp(Position, Position + Size, texCoord) - Offset;
    RealPos.y *= -1;
    
    float DoubleTest = -1000;
    if(AngleMax > 3.141593f)
    {
		DoubleTest = AngleMax - 6.283186f;
	}
    
    float angleTest = GetAngle(Position.y / Position.x);
    if(Position.y < 0)
		angleTest += 1.5708;
    
    if(angleTest < AngleMin || angleTest > AngleMax)
	{	
		if(DoubleTest != -1000)
		{
			if(angleTest > DoubleTest && angleTest < AngleMin)
				Color.a = 0.0f;
		}
		else
			Color.a = 0.0f;
	}
            
    return Color;
}

technique SelectorAlphaTest
{
    pass P0
    {
        PixelShader = compile ps_3_0 PixelShader();
    }
}

technique SelectorAlphaTestSub
{
	pass P0
	{
		PixelShader = compile ps_2_0 PixelShaderSub();
	}
}

Share this post


Link to post
Share on other sites
i understand the process but not the reason, why are you trying to transform a texture in PS, it is more convenient to draw it to render target in order to get this effect. but, if you still want to do this way, so, i think you could transform the UV's using a matrix, like transforming vertices, and then use Tex2d, not using a loop.

Share this post


Link to post
Share on other sites
Well the real underlying question is how to draw only part of the screen between two angles starting from some point (the center in this case).

Share this post


Link to post
Share on other sites

This topic is 3668 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this