I have coded a flat terrain made up of triangles, but it seems like there some mirroring occurs. I want it to imitate grass, but it is blurried in some spots. Do I need to add some params in glTexParameteri? Or maybe it is an error which is associated with the drawing code?
A function which reads in a texture:
GLuint Terrain::write_model_texture(const char* filename)
{
GLuint tex;
// Activate texture 0
glActiveTexture(GL_TEXTURE0);
// Read into computers memory
std::vector<unsigned char> image;
unsigned width, height;
// Read the image
unsigned error = lodepng::decode(image, width, height, filename);
// Import to graphics card memory
glGenTextures(1, &tex); //Initialize one handle
glBindTexture(GL_TEXTURE_2D, tex); //Activate handle
// Copy image to graphics cards memory represented by the active handle
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char*)image.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return tex;
}
Also code which draws triangles:
this->P = glm::mat4(1.0f);
this->V = glm::mat4(1.0f);
this->M = glm::mat4(1.0f);
P = in.P;
V = in.V;
//M = glm::rotate(M, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
M = glm::translate(M, glm::vec3(-5.0f, -5.0f, 0.0f));
//M = glm::scale(M, glm::vec3(10.0f, 10.0f, 10.0f));
for (int row = 0; row < terrain_height; row++)
{
int col;
// adding a row of vertices
for (col = 0; col < terrain_width; col++) {
// x, y, z, 1
//std::cout << random_num << std::endl;
terrain_verts.emplace_back(col, row, 0, 1);
terrain_norms.emplace_back(0.0f, 0.0f, 1.0f, 0);
}
// adding a row of indices
for (col = 0; col < terrain_width; col++)
{
terrain_indices.emplace_back(col + row * terrain_width);
terrain_indices.emplace_back(col + row * terrain_width + 1);
terrain_indices.emplace_back(col + terrain_width * (row + 1) - 1);
}
for (col = terrain_width - 1; col >= 0; col--)
{
terrain_indices.emplace_back(col + row * terrain_width);
terrain_indices.emplace_back(col + terrain_width * (row + 1) - 1);
terrain_indices.emplace_back(col + terrain_width * (row + 1));
}
// adding a row of texture coordinates
if (row % 2 == 0)
{
for (col = 0; col < terrain_width; col += 2)
{
terrain_texture_coordinates.emplace_back(0, 0);
terrain_texture_coordinates.emplace_back(1, 0);
}
}
else
{
for (col = 0; col < terrain_width; col += 2)
{
terrain_texture_coordinates.emplace_back(0, 1);
terrain_texture_coordinates.emplace_back(1, 1);
}
}
}
spTextured->use();
glUniformMatrix4fv(spTextured->u("P"), 1, false, glm::value_ptr(P));
glUniformMatrix4fv(spTextured->u("V"), 1, false, glm::value_ptr(V));
glEnableVertexAttribArray(spTextured->a("vertex"));
glEnableVertexAttribArray(spTextured->a("texCoord"));
glEnableVertexAttribArray(spTextured->a("normal"));
glUniformMatrix4fv(spTextured->u("M"), 1, false, glm::value_ptr(M));
glVertexAttribPointer(spTextured->a("vertex"), 4, GL_FLOAT, false, 0, terrain_verts.data());
glVertexAttribPointer(spTextured->a("texCoord"), 2, GL_FLOAT, false, 0, terrain_texture_coordinates.data());
glVertexAttribPointer(spTextured->a("normal"), 4, GL_FLOAT, false, 0, terrain_norms.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(spTextured->u("tex"), 0);
glDrawElements(GL_TRIANGLES, terrain_indices_count(), GL_UNSIGNED_INT, terrain_indices.data());
glDisableVertexAttribArray(spTextured->a("vertex"));
glDisableVertexAttribArray(spTextured->a("color"));
glDisableVertexAttribArray(spTextured->a("normal"));
Your indices do not make the slightest sense:
for (col = 0; col < terrain_width; col++) { terrain_indices.emplace_back(col + row * terrain_width); terrain_indices.emplace_back(col + row * terrain_width + 1); terrain_indices.emplace_back(col + terrain_width * (row + 1) - 1); } for (col = terrain_width - 1; col >= 0; col--) { terrain_indices.emplace_back(col + row * terrain_width); terrain_indices.emplace_back(col + terrain_width * (row + 1) - 1); terrain_indices.emplace_back(col + terrain_width * (row + 1)); }
If you look at your grid of data:
row = 0: 0 --- 1 --- 2 --- 3
| | | |
| | | |
row = 1: 4 --- 5 --- 6 ----7
^ ^ ^ ^
col=0 1 2 3
For row 0, column 0, you generate two triangles with the following vertices:
0, 1, 3
which is a deformed triangle with zero area0, 3, 4
which goes completely across your grid:For inner cells like row=0, col=1, you get:
1, 2, 4
which crosses 2 grid cells1, 4, 5
which is at least belonging to a grid cell (although not the one it should)You can actually see these patterns in your screenshot, you just need to take into account that you draw lots of weirdly overlapping triangles.
Your tex coords also won't work that way. You generate tex coords for alternating rows like this:
row = 0: (0,0) --- (1,0)
| |
| |
row = 1: (0,1) --- (1,1)
| |
| |
row = 2: (0,0) --- (1,0)
If you map texcoords that way, the cells between row 1 and row 2 will have the image vertically mirrored to those between row 0 and 1. You can't share the vertices of a row for the grid cella below and above it that way, you would have to duplicate the row vertices with different texcoords to make that work.
However, that is not necessary as you can use GL_REPEAT
texture wrap mode and simply use texoords outside the [0,1]
range like:
row = 0: (0,0) --- (1,0) --- (2,0)
| | |
| | |
row = 1: (0,1) --- (1,1) --- (2,1)
| | |
| | |
row = 2: (0,2) --- (1,2) --- (2,2)