Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a pixel shader that calculates a mandelbrot fractal. It uses the standard formula:

z = z2 + c

I'd like to extend it so the power z is raised by varies. To do this i have the following function:

float2 ComPow(float2 Arg, float Power)
{
    float Mod = pow(Arg.x * Arg.x + Arg.y * Arg.y, Power / 2);
    float Ang = atan2(Arg.y, Arg.x) * Power;

    return float2(Mod * cos(Ang), Mod * sin(Ang));
}

The problem i've got is the xbox does this really slowly compared to squaring a complex number. I'm thinking it's partly because of the increased number of instructions, but mainly it's using trig functions (cos, sin and atan2).

I tested this by adding a single atan2 within the for loop and it's visibly jerky, whereas before it was getting a good FPS.

Can i use texture lookup to speed up / replace the cos, sin and atan2 calls? If so, how?

share|improve this question

1 Answer 1

up vote 4 down vote accepted

Maybe. The problem you'll likely run into with replacing math functions with a texture lookup is precision and range. The texture can only be so large, and you have to decide what region of the function's domain it's going to cover and how finely subdivided in the domain it needs to be. Then, with standard texture formats you have only 8 bits to encode the output value, so again you need to decide what range of outputs you're going to support and how precise the output needs to be. You can use floating-point textures as well, but then they will be slower to read, and I think you also do not get bilinear filtering on floating-point textures on the X360.

It also may or may not be faster than just evaluating the math functions directly. Texture lookups are vastly more expensive than ALU (math) operations on a GPU, because of the high latency of memory access.

All that said, if you want to give it a shot, you'll basically need to allocate a texture of the size you picked, and write some init code to populate it by looping over all the pixels and evaluating the function at the domain point corresponding to each pixel. Then bind it like any other texture in your shader, and replace your math function with a tex2D call (with appropriate scale-biasing to convert the domain point to a UV point). I'm not familiar enough with XNA to tell you the exact calls you'll need, but it shouldn't be too hard to figure out.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.