0

次のように glsl シェーダーを作成しました。

<script id="player-fragment-shader" type="x-shader/x-fragment">
precision highp float;

varying vec3 fNormal;
uniform vec2 resolution;

float circle(in vec2 _pos, in float _radius) {
  vec2 dist = _pos - vec2(0.5);
  return 1.-smoothstep(_radius - (_radius * 0.5),
                       _radius + (_radius * 0.5),
                       dot(dist, dist) * 20.0);
}

void main() {
  vec2 pos = gl_FragCoord.xy/resolution.xy;

  // Subtract the inverse of orange from white to get an orange glow
  vec3 color = vec3(circle(pos, 0.8)) - vec3(0.0, 0.25, 0.5);

  gl_FragColor = vec4(color, 0.8);
}
</script>
<script id="player-vertex-shader" type="x-shader/x-vertex">
precision highp float;

attribute vec3 position;
attribute vec3 normal;

uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

void main() {
  vec4 pos = modelViewMatrix * vec4(position, 0.25);
  gl_Position = projectionMatrix * pos;
}
</script>

次を実行して、ゲームのロードで初期化します。

var vertShader = document.getElementById("player-vertex-shader").text;
var fragShader = document.getElementById("player-fragment-shader").text;
var shader = me.video.shader.createShader(me.video.renderer.compositor.gl, vertShader, fragShader);

これは、ビデオが初期化された後に行われ、シェーダー プログラムをコンパイルして正常にロードされるようです。シェーダーは、shaderfrog.com や他の同様のサイトにロードすると、正常に動作するようです。

問題は、キャラクターを移動して再描画するまで、完全に黒い画面が表示されることです。私は webgl の基礎サイトを読みましたが、文字位置を GL バッファーにバインドしているようです。

melonjsでこれを行うにはどうすればよいですか。

4

1 に答える 1

0

こんにちは、melonJS 用のオリジナルの WebGL コンポジターを作成しました。

truetl;dr:キャラクターのentity.update()メソッドから戻って、フレームを強制的に再描画します。(または、アニメーションのフレーム レートを上げてゲームのフレーム レートに合わせます)。

メソッドをオーバーライドする例update:

update: function (dt) {
    this._super(me.Entity, "update", [dt]);
    return true;
}

これにより、更新は正常に動作し続けますが (アニメーション状態の更新など) true、フレームを毎回強制的に再描画するように戻ります。


コンポジターがどのように機能するか、およびシェーダーが melonJS エンティティとどのように相互作用しているかを理解することが役立つ場合があります。これは、WebGL と melonJS の統合の内部動作について説明しています。つまり、位置をシェーダーにバインドする明示的な手順はありません。位置は頂点属性バッファーを介して送信されます。このバッファーは (通常はフレーム全体に対して) バッチ処理され、1 つの大きな配列として WebGL に送信されます。

頂点バッファーの構築をより詳細に制御する必要がある場合、または他のカスタム レンダリング パスを実行する場合は、既定のコンポジターを置き換えることができます。me.video.initこれは、options.compositor引数でクラス参照を渡すことによって行われます。デフォルトはme.WebGLRenderer.Compositor次のとおりです。

me.video.init(width, height, {
    wrapper: "screen",
    renderer : me.video.WEBGL,
    compositor: me.WebGLRenderer.Compositor
});

描画ループ中、デフォルトのコンポジターは、呼び出しごとに新しいクワッド要素を頂点属性配列バッファーに追加しme.WebGLRenderer.drawImageます。このメソッドは、同名のDOM キャンバス メソッドをエミュレートします。実装は非常に簡単です。引数をクワッドに変換し、コンポジターのaddQuadメソッドを呼び出すだけです。これは、頂点属性バッファが実際に読み込まれる場所です。

頂点属性バッファが完了した後、flushメソッドが呼び出され、頂点バッファが GPU に送信されますgl.drawElements

melonJS は、描画の最適化を極限まで行います。(上記のように) 描画呼び出しの数を減らすために、同様のレンダリング可能オブジェクトをバッチ処理するだけでなく、描画するものが何もない場合は描画呼び出しを送信しません。この状態は、フレームが描画された最後のフレームと同一である場合に発生します。たとえば、エンティティが移動していない、ビューポートがスクロールしていない、アイドル アニメーションが次の状態に進んでいない、オンスクリーン タイマーが 1 秒も経過していない、などです。

trueシーン内の任意のエンティティをそのupdateメソッドから返すことで、フレームを強制的に再描画することができます。これは、フレームを再描画する必要があるというゲーム エンジンへの信号です。このプロセスはwikiで詳しく説明されています。

于 2018-04-25T17:04:17.280 に答える