Danny G
Danny G

Reputation: 61

OpenGL how to use texture maps in shaders

I have a scene with a heightmap, and two textures loaded: sand.png and sandmap.png. I want to write a shader that will only draw the sand texture in the correct places using sandmap.png.

Here is my draw method: (glClear is called elsewhere)

void Terrain::Draw(OGLRenderer& r)
{
    r.BindShader(shader);
    r.UpdateShaderMatrices();
    r.SetTextureRepeating(sand, true);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, sand);
    glUniform1i(glGetUniformLocation(shader->GetProgram(), "sandTex"), 0);

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, sandMap);
    glUniform1i(glGetUniformLocation(shader->GetProgram(), "sandMap"), 1);

    terrainHeightMap->Draw();   
}   

The textures and shader are loaded in elsewhere like so:

terrainHeightMap = new HeightMap(TEXTUREDIR"islandmap.PNG");

sand = SOIL_load_OGL_texture(TEXTUREDIR"sand.PNG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS);

sandMap  = SOIL_load_OGL_texture(TEXTUREDIR"sandmap.PNG ", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS);

shader = new Shader(SHADERDIR"terrainVertex.glsl", SHADERDIR"terrainFragment.glsl");

Here is the fragment shader:

#version  330  core

uniform sampler2D sandTex;

uniform sampler2D sandMap;

in Vertex
{
 vec2  texCoord;
} IN;


vec4 getTexture() 
{
    if (texture(sandMap, IN.texCoord ).g >= 0.2) 
    {
        return texture(sandTex, IN.texCoord);
    }
    //return texture(grassTex, IN.texCoord);
   
}

out  vec4  fragColour;

void  main(void)
{
   fragColour = getTexture();
}

The expectation is that most of the heightmap will be black except for the places where the sand is meant to be. However, the entire heightmap is drawn with the sand texture instead:

enter image description here

I can also confirm that I am using the correct path for the sandmap.png by replacing the sand texture with the sandmap.png which draws the sandmap texture instead:

enter image description here

What am I doing wrong here?

Upvotes: 0

Views: 391

Answers (2)

Danny G
Danny G

Reputation: 61

Okay, so the issue here is very silly. Both the sand texture and sand map texture have the same scaling applied. This means that what you see on the second image is the actual size of the map texture, except it is not set to repeat. This means that the actual texture mapping was happening on the very edge of the terrain (it's cut-off in the image). The reason why the rest of the map was painted with the texture is most likely due to undefined behavior in the getTexture function, as pointed out by @Yakov

Upvotes: 0

Yakov Galka
Yakov Galka

Reputation: 72489

Your getTexture function does not return a value if the sand condition fails:

vec4 getTexture() {
    if (texture(sandMap, IN.texCoord ).g >= 0.2) {
        return texture(sandTex, IN.texCoord);
    }
    // ??? what if we reach here ???   
}

I cannot find the exact phrasing in the spec -- but I'm pretty sure that the default would not be 'black' (most likely it's undefined behavior).

Instead you should specify the default color:

vec4 getTexture() {
    if (texture(sandMap, IN.texCoord ).g >= 0.2) {
        return texture(sandTex, IN.texCoord);
    }
    return vec4(0,0,0,1);
}

Upvotes: 1

Related Questions