Sign in to follow this  

[solved] Perlin noise shader: almost there, but some minor discontinuities

Recommended Posts

I've been working on a shader to create a perlin noise texture. I've got it almost working, but I can still see some minor discontinuities in the higher octaves and I can't quite place what is the issue :S Anyway here is my best result so far. You can see that the cloud texture is almost like I want it, but I can still see minor grids of discontinuity where the texture is repeating (you can see it in the fullsize image): Free Image Hosting at How I create the texture: On CPU I generate a small texture of the gradients used for perlin shader.Each texel of the texture represents a 2d vector in a random direction. To enable tiling, I duplicate the vectors around the edge: Free Image Hosting at Finally the pixel shader. For this shader I'm just drawing a fullscreen quad, with texture coordinates from (0..numGradients, 0..numGradients). maxTex is the same as numGradients, and allows me to wrap the texcoord for higher octaves.
uniform sampler2D gradientTex;
uniform vec2 maxTex;
in vec2 vTexCoord;

void main()
	float finalval=0;
	for(int i=0;i<4;i++){ //Four Octaves of Noise
		//Mod the texture coordinate for tiling
		//Each octave is 2x the frequency of the last
		vec2 modTex = mod(vTexCoord*pow(2,float(i)), maxTex);
		vec2 whole;
		vec2 fraction;
		//Split into whole and fractional parts
		fraction = modf(modTex ,whole);
		ivec2 texindex00 = ivec2(whole);
		//Get the four gradients surrounding the pixel
	 	vec2 texel00 = texelFetch2D(gradientTex,texindex00,0).rg;
		vec2 texel10 = texelFetch2D(gradientTex,ivec2(texindex00.x+1,texindex00.y),0).rg;
		vec2 texel01 = texelFetch2D(gradientTex,ivec2(texindex00.x,texindex00.y+1),0).rg;
		vec2 texel11 = texelFetch2D(gradientTex,ivec2(texindex00.x+1,texindex00.y+1),0).rg;
		//Compute the value at the four corners
		float val00 = dot(fraction, texel00);
		float val10 = dot(fraction-vec2(1,0), texel10);
		float val01 = dot(fraction-vec2(0,1), texel01);
		float val11 = dot(fraction-vec2(1,1), texel11);
		//Smooth polynomial bi-lerp
		float interp0 = val00 + (3*pow(fraction.x,2)-2*pow(fraction.x,3))*(val10-val00);
		float interp1 = val01 + (3*pow(fraction.x,2)-2*pow(fraction.x,3))*(val11-val01);
		float interp2 = interp0 + (3*pow(fraction.y,2)-2*pow(fraction.y,3))*(interp1-interp0);
		//Let the first octave be between 0-1
		//successive octaves between -1/2^n,1/2^n
			finalval += (interp2+1)/2;
		} else {
			finalval += interp2/pow(2,float(i));
	gl_FragColor = vec4(finalval,finalval,finalval,1.0);

Thanks to anyone who has any ideas on where my miscalculation might be! [Edited by - karwosts on April 25, 2010 7:00:48 PM]

Share this post

Link to post
Share on other sites
Found the issue. When uploading my gradients through OpenGL I used the wrong texture type, causing the x and y components of the gradients to be clamped to [0,1], when they should have been [-1,1]. Whenever either component of the gradient vector was negative it was zeroing it causing lots of bad visual artifacts.

Looks great now!

Free Image Hosting at

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this