Search code examples
c++openglopengl-3

OpenGL Vertices being clipped from the side


I'm having my vertices clipped on the edged as shown on this album:

https://i.sstatic.net/a03e7.jpg

When my terrain size if 400 x 400 i get clipping, yet at 40x40 or anything less, i don't get any clipping. This is my code to fill the position and indices:

void Terrain::fillPosition()
{
  //start from the top right and work your way down to 1,1
  double x = -1, y = 1, z = 1;
  float rowValue = static_cast<float>((1.0f / _rows) * 2.0); // .05 if 40
  float colValue = static_cast<float>((1.0f / _columns) * 2.0); // .05 if 40

 for (y; y > -1; y -= colValue)
 {
    for (x; x < 1; x += rowValue)
    {
        _vertexPosition.emplace_back(glm::vec3(x, y, z));
    }
    x = -1;
 }
}

This properly sets my position, I've tested it with GL_POINTS. It works fine at 400x400 and 40x40 and other values in between. Index code:

void Terrain::fillIndices()
{
    glm::ivec3 triangle1, triangle2;
    for (int y = 0; y < _columns - 1; y++)
    {
        for (int x = 0; x < _rows - 1; x++)
        {
            // Triangle 1
            triangle1.x = x       + y       * _rows;
            triangle1.y = x       + (y + 1) * _rows;
            triangle1.z =(x + 1)  + y       * _rows;
            // Triangle 2
            triangle2.x = triangle1.y;
            triangle2.y = (x + 1) + (y + 1) * _rows;
            triangle2.z = triangle1.z;

            // add our data to the vector
            _indices.emplace_back(triangle1.x);
            _indices.emplace_back(triangle1.y);
            _indices.emplace_back(triangle1.z);

            _indices.emplace_back(triangle2.x);
            _indices.emplace_back(triangle2.y);
            _indices.emplace_back(triangle2.z);
        }
    }
}

_indices is std::vector.I'm not sure what's causing this, But I'm pretty sure it's the way I'm filling the indices for the mesh. I've re-written my algorhithm and it ends up with the same result, small values work perfectly fine, and large values over ~144 get clipped. I fill my buffers like this:

void Terrain::loadBuffers()
{
    // generate the buffers and vertex arrays
    glGenVertexArrays(1, &_vao);
    glGenBuffers(1, &_vbo);
    glGenBuffers(1, &_ebo);
    // bind the vertex array
    glBindVertexArray(_vao);
    // bind the buffer to the vao
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, _vertexPosition.size() * sizeof(_vertexPosition[0]), _vertexPosition.data(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(_indices[0]), _indices.data(), GL_STATIC_DRAW);
    // enable the shader locations
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
    // unbind our data
    glBindVertexArray(0);
}

and my draw call:

void Terrain::renderTerrain(ResourceManager& manager, ResourceIdTextures id)
{
    // set the active texture
    glActiveTexture(GL_TEXTURE0);
    // bind our texture
    glBindTexture(GL_TEXTURE_2D, manager.getTexture(id).getTexture());
    _shaders.use();
    // send data the our uniforms
    glUniformMatrix4fv(_modelLoc, 1, GL_FALSE, glm::value_ptr(_model));
    glUniformMatrix4fv(_viewLoc, 1, GL_FALSE, glm::value_ptr(_view));
    glUniformMatrix4fv(_projectionLoc, 1, GL_FALSE, glm::value_ptr(_projection));
    glUniform1i(_textureLoc, 0);
    glBindVertexArray(_vao);
    // Draw our terrain;
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_INT, 0);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glBindVertexArray(0);
    _shaders.unuse();
}

I thought it was because of my transformations to the model, so i removed all transformations and it's the same result. I tried debugging by casting the glm::vec3 to_string but the data looks fine, My projectionMatrix is:

glm::perspective(glm::radians(_fov), _aspRatio, 0.1f, 1000.0f);

So i doubt it's my perspective doing the clipping. _aspRatio is 16/9.

It's really strange that it works fine with small rowsxcolumns and not large ones, I'm really not sure what the problem is.


Solution

  • I would check the length of _vertexPosition; I suspect the problem is that you are (depending on the number of _rows) generating an extra point at the end of your inner loop (and your outer loop too, depending on _columns).

    The reason is that the termination condition of your vertex loops depends on the exact behavior of your floating point math. Specifically, you divide up the range [-1,1] into _rows segments, then add them together and use them as a termination test. It is unclear whether you expect a final point (yielding _rows+1 points per inner loop) or not (yielding a rectangle which doesn't cover the entire [-1,1] range). Unfortunately, floating point is not exact, so this is a recipe for unreliable behavior: depending on the direction of your floating point error, you might get one or the other.

    For a larger number of _rows, you are adding more (and significantly smaller) numbers to the same initial value; this will aggravate your floating point error.

    At any rate, in order to get reliable behavior, you should use integer loop variables to determine loop termination. Accumulate your floating point coordinates separately, so that exact accuracy is not required.