Reputation: 15
Im trying to texture my terrain but it seems to be either taking the average color of the texture of just picking one color from the texture and using it everywhere. I have looked at other solutions but they havent help me. I am new so it could be a simple mistake
The textures are generated from SOIL2
Generates Texture
int texID = SOIL_load_OGL_texture(
filename.c_str(),
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
Generates UV coordinates (removed the not important stuff for my question)
int i=0;
for (int z = 0; z < m_Size; z++) // loop through columns
{
for (int x = 0; x < m_Size; x++) // loop through rows
{
model.mesh.uvs[i] = Math::Vector2(x / m_Size, z / m_Size); //Terrain is square
i++;
}
}
Creates Texture buffer
if (model->mesh.numOfUVs != 0)
{
glGenBuffers(1, &model->textureBufferID);
glBindBuffer(GL_ARRAY_BUFFER, model->textureBufferID);
glBufferData(GL_ARRAY_BUFFER, model->mesh.numOfUVs * sizeof(Math::Vector2), model->mesh.uvs, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Math::Vector2), (void*)(0));
}
Drawing the terrain (not full code)
glBindVertexArray(ID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, model->textureID1);
unsigned int textureLocation = glGetUniformLocation(shaderID, "grassTex");
glUniform1i(textureLocation, 0);
glUniformMatrix4fv(glGetUniformLocation(shaderID, "MVP"), 1, false, &newMVP.mat[0][0]);
glDrawElements(GL_TRIANGLES, model->mesh.numOfIndices, GL_UNSIGNED_INT, (void*)0);
glBindVertexArray(0);
Vert Shader
#version 330 core
layout(location = 0) in vec2 texturecoord;
uniform mat4 MVP;
out vec2 texcoord;
void main(){
texcoord = texturecoord;
gl_Position = MVP * vec4(in_position, 1);
}
Frag Shader
#version 330 core
layout(location = 0) out vec4 out_colour;
in vec2 texcoord;
uniform sampler2D grassTex;
void main()
{
out_colour = texture2D(grassTex, texcoord);
}
If something doesnt make sense it might be because i have removed a lot of code to try reduce how much code i post
what it looks like(theres 3 textures in the pic but i have removed the code in this post as i dont think it has anything to do with the number of textures im using) https://i.sstatic.net/kPfWt.jpg
Upvotes: 0
Views: 280
Reputation: 5341
The problem is integer division. When you divide integers, you get an integer. This is where you're generating UV coordinates.
for (int z = 0; z < m_Size; z++) // loop through columns
{
for (int x = 0; x < m_Size; x++) // loop through rows
{
model.mesh.uvs[i] = Math::Vector2(x / m_Size, z / m_Size); //Terrain is square
i++;
}
}
x
and z
are always smaller than m_Size
. This means that x / m_Size
and z / m_Size
are always 0
because you can't store 0.2
in an int
. Since all of your UV coordinates are 0, 0
, you're just seeing one corner (I think it's bottom-left) of the texture across the whole triangle.
To solve this, cast one of the operands to a float
or double
.
model.mesh.uvs[i] = Math::Vector2(
static_cast<float>(x) / m_Size,
static_cast<float>(z) / m_Size
);
If you divide a float
by an int
, the int
is promoted to a float
so float
division will be performed.
Upvotes: 1