Hello everybody, I am new here.
Nobody likes lengthy posts so I will try to keep it very brief while making sure you understand the problem I am facing.
I recently loaded my very first terrain using a heightmap for the first time, it was one of the greatest things I’ve ever done in computer graphics so far. I noticed some strange line segments that are being drawn from the top of the terrain stretching all the way down to the bottom and basically ruining it. I’d be very thankful if somebody here could review the code with me and help me identify the problem. I will also link you the resource I used to generate my terrain, I only used this person’s YouTube tutorial: OpenGL tutorial 21 - heightmap - YouTube
Oddly enough, he seemed to have had the same problem I am having at 18:38 but he fixed it by adding one simple thing which I later added but didn’t fix it for me. Also, he is using the fixed function pipeline whereas I am using the programmable pipeline for better performance.
Here is the result of my terrain:
[ATTACH=CONFIG]1566[/ATTACH]
Closer look at the unwanted line segments:
[ATTACH=CONFIG]1567[/ATTACH]
[ATTACH=CONFIG]1568[/ATTACH]
As you can see, I also have grass (very awful looking grass :p) on top of it.
Here is how I am loading the heightmap, and here is where I believe the problem is:
void TerrainLoader::LoadHeightmapImage(const char* file)
{
// Load the bitmap
m_pImage = SDL_LoadBMP(file);
Uint32 Pixel = 0;
// Check for errors
if (m_pImage == nullptr)
{
std::cerr << "error: Heightmap image could not be loaded.
";
return;
}
// Get bitmap's width and height
m_HeightmapHeight = m_pImage->h;
m_HeightmapWidth = m_pImage->w;
// Read the bitmap (stores in this 2D STL vector of floats: vector<vector<float> > m_vHeights;)
std::vector<float> tmp;
for (int i = 0; i < m_HeightmapHeight; ++i)
{
for (int j = 0; j < m_HeightmapWidth; ++j)
{
Pixel = ((Uint32*)m_pImage->pixels)[i * m_pImage->pitch / 4 + j];
unsigned char r, g, b;
SDL_GetRGB(Pixel, m_pImage->format, &r, &g, &b);
tmp.push_back((float)r / 255.0);
}
m_vHeights.push_back(tmp);
tmp.clear();
}
SDL_FreeSurface(m_pImage);
float h = 0.4f, terrainSize = 0.005f;
std::vector<glm::vec3> Vertices;
std::vector<glm::vec2> Textures;
for (int i = 0; i < m_vHeights.size() - 1; ++i)
{
for (int j = 0; j < m_vHeights.size() - 1; ++j)
{
// Put the vertices and texture coordinates in their respective buffers
Textures.push_back(glm::vec2(0.0f, 0.0f));
Vertices.push_back(glm::vec3(i * terrainSize, m_vHeights[i][j] * h, j * terrainSize));
Textures.push_back(glm::vec2(1.0f, 0.0f));
Vertices.push_back(glm::vec3((i + 1) * terrainSize, m_vHeights[i + 1][j] * h, j * terrainSize));
Textures.push_back(glm::vec2(1.0f, 1.0f));
Vertices.push_back(glm::vec3(i * terrainSize, m_vHeights[i][j + 1] * h, (j + 1) * terrainSize));
Textures.push_back(glm::vec2(0.0f, 1.0f));
Vertices.push_back(glm::vec3((i + 1) * terrainSize, m_vHeights[i + 1][j + 1] * h, (j + 1) * terrainSize));
}
}
// Send the data to the GPU
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glGenBuffers(1, &m_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, Vertices.size() * sizeof(glm::vec3), &Vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glGenBuffers(1, &m_VBO[1]);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO[1]);
glBufferData(GL_ARRAY_BUFFER, Textures.size() * sizeof(glm::vec2), &Textures[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// This concludes the function
}
Here is simply how I am drawing the terrain:
void TerrainLoader::Draw()
{
glBindVertexArray(m_VAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (m_HeightmapWidth - 1) * (m_HeightmapHeight - 1) * 6);
}
I hope somebody can tell me what the issue here is and how I can fix this.
Thank you so much for taking the time to read my thread.