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: https://www.youtube.com/watch?v=pAHzHcUXsYA
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:
The unwanted line segments:
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[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
}
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!
↧