Java 3DGame LWJGL GitBook chapter7-2〜Texture〜

イントロダクション

LWJGL GitBookChapterを写経しながら理解していきます。Git(ソース)はこちら。。。

前回は、Chapter7-1をやりました。

今回は前回作詞したCubeにテクスチャを貼り付けます。

コードを読む(Read Code)

今までに見て来た部分は割愛します。

  1.  Chapter1[外枠の表示のみ]
  2. Chapter2-1〜クラスの構成〜
  3. Chapter2-2〜インターフェースの使い方と詳細〜
  4. Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
  5. Chapter2-4〜Windowクラス(サンプルクラス)〜
  6. Chapter3〜描画処理を読む〜
  7. Chapter4〜シェーダについて〜
  8. Chapter5-1〜レンダリングについて〜
  9. Chapter5-2〜レンダリング詳細〜
  10. Chapter6〜Projection(投影)〜
  11. Chapter7-1〜Cubeを作る〜

https://ahbejarano.gitbook.io/lwjglgamedev/chapter7

写経前の準備

上のリンクにあるGitBookを読んでみるとMavenでのライブラリ追加に関して記載があります。なのでライブラリの追加(依存関係の追加)を行います。

依存関係の追加(Maven、POMファイル)

上のキャプチャの様にPOMファイルを開きます。

そして、GitBookのページからPOMファイルの記載部分をコピって「ぺっ」ってやります。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  <modelVersion>4.0.0modelVersion>
  <groupId>zenryokuservicegroupId>
  <artifactId>gui.mtmartifactId>
  <version>0.0.1-SNAPSHOTversion>
  <packaging>jarpackaging>
  <name>gui.mtmname>
  <url>http://maven.apache.orgurl>
  <properties>
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
  properties>
  
  <dependencies>
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>3.8.1version>
      <scope>testscope>
    dependency>
    
    <dependency>
         <groupId>org.jomlgroupId>
         <artifactId>jomlartifactId >
         <version>1.9.6version >
    dependency>
    
    <dependency>
      <groupId>org.l33tlabs.twlgroupId>
      <artifactId>pngdecoderartifactId>
      <version>バージョンを記載version>
    dependency>
  dependencies>
project>

上記の様な感じでPOMファイルができると思いますが、「バージョン」に関しては調べる必要あります。今回追加するのは

PNGDecoder

なのでそのサイトへいきバージョンを調べます。

ちょっとわかりづらいけど「1.0」と記載してありました。

上の様にpom.xmlを右クリック→Maven→Maven installでインストール完了です。

そして実行結果は以下の様になりました。

中身を見る

今回は、前回作成したCube(立方体)にテクスチャを貼り付ける作業になります。

ソースの差分を見るのでなく面倒なのでソースをそのまま読みます。

Main: 変化なし(やってることは変わらない)

DummyGame:Textureクラスを生成、Meshクラスに渡す

Texture texture = new Texture("/textures/grassblock.png");
Mesh mesh = new Mesh(positions, textCoords, indices, texture);

GitBookの説明には以下の様にありました。


次のステップは、テクスチャをグラフィックスカードメモリにアップロードすることです。まず、新しいテクスチャ識別子を作成する必要があります。テクスチャに関連する各操作はその識別子を使用するため、バインドする必要があります。

//新しいOpenGLテクスチャを作成する 
int textureId = glGenTextures ; 
//テクスチャをバインドする
glBindTexture GL_TEXTURE_2D textureId ;

次に、RGBAバイトを解凍する方法をOpenGLに伝える必要があります。各コンポーネントのサイズは1バイトなので、次の行を追加する必要があります。

glPixelStorei GL_UNPACK_ALIGNMENT 1 ; 

最後にテクスチャデータをアップロードすることができます:

glTexImage2D GL_TEXTURE_2D, 0, GL_RGBA,cgetWidth, 
    decoder.getHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf; 

Mesh: TextureのVBOのIDを取得して〜とCubeと同じ処理をする

textCoordsBuffer = MemoryUtil.memAllocFloat(textCoords.length);
textCoordsBuffer.put(textCoords).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, textCoordsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

※詳細はChapter5-2を参照してください。

Cubeを作成した時と同様に各頂点(V0〜V7)までの点に対して順序を指定します。

<頂点イメージ>

<テクスチャとモデルの関係>

<テクスチャ>

grassblock

テクスチャをCubeの頂点とOpenGLに結びつけてやる。

        // Load Texture file=>Mavenで追加したライブラリのクラス
        PNGDecoder decoder = new PNGDecoder(Texture.class.getResourceAsStream(fileName));

        // Load texture contents into a byte buffer
        ByteBuffer buf = ByteBuffer.allocateDirect(
                4 * decoder.getWidth() * decoder.getHeight());
        decoder.decode(buf, decoder.getWidth() * 4, Format.RGBA);
        buf.flip();

        // Create a new OpenGL texture 
        int textureId = glGenTextures();
        // Bind the texture
        glBindTexture(GL_TEXTURE_2D, textureId);

        // Tell OpenGL how to unpack the RGBA bytes. Each component is 1 byte size
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        // Upload the texture data
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0,
                GL_RGBA, GL_UNSIGNED_BYTE, buf);
        // Generate Mip Map
        glGenerateMipmap(GL_TEXTURE_2D);

Cubeの頂点とテクスチャの頂点をセットした配列を用意して、OpenGLに結びつける(Bind)

        // Create the Mesh
        float[] positions = new float[] {
            // V0
            -0.5f, 0.5f, 0.5f,
            // V1
            -0.5f, -0.5f, 0.5f,
            // V2
            0.5f, -0.5f, 0.5f,
            // V3
            0.5f, 0.5f, 0.5f,
            // V4
            -0.5f, 0.5f, -0.5f,
            // V5
            0.5f, 0.5f, -0.5f,
            // V6
            -0.5f, -0.5f, -0.5f,
            // V7
            0.5f, -0.5f, -0.5f,
            
            // For text coords in top face
            // V8: V4 repeated
            -0.5f, 0.5f, -0.5f,
            // V9: V5 repeated
            0.5f, 0.5f, -0.5f,
            // V10: V0 repeated
            -0.5f, 0.5f, 0.5f,
            // V11: V3 repeated
            0.5f, 0.5f, 0.5f,

            // For text coords in right face
            // V12: V3 repeated
            0.5f, 0.5f, 0.5f,
            // V13: V2 repeated
            0.5f, -0.5f, 0.5f,

            // For text coords in left face
            // V14: V0 repeated
            -0.5f, 0.5f, 0.5f,
            // V15: V1 repeated
            -0.5f, -0.5f, 0.5f,

            // For text coords in bottom face
            // V16: V6 repeated
            -0.5f, -0.5f, -0.5f,
            // V17: V7 repeated
            0.5f, -0.5f, -0.5f,
            // V18: V1 repeated
            -0.5f, -0.5f, 0.5f,
            // V19: V2 repeated
            0.5f, -0.5f, 0.5f,
        };
        float[] textCoords = new float[]{
            0.0f, 0.0f,
            0.0f, 0.5f,
            0.5f, 0.5f,
            0.5f, 0.0f,
            
            0.0f, 0.0f,
            0.5f, 0.0f,
            0.0f, 0.5f,
            0.5f, 0.5f,
            
            // For text coords in top face
            0.0f, 0.5f,
            0.5f, 0.5f,
            0.0f, 1.0f,
            0.5f, 1.0f,

            // For text coords in right face
            0.0f, 0.0f,
            0.0f, 0.5f,

            // For text coords in left face
            0.5f, 0.0f,
            0.5f, 0.5f,

            // For text coords in bottom face
            0.5f, 0.0f,
            1.0f, 0.0f,
            0.5f, 0.5f,
            1.0f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            8, 10, 11, 9, 8, 11,
            // Right face
            12, 13, 7, 5, 12, 7,
            // Left face
            14, 15, 6, 4, 14, 6,
            // Bottom face
            16, 18, 19, 17, 16, 19,
            // Back face
            4, 6, 7, 5, 4, 7,};

テクスチャをアクティブにする(と思う)

        // Activate firs texture bank
        glActiveTexture(GL_TEXTURE0);

他のクラスは変わりなし。。。多分(実行結果からその様に予測。。。)

まとめ

大まかな流れが読めて来ました。テクスチャもCubeなど3DモデルもOpenGLに頂点座標を渡して描画する様です。

  1. 必要な頂点座標(配列)を用意する
  2. 各頂点をOpenGLにバインド(結びつける)
  3. 描画用に使用する値を「シェーダプログラム」に渡す
    1.         // Create uniforms for world and projection matrices and texture
              shaderProgram.createUniform("projectionMatrix");
              shaderProgram.createUniform("worldMatrix");
              shaderProgram.createUniform("texture_sampler");
  4. 描画

の様な順序で処理していました。実際に触って見るのが良いと思います。

Gitにソースアップしています。(上のリンクからもダウンロードできます。)わかりやすい方でどうぞ。

追伸:自分の写経したソースは、resourcesフォルダにfs, vsファイルがあるのでそちらもダウンロードされたし。。。。

次のChapterが楽しみです。

でわでわ。。。