2012-03-30 9 views
1

私は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でした。

編集:私はローダーを書き直し

(上記のコードは更新された)が、私はまだ同じライン上でクラッシュを取得します。行で

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); 

はまた、ここでのスクリーンショットは、その代わりにクラッシュした、時々私は(同じエラーメッセージは、私が正しくリコールされる)mlock.cにクラッシュを取得しますアプリケーションがクラッシュしない当時の1(テクスチャは右、明らかではありません): http://i.stack.imgur.com/4Mtso.jpg

EDIT2:

新しいコードでコードを更新しました。 (応答としてマークされた応答には、これが動作するために必要なものすべてが含まれているわけではありませんでしたが、重要でした)

+0

そのメモリ位置は、初期化されていないポインタを示すものではないようです...私の次の推測は、OpenGLが 'data'の境界を越えて読み込もうとしていることです。正しいデータ量を指定していることを確認できますか? – kevintodisco

+0

これはC++よりCのように見える – Pubby

+0

@ktodiscoデータサイズは実際には正しいです。 – zeluisping

答えて

2

私が知っている、それがこの

BitmapHeader header; 
BitmapInfoHeader dibheader; 
/*...*/ 
// Read header. 
fread(&header, sizeof(BitmapHeader), 1, file); 

// Read info header. 
fread(&dibheader, sizeof(BitmapInfoHeader), 1, file); 

のようなバイナリデータを読み込むために魅力的ですが、あなたは本当にそのようにすべきではありません。どうして?構造体のメモリレイアウトは、配置制約を満たすために埋め込まれる可能性があるため(使用するコンパイラの型サイズはバイナリファイルのデータサイズと一致しない可能性があります) 。

常にバイナリデータを中間バッファに読み込み、正確に指定されたオフセットと型付けで明確に定義された方法でフィールドを抽出します。

// Allocate memory for the image data. 
data = (unsigned char*)malloc(dibheader.dataSize); 

これがC++の場合は、new演算子を使用します。これがCの場合は、void *からL値の型にキャストしないでください。スタイルが悪く、便利なコンパイラの警告が表示される可能性があります。 dataがNULLである

// Verify memory allocation. 
if (!data) 
{ 
    free(data); 

場合、あなたはそれを解放してはなりません。

// Swap R and B because bitmaps are BGR and OpenGL uses RGB. 
for (unsigned int i = 0; i < dibheader.dataSize; i += 3) 
{ 
    B = data[i]; // Backup Blue. 
    data[i] = data[i + 2]; // Place red in right place. 
    data[i + 2] = B; // Place blue in right place. 
} 

OpenGLは確かにBGRアラインメントをサポートします。フォーマットパラメータは、GL_BGR

// Generate texture image. 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dibheader.width, dibheader.height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 

まあ驚きであり、これはピクセルストアパラメータのすべて設定ミス。ピクセル転送を行う前に、必ずピクセルストアパラメータをすべて設定してください。以前の操作から望ましくない状態になっている可能性があります。転ばぬ先の杖。

+0

私はずっと前にGL_BGRを試しました、私はちょうど未定義のエラーを取得します。 いずれにしても、ローダーを書き直しました。新しいコードで質問を更新します(別のエラーが時々発生します)。 – zeluisping

+0

@ 100GPing100:GL_BGRはOpenGL-1.1の後に導入されたので、それを使用するには拡張ヘッダが必要です。私はGLEWを推奨しますが、そのトークンのためにすべての関数ポインタを初期化する必要はありません。 – datenwolf

+0

私は実際にglewを使用しています(最初の投稿に記載されています)。 タイプをインポートする必要がありますか? (C#のように、dllから関数をインポートする必要がある場合) – zeluisping

6

glTexImage2D()コールの前にglPixelStorei(GL_UNPACK_ALIGNMENT, 1)を試してみてください。

+0

私はすでにそれを試したことに言及するのを忘れました。画像は24bpp 512x512です。同じエラーでクラッシュしました(もう一度試しました)。 – zeluisping

関連する問題