Hey guys, I need your help again if somebody here would kindly help me out.
I recently loaded my very first terrain using a heightmap image for the first time. It worked great! However, I noticed some strange line segments that are being drawn from the top of the terrain stretching all the way down to the very bottom. I will post images of this below so you could see what I mean, I will also link you the resource I used to generate my terrain (which is really just 1 YouTube video) here: " rel="external" style="background-color:#fafafa;color:#5381ac;font-size:13px;text-align:left;">
I'd be very thankful if somebody could review the code with me and help me identify the problem...
Oddly enough, the person in the YouTube video seemed to have had a very similar (if not the exact same) problem I am having at 18:38 but he fixed it by adding one simple thing which I also added but didn't do the trick for me Also he is using the fixed function pipeline to demonstrate the technique, I am using the programmable pipeline for better performance. Anyway, here is the result of my terrain:
As you can see, I also have grass (very awful looking grass too :p) on top of my terrain while playing around with the geometry shader the other day.
Here is how I am loading the heightmap, and here is where I believe the problem lies:
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.\n";
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[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[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
}
Then, this is how I'm simply drawing the terrain to the scene:
void TerrainLoader::Draw()
{
glBindVertexArray(m_VAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (m_HeightmapWidth - 1) * (m_HeightmapHeight - 1) * 4);
}
Alright, I hope that's enough information for someone to help me figure out the issue with this...
Thank you very much for taking the time to read my thread, I really appreciate it! Enjoy your day!