我正在尝试将OpenCV cv::Mat
图像转换为OpenGL纹理(我需要一个指向纹理的GLuint
)。这是我到目前为止的代码,拼凑在众多Google搜索中:
void otherFunction(cv::Mat tex_img) // tex_img is a loaded image
{
GLuint* texID;
cvMatToGlTex(tex_img, texID);
// Operations on the texture here
}
void cvMatToGlTex(cv::Mat tex_img, GLuint* texID)
{
glGenTextures(1, texID);
// Crashes on the next line:
glBindTexture(GL_TEXTURE_2D, *texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img.cols, tex_img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, tex_img.ptr());
return;
}
调用glBindTextures
时会发生崩溃。
我尝试了catch (const std::exception& ex)
和catch (...)
的所有异常的try-catch,但它似乎没有抛出任何东西,只是让我的程序崩溃。
如果我正在做任何明显错误的事情,我道歉,这是我第一次使用OpenGL,而且对于我来说,使用C ++还是处于早期阶段。从昨天开始我一直坚持这个。我对OpenGL纹理有一个基本的误解吗?如有必要,我愿意对代码进行重大修改。我正在运行Ubuntu 16.04,如果它改变了什么。
答案 0 :(得分:2)
好的,这就是发生的事情:
void otherFunction(cv::Mat tex_img)
{
GLuint* texID; // You've created a pointer but not initialised it. It could be pointing
// to anywhere in memory.
cvMatToGlTex(tex_img, texID); // You pass in the value of the GLuint*
}
void cvMatToGlTex(cv::Mat tex_img, GLuint* texID)
{
glGenTextures(1, texID); // OpenGL will dereference the pointer and write the
// value of the new texture ID here. The pointer value you passed in is
// indeterminate because you didn't assign it to anything.
// Dereferencing a pointer pointing to memory that you don't own is
// undefined behaviour. The reason it's not crashing here is because I'll
// bet your compiler initialised the pointer value to null, and
// glGenTextures() checks if it's null before writing to it.
glBindTexture(GL_TEXTURE_2D, *texID); // Here you dereference an invalid pointer yourself.
// It has a random value, probably null, and that's
// why you get a crash
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img.cols, tex_img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, tex_img.ptr());
return;
}
解决此问题的一种方法是将指针分配给GLuint,如:
GLuint* texID = new GLuint; // And pass it in
这对初学者有用,但你应该小心你如何解决这个问题。任何分配了新内容的东西都必须通过调用删除来删除,否则你将泄漏内存。智能指针一旦超出范围就会自动删除它。
你也可以这样做:
GLuint texID;
cvMatToGlTex(tex_img, &texID);
请记住,虽然GLuint texID的生命周期只在你声明它的那个函数中,因为它是一个局部变量。我不确定有什么更好的方法可以做到这一点,因为我不知道你的程序是什么样的,但至少应该让崩溃消失。