OpenGl,glUseProgram() 返回 GL_INVALID_VALUE 即使着色器的 ID 是正确的 [重复]
Posted
技术标签:
【中文标题】OpenGl,glUseProgram() 返回 GL_INVALID_VALUE 即使着色器的 ID 是正确的 [重复]【英文标题】:OpenGl, glUseProgram() returns GL_INVALID_VALUE even the shader's ID is right [duplicate] 【发布时间】:2019-10-15 15:53:38 【问题描述】:我正在尝试使用 ASSIMP 库在 OpenGl/GLEW/GLFW 中创建模型加载器。我的问题是我在主循环 的 第二次 迭代中 glUseProgram()
收到 GL_INVALID_VALUE
错误 (我已经设置了宏,名为 GLCall
这会破坏调试 glGetError
返回一些东西)。
这里有一些代码使上下文更清晰:
绘制模型的主循环中的代码,第一次运行良好,model.Draw()
第二次出现错误
model_shader.Bind();
glm::mat4 View = inputCompute(deltaTime, window);
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float)CONFIG::WINDOW_WIDTH / (float)CONFIG::WINDOW_HEIGHT, 0.1f, 100.0f);
glm::mat4 Model = glm::translate(glm::mat4(1.0f), lampPosition) * glm::translate(glm::mat4(1.0f), transVectorControl(deltaTime, window)) * glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f));
glm::mat4 mvp = Projection * View * Model;
model_shader.SetUniformMat4f("u_MVP", mvp);
model.Draw(model_shader);
model_shader.Unbind();
所以我认为函数 model.Draw()
必须对着色器的 id 做一些事情,但在这里它实际上只读取着色器的 id。
这是model.Draw()
函数(它是Mesh
类的成员):
void Mesh::Draw(Shader shader)
// bind appropriate textures
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
unsigned int normalNr = 1;
unsigned int heightNr = 1;
for (unsigned int i = 0; i < textures.size(); i++)
GLCall(glActiveTexture(GL_TEXTURE0 + i)); // active proper texture unit before binding
// retrieve texture number (the N in diffuse_textureN)
std::string number;
std::string name = textures[i].type;
if (name == "texture_diffuse")
number = std::to_string(diffuseNr++);
else if (name == "texture_specular")
number = std::to_string(specularNr++); // transfer unsigned int to stream
else if (name == "texture_normal")
number = std::to_string(normalNr++); // transfer unsigned int to stream
else if (name == "texture_height")
number = std::to_string(heightNr++); // transfer unsigned int to stream
// now set the sampler to the correct texture unit
GLCall(glUniform1i(glGetUniformLocation(shader.getID(), (name + number).c_str()), i));
// and finally bind the texture
GLCall(glBindTexture(GL_TEXTURE_2D, textures[i].id));
// draw mesh
GLCall(glBindVertexArray(VAO));
GLCall(glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0));
GLCall(glBindVertexArray(0));
// always good practice to set everything back to defaults once configured.
GLCall(glActiveTexture(GL_TEXTURE0));
如您所见,着色器的 id 只是被读取,而不是被写入。
我实际上检查了第二次 ID 与执行 model.Draw()
之前相同。该模型实际上是在主循环的第二次迭代之前绘制的。
我尝试从glUseProgram()
中删除错误检查,但是glUniform()
给了我关于没有绑定着色器的错误。
【问题讨论】:
我敢打赌,着色器程序对象在Shader
类的析构函数中被销毁。在Draw
中使用引用参数:void Mesh::Draw(Shader &shader)
并阅读OpenGL object in C++ RAII class no longer works
@Rabbid76 我想过,但是着色器在int main()
中被实例化,所以它在程序退出之前是“活动的”。我按照你的建议做了,还是不行
@Rabbid76 好吧,请原谅我的收入,正如我所说,我仍然是初学者,通过参考并没有做任何工作。
@Rabbid76 但这一切都无关紧要,因为我在 int main()
和 mes.Draw()
中绑定着色器只将着色器作为参数来使用其 Id
@Rabbid76 我必须承认你是对的,我忘记了我通过另一个类调用了Mesh.Draw()
,我不得不将所有参数切换为通过引用传递。请原谅我脾气这么轻。感谢您帮助我解决问题!
【参考方案1】:
解决这个问题的方法非常简单,我只是传递了 ID 而不是整个着色器,它工作得很好。通过引用传递着色器也解决了这个问题。
【讨论】:
以上是关于OpenGl,glUseProgram() 返回 GL_INVALID_VALUE 即使着色器的 ID 是正确的 [重复]的主要内容,如果未能解决你的问题,请参考以下文章