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); };