イントロダクション
LWJGL GitBookのChapterを写経しながら理解していきます。Git(ソース)はこちら。。。
前回は、Chapter7-1をやりました。
今回は前回作詞したCubeにテクスチャを貼り付けます。
コードを読む(Read Code)
今までに見て来た部分は割愛します。
- Chapter1[外枠の表示のみ]
- Chapter2-1〜クラスの構成〜
- Chapter2-2〜インターフェースの使い方と詳細〜
- Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
- Chapter2-4〜Windowクラス(サンプルクラス)〜
- Chapter3〜描画処理を読む〜
- Chapter4〜シェーダについて〜
- Chapter5-1〜レンダリングについて〜
- Chapter5-2〜レンダリング詳細〜
- Chapter6〜Projection(投影)〜
- 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 #PGボックスhttps://t.co/IGbZqtEhE2 pic.twitter.com/1pSiQPbEIx
— たくのじ (@java_takunoji) October 30, 2018
中身を見る
今回は、前回作成した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)までの点に対して順序を指定します。
<頂点イメージ>
<テクスチャとモデルの関係>
<テクスチャ>
テクスチャを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に頂点座標を渡して描画する様です。
- 必要な頂点座標(配列)を用意する
- 各頂点をOpenGLにバインド(結びつける)
- 描画用に使用する値を「シェーダプログラム」に渡す
-
// Create uniforms for world and projection matrices and texture shaderProgram.createUniform("projectionMatrix"); shaderProgram.createUniform("worldMatrix"); shaderProgram.createUniform("texture_sampler");
-
- 描画
の様な順序で処理していました。実際に触って見るのが良いと思います。
Gitにソースアップしています。(上のリンクからもダウンロードできます。)わかりやすい方でどうぞ。
追伸:自分の写経したソースは、resourcesフォルダにfs, vsファイルがあるのでそちらもダウンロードされたし。。。。
次のChapterが楽しみです。
でわでわ。。。