从侧面剪裁 OpenGL 顶点
OpenGL Vertices being clipped from the side
我将我的顶点裁剪到边缘,如这张专辑所示:
当我的地形大小为 400 x 400 时,我得到裁剪,但在 40x40 或更小时,我没有得到任何裁剪。
这是我填充位置和索引的代码:
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;
}
}
这正确地设置了我的位置,我用 GL_POINTS 测试过它。它适用于 400x400 和 40x40 以及介于两者之间的其他值。
索引代码:
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 是 std::vector。我不确定是什么原因造成的,但我很确定这是我为网格填充索引的方式。我重写了我的算法,它最终得到了相同的结果,小值工作得很好,超过 ~144 的大值被剪掉了。我这样填充缓冲区:
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);
}
我的抽奖电话:
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();
}
我以为是因为我对模型进行了转换,所以我删除了所有转换,结果是一样的。我尝试通过投射 glm::vec3 to_string 进行调试,但数据看起来不错,我的 projectionMatrix 是:
glm::perspective(glm::radians(_fov), _aspRatio, 0.1f, 1000.0f);
所以我怀疑剪辑是我的视角。 _aspRatio 是 16/9。
很奇怪,它适用于小行x列而不是大行,我真的不确定问题出在哪里。
我会检查 _vertexPosition
的长度;我怀疑问题是你(取决于 _rows
的数量)在你的内部循环(以及你的外部循环,取决于 _columns
)的末尾生成一个额外的点。
原因是顶点循环的终止条件取决于浮点数学的确切行为。具体来说,您将范围 [-1,1] 划分为 _rows
段,然后将它们相加并将它们用作终止测试。目前尚不清楚您是否期望最终点(每个内部循环产生 _rows+1
点)或不期望(产生不覆盖整个 [-1,1] 范围的矩形)。不幸的是,浮点数并不精确,因此这是导致不可靠行为的秘诀:根据浮点数错误的方向,您可能会得到一个或另一个。
对于更多的 _rows
,您将更多(并且明显更小)的数字添加到相同的初始值;这会加重你的浮点错误。
无论如何,为了获得可靠的行为,您应该使用整数循环变量来确定循环终止。分别累加你的浮点坐标,这样就不需要精确了。
我将我的顶点裁剪到边缘,如这张专辑所示:
当我的地形大小为 400 x 400 时,我得到裁剪,但在 40x40 或更小时,我没有得到任何裁剪。 这是我填充位置和索引的代码:
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;
}
}
这正确地设置了我的位置,我用 GL_POINTS 测试过它。它适用于 400x400 和 40x40 以及介于两者之间的其他值。 索引代码:
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 是 std::vector。我不确定是什么原因造成的,但我很确定这是我为网格填充索引的方式。我重写了我的算法,它最终得到了相同的结果,小值工作得很好,超过 ~144 的大值被剪掉了。我这样填充缓冲区:
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);
}
我的抽奖电话:
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();
}
我以为是因为我对模型进行了转换,所以我删除了所有转换,结果是一样的。我尝试通过投射 glm::vec3 to_string 进行调试,但数据看起来不错,我的 projectionMatrix 是:
glm::perspective(glm::radians(_fov), _aspRatio, 0.1f, 1000.0f);
所以我怀疑剪辑是我的视角。 _aspRatio 是 16/9。
很奇怪,它适用于小行x列而不是大行,我真的不确定问题出在哪里。
我会检查 _vertexPosition
的长度;我怀疑问题是你(取决于 _rows
的数量)在你的内部循环(以及你的外部循环,取决于 _columns
)的末尾生成一个额外的点。
原因是顶点循环的终止条件取决于浮点数学的确切行为。具体来说,您将范围 [-1,1] 划分为 _rows
段,然后将它们相加并将它们用作终止测试。目前尚不清楚您是否期望最终点(每个内部循环产生 _rows+1
点)或不期望(产生不覆盖整个 [-1,1] 范围的矩形)。不幸的是,浮点数并不精确,因此这是导致不可靠行为的秘诀:根据浮点数错误的方向,您可能会得到一个或另一个。
对于更多的 _rows
,您将更多(并且明显更小)的数字添加到相同的初始值;这会加重你的浮点错误。
无论如何,为了获得可靠的行为,您应该使用整数循环变量来确定循环终止。分别累加你的浮点坐标,这样就不需要精确了。