我正在创建一个使用OpenGL管理图像的类。 要加载图像我正在使用SOIL加载PNG。 因为我需要检查碰撞我想获得透明像素。 所以我试图使用:glGetTexImage
来获取数据构造函数加载图像:
Image::Image(string imagePath, unsigned int flags){
this->imagePath=imagePath;
this->pxData=NULL;
texture=SOIL_load_OGL_texture
(
imagePath.c_str(),
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
flags
);
//Use that to subdivide in sprites the texture
glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_HEIGHT, &textureHeight);
glBindTexture(GL_TEXTURE_2D, this->texture);
//cout << "Real Dimensions - " << textureWidth << "-" << textureHeight;
loadPixels(); //multiple instances of image generates error here
}
LoadPixels在我的结构中加载像素数据。
typedef struct PixelData{
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
} PixelData;
PixelData* pxData;
然后在loadPixels中存储该数据:
void Image::loadPixels(){
pxData = new PixelData[textureHeight*textureWidth];
glGetTexImage(GL_TEXTURE_2D, 1, GL_RGBA, GL_UNSIGNED_BYTE , pxData);
}
问题是,如果我创建一个图像:
Image img("/Developer/img.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
工作正常。
如果我创建了很多图片:
Image img("/Developer/img.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img2("/Developer/img2.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img3("/Developer/img3.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img4("/Developer/img4.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img5("/Developer/img5.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img6("/Developer/img6.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img7("/Developer/img7.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img8("/Developer/img8.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img9("/Developer/img9.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
Image img10("/Developer/img10.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
然后我的程序崩溃了:
错误是:
OpenGL Game Engine(35463,0x7fff7b121310) malloc: *** error for object 0x104017808: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
如果我评论glGetTexImage(GL_TEXTURE_2D,1,GL_RGBA,GL_UNSIGNED_BYTE,pxData);它工作正常,所以我想问题不是分配。
我只需要获取像素数据来存储它,我想使用这些像素创建一些数据,所以我需要获得纹理的像素。
注:
如果我取消注释loadPixels,程序会停止在带有sigabort的imagePath.c_str(),如果我对它进行注释,它会加载所有纹理
感谢Audrey我获得了更多信息。
glGetTexLevelParameteriv(GL_TEXTURE_2D, this->texture, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, this->texture, GL_TEXTURE_HEIGHT, &textureHeight);
Real Dimensions - 128-128
Real Dimensions - 64-64
Real Dimensions - 32-32
Real Dimensions - 16-16
它是相同的图像,但尺寸越来越小。
我检查了ID,每次都会创建一个新ID,那么为什么尺寸会变得混乱?
是否有另一种获取数据的方法,我在这里缺少什么? 另一个问题,这个方法获取绑定纹理,有没有办法使用纹理ID获取纹理数据?
答案 0 :(得分:2)
根据评论中的讨论,看起来getGlTexImage
溢出了pxData
缓冲区。如果您发布了给您textureWidth
和textureHeight
的函数输出的内容,我们可能会发现错误。 (例如,你确定getter函数的返回类型和变量textureWidth
等之间的兼容性吗?)
修改:我会检查您的<Gl.h>
以查看函数glGetTexLevelParametersiv
的签名。我在网上浏览了一下,其中微软WINAPI版本的签名与OpenGL.org上的签名不同,并且都不同意您使用的签名。
尝试重新排序并重写:
glBindTexture(GL_TEXTURE_2D, this->texture);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &textureHeight);
答案 1 :(得分:1)
glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_HEIGHT, &textureHeight);
第二个参数不带纹理ID。这是一个mipmap级别。你需要绑定纹理 first ,然后在你放置纹理的地方调用这个函数。
具体来说,您的纹理ID几乎肯定会被实例化为“0”,“1”,“2”等...每次使用连续值调用glGetTexLevelParameteriv
时,您都要求使用较小的mipmap 当前绑定纹理的级别。你的第一次电话没有失败的事实让我怀疑SOIL_load_OGL_texture
实际上并没有在它返回之前解除它。
请记住,几乎没有OpenGL函数将纹理,缓冲区或着色器ID作为参数,而是作用于当前绑定的对象。您通常使用实际ID的唯一函数是创建,销毁或绑定对象的函数,例如glGenTextures
,glDeleteTextures
和glBindTexture