Jump to content

  • Log In with Google      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.

  • You cannot reply to this topic
5 replies to this topic

#1 multifractal   Members   -  Reputation: 198

Like
0Likes
Like

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:

 

Screen_Shot_2013_09_04_at_10_22_17_PM.pn

 

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.


Sponsor:

#2 Bacterius   Crossbones+   -  Reputation: 7990

Like
2Likes
Like

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.


The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

 

- Pessimal Algorithms and Simplexity Analysis


#3 multifractal   Members   -  Reputation: 198

Like
1Likes
Like

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: 

 

Screen_Shot_2013_09_04_at_11_33_09_PM.pn

 

Which looks far too...ordered. 

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

texquad.png

 

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.


#4 multifractal   Members   -  Reputation: 198

Like
1Likes
Like

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): 

 

Screen_Shot_2013_09_05_at_12_50_58_AM.pn



#5 Bacterius   Crossbones+   -  Reputation: 7990

Like
0Likes
Like

Posted 04 September 2013 - 11:10 PM

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


The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

 

- Pessimal Algorithms and Simplexity Analysis


#6 born49   Members   -  Reputation: 204

Like
0Likes
Like

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.



PARTNERS