2011-02-02 7 views
1

私はSDLとOpenGLをDプログラミング言語で使って2Dゲームを書いています。現時点では、単にテクスチャマッピングされたクワッドを画面にレンダリングしようとします。問題は、全体のテクスチャマッピング部分がうまく動作していないことです。明らかに読み込み中のテクスチャにもかかわらず(ゼロ以外のテクスチャ番号が割り当てられ、glGetErrorがゼロ以外の値を返すことはありません)、クォードはglColorで最後に設定された色でレンダリングされ、テクスチャは完全に無視されます。OpenGLテクスチャマッピングは頑固に拒否します

this questionなどのテクスチャマッピングが失敗する一般的な理由を探しました。ロードされるイメージファイルは64x64で、有効な2の累乗サイズです。

これはD-itのほぼ完全にCスタイルのSDLとOpenGL呼び出しのため、怖がらないでください。

SDL初期化コード:

if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) == -1 || 
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0) == -1) 
    throw new Exception("An OpenGL attribute could not be set!"); 

uint videoFlags = SDL_OPENGL | SDL_HWSURFACE | SDL_ANYFORMAT; 

if (threadsPerCPU() > 1) 
    videoFlags |= SDL_ASYNCBLIT; 

SDL_Surface* screen = SDL_SetVideoMode(800, 600, 32, videoFlags); 

if (screen == null) 
    throw new Exception("SDL_SetVideoMode failed!"); 

OpenGLの初期化コード:

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0., 800, 600, 0., 0., 1.); 
glMatrixMode(GL_MODELVIEW); 

glDisable(GL_DEPTH_TEST); 
glDisable(GL_LIGHTING); 

glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

glEnable(GL_TEXTURE_2D); 

glClearColor(0.f, 0.f, 0.f, 0.f); 

テクスチャローディングコード:

SDL_Surface* s = IMG_Load(toStringz("hello.png")); 

if (s == null) 
    throw new Exception("Image file could not be loaded!"); 

uint texFormat; 

switch (s.format.BytesPerPixel) 
{ 
case 4: 
    texFormat = (s.format.Rmask == 0x000000ff ? GL_RGBA : GL_BGRA); 
    break; 
case 3: 
    texFormat = (s.format.Rmask == 0x000000ff ? GL_RGB : GL_BGR); 
    break; 
default: 
    throw new Exception("Bad pixel format!"); 
    break; 
} 

if ((s.w & (s.w - 1)) != 0) 
    throw new Exception("Width must be a power of 2!"); 
if ((s.h & (s.h - 1)) != 0) 
    throw new Exception("Height must be a power of 2!"); 

uint glName; 

glGenTextures(1, &glName); 

glBindTexture(GL_TEXTURE_2D, glName); 
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
glTexImage2D(GL_TEXTURE_2D, 0, s.format.BytesPerPixel, s.w, s.h, 0, 
    texFormat, GL_UNSIGNED_BYTE, s.pixels); 

SDL_FreeSurface(s); 

レンダリングコード:

glClear(GL_COLOR_BUFFER_BIT); 

glBegin(GL_QUADS); 
    glColor4ub(255, 255, 255, 255); 
    glBindTexture(GL_TEXTURE_2D, glName); 
    glTexCoord2i(0, 0); glVertex2i(0, 0); 
    glTexCoord2i(1, 0); glVertex2i(64, 0); 
    glTexCoord2i(1, 1); glVertex2i(64, 64); 
    glTexCoord2i(0, 1); glVertex2i(0, 64); 
glEnd(); 

SDL_GL_SwapBuffers(); 

私のプログラムではDのSDLとOpenGLバインディングを提供するライブラリであるDerelict2を使用しています。

ここでは何が起こっているのでしょうか?

編集:

http://www.opengl.org/wiki/Common_Mistakes#Creating_a_Texture

私は前glTexImage2Dを呼び出すか、他の私の質感は技術的に不完全であったにカップルのパラメータを設定するために必要な:今後の参考のために、ここで私の問題への解決策です。その呼び出しは、トリックをした直前に、次の4行を追加:

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

glTexImageの3番目のパラメータである "format"は1ピクセルあたりのバイト数ではありません。歴史的に、値1,2,3,4はOpenGL-1.0によって受け入れられました。 OpenGL-1以降。1以降では、formatパラメータは、GL_RGBA、GL_RGBなどのように実際のフォーマットとは関係のない明確に定義されたトークンのみを受け入れます。 – datenwolf

+0

"OpenGL初期化"の概念を忘れてください。はい、テクスチャや素材を読み込みますが、実際のアプリケーションではこれは一度だけではありませんが、必要に応じて実行されます。すべての描画状態、すなわち投影、クリアカラー、ビューポートなどは、レンダリング手順で必要とされる直前に設定する必要があります。 「OpenGL初期化コード」セクションに配置したすべてのものは、「レンダリングコード」セクションの先頭に属します。 – datenwolf

+0

@datenwolf:得点。あなたの最初のコメントに関して、私が使用していたドキュメントは古いものでなければならないので、代わりにOpenGL enum値の1つを使用するように呼び出しを更新します。 2番目のコメントに関しては、私の特定のアプリでは、投影、ビューポートなどのようなものをinitコードにまとめるのが適切だと思います。ハードウェアアクセラレーションによる2D描画が可能です)。私は間違いなくあなたのポイントを参照してください。 – jgottula

答えて

7

よくある間違いは、不完全なテクスチャを作成/使用することです(hereを参照)。任意のミップマップの作成を示していないにも

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR/*or GL_NEAREST*/); 
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*or GL_NEAREST*/); 

と:

あなたのコードでは、への呼び出しを示していません。

テクスチャが不完全である可能性があります。

+0

うわー、あなたは完全に正しいです。リンクされたページにリストされている4行を追加した後、テクスチャは意図したとおりに完全にレンダリングされるようになりました。正しい方向へ私を導いてくれてありがとう! – jgottula

+0

glGetErrorがglTexImage2Dの後に何も表示していないのは不思議です。おそらくその利用可能なエラーコードは、この種のものをカバーしていません。いずれにしても、少なくとも私は今何か働いているので、後にミップマップやその他の変更について心配することができます。 – jgottula

+0

hm glTexImage2Dは、テクスチャの構築に使用されているエラーを示す/検出することはできません。プロセス中に、不完全なテクスチャに対しては「合法」です。おそらく 'glBindTexture'はこれをエラーとして検出できますが、シェーダーと同様に、ミップマップ0でのみテクスチャをサンプリングすると、(テストされていない)動作する可能性があります。この問題によって何度も噛まれてしまえば、それに慣れます;) – rotoglup

0

あなたはpaintGL機能でglOrtho(0., 800, 600, 0., 0., 1.);を必要としないのですか?

+0

私は間違いなくスクリーン上の白い四角形を得ているので、これはそうではありません。 glOrthoの問題は、シーンの位置/方向に関する問題でしょうか? – jgottula

1

ちょうど漠然とした理論です:時計回りではなく反時計回りに頂点を描こうとしましたか?

glTexCoord2i(0, 0); glVertex2i(0, 0); 
glTexCoord2i(0, 1); glVertex2i(0, 64); 
glTexCoord2i(1, 1); glVertex2i(64, 64); 
glTexCoord2i(1, 0); glVertex2i(64, 0); 
+0

方向変更で再コンパイル。同じ取引。 :( – jgottula

+0

glBindTexture呼び出しがテクスチャ読み込みコードに(少なくともそこにある位置で)呼び出される理由はありますか?glTexImage2D呼び出しの後に行くと思っていたでしょう。 – Xono

+0

@ Xono:私が知っているように、 'glBindTexture'呼び出しはOpenGLステートマシンに"現在このテクスチャで作業しています "と言っていますが、' glTexImage2D'呼び出しは現在バインドされているテクスチャに適用する必要があることを暗黙的に理解しています。もし私が間違っていたら、もちろん。 – jgottula

0

GL_COLOR_MATERIALを有効にしてみてください。私はしばらくの間、固定機能のパイプラインを使用していないが、私はそれを行うかもしれないと思う。

+0

私は 'glEnable(GL_COLOR_MATERIAL)'を私の初期コードに追加しましたが、残念ながらそれは役に立たないようです。 – jgottula

関連する問題