我在写一个使用OpenGL(freeglut和glew)的应用程序。C++ OpenGL glTexImage2D访问冲突
我也想要纹理,所以我做了一些关于位图文件格式的研究,并为主标题和另一个DIB标题(信息标题)写了一个结构。
然后我开始写装载机。它会自动将纹理绑定到OpenGL。下面是函数:
static unsigned int ReadInteger(FILE *fp)
{
int a, b, c, d;
// Integer is 4 bytes long.
a = getc(fp);
b = getc(fp);
c = getc(fp);
d = getc(fp);
// Convert the 4 bytes to an integer.
return ((unsigned int) a) + (((unsigned int) b) << 8) +
(((unsigned int) c) << 16) + (((unsigned int) d) << 24);
}
static unsigned int ReadShort(FILE *fp)
{
int a, b;
// Short is 2 bytes long.
a = getc(fp);
b = getc(fp);
// Convert the 2 bytes to a short (int16).
return ((unsigned int) a) + (((unsigned int) b) << 8);
}
GLuint LoadBMP(const char* filename)
{
FILE* file;
// Check if a file name was provided.
if (!filename)
return 0;
// Try to open file.
fopen_s(&file, filename, "rb");
// Return if the file could not be open.
if (!file)
{
cout << "Warning: Could not find texture '" << filename << "'." << endl;
return 0;
}
// Read signature.
unsigned char signature[2];
fread(&signature, 2, 1, file);
// Use signature to identify a valid bitmap.
if (signature[0] != BMPSignature[0] || signature[1] != BMPSignature[1])
{
fclose(file);
return 0;
}
// Read width and height.
unsigned long width, height;
fseek(file, 16, SEEK_CUR); // After the signature we have 16bytes until the width.
width = ReadInteger(file);
height = ReadInteger(file);
// Calculate data size (we'll only support 24bpp).
unsigned long dataSize;
dataSize = width * height * 3;
// Make sure planes is 1.
if (ReadShort(file) != 1)
{
cout << "Error: Could not load texture '" << filename << "' (planes is not 1)." << endl;
return 0;
}
// Make sure bpp is 24.
if (ReadShort(file) != 24)
{
cout << "Error: Could not load texture '" << filename << "' (bits per pixel is not 24)." << endl;
return 0;
}
// Move pointer to beggining of data. (after the bpp we have 24 bytes until the data)
fseek(file, 24, SEEK_CUR);
// Allocate memory and read the image data.
unsigned char* data = new unsigned char[dataSize];
if (!data)
{
fclose(file);
cout << "Warning: Could not allocate memory to store data of '" << filename << "'." << endl;
return 0;
}
fread(data, dataSize, 1, file);
if (data == NULL)
{
fclose(file);
cout << "Warning: Could no load data from '" << filename << "'." << endl;
return 0;
}
// Close the file.
fclose(file);
// Create the texture.
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //NEAREST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, data);
return texture;
}
我知道,位图的数据被正确读取,因为我输出它的数据到控制台,并用油漆打开图像相比。
这里的问题是这一行:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dibheader.width,
dibheader.height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
大多数我跑这条线与错误的应用程序崩溃的时代:
Unhandled exception at 0x008ffee9 in GunsGL.exe: 0xC0000005: Access violation reading location 0x00af7002.
这是发生错误的拆卸:
movzx ebx,byte ptr [esi+2]
这不是我的装载机的错误,因为我已经下载了其他装载机。 我使用的下载的加载程序是NeHe的this one。
编辑:(以上代码修订版)
我改写了装载机,但我仍然可以在同一行的崩溃。而不是崩溃,有时我得到(同样的错误消息是我记错)上mlock.c崩溃:
void __cdecl _lock (
int locknum
)
{
/*
* Create/open the lock, if necessary
*/
if (_locktable[locknum].lock == NULL) {
if (!_mtinitlocknum(locknum))
_amsg_exit(_RT_LOCK);
}
/*
* Enter the critical section.
*/
EnterCriticalSection(_locktable[locknum].lock);
}
就行了:
EnterCriticalSection(_locktable[locknum].lock);
而且,这里是一个截屏那个时代的应用程序不会崩溃的一个(纹理显然是不正确的): http://i.stack.imgur.com/4Mtso.jpg
EDIT2:
更新后的代码与新的工作。 (答复标记为答案,不包含,需要为这样工作,但它是至关重要的)
该内存位置似乎不是一个指示未初始化指针的位置......我的下一个猜测是OpenGL试图超出数据范围来读取数据。你能否验证你是否指定了正确的数据量来读取? – kevintodisco 2012-03-30 21:21:45
这看起来更像是C而不是C++ – Pubby 2012-03-30 21:26:42
@ktodisco数据大小实际上是正确的。 – zeluisping 2012-03-30 21:52:59