Jump to content
  • Advertisement
Sign in to follow this  

Problem with procedural bumpmapping

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

Hi I am currently playing around with some procedural bump mapping, and by using a height map I created my bump map on run time. Now due to the fact this results in some visible tiling, I thought I would try to implement Perlin noise directly into the pixel shader. I take an awfully lot of computation and this is just to explore the area. Well I did, but not properly I guess since the result is weird. Now as you can see, it makes random stuff as one would expect, but only in all these little squares, and I have really no idea why. Now here is process of creating this. Usually when Perlin Noise is generated one has a list of gradients and a list of permutations to make it randomly chose a gradient for a point. Instead of doing this in the shader, due to the fact that it take up to many registers, I have just created a texture which consist of random gradients, which are all normalized and are in the range of [0; 255]. Now here is my shader code for creating the noise:
uniform extern texture gradients;

sampler GradientsSampler = sampler_state
	Texture = < gradients >;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = POINT;
	AddressU  = WRAP;
	AddressV  = WRAP;

float sCurve( float x, float x0 )
	return ( 6.0f * ( x - x0 ) * ( x - x0 ) - 15.0f * ( x - x0 ) + 10.0f ) * ( x - x0 ) * ( x - x0 ) * ( x - x0 );

float noise3D( float3 position )
	// locate the eight nodes which constitutes the eight corners of
	// the grid cube the point is based within
	float gX0 = floor( position.x );
	float gY0 = floor( position.y );
	float gZ0 = floor( position.z );
	float gX1 = gX0 + 1;
	float gY1 = gY0 + 1;
	float gZ1 = gZ0 + 1;
	float3 leftDownBack  = { gX0, gY0, gZ0 };
	float3 rightDownBack = { gX1, gY0, gZ0 };
	float3 leftUpBack    = { gX0, gY1, gZ0 };
	float3 rightUpBack   = { gX1, gY1, gZ0 };

	float3 leftDownFront  = { gX0, gY0, gZ1 };
	float3 rightDownFront = { gX1, gY0, gZ1 };
	float3 leftUpFront    = { gX0, gY1, gZ1 };
	float3 rightUpFront   = { gX1, gY1, gZ1 };
	// calculate the vectors going from cube points to 
	// the look-up point
	float3 leftDownBackToPoint  = float3( position.x - leftDownBack.x, position.y - leftDownBack.y, position.z - leftDownBack.z );
	float3 rightDownBackToPoint = float3( position.x - rightDownBack.x, position.y - rightDownBack.y, position.z - rightDownBack.z );
	float3 leftUpBackToPoint    = float3( position.x - leftUpBack.x, position.y - leftUpBack.y, position.z - leftUpBack.z );
	float3 rightUpBackToPoint   = float3( position.x - rightUpBack.x, position.y - rightUpBack.y, position.z - rightUpBack.z );

	float3 leftDownFrontToPoint  = float3( position.x - leftDownFront.x, position.y - leftDownFront.y,  position.z - leftDownFront.z  );
	float3 rightDownFrontToPoint = float3( position.x - rightDownFront.x, position.y - rightDownFront.y, position.z - rightDownFront.z );
	float3 leftUpFrontToPoint    = float3( position.x - leftUpFront.x, position.y - leftUpFront.y,    position.z - leftUpFront.z );
	float3 rightUpFrontToPoint   = float3( position.x - rightUpFront.x, position.y - rightUpFront.y,   position.z - rightUpFront.z );

	// calculate influence of each corner
	float sb = dot( tex2D( GradientsSampler, float2( leftDownBackToPoint.x,  leftDownBackToPoint.z  ) ), leftDownBackToPoint  );
	float tb = dot( tex2D( GradientsSampler, float2( rightDownBackToPoint.x, rightDownBackToPoint.z ) ), rightDownBackToPoint );
	float ub = dot( tex2D( GradientsSampler, float2( leftUpBackToPoint.x,    leftUpBackToPoint.z    ) ), leftUpBackToPoint    );
	float vb = dot( tex2D( GradientsSampler, float2( rightUpBackToPoint.x,   rightUpBackToPoint.z   ) ), rightUpBackToPoint   );
	float sf = dot( tex2D( GradientsSampler, float2( leftDownFrontToPoint.x,  leftDownFrontToPoint.z  ) ), leftDownFrontToPoint  );
	float tf = dot( tex2D( GradientsSampler, float2( rightDownFrontToPoint.x, rightDownFrontToPoint.z ) ), rightDownFrontToPoint );
	float uf = dot( tex2D( GradientsSampler, float2( leftUpFrontToPoint.x,    leftUpFrontToPoint.z    ) ), leftUpFrontToPoint    );
	float vf = dot( tex2D( GradientsSampler, float2( rightUpFrontToPoint.x,   rightUpFrontToPoint.z   ) ), rightUpFrontToPoint   );

	// calculate the curve value with respect to X used in the linear interpolation
	float sX = sCurve( position.x, gX0 );

	// linear interpolate over t and s
	float ab = lerp( sX, sb, tb );
	float af = lerp( sX, sf, tf );

	// linear interpolate over u and v
	float bb = lerp( sX, ub, vb );
	float bf = lerp( sX, uf, vf );

	// calculate the curve value with respect to Y
	float sY = sCurve( position.y, gY0 );

	// linear interpolate with respect to Y-axis
	float cb = lerp( sY, ab, bb );
	float cf = lerp( sY, af, bf );

	// calculate the curve value with respect to Z-axis
	float sZ = sCurve( position.z, gZ0 );

	// linear interpolation with respect to Z-axis
	float val = lerp( sZ, cb, cf );

	// return the noise value
	return val;

Can anybody spot what to change in this? Maybe it is the way I look up gradients? If so then how can I do it such that it will always return the same gradients at the same position? Hope somebody can help me Best Regards

Share this post

Link to post
Share on other sites
breaking your shader down into basic parts might be a useful strategy - chances are you've got a single term that's repeating and that has a knock-on effect. Using 'PIX for Windows' pixel history feature might well give you some insight.

This Nvidia page contains an HLSL implementation of Perlin's Noise function - have you considered copy-n-pasting that just as a reference?


Share this post

Link to post
Share on other sites
Well I tried to use the nVidia sample instead and this result in an error that I have previously experienced. It tries to compile the shader for a while then spams the output channel with

maximum temp register index exceeded

This is why I tried switching to the texture lookup instead of a const array approach in the first place.

What causes this issue and what can I do to remove this issue? I have tried to google it, but can not find anything information that really helps me on the subject.

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!