Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have successfully made a Perlin noise algorithm on the GPU. It works as expected, and generates great results. Now, as part of the physics calculations in my game, I need to replicate the exact same algorithm on the CPU, so that I can (given an X, Y and Z coordinate) determine whether or not that is inside a wall, or a walkable area.

I have debugged the shader through PIX, and I've gotten everything almost right, except for the part below (seen in shader code).

GPU (shader) code (HLSL)

float4 perm2d(float2 p)
    return tex2D(permSampler2d, p);

permSampler2d samples a texture that I generate out of Color structures and then pump to the GPU. The way I generate the texture on the CPU is the following:

CPU code (XNA C#)

int createPerm2d(int i)
    return permutation[i % 256];

public Texture2D GeneratePermTexture2d()
    permTexture2d = new Texture2D(device, 256, 256, true, SurfaceFormat.Color);
    permutationData = new Color[256 * 256];
    for (int x = 0; x < 256; x++)
        for (int y = 0; y < 256; y++)
            int A = createPerm2d(x) + y;
            int AA = createPerm2d(A);
            int AB = createPerm2d(A + 1);
            int B = createPerm2d(x + 1) + y;
            int BA = createPerm2d(B);
            int BB = createPerm2d(B + 1);
            permutationData[x + (y * 256)] = new Color((byte)(AA), (byte)(AB),
                                            (byte)(BA), (byte)(BB));
    return permTexture2d;

As said before, all this works as expected, until I run the code on the CPU to get the noise data back later.

According to PIX, the part that fails is indeed perm2d on the CPU (as seen below), which produces incorrect results.

CPU code (XNA C#)

static Vector4 perm2d(Vector2 p)
    return permutationData[(int)p.X + ((int)(p.Y) * 256)].ToVector4();

At the particular area (in the exact same pixel with the exact same seed used to generate the map, where it returns the incorrect results, PIX reports that the GPU returns "{0.035, 0.067, 0.365, 0.408}" from the perm2d function whereas the CPU code returns "{X:0,7450981 Y:0,345098 Z:0,5137255 W:0,09803922}".

Other than that, the rest of the functions produce the right outputs.

share|improve this question
up vote 3 down vote accepted

Are your vector x/y values that you're passing to perm2d always integers? On the GPU that will interpolate, on the CPU you're truncating and always getting an exact value.

(This also doesn't look like Perlin noise.)

share|improve this answer
Aha! Now that's very interesting. Can I turn off interpolation on the GPU? And yes, it is indeed Perlin Noise. – Mathias Lykkegaard Lorenzen Aug 7 '11 at 11:37
@Mathias You can turn off interpolation during texture sampling by using SamplerState.PointClamp or PointWrap. – Andrew Russell Aug 7 '11 at 12:24
Turning off interpolation on the GPU makes weird-shaped patterns in the map. And using interpolation on the GPU (as seen here…) will not work. Could it be because everything is rendered as colors with alpha, and when the GPU reads it, it can only read RGB? – Mathias Lykkegaard Lorenzen Aug 7 '11 at 12:59
Note that neither Perlin noise nor improved Perlin noise requires GPU interpolation to generate the gradients correctly; your code really looks like some kind of value noise, in which case you should get accurate results doing the same bilerp on the CPU. Nothing in your example is getting rendered, so I don't know what your last sentence refers to. Do you mean your texture format might different dramatically, RGBA on the CPU but something else on the GPU? I suppose, but I can't tell you if that's the case. – user744 Aug 7 '11 at 13:17

Your Answer


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.