イントロダクション
前々回、惨敗を喫してしまったのでリベンジきめます。前回は3次元描画ではなく2次元描画にレベルを落として動かしてみました。PNGファイルを読んでいるところまでは、確認できているのですが。。。そのあと描画するときに指定する座標に関してはまるで判らない状態なのでそこを解決しようと思います。
デバック方法
- まずはコードを見直す
- 想定通りの結果を得るための処理として正しいか、否か?
- 原因を探る
- 解決策を打つ
参照するドキュメント:LWJGL GitBookのChapterのChapter5
カスタムするコード:LWJGL GitBook Chapter5
座標に関して(ソースを見直す)
ソースコード上では以下のようになっています。
<DummyGame#createFloor()>
/** * 床のような土台のメッシュ(3Dモデル)を作成します * @return GameItem 床型のメッシュ */ private GameItem createFloor() { float[] positions = new float[]{ // V0 0.0f, 0.25f, 0.0f, // V1 -0.0f, -0.0f, 0.0f, // V2 0.5f, -0.0f, 0.0f, // V3 0.5f, 0.25f, 0.0f,}; int[] indices = new int[]{ 0, 1, 3, 3, 1, 2,}; // 追記 2018/10/27 float[] textCoord = new float[] { 0.5f, 0.0f, 0.0f, //V0の色(赤(R)) 0.0f, 0.5f, 0.0f, // V1の色(緑(G)) 0.0f, 0.0f, 0.5f, // V2の色(青(B)) 0.8f, 0.8f, 0.0f,}; // V3の色(黄) return new GameItem(new Mesh(positions, indices, textCoord)); }
上記の赤字部分が理解できていない部分です。ここの部分は、元々色を指定していた部分です。変数名が「colour」から「textCoords」に変わっただけです。
現状の理解は、上のコードにあるように各頂点の色を指定している認識です。実行結果もそのようになりました。
これがTextureに変わることで下のようになってしまいました。
ちょっとホラーな感じがします(自分だけ?)
調査開始(正しい処理か?否か?)
まずは、未着手部分→シェーダについて調べます。現状のシェーダは以下のようになっています。
<Renderer#init()>
public void init() throws Exception { shaderProgram = new ShaderProgram(); shaderProgram.createVertexShader(Utils.loadResource("/vertex5.vs")); shaderProgram.createFragmentShader(Utils.loadResource("/fragment5.fs")); shaderProgram.link(); }
上のコードから「/vertex5.vs」「/fragment5.fs」を参照していることを確認。
そして、フォルダー構成より以下の階層を確認(ビルドパスには「resources」を追加してあります。
<vertex5.vs>
#version 330 // 追記 2018/10/27 in vec3 exColour; out vec4 fragColor; void main() { fragColor = vec4(exColour, 1.0); }
<fragment5.fs>
#version 330 layout (location =0) in vec3 position; // 追記 2018/10/27 layout(location=1) in vec3 inColour; out vec3 exColour; void main() { gl_Position = vec4(position, 1.0); // 追記 2018/10/27 exColour = inColour; }
以前追加したコードがあるようです。
これで考える材料が揃いました。
処理を追いかけます。参照するコードはイントロダクション部分にリンクがあるのでそちらをご覧ください。
- Main#main(): DummyGame, GameEngineをインスタンス化してGameEngine#satrt()を起動
- DummyGameのコンストラクタ: Rendererクラスのインスタンス化→フィールドで保持
- GameEngineのコンストラクタ: 自分自身をスレッド化してWindowクラスのインスタンス化、DummyGame(インターフェース)をフィールドに保持、Timerクラスをインスタンス化してフィールドに保持
- 「1」でGameEngine#start()が起動される、OSの判定をして結局GameEngine#run()が起動する
- GameEngine#init()とgameLoop()を起動する
- 最後にclearnup()が起動する
- GameEngine#init()でフィールドに保持した「Window」「Timer」「gameLogic(DummyGame)」のinit()を起動する
- 今回は描画部分を調査するのでDummyGame#init()(gameLogic.init())を眺める
- DummyGame#init()ではRenderer#init()とGameItem(Mesh)を作成している
- Renderer#init(): ShaderProgram をインスタンス化、shader, fragmentプログラムを読み込み最後にShapderProgram#link()を起動する
- 「glLinkProgram()」でShaderをインスタンス化したときにフィールドで保持したprogramIdをリンクする(OpenGLのメソッドなので深堀はしないでおく→ハマることが多い)そのほか設定する処理を走らせる。
- 今回の目玉四角形を作成する
そして、ドキュメントを読むと「Meshクラスを変更して、色の代わりにテクスチャ座標を含む浮動小数点数の配列を受け入れるようにします」とあるので単純に「colour」を「textCoords」に変更した状態が今のコードです。
上記の部分を修正して実行してみると。。。
まっくろくろすけでわ、あーりませんか?
試しに背景を白くしてみます。。。とその前に今までのソースは「import static XXXX.GL?」というクラスをstaticでインポートしているのでどのメソッドがどのクラスのメソッドかわからなかったので「static」を消します。
<Rendererクラス>
package zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.game; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; import org.joml.Matrix4f; import zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.engine.Utils; import zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.engine.Window; import zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.engine.graph.GameItem; import zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.engine.graph.Mesh; import zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.engine.graph.ShaderProgram; import zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter5.engine.graph.Transformation; public class Renderer { private ShaderProgram shaderProgram; // 2018/11/08 private Transformation transformation; public Renderer() { transformation = new Transformation(); } public void init() throws Exception { shaderProgram = new ShaderProgram(); shaderProgram.createVertexShader(Utils.loadResource("/vertex5.vs")); shaderProgram.createFragmentShader(Utils.loadResource("/fragment5.fs")); shaderProgram.link(); // 2018/11/08追記 shaderProgram.createUnitform("projectionMatrix"); shaderProgram.createUnitform("worldMatrix"); shaderProgram.createUnitform("texture_sampler"); } public void clear() { GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); } public void render(Window window, GameItem[] gameItems) { clear(); if (window.isResized()) { GL11.glViewport(0, 0, window.getWidth(), window.getHeight()); window.setResized(false); } shaderProgram.bind(); int i = -1; for (GameItem item : gameItems) { // Meshクラスに処理を移動 // // Draw the mesh // glBindVertexArray(item.getMesh().getVaoId()); // glEnableVertexAttribArray(++i); // // 追記 2018/10/27 // glEnableVertexAttribArray(++i); // glDrawElements(GL_TRIANGLES, item.getMesh().getVertexCount(), GL_UNSIGNED_INT, 0); // ワールド座標を設定する Matrix4f worldMatrix = transformation.getWorldMatrix(item.getPosition(), item.getRotation(), item.getScale()); shaderProgram.setUniform("worldMatrix", worldMatrix); item.getMesh().render(); } // Restore state GL20.glDisableVertexAttribArray(0); GL30.glBindVertexArray(0); shaderProgram.unbind(); } public void cleanup() { if (shaderProgram != null) { shaderProgram.cleanup(); } } }
今度は真っ白です、つまり何も描画していないことになります。
※背景の色を変えるのはWindow#colorの値を1.0fにしてやるとできます。
もう何がわからないので、ネットで探します。
色々探してみたが、Textureの座標とMeshの頂点座標の関係がわからない。。。
次は、貼れたテクスチャを解剖してみるかな?
参照するのはChapter7-1です。(Cubeの動画あり)
関連ページ一覧
<今回のやっていること>
<Java Basic>
- Java Basic for文 〜Step1_3_1〜
- Java Basic Level8 〜How to use for statement〜
- Java Basic Level 9〜Training of for statement〜
- Java 3DGame LWJGL GitBook chapter7-1〜Cube作成〜「動画あり」
<サイトマップ>