Java 3DGame LWJGL Chapter4〜シェーダについて〜

イントロダクション

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

前回は、Chapter3をやりました。

今回は、前回やったプログラムの続きです。前回はプログラムの全体的な流れを見ていきましたので、今回は詳細部分描画処理を見ていきます、前回示した目玉の部分です。

Introduction

LWJGL We will understand GitBook ‘s chapter while shooting. Git (source) is here. . . Last time I did Chapter 3 so We will do Chapter 4 this time.

Last time. we have larned rough processing of this program.This time we will learn sight of this program.

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

シェーダについて

ShaderProgramクラスについて学びます。このクラスはRendererクラスから呼ばれていますので、そこから追いかけます。

Renderer#init()

        shaderProgram = new ShaderProgram();
        shaderProgram.createVertexShader(Utils.loadResource("/vertex.vs"));
        shaderProgram.createFragmentShader(Utils.loadResource("/fragment.fs"));
        shaderProgram.link();

LWJGLフレームワークの部品GL20のメソッド「glCreateProgram」を呼び出しています。

ShaderProgram

    public ShaderProgram() throws Exception {
        programId = glCreateProgram();
        if (programId == 0) {
            throw new Exception("Could not create Shader");
        }
    }

ここでの注意点は、赤字のメソッドがメソッド内のコードだけでは「どのクラスのメソッドかわからない」と言うことです。

結論から言うと「import static」しているので呼び出すことが可能です。

import static org.lwjgl.opengl.GL20.*;

そして、参照しているドキュメントには以下の様な記述があります。

    1. OpenGLプログラム(空のオブジェクト)を作成する:glCreateProgram
    2. 頂点とフラグメントのシェーダコードファイルをロードします。
        • シェーダを定義します:glCreateShaderSource
        • シェーダをコンパイル(実行できる様にします。上で定義した時のIDでコンパイルする様です。:glCompileShader
    3. 各シェーダーについて、新しいシェーダープログラムを作成し、そのタイプ(頂点、フラグメント)を指定します:glCreateShaderSource
    4. シェーダをコンパイルします。:glCompileShader
    5. シェーダをプログラムに接続します。:glAttachShader
    6. プログラムをリンクします。:glLinkProgram
public class ShaderProgram {

    private final int programId;

    private int vertexShaderId;

    private int fragmentShaderId;

    public ShaderProgram() throws Exception {
        /* 1.OpenGLプログラム(空のオブジェクト)を作成する */
        programId = glCreateProgram();
        if (programId == 0) {
            throw new Exception("Could not create Shader");
        }
    }
    /*新しいシェーダープログラムを作成 */
    public void createVertexShader(String shaderCode) throws Exception {
        /*空のシェーダを作成(Vertex(点用)) */
        vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
    }
    /*新しいシェーダープログラムを作成 */
    public void createFragmentShader(String shaderCode) throws Exception {
        /*空のシェーダを作成(フラグメント用))*/
        fragmentShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
    }

    protected int createShader(String shaderCode, int shaderType) throws Exception {
        /* 空のシェーダを作成 */
        int shaderId = glCreateShader(shaderType);
        if (shaderId == 0) {
            throw new Exception("Error creating shader. Type: " + shaderType);
        }
        /*頂点とフラグメントのシェーダコードファイルをロード */
        glShaderSource(shaderId, shaderCode);
        /*シェーダをコンパイル */
        glCompileShader(shaderId);
        /* コンパイルができたか確認する */
        if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) {
            throw new Exception("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024));
        }
        /* シェーダとプログラムとを関連付ける(アタッチする) */
        glAttachShader(programId, shaderId);

        return shaderId;
    }

    public void link() throws Exception {
        /* */
        glLinkProgram(programId);
        if (glGetProgrami(programId, GL_LINK_STATUS) == 0) {
            throw new Exception("Error linking Shader code: " + glGetProgramInfoLog(programId, 1024));
        }

        if (vertexShaderId != 0) {
            /* アタッチの反対を行います*/
            glDetachShader(programId, vertexShaderId);
        }
        if (fragmentShaderId != 0) {
            glDetachShader(programId, fragmentShaderId);
        }
     /* シェーダプログラムが使用可能かチェックする */
        glValidateProgram(programId);
        if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
            System.err.println("Warning validating Shader code: " + glGetProgramInfoLog(programId, 1024));
        }

    }

    public void bind() {
        /* シェーダプログラムをインストール(実行じゅんびOK状態にする) */
        glUseProgram(programId);
    }

    public void unbind() {
        /* シェーダプログラムを解放する */
        glUseProgram(0);
    }

    public void cleanup() {
        unbind();
        if (programId != 0) {
            /* シェーダプログラムの破棄 */
            glDeleteProgram(programId);
        }
    }
}

<補足>
フラグメントシェーダプログラム

#version 330

out vec4 fragColor;

void main()
{
	fragColor = vec4(0.0, 0.5, 0.5, 1.0);
}

Vertexシェーダプログラム

#version 330

layout (location =0) in vec3 position;

void main()
{
	gl_Position = vec4(position, 1.0);
}

シェーダプログラムに関しては触れていなかったので、ちょいと保留します。

今回は、ここまでにしておきます。