2016-07-15 8 views
0

preserveDrawingBuffertrueに設定しました。 これを行うとバッファに描画されたすべてのデータが一度にすべて表示されますが、 時間がたつにつれてバッファが消えていくので、古い要素が時間の経過とともに消えてしまい、描画された要素は、消えるまで相対的に高い不透明度で表示されます。WebGL:フェード描画バッファ

このような効果を得るには良い方法はありますか?

私はそれが0に達するまで、その不透明度を下げることによって、再び以前の要素をレンダリングしようとしたが、それは何かが、私はそれを変更する予定がない描画された後のようにフェージングの効率的な方法のように見えるしていませんでした。

ありがとうございます!

答えて

1

それはちょうど私がここに

WebGL: smoothly fade lines out of canvas

渡ったものを再描画すると、あなたがフェードアウトないからいくつかのことを保つことができる意味のものを再描画し、実際に一般的です。たとえば、宇宙戦闘ゲームを作っていて、爆発やミサイルの痕跡が消えてしまいますが、宇宙船や小惑星が消えてしまわないようにするには、すべてを再描画して手動でフェードアウトする必要がありますアルファを減らしながら描画します

すべてをフェードアウトさせたい場合は、ポスト処理タイプのエフェクトを使用できます。

2つのテクスチャを作成し、2つのフレームバッファにアタッチします。あなたは/ブレンドあなたが、あなたは結果を見ることができるように、そして、最終的にキャンバスにfadeFb2を描くfadeFb2

に新しいものを描く

gl_FragColor = mix(textureColor, fadeColor, mixAmount); 

を使用してfadeColorを有する第二1 fadeFb2に最初のフレームバッファfadeFb1をフェード。

次のフレームでは、描画するバッファーとフェードするバッファーを交換する以外は同じことを行います。

frame 0: mix(fadeFb1,fadeColor)->fadeFb2, draw->fadeFb2, fadeFB2->canvas 
frame 1: mix(fadeFb2,fadeColor)->fadeFb1, draw->fadeFb1, fadeFB1->canvas 
frame 2: mix(fadeFb1,fadeColor)->fadeFb2, draw->fadeFb2, fadeFB2->canvas 
... 

あなたは

取り残さされる結果を必要とするので

http://webglfundamentals.org/webgl/lessons/webgl-image-processing-continued.html

便利かもしれませんここにチュートリアルがありますフレームバッファを設定するとして、あなたが描くとき、​​あなたが明確でないことに注意してください

ここでは、twglを使用した例です。私はまっすぐなWebGLのために怠惰です。

var vs = ` 
 
attribute vec4 position; 
 

 
uniform mat4 u_matrix; 
 

 
void main() { 
 
    gl_Position = u_matrix * position; 
 
} 
 
`; 
 

 
var fs = ` 
 
precision mediump float; 
 

 
uniform vec4 u_color; 
 

 
void main() { 
 
    gl_FragColor = u_color; 
 
} 
 
`; 
 
var vsQuad = ` 
 
attribute vec4 position; 
 
attribute vec2 texcoord; 
 

 
varying vec2 v_texcoord; 
 

 
void main() { 
 
    gl_Position = position; 
 
    v_texcoord = texcoord; 
 
} 
 
`; 
 
var fsFade = ` 
 
precision mediump float; 
 

 
varying vec2 v_texcoord; 
 

 
uniform sampler2D u_texture; 
 
uniform float u_mixAmount; 
 
uniform vec4 u_fadeColor; 
 

 
void main() { 
 
    vec4 color = texture2D(u_texture, v_texcoord); 
 
    gl_FragColor = mix(color, u_fadeColor, u_mixAmount); 
 
} 
 
`; 
 
var fsCopy = ` 
 
precision mediump float; 
 

 
varying vec2 v_texcoord; 
 

 
uniform sampler2D u_texture; 
 

 
void main() { 
 
    gl_FragColor = texture2D(u_texture, v_texcoord); 
 
} 
 
`; 
 

 
var $ = document.querySelector.bind(document); 
 

 
var mixAmount = 0.05; 
 
var mixElem = $("#mix"); 
 
var mixValueElem = $("#mixValue"); 
 
mixElem.addEventListener('input', function(e) { 
 
    setMixAmount(e.target.value/100); 
 
}); 
 

 
function setMixAmount(value) { 
 
    mixAmount = value; 
 
    mixValueElem.innerHTML = mixAmount; 
 
} 
 
setMixAmount(mixAmount); 
 

 
var gl = $("canvas").getContext("webgl"); 
 
var m4 = twgl.m4; 
 
var programInfo = twgl.createProgramInfo(gl, [vs, fs]); 
 
var fadeProgramInfo = twgl.createProgramInfo(gl, [vsQuad, fsFade]); 
 
var copyProgramInfo = twgl.createProgramInfo(gl, [vsQuad, fsCopy]); 
 

 
// Creates a -1 to +1 quad 
 
var quadBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl); 
 

 
// Creates an RGBA/UNSIGNED_BYTE texture and depth buffer framebuffer 
 
var imgFbi = twgl.createFramebufferInfo(gl); 
 

 
// Creates 2 RGBA texture + depth framebuffers 
 
var fadeAttachments = [ 
 
    { format: gl.RGBA, min: gl.NEAREST, max: gl.NEAREST, wrap: gl.CLAMP_TO_EDGE, }, 
 
    { format: gl.DEPTH_STENCIL }, 
 
]; 
 
var fadeFbi1 = twgl.createFramebufferInfo(gl, fadeAttachments); 
 
var fadeFbi2 = twgl.createFramebufferInfo(gl, fadeAttachments); 
 

 
function drawThing(gl, x, y, rotation, scale, color) { 
 
    var matrix = m4.ortho(0, gl.canvas.width, gl.canvas.height, 0, -1, 1); 
 
    matrix = m4.translate(matrix, [x, y, 0]); 
 
    matrix = m4.rotateZ(matrix, rotation); 
 
    matrix = m4.scale(matrix, [scale, scale, 1]); 
 

 
    gl.useProgram(programInfo.program); 
 
    twgl.setBuffersAndAttributes(gl, programInfo, quadBufferInfo); 
 
    twgl.setUniforms(programInfo, { 
 
    u_matrix: matrix, 
 
    u_color: color, 
 
    }); 
 
    twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo); 
 
} 
 

 
function rand(min, max) { 
 
    if (max === undefined) { 
 
    max = min; 
 
    min = 0; 
 
    } 
 
    return min + Math.random() * (max - min); 
 
} 
 

 
function render(time) { 
 
    if (twgl.resizeCanvasToDisplaySize(gl.canvas)) { 
 
    twgl.resizeFramebufferInfo(gl, fadeFbi1, fadeAttachments); 
 
    twgl.resizeFramebufferInfo(gl, fadeFbi2, fadeAttachments); 
 
    } 
 
    
 
    // fade by copying from fadeFbi1 into fabeFbi2 using mixAmount. 
 
    // fadeFbi2 will contain mix(fadeFb1, u_fadeColor, u_mixAmount) 
 
    twgl.bindFramebufferInfo(gl, fadeFbi2); 
 

 
    gl.useProgram(fadeProgramInfo.program); 
 
    twgl.setBuffersAndAttributes(gl, fadeProgramInfo, quadBufferInfo); 
 
    twgl.setUniforms(fadeProgramInfo, { 
 
    u_texture: fadeFbi1.attachments[0], 
 
    u_mixAmount: mixAmount, 
 
    u_fadeColor: [0, 0, 0, 0], 
 
    }); 
 
    twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo); 
 

 
    // now draw new stuff to fadeFb2. Notice we don't clear! 
 
    twgl.bindFramebufferInfo(gl, fadeFbi2); 
 

 
    var x = rand(gl.canvas.width); 
 
    var y = rand(gl.canvas.height); 
 
    var rotation = rand(Math.PI); 
 
    var scale = rand(10, 20); 
 
    var color = [rand(1), rand(1), rand(1), 1]; 
 
    drawThing(gl, x, y, rotation, scale, color); 
 

 

 
    // now copy fadeFbi2 to the canvas so we can see the result 
 
    twgl.bindFramebufferInfo(gl, null); 
 

 
    gl.useProgram(copyProgramInfo.program); 
 
    twgl.setBuffersAndAttributes(gl, copyProgramInfo, quadBufferInfo); 
 
    twgl.setUniforms(copyProgramInfo, { 
 
    u_texture: fadeFbi2.attachments[0], 
 
    }); 
 
    twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo); 
 

 
    // swap the variables so we render to the opposite textures next time 
 
    var temp = fadeFbi1; 
 
    fadeFbi1 = fadeFbi2; 
 
    fadeFbi2 = temp; 
 

 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render);
body { margin: 0; } 
 
canvas { display: block; width: 100vw; height: 100vh; } 
 
#ui { position: absolute; top: 0 }
<script src="https://twgljs.org/dist/twgl-full.min.js"></script> 
 
<canvas></canvas> 
 
<div id="ui"> 
 
<span>mix:</span><input id="mix" type="range" min="0" max="100" value="5" /><span id="mixValue"></span> 
 
</div>

+0

あなたの答えにもう一度感謝します!私は再描画の事柄はよくあることを理解していますが、このプログラムはFPGAボード上にあるので、できるだけ効率的かつ小さくする必要があります。あなたのtwglの例はまさに私が探しているものですが、別の質問があります!私は 'TRIANGLES'の代わりに' LINE_STRIP'を描画しているので、私は描画モードを変更するだけでしょうか、それともクワッドバッファでは動作しませんか? –

+0

^スクラッチ、私はあなたの例に従って、メソッドを動作させることができましたが、ラインは何らかの理由でスーパーピクセル化されて見えます。 http://i.imgur.com/dQCG5dH.pngをチェックしてください。 'fbi'サイズを512に変更すると、より良い結果になります。 –

+0

答えに追加する質問に無関係な量が分かりません。キャンバスのサイズを変更し、フレームバッファを新しいサイズに合わせるように頼んだわけではありません。そのコードは入れませんでした。ウィンドウを埋めるようにサイズが変更されました。 – gman

0

preserveDrawingBufferフラグは、メモリが限られているデバイス(携帯電話)では、そのデバイスがそのメモリのチャンクを再利用できるため便利です。

フェーディング/ゴースト効果は、ビューポートと同じサイズのテクスチャを割り当てて、代わりにこのテクスチャを暗くします。すべてのフレームで、このテクスチャの内容を自身に再描画し、カラー値にフェーディング係数(たとえば0.9)を掛けます。その後、同じテクスチャで新しい要素をレンダリングし、最後にテクスチャをビューポートにレンダリングします(単純な "コピーレンダリング")。

+0

ああなるほど、私はWebGLのに比べて初心者だとして、あなたは、私はその結果を達成するために見ることができ任意のチュートリアルを知っていたならば、私は不思議でしたか? –

+0

'preserveDrawingBuffer'はメモリを節約することとは関係ありません。 'preserveDrawingBuffer'は、一部のモバイルデバイスで保存しないほうが速いため、特に追加されました。 – gman

関連する問題