似乎在我的调用glBufferSubData
之间覆盖或以某种方式破坏数据。glDrawArrays
我正在使用 Nvidia GeForce GT520M CUDA 1GB 的最新驱动程序在 Windows 7 64 位中工作。
我有 2 个模型,每个模型都有一个动画。这些模型有 1 个网格,并且该网格存储在同一个 VAO 中。它们每个也有 1 个动画,用于渲染网格的骨骼变换存储在同一个 VBO 中。
我的工作流程如下所示:
- 计算模型的骨骼变换矩阵
- 使用 将骨骼转换矩阵加载到 opengl 中
glBufferSubData
,然后绑定缓冲区 - 使用渲染模型网格
glDrawArrays
对于一个模型,这是有效的(至少,大多数情况下——有时我会在顶点之间出现奇怪的间隙)。
然而,对于不止一个模型,看起来骨骼变换矩阵数据在对网格的渲染调用之间混杂在一起。
我像这样加载我的骨骼转换数据:
void Animation::bind()
{
glBindBuffer(GL_UNIFORM_BUFFER, bufferId_);
glBufferSubData(GL_UNIFORM_BUFFER, 0, currentTransforms_.size() * sizeof(glm::mat4), ¤tTransforms_[0]);
bindPoint_ = openGlDevice_->bindBuffer( bufferId_ );
}
我像这样渲染我的网格:
void Mesh::render()
{
glBindVertexArray(vaoId_);
glDrawArrays(GL_TRIANGLES, 0, vertices_.size());
glBindVertexArray(0);
}
如果我在调用 toglFinish()
之后添加一个调用render()
,它就可以正常工作!这似乎向我表明,出于某种原因,一个动画的变换矩阵数据正在“流血”到下一个动画。
这怎么可能发生?我的印象是,如果我glBufferSubData
在使用该缓冲区时调用(glDrawArrays
例如),那么它会阻塞。不是这样吗?
值得一提的是,同样的代码在 Linux 中也能正常工作。
注意:与之前的帖子有关,我已删除。
网格加载代码:
void Mesh::load()
{
LOG_DEBUG( "loading mesh '" + name_ +"' into video memory." );
// create our vao
glGenVertexArrays(1, &vaoId_);
glBindVertexArray(vaoId_);
// create our vbos
glGenBuffers(5, &vboIds_[0]);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[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, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[1]);
glBufferData(GL_ARRAY_BUFFER, textureCoordinates_.size() * sizeof(glm::vec2), &textureCoordinates_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[2]);
glBufferData(GL_ARRAY_BUFFER, normals_.size() * sizeof(glm::vec3), &normals_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[3]);
glBufferData(GL_ARRAY_BUFFER, colors_.size() * sizeof(glm::vec4), &colors_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, 0);
if (bones_.size() == 0)
{
bones_.resize( vertices_.size() );
for (auto& b : bones_)
{
b.weights = glm::vec4(0.25f);
}
}
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[4]);
glBufferData(GL_ARRAY_BUFFER, bones_.size() * sizeof(VertexBoneData), &bones_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(4);
glVertexAttribIPointer(4, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)(sizeof(glm::ivec4)));
glBindVertexArray(0);
}
动画 UBO 设置:
void Animation::setupAnimationUbo()
{
bufferId_ = openGlDevice_->createBufferObject(GL_UNIFORM_BUFFER, Constants::MAX_NUMBER_OF_BONES_PER_MESH * sizeof(glm::mat4), ¤tTransforms_[0]);
}
其中Constants::MAX_NUMBER_OF_BONES_PER_MESH
设置为 100。
在OpenGlDevice
:
GLuint OpenGlDevice::createBufferObject(GLenum target, glmd::uint32 totalSize, const void* dataPointer)
{
GLuint bufferId = 0;
glGenBuffers(1, &bufferId);
glBindBuffer(target, bufferId);
glBufferData(target, totalSize, dataPointer, GL_DYNAMIC_DRAW);
glBindBuffer(target, 0);
bufferIds_.push_back(bufferId);
return bufferId;
}