0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FlashAdvent Calendar 2020

Day 8

Flash Advent Calendar 8日目 - WebGL導入への道のり01 -

Last updated at Posted at 2020-12-15

これまで、Canvas2Dで描画部分を作っていたのですが
やはり、速度面で問題があり、WebGLを導入する事にしました。

とはいえ、全くやった事がないので、何から始めるか悩んだのですが
まずはCanvas2Dの機能をラッピングする事からはじめて見ました。

が、そんな簡単な話ではなかったので、何日かに分けて掲載できればと思います。
ますは、基盤を作っていこうかと思います。

目次

  • Programを作る
  • Shaderで必要なUniformを動的に取得する

Programを作る

ProgramにセットするShaderは後日記載できればと思います。
なので、Shaderがある程で書いていきます。


/**
 * @param {WebGLRenderingContext} gl
 * @constructor
 * @public
 */ 
constructor (gl) 
{
    // 他の関数でコンテキスト使えるようにしておき
    this.gl = gl;
}

/**
 * @param  {string} vertex_source
 * @param  {string} fragment_source
 * @return {WebGLProgram}
 * @public
 */ 
createProgram (vertex_source, fragment_source) 
{
    // 新規のprogramを作成
    const program = this.gl.createProgram();

    // 頂点シェーダーを作成
    const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
    this.gl.shaderSource(vertexShader, vertex_source);
    this.gl.compileShader(vertexShader);

    // 頂点シェーダーのエラーを感知する。
    // ただ処理が重いので本番用のビルド時は対象外にする。
    if (!this.gl.getShaderParameter(vertexShader, this.gl.COMPILE_STATUS)) {
        console.log(this.gl.getShaderInfoLog(vertexShader));
    }

    // フラグメントシェーダーを作成
    const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
    this.gl.shaderSource(fragmentShader, fragment_source);
    this.gl.compileShader(fragmentShader);

    // フラグメントシェーダーのエラーを感知する。
    // ただ処理が重いので本番用のビルド時は対象外にする。
    if (!this.gl.getShaderParameter(fragmentShader, this.gl.COMPILE_STATUS)) {
        console.log(this.gl.getShaderInfoLog(fragmentShader));
    }

    // 頂点シェーダーをプログラムにアタッチ
    this.gl.attachShader(program, vertexShader);
    
    // フラグメントシェーダーをプログラムにアタッチ
    this.gl.attachShader(program, fragmentShader);

    // プログラムを起動 
    this.gl.linkProgram(program);

    // プログラムの起動時のエラーを感知する。
    // ただ処理が重いので本番用のビルド時は対象外にする。
    if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
        console.log(this.gl.getProgramInfoLog(program));
    }

    // プログラムを起動した後は不要になるので、デタッチしておく
    this.gl.detachShader(program, vertexShader);
    this.gl.detachShader(program, fragmentShader);

    // デタッチ後は削除して綺麗にしておく
    this.gl.deleteShader(vertexShader);
    this.gl.deleteShader(fragmentShader);
    
    return program;
}

これで、汎用的にプログラムを生成させる事ができます。

Shaderで必要なUniformを動的に取得する

Shaderで記載したUniformを毎回個別に書くのは大変なので
生成したプログラムから必要なUniformやpositionなどを動的に取得する。


/**
 * @param {WebGLProgram}
 * @public
 */
createUniform (program) 
{
    const uniformInfo = {};

    // シェーダーで使ってるUniformを取得
    const activeUniforms = this.gl.getProgramParameter(program, this.gl.ACTIVE_UNIFORMS);
    for (let idx = 0; idx < activeUniforms; idx++) {

        // Uniformの情報をセット
        // 変数名や引き渡しに必要な関数を動的に取得する
        const info  = this.gl.getActiveUniform(program, idx);
        const names = info.name.split(".");

        // 配列の変数も扱えるようにする
        const name = (names[0].endsWith("[0]")) 
            ? names[0].slice(0, -3) 
            : names[0];
        
        const block    = {};
        block.location = this.gl.getUniformLocation(program, name);
        block.type     = info.type;

        // typeから必要な関数に対して、positionをセットする
        switch (info.type) {

            case this.gl.FLOAT:
                block.method = this.gl.uniform1f;
                break;
            // ...他の関数も同様にセットしていく。
        }

        uniformInfo[name] = block;
    }
    
    return uniformInfo;
}

途中の処理を省いてますが、最終的にシェーダーで利用するUniformの命名はu_変名で運用する。
これで、最低限必要な引き渡しの環境は整ったので、次はシェーダー側への引き渡し部分を記載できたらと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?