ねむみ高まる

文章力がないので、文章を書く練習をしています。

【OpenGL/GLUT】raw画像をテクスチャマッピングすると上下反転した

テクスチャマッピングの知識があまりない状態でGLUTテクスチャマッピングをやってみたら、何故か画像が上下反転しました。

f:id:nemumitakamaru:20181224111825p:plain

上下反転するソースコード

#include <stdio.h>
#include <windows.h>
#include <GL/gl.h>
#include <GL/glut.h>

namespace {
const int TEX_SIZE = 256;
const int WINDOW_SIZE = 256;

GLubyte pixels[TEX_SIZE][TEX_SIZE][4];
GLuint texName;
}

void disp()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, texName);

    glBegin(GL_POLYGON);
    {
        // 間違っていた箇所
        glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f);
    }
    glEnd();
    glFlush();
}

int main(int argc, char ** argv)
{
    FILE *fp;

    errno_t error = fopen_s(&fp, "miya.data", "rb");
    if (error != 0) {
        return -1;
    }

    fread(pixels, sizeof pixels, 1, fp);
    fclose(fp);

    glutInit(&argc, argv);
    glutInitWindowSize(WINDOW_SIZE, WINDOW_SIZE);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);

    glutCreateWindow("テクスチャマッピング");
    glutDisplayFunc(disp);

    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glutMainLoop();

    glDeleteTextures(1, &texName);

    return 0;
}

uv座標は左下が原点のはずなので、頂点をその順に対応させて貼り付ければ大丈夫なはずでは…と思っていたのですがそんなことはありませんでした。

ぐーぐる先生で検索をかけてみると、床井先生のサイトで下記のような説明を見つけました。
床井研究室 - 第2回 テクスチャの割り当て

ただし,画像の原点(画像ファイルの最初の画素)の位置は通常画像の左上隅ですが,テクスチャ空間上では原点はテクスチャの左下にあるので,このプログラムの方法で画像を読み込んだ場合,画像は上下反転した形で読み込まれています.ポリゴンの頂点にテクスチャ座標を割り当てるときは,このことを考慮に入れる必要があります.たとえば,上図のように四角形ポリゴンの全面にテクスチャを貼り付けようとしたとき,ポリゴンの左下の頂点 (-1, -1, 0) に対応するテクスチャ座標は,テクスチャの左上 (0, 1) になります.

画像を普通に読み込むと上下反転するんですね。
結局のところ、正確には違いますが、uv座標も左上原点と考えると実装するときはわかりやすい気がします。

というわけで、頂点を指定している箇所のみ下記のように変更すると、反転せずに表示することができました。

glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, -1.0f);

f:id:nemumitakamaru:20181224113910p:plain

画像は下記のゲームのものを使わせていただきました(美也可愛い)。
アマガミ ちょっとおまけ劇場 EX3