• FEATURED

View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

# Weird artifacts with multi layered terrain

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.

13 replies to this topic

### #1Ardan  Members

Posted 08 March 2014 - 10:26 AM

I've implemented a terrain in my application and I wanted to use several textures to render it with. I found a tutorial on the web http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=24 which used 3 textures and transitioned between them.

I've got everything working except that i get weird lines on the heights that the mixing occurs.

What could be the cause of this?

I've attached an image showing the problem

### #2kauna  Members

Posted 08 March 2014 - 11:38 AM

Can you show your shader code?

Cheers!

### #33TATUK2  Members

Posted 08 March 2014 - 12:20 PM

Possibly need a slight offset to your texCoords? Or maybe mipmapping is causing it?

### #4Ardan  Members

Posted 08 March 2014 - 02:13 PM

Oh yes sorry, here it is:

#version 330

out vec4 out_Color;
uniform sampler2D sandTexture;
uniform sampler2D grassTexture;
uniform sampler2D rockTexture;

uniform float TerrainHeight;

//From vertex shader
in vec2 texCoord;
in vec3 normal;
in vec3 position;

vec4 texColor = vec4(0);
float shade;

void main(void)
{
const vec3 light = vec3(0.5, 1, 0.5);
shade = dot(light, normalize(normal));

const float fRange1 = 0.01f;
const float fRange2 = 0.1f;
const float fRange3 = 0.5f;
const float fRange4 = 0.9f;

float fScale = position.y/TerrainHeight;
if(fScale >= 0.0 && fScale <= fRange1)
texColor = texture(sandTexture, texCoord);
else if(fScale <= fRange2)
{
fScale -= fRange1;
fScale /= (fRange2-fRange1);

float fScale2 = fScale;
fScale = 1.0-fScale;

texColor += texture(sandTexture, texCoord)*fScale;
texColor += texture(grassTexture, texCoord)*fScale2;
}
else if(fScale <= fRange3)
texColor = texture(grassTexture, texCoord);
else if(fScale <= fRange4)
{
fScale -= fRange3;
fScale /= (fRange4-fRange3);

float fScale2 = fScale;
fScale = 1.0-fScale;

texColor += texture(grassTexture, texCoord)*fScale;
texColor += texture(rockTexture, texCoord)*fScale2;
}
else
texColor = texture(rockTexture, texCoord);

out_Color = texColor * shade;
}



Basically its the same as the fragment shader in the tutorial

### #5mark ds  Members

Posted 08 March 2014 - 02:41 PM

They look like stitching artefacts to me, not a texturing problem. Are they running north to south, and east to west?

How are you rendering your terrain?

Edited by mark ds, 08 March 2014 - 02:44 PM.

### #6Ardan  Members

Posted 08 March 2014 - 04:12 PM

The problem don't occur when i use a single texture or when just coloring the terrain

### #7L. Spiro  Members

Posted 08 March 2014 - 04:46 PM

The problem is related to the blending of textures somehow.
The artifacts all occur at the same respective heights as they circle the mountain. The bottom artifact is always at the point where the sand begins to fade to grass (look carefully; there is an artifact in the sand as well).
Then when the sand ends completely and grass begins fully.
Then when grass starts to fade to rock, and again when the fading stops and there is only pure rock.

4 bands of artifacts, each at a “blending split”.

I would say it makes it quite obvious where to look for the problem and what the nature of the problem is.

L. Spiro

### #8Ardan  Members

Posted 09 March 2014 - 02:10 PM

Yeah I see where the problem occurs, but I dont understand why.

### #9Ashaman73  Members

Posted 11 March 2014 - 06:41 AM

It might be a numerical problem.

fScale -= fRange1;

fScale /= (fRange2-fRange1);

In this case, if fScale equals to fRange2, you should get 1.0 or 0.0 if it equals fRange1. To ensure that you dont have a numerical precision problem clamp the fScale value to 0.0..1.0.

fScale = clamp(fScale,0.0,1.0);

Ashaman

### #10L. Spiro  Members

Posted 11 March 2014 - 06:27 PM

I was thinking numerical issue too, but not seeing where one could exist based off his code. The values for the ranges are constants on top and seem to be well defined.

I also looked for division by 0 but it seems impossible as well.

Still, a clamp would not hurt.

Also, provide a screenshot of a close-up of one of the artifacts. I need to see one of them up close to get an idea of what type of numerical issue it could be.

L. Spiro

### #11Ohforf sake  Members

Posted 12 March 2014 - 07:00 AM

Maybe this has to do with mipmapping. The hardware selects the mipmap level based on the texture coordinates used in 2x2 pixel groups. This means that it only works, if all the pixels of a 2x2 group sample the same textures. This is exactly not the case for the regions where the artifacts occure.

Maybe, just for testing this hypothesis, you can always sample and mix all textures and set the scaling factor to zero for those that you don't need.

Edit: Like so (Note that this could also be done without branches):
void main(void)
{
const vec3 light = vec3(0.5, 1, 0.5);
shade = dot(light, normalize(normal));

const float fRange1 = 0.01f;
const float fRange2 = 0.1f;
const float fRange3 = 0.5f;
const float fRange4 = 0.9f;

float fScale = position.y/TerrainHeight;

float ScaleSand = 0.0f;
float ScaleGrass = 0.0f;
float ScaleRock = 0.0f;

if(fScale >= 0.0 && fScale <= fRange1)
ScaleSand = 1.0f;
else if(fScale <= fRange2)
{
fScale -= fRange1;
fScale /= (fRange2-fRange1);

float fScale2 = fScale;
fScale = 1.0-fScale;

ScaleSand = fScale;
ScaleGrass = fScale2;

}
else if(fScale <= fRange3)
ScaleGrass = 1.0f;
else if(fScale <= fRange4)
{
fScale -= fRange3;
fScale /= (fRange4-fRange3);

float fScale2 = fScale;
fScale = 1.0-fScale;

ScaleGrass = fScale;
ScaleRock = fScale2;
}
else
ScaleRock = 1.0f;

texColor = texture(sandTexture, texCoord) * ScaleSand +
texture(grassTexture, texCoord) * ScaleGrass +
texture(rockTexture, texCoord) * ScaleRock;

out_Color = texColor * shade;

}


### #12dave j  Members

Posted 12 March 2014 - 11:09 AM

I was thinking numerical issue too, but not seeing where one could exist based off his code. The values for the ranges are constants on top and seem to be well defined.

I also looked for division by 0 but it seems impossible as well.

Still, a clamp would not hurt.

Also, provide a screenshot of a close-up of one of the artifacts. I need to see one of them up close to get an idea of what type of numerical issue it could be.

L. Spiro

If you zoom in on the image you can see that the errors are not contiguous. It also looks like they might be in 2x2 blocks of pixels - most noticeable at the start of the grass to rock transition. There also seems to be two separate lines in the sand.

### #13dave j  Members

Posted 14 March 2014 - 09:41 AM

Thinking more on this, I'm beginning to suspect you might have found a driver bug.

Fragments are rendered as screen aligned quads (2x2 pixels at a time) because it helps optimize texture access, derivatives calculation, z-culling and other things besides. If you zoom in on the errors in the image, you can see that they are in 2x2 pixel quads - the quads also appear aligned on even boundaries which also fits.

I'm wondering if the errors only appear when the four pixels in a quad do not all take the same execution path through the shader. When comfortably within the same range all the quad's pixels will pass/fail the same tests and so take the same path. If some pixels in a quad fall within different ranges they will take different execution paths - which might be the cause of the problem. This would explain why it works most of the time but only fails at the transition between ranges.

The fact that the errors don't always appear might also fit this explanation. Think of a situation where the transition between the layers occurs as a horizontal line. When the line and quads are aligned such that this line passes through a single quad, the pixels will fall within different ranges and follow different execution paths. If the horizontal line falls exactly between two quads, both quads will have all their pixels in the same range/execution path even though the two quads are in different ranges.

Try to rewrite the shader so all pixels follow the same execution paths regardless of the ranges they fall in. (Maybe try Ohforf sake's suggestion of always blend all the textures as a first quick test as this does seem to be texture related).

### #14Ardan  Members

Posted 15 March 2014 - 03:01 AM

Thanks for your suggestions, I will look into all you've said and I'll post back with my results.

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.