Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


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.

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

#1 Ardan   Members   -  Reputation: 138

Like
1Likes
Like

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

Attached Thumbnails

  • TerrainTest.png


Sponsor:

#2 kauna   Crossbones+   -  Reputation: 2753

Like
0Likes
Like

Posted 08 March 2014 - 11:38 AM

Can you show your shader code? 

 

Cheers!



#3 3TATUK2   Members   -  Reputation: 730

Like
0Likes
Like

Posted 08 March 2014 - 12:20 PM

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



#4 Ardan   Members   -  Reputation: 138

Like
1Likes
Like

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



#5 mark ds   Members   -  Reputation: 1400

Like
0Likes
Like

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.


#6 Ardan   Members   -  Reputation: 138

Like
0Likes
Like

Posted 08 March 2014 - 04:12 PM

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



#7 L. Spiro   Crossbones+   -  Reputation: 14032

Like
4Likes
Like

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
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#8 Ardan   Members   -  Reputation: 138

Like
0Likes
Like

Posted 09 March 2014 - 02:10 PM

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



#9 Ashaman73   Crossbones+   -  Reputation: 7872

Like
4Likes
Like

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



#10 L. Spiro   Crossbones+   -  Reputation: 14032

Like
2Likes
Like

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
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#11 Ohforf sake   Members   -  Reputation: 1832

Like
0Likes
Like

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;

}


#12 dave j   Members   -  Reputation: 595

Like
0Likes
Like

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.

#13 dave j   Members   -  Reputation: 595

Like
0Likes
Like

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

#14 Ardan   Members   -  Reputation: 138

Like
0Likes
Like

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.



PARTNERS