Normals very blocky

I have got another question, to go with the flow with the story, i will post it in my old thread.
The terrain rendering is coming along nicely, but im having an problem with interpolating in the shader.

Example (the texturing is not complete, evrything above some value is atomaticly grass, this will get replaced by an noise function):

Bigger version: http://i49.tinypic.com/fyh8i0.png

Im sending an float value using the vbo, telling the shader what points needs to blend:

glVertexAttribPointer(attrib, 1, GL_FLOAT, false, stride, 32);

But because this is for each vertex, it gets blocky like shown above.
Is there an way to smooth this value out for an rounder effect, like with normals (not using splatmaps)?

Corresponding fragment-shader fragment :slight_smile:


    if(t > 1){
        dist = (2-t)*0.6;

        c2 = texture2D(Texture0, vec2(gl_TexCoord[0].x+0.5, gl_TexCoord[0].y));
    	c = mix(c2, c, dist);
    }

  • dirt & grass image are stored in the same texture, hence why im using +0.5 (take part 2 of texture)
    ** mix can also mess up textures with some combinations, need to find some replacement for that one to, but i guess thats easyer then my first problem.

Assuming 1 < t < 2, dist will be between 0 and 0.6. If t <= 1, then the texture doesn’t get mixed. Shouldn’t dist range from 0 to 1?

You are correct when i leave this behind, they are smoother, but are still really pointy.
multiplying by 0.6 exerragates this effect, so its easyer to show :slight_smile:

multiplying with 1.5 gives the best effect, but its still not good enough :frowning:

+1 to what Best Username Ever said.

Also, that’s not how you usually do texture splatting. Let’s say you have 3 different terrain types. 0 is grass, 1 is dirt, 2 is snow and 3 is rock. What if you want to do a transition from dirt to rock or snow to grass? With your code it’s only possible to do smooth transitions between adjacent types, which limits its use case a lot. Instead, I’d recommend using 4 different values, one for each type. Bytes should be enough for it (256 different values). In the fragment shader, just sample all 4 of them (should be cheaper than branching anyway) and blend them based on the 4 values. At all times should the sum of the values equal 1.0 of course, you might have to manually ensure that since the values are interpolated. Anyway, the point is that this will give you fine control over how the terrain types are blended.

Thats clear, since i already had an float array im just using an float for siplicity while testing.
Like you are saying im indeed planning to use some bytes for multiple textures.

But thats not the problem, the problem are the ugly edges.

In your fragment shader code we can only see you sampling from one texture. Can you post the full fragment shader code?

If you scale the boundary between transitions, you still need to normalize the “mix” range. Given the lack of information, there is no way to know the origin of the problem if that is not it. But regardless of what the original issue is, there will be extra artifacts if that problem is not fixed.

No problem, ill remove all normal calls to make it a little more clear what im doing.

Fragment shader:


uniform sampler2D Texture0;
varying float t;

vec4 c, c2;
float dist;

void main()
{   
    c = texture2D(Texture0,gl_TexCoord[0].xy);

    if(t > 1){
        dist = (2-t) * 1.6;

        c2 = texture2D(Texture0, vec2(gl_TexCoord[0].x+0.5, gl_TexCoord[0].y));
    	c = mix(c2, c, dist);
    }
    
    gl_FragColor = vec4(c.xyz, 1);

}

Vertex Shader:


varying float t;
attribute float terrain;

void main()
{
    gl_TexCoord[0] = gl_MultiTexCoord0;	
    gl_Position = ftransform();
    
    t = terrain;
}

So each vertex has an value of the texture (float terrain) and gets passed to the fragment shader (float t).
if t > 1 then mix the second texture on the base texture.
As experiment im trying to merge multiple textures into one (so many textures next to eachother), im just telling this to explain the “missing” textures, it works like it should so dont bother about this :).

However the sampling of the second texture gives very hard edges (dist = (2-t) * 1.6; gives a little smoother effect, but still not good enough).
I think this effect has the same problem as with the normals, since the triangle only has 3 values to interpolate between.
So is there any way to interpolate nicely between those values in the fragment shader like with the normals (from very blocky to perfect round)?

I didnt get the part about normalizing, c is the value passed to gl_FragColor.

Try this code:


uniform sampler2D Texture0;
varying float t;

vec3 getSample(float tValue, vec2 texCoordOffset){
    float weight = max(1 - abs(t - tValue), 0.0);
    return texture2D(Texture0, gl_TexCoord[0].xy + texCoordOffset).xyz * weight;
}

void main()
{
    vec3 samples = getSample(0.0, vec2(0.0, 0.0)); //First sample, same as c before.
    samples += getSample(1.0, vec2(0.5, 0.0));
    //Etc for more different terrain types.

    gl_FragColor = vec4(samples, 1.0);
}

Really awsome, this did the trick.
Also cleaned up my code a great bit haha :slight_smile:
Again i was thinking to much in the wrong direction :(.

Also added some noise to show the new transitions better:

Its really becoming something nice, im learning loads of stuff from you guys, thanks very much again.

Looking good, but be sure too use one byte value per terrain type or you won’t be able to get transitions between all different terrain types. =S

Thank you.
I am indeed going to, but it needs an second buffer am i right?
Since the used buffer is an float buffer, i cant use it to send bytes?

If in the next couple of weeks I don’t throw up something on feature-points…someone poke me with a reminder.

You got me curious.
What are you talking about?

Just use a ByteBuffer and you can mix and match any data type. They have a putFloat() function as well as versions for any data type.

Awsome!

Pah! Easy :persecutioncomplex: