1
votes

I have been trying to implement a heightmap to my terrain shader, but the terrain remains flat. The texture is properly loaded in the vertex shader, and I try to use the greyscale values of the texture based on the mesh's uvs to adjust the vertex height:

//DIFFUSE VERTEX SHADER
#version 330 

uniform mat4    projectionMatrix;
uniform mat4    viewMatrix;
uniform mat4    modelMatrix;

in vec3 vertex;
in vec3 normal;
in vec2 uv;

uniform sampler2D heightmap;

out vec2 texCoord;

void main( void ){

vec3 _vertex = vertex;
_vertex.y = texture(heightmap, uv).r * 2.f;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(_vertex, 1.f);
texCoord = uv;

}

Fragment: (the splatmap works so ignore that)

uniform sampler2D splatmap;
uniform sampler2D diffuse1;
uniform sampler2D diffuse2;
uniform sampler2D diffuse3;
uniform sampler2D diffuse4;

in vec2 texCoord;
out vec4 fragment_color;

void main( void ) {
///Loading the splatmap and the diffuse textures
vec4 splatTexture = texture2D(splatmap, texCoord);
vec4 diffuseTexture1 = texture2D(diffuse1, texCoord);
vec4 diffuseTexture2 = texture2D(diffuse2, texCoord);
vec4 diffuseTexture3 = texture2D(diffuse3, texCoord);
vec4 diffuseTexture4 = texture2D(diffuse4, texCoord);
//Interpolate between the different textures using the splatmap's rgb values (works)
diffuseTexture1 *= splatTexture.r;
diffuseTexture2 = mix (diffuseTexture1, diffuseTexture2, splatTexture.g);
diffuseTexture3 = mix (diffuseTexture2,diffuseTexture3, splatTexture.b);
vec4 outcolor = mix (diffuseTexture3, diffuseTexture4, splatTexture.a);

fragment_color = outcolor;

}

Some additional info: All textures are loaded like this in my terrain material and passed to the shader (works properly):

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, heightMap->getId());
glUniform1i (_shader->getUniformLocation("heightMap"),0);
...

The plane mesh uvs are mapped like this:

(0,1) (1,1)

(0,0) (1,0)

I guess I am doing something horribly wrong, but I can't figure out what. Any help is appreciated!

1
What is the purpose of _vertex? You set _vertex.y but after that you never use it again.Mukesh Ingham
I'm sorry, it's supposed to say _vertex instead of vertex at GL_position. I forgot to editPossimpible
You should try finding a random height generation function and try that instead of the texture map. That way you can see whether its the texture map or the gl_Position that's causing the problem.Mukesh Ingham
Why don't you create a mesh once of your heightmap and passing the vertices to your shader instead of recalculating the y value of each vertex forever?eldo
That would cause me to write an additional mesh loader specifically for my heightmap. The current way is a way I found in several tutorials and should do the job. I'm not saying it's the most flexible way, but I want to find out why it does not work.Possimpible

1 Answers

4
votes

Does your writing this:

The plane mesh uvs are mapped like this:

(0,1) (1,1)

(0,0) (1,0)

… mean that your mesh consists of just 4 vertices? If so, then that's your problem right there: The Vertex shader can not magically create "new" vertices, so your heightmap texture is sampled at only 4 points (and nothing in between).

And because you sample the texture coordinates at integer values and your texture coordinates and are at 0 and 1, you're effectively sampling the very same texture coordinate, so you're going to see the same displacement for all four vertices.

Solution: Tesselate your base mesh so that there are actually vertices available to displace. A tesselation shader is perfectly fine for that.

EDIT:

BTW, you can simplyfiy your vertex shader a bit: For the attributes make it a

in vec2 vertex;

which requires just 2/3 of the space of vec3, since you're not using the z component anyway.

float y = texture(heightmap, uv).r * 2.f;
gl_Position =
    projectionMatrix
  * viewMatrix
  * modelMatrix
  * vec4(vertex.x, y, vertex.y, 1.f);