私は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);
glTexImageの3番目のパラメータである "format"は1ピクセルあたりのバイト数ではありません。歴史的に、値1,2,3,4はOpenGL-1.0によって受け入れられました。 OpenGL-1以降。1以降では、formatパラメータは、GL_RGBA、GL_RGBなどのように実際のフォーマットとは関係のない明確に定義されたトークンのみを受け入れます。 – datenwolf
"OpenGL初期化"の概念を忘れてください。はい、テクスチャや素材を読み込みますが、実際のアプリケーションではこれは一度だけではありませんが、必要に応じて実行されます。すべての描画状態、すなわち投影、クリアカラー、ビューポートなどは、レンダリング手順で必要とされる直前に設定する必要があります。 「OpenGL初期化コード」セクションに配置したすべてのものは、「レンダリングコード」セクションの先頭に属します。 – datenwolf
@datenwolf:得点。あなたの最初のコメントに関して、私が使用していたドキュメントは古いものでなければならないので、代わりにOpenGL enum値の1つを使用するように呼び出しを更新します。 2番目のコメントに関しては、私の特定のアプリでは、投影、ビューポートなどのようなものをinitコードにまとめるのが適切だと思います。ハードウェアアクセラレーションによる2D描画が可能です)。私は間違いなくあなたのポイントを参照してください。 – jgottula