MMD on WebGL レンダリング部分のマイナーチェンジ

Lat 式を表示できるようにして以来の変更。

Lat 式と構造の似ている ulaP さんの雪歌ユフを表示してみたところ、なんかヒゲができてしまった。

それ以外はほとんど同じなのになぜ…

とアレコレ捻り回して眺めてたら、顔の前にほぼ真透明の材質があることに気づいた。左が透過を有効にした法線マップ。右が透過無効の法線マップ。

この前は気づかなかったけど Lat 式も同じようになってたみたい。

これを見て閃いた。もしかすると透明な材質の奥ではエッジを描画しないことになっているのでは?

ということで「透明な髪」でピンと来たデフォ子(byななみさん)で試してみたら、予想は当たってたっぽい。(赤で囲んだところ)

それでまた色々試した結果、レンダリング部分をこういう感じから

    gl.enable(gl.CULL_FACE);
    gl.enable(gl.BLEND);
    gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA, gl.DST_ALPHA);

    model.materials.forEach(function(material){
      gl.cullFace(gl.BACK);
      renderMaterial(material);

      gl.cullFace(gl.FRONT);
      renderEdge(material);
    });

    gl.disable(gl.BLEND);
    gl.disable(gl.CULL_FACE);

こういうふうに変えて、エッジ描画の前にアルファブレンディングを切ることで対処した。

    gl.enable(gl.CULL_FACE);
    gl.enable(gl.BLEND);
    gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA, gl.DST_ALPHA);

    model.materials.forEach(function(material){
      gl.cullFace(gl.BACK);
      renderMaterial(material);
    });

    gl.disable(gl.BLEND);

    model.materials.forEach(function(material){
      gl.cullFace(gl.FRONT);
      renderEdge(material);
    });

    gl.disable(gl.CULL_FACE);

ループが2つになって、(しかも今やってる方法だと材質ごとにボーンの付け替えをするので)処理としては数ミリ秒増えてしまったのが残念。

しかしこれで雪歌ユフも表示できるようになりましたとさ。