OpenGL 在多边形上绘制奇怪的线条
OpenGL draws weird lines on top of polygons
让我向您介绍一下 Fishtank:
这是我在进入 Vulkan 之前在 OpenGL 上做的水族馆模拟器。
我画过很多这样的鱼:
水族馆
现在我添加了这样的网格功能:
网格
但是当我让它转动一段时间后,出现这些行:
奇怪的台词
我在某个地方看到可以清除深度缓冲区,我也这样做了,但这并没有解决问题。
函数代码如下:
void Game::drawGrid()
{
std::vector<glm::vec2> gridVertices;
for (unsigned int x = 1; x < mGameMap.mColCount; x += 1) //Include the last one as the drawed line is the left of the column
{
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, x*mGameMap.mCellSize, mGameMap.mCellSize)));
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, x*mGameMap.mCellSize, (mGameMap.mRowCount-1)*mGameMap.mCellSize)));
}
for (unsigned int y = 1; y < mGameMap.mRowCount; y += 1) //Same here but special info needed:
// Normally, the origin is at the top-left corner and the y-axis points to the bottom. However, OpenGL's y-axis is reversed.
// That's why taking into account the mRowCount-1 actually draws the very first line.
{
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, mGameMap.mCellSize, y*mGameMap.mCellSize)));
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, (mGameMap.mColCount - 1)*mGameMap.mCellSize, y*mGameMap.mCellSize)));
}
mShader.setVec3("color", glm::vec3(1.0f));
glBufferData(GL_ARRAY_BUFFER, gridVertices.size()*sizeof(glm::vec2), gridVertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT_VEC2, GL_FALSE, sizeof(glm::vec2), (void*)0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_LINES, 0, gridVertices.size()*sizeof(glm::vec2));
glClear(GL_DEPTH_BUFFER_BIT);
}
我想擦掉这些线条并理解为什么 OpenGL 会这样做(或者可能是我,但我不知道在哪里)。
这是有问题的行:
glDrawArrays(GL_LINES, 0, gridVertices.size()*sizeof(glm::vec2));
如果你查看documentation for this function,你会发现
void glDrawArrays( GLenum mode, GLint first, GLsizei count);
count: Specifies the number of indices to be rendered
但是你传递的是字节大小。因此,您要求 OpenGL 绘制比顶点缓冲区中更多的顶点。您正在使用的特定 OpenGL 实现可能正在读取网格顶点缓冲区的末尾并从鱼顶点缓冲区中找到要绘制的顶点(但此行为未定义)。
所以,只需将其更改为
glDrawArrays(GL_LINES, 0, gridVertices.size());
一般性评论:不要在每次要绘制相同的东西时都创建顶点缓冲区。在应用程序的开头创建它们并重新使用它们。如果需要,您也可以更改它们的内容,但要小心,因为它会带来性能价格。创建顶点缓冲区的成本更高。
让我向您介绍一下 Fishtank:
这是我在进入 Vulkan 之前在 OpenGL 上做的水族馆模拟器。
我画过很多这样的鱼:
水族馆
现在我添加了这样的网格功能:
网格
但是当我让它转动一段时间后,出现这些行:
奇怪的台词
我在某个地方看到可以清除深度缓冲区,我也这样做了,但这并没有解决问题。
函数代码如下:
void Game::drawGrid()
{
std::vector<glm::vec2> gridVertices;
for (unsigned int x = 1; x < mGameMap.mColCount; x += 1) //Include the last one as the drawed line is the left of the column
{
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, x*mGameMap.mCellSize, mGameMap.mCellSize)));
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, x*mGameMap.mCellSize, (mGameMap.mRowCount-1)*mGameMap.mCellSize)));
}
for (unsigned int y = 1; y < mGameMap.mRowCount; y += 1) //Same here but special info needed:
// Normally, the origin is at the top-left corner and the y-axis points to the bottom. However, OpenGL's y-axis is reversed.
// That's why taking into account the mRowCount-1 actually draws the very first line.
{
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, mGameMap.mCellSize, y*mGameMap.mCellSize)));
gridVertices.push_back(glm::vec2(transformToNDC(mWindow, (mGameMap.mColCount - 1)*mGameMap.mCellSize, y*mGameMap.mCellSize)));
}
mShader.setVec3("color", glm::vec3(1.0f));
glBufferData(GL_ARRAY_BUFFER, gridVertices.size()*sizeof(glm::vec2), gridVertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT_VEC2, GL_FALSE, sizeof(glm::vec2), (void*)0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_LINES, 0, gridVertices.size()*sizeof(glm::vec2));
glClear(GL_DEPTH_BUFFER_BIT);
}
我想擦掉这些线条并理解为什么 OpenGL 会这样做(或者可能是我,但我不知道在哪里)。
这是有问题的行:
glDrawArrays(GL_LINES, 0, gridVertices.size()*sizeof(glm::vec2));
如果你查看documentation for this function,你会发现
void glDrawArrays( GLenum mode, GLint first, GLsizei count);
count: Specifies the number of indices to be rendered
但是你传递的是字节大小。因此,您要求 OpenGL 绘制比顶点缓冲区中更多的顶点。您正在使用的特定 OpenGL 实现可能正在读取网格顶点缓冲区的末尾并从鱼顶点缓冲区中找到要绘制的顶点(但此行为未定义)。
所以,只需将其更改为
glDrawArrays(GL_LINES, 0, gridVertices.size());
一般性评论:不要在每次要绘制相同的东西时都创建顶点缓冲区。在应用程序的开头创建它们并重新使用它们。如果需要,您也可以更改它们的内容,但要小心,因为它会带来性能价格。创建顶点缓冲区的成本更高。