マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

カスタムシェーダーを試してみた

gl.enchant.jsでカスタムシェーダーを使おうとして、前回値が渡せないという事件が起こった。その後、TwitterでSprite3Dの_renderを書き換えればいいと教えてもらい試してみた。それが以下のコード。uniformsに渡したいキーと値のペアを入れればOK。そして試しにSphereとか表示してみると、うまくいったのだが...問題が発生した。それはmqo.gl.enchant.jsで読み込んだモデルにはシェーダーが適用されてなかった。

なぜかと思いソースを読んでみると、モデルはSprite3Dの下にさらにSprite3Dを作っていた。そしてgl.enchant.jsではSprite3D毎にシェーダーがあるか確認してた。そこで気づく。一番上のSprite3Dにしてシェーダーを設定してないことに(でも親のSprite3Dのシェーダーを子供に渡してもらいたいものだが...)。そこでgl.enchant.jsを改造して、子供に親のシェーダーを渡すように修正し。無事モデルも表示された。めでたしめでたし。

カスタムシェーダーで描画した銃のモデル(普通のLambertシェーダー)モデル配布元

Sprite3Dの書き換え部分(gl.enchant.js 0.3.5用)

enchant();

Sprite3D.prototype._render = function() {
    mat4.toInverseMat3(this.tmpMat, this._normMat);
    mat3.transpose(this._normMat);

    var attributes = {
        aVertexPosition: this.mesh._vertices,
        aVertexColor: this.mesh._colors,
        aNormal: this.mesh._normals,
        aTextureCoord: this.mesh._texCoords
    };

    var uniforms = {
        uModelMat: this.tmpMat,
        uNormMat: this._normMat,
        uProjMat: this.scene.projMat,
        uUseCamera: 1.0,
        uCameraMat: this.scene.cameraMat,
        uDiffuse: this.diffuse,
        uLookVec: [
                this.scene._camera._centerX - this.scene._camera._x,
                this.scene._camera._centerY - this.scene._camera._y,
                this.scene._camera._centerZ - this.scene._camera._z ]
    };

    for (var name in this.uniformsExtension) {
        if (this.uniformsExtension.hasOwnProperty(name)) {
            uniforms[name] = this.uniformsExtension[name];
        }
    }

    var length = this.mesh.indices.length;
    enchant.Game.instance.GL.renderElements(this.mesh._indices, 0, length, attributes, uniforms);
};