Reputation: 61
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:
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:
What am I doing wrong here?
Upvotes: 0
Views: 391
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
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