Jump to content
  • Advertisement
Sign in to follow this  
multifractal

Perlin Noise Pixel Shader Error

This topic is 2143 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

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

Share this post


Link to post
Share on other sites
Advertisement

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!