•      Sign In
• Create Account

## Perlin Noise Pixel Shader Error

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

5 replies to this topic

### #1multifractal  Members

Posted 04 September 2013 - 06:29 PM

Hello,

I am attempting to use perlin noise in a pixel shader as described here: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter26.html

I believe my look up textures are correct yet this is the result of the noise output:

As one can see this doesn't look very much like perlin noise..

Here is the code used to produce that:

Lookup texture generation:

long seed = new Random().nextLong();
Random r = new Random(seed);
permutation = new int[256];
for(int i = 0; i<permutation.length; i++){
permutation[i] = -1;
}

for(int i = 0; i< permutation.length; i++){
while(true){
int iP = Math.abs(r.nextInt()) % permutation.length;
if(permutation[iP] == -1){
permutation[iP] = i;
break;
}
}
}
ImageRaster rP = ImageRaster.create(permImage);
for(int x = 0; x < 256; x++){
for(int y = 0; y < 256; y++){
int A = perm2d(x) + y;
int AA = perm2d(A);
int AB = perm2d(A + 1);
int B = perm2d(x + 1) + y;
int BA = perm2d(B);
int BB = perm2d(B + 1);
ColorRGBA c = new ColorRGBA((float)AA/255f, (float)AB/255f, (float)BA/255f, (float)BB/255f);
rP.setPixel(x, y, c);

}
}

ImageRaster rG = ImageRaster.create(gradImage);
for(int x = 0; x<256; x++){
for(int y = 0; y < 1; y++){
ColorRGBA c = new ColorRGBA(grads[permutation[x]%16][0],
grads[permutation[x] % 16][ 1],
grads[permutation[x] % 16][2], 1);
rG.setPixel(x, y, c);
}
}

Texture2D permutationTable = new Texture2D(permImage);
permutationTable.setWrap(WrapMode.Repeat);
permutationTable.setMagFilter(MagFilter.Nearest);
permutationTable.setMinFilter(MinFilter.NearestNoMipMaps);

Texture2D gradientTable = new Texture2D(gradImage);
gradientTable.setWrap(WrapAxis.S, WrapMode.Repeat);
gradientTable.setWrap(WrapAxis.T, WrapMode.Clamp);
gradientTable.setMagFilter(MagFilter.Nearest);
gradientTable.setMinFilter(MinFilter.NearestNoMipMaps);


Pixel Shader:

uniform sampler2D permSampler2d;
uniform sampler2D permGradSampler;

varying vec4 pos;

vec3 fade(vec3 t)
{
return (t * t * t * (t * (t * 6.0 - 15.0) + 10.0));
}
vec4 perm2d(vec2 p)
{
return texture2D(permSampler2d, p);
}
float gradperm(float x, vec3 p)
{
return dot(vec3(texture2D(permGradSampler, vec2(x,0.0)).xyz), p);
}

float inoise(vec3 p)
{
vec3 P = mod(floor(p), 256.0);
p -= floor(p);
vec3 f = fade(p);

P = P / 256.0;
const float one = 1.0 / 256.0;

vec4 AA = perm2d(P.xy) + P.z;

return mix( mix( mix( gradperm(AA.x, p ),
gradperm(AA.z, p + vec3(-1.0, 0.0, 0.0) ), f.x),
mix( gradperm(AA.y, p + vec3(0.0, -1.0, 0.0) ),
gradperm(AA.w, p + vec3(-1.0, -1.0, 0.0) ), f.x), f.y),

mix( mix( gradperm(AA.x+one, p + vec3(0.0, 0.0, -1.0) ),
gradperm(AA.z+one, p + vec3(-1.0, 0.0, -1.0) ), f.x),
mix( gradperm(AA.y+one, p + vec3(0.0, -1.0, -1.0) ),
gradperm(AA.w+one, p + vec3(-1.0, -1.0, -1.0) ), f.x), f.y), f.z);
}

void main(void){
float n = (inoise(vec3(pos.xyz/20.0)) + 0.5) * 0.5 ;

gl_FragColor = vec4(n,n,n,1.0);
}



If anyone can spot any errors with this I would be extremely appreciative. Thanks for any help.

Edited by multifractal, 04 September 2013 - 08:24 PM.

### #2Bacterius  Members

Posted 04 September 2013 - 08:37 PM

Looks fine to me (the picture), but it seems you're just not sampling over a large enough area. Can you try increasing the range of your test render, such as pos.xyz / 4 or something? And after all, perlin noise "as is" is pretty dull. You typically want to implement something like fBm which is just a summation of octaves of perlin noise (aka a fractal).

I also recall perlin noise returning values between -1 and 1, so your scaling code might not be correct (don't quote me on this though), as it puts your "n" in (-0.25.. 0.75). Try doing "(noise + 1) * 0.5" and see if that gives you gradients between black and white as expected. I could be wrong on that part though.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

### #3multifractal  Members

Posted 04 September 2013 - 09:37 PM

Looks fine to me (the picture), but it seems you're just not sampling over a large enough area. Can you try increasing the range of your test render, such as pos.xyz / 4 or something? And after all, perlin noise "as is" is pretty dull. You typically want to implement something like fBm which is just a summation of octaves of perlin noise (aka a fractal).

I also recall perlin noise returning values between -1 and 1, so your scaling code might not be correct (don't quote me on this though), as it puts your "n" in (-0.25.. 0.75). Try doing "(noise + 1) * 0.5" and see if that gives you gradients between black and white as expected. I could be wrong on that part though.

Hmm well decreasing 20 to 4 returned the following image:

Which looks far too...ordered.

Especially compared to this, which is output from this same function:

Also I ran a few tests and I think you are right about (noise + 0.5) * 0.5...changing it to what you suggested returns values dispersed through -1 - 1

Edited by multifractal, 04 September 2013 - 09:38 PM.

### #4multifractal  Members

Posted 04 September 2013 - 10:54 PM

UPDATE:

Looks fine to me (the picture), but it seems you're just not sampling over a large enough area. Can you try increasing the range of your test render, such as pos.xyz / 4 or something? And after all, perlin noise "as is" is pretty dull. You typically want to implement something like fBm which is just a summation of octaves of perlin noise (aka a fractal).

I also recall perlin noise returning values between -1 and 1, so your scaling code might not be correct (don't quote me on this though), as it puts your "n" in (-0.25.. 0.75). Try doing "(noise + 1) * 0.5" and see if that gives you gradients between black and white as expected. I could be wrong on that part though.

I found that the problem was how the textures were being passed to the shaders. Once that was fixed it began to work! Thanks for the help (and the tip about normalizing the range).

Here is the end result (for comparisons sake):

### #5Bacterius  Members

Posted 04 September 2013 - 11:10 PM

Glad you got it fixed, and yeah the second picture didn't look at all right.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

### #6born49  Members

Posted 09 September 2013 - 07:54 AM

You can also use 'texture-less' GPU noise, which can save you lot of pain :-) For inspiration you can look at

Brian Sharpe's high quality + high performance GPU noise lib here: https://github.com/BrianSharpe/GPU-Noise-Lib.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.