2017-11-21 4 views
-2

Ich versuche, die Frames pro Sekunde auf meinem HTML-Canvas anzuzeigen. Es macht mir nichts aus, wo es auf der Leinwand für jetzt platziert wird, da ich es zu späterer Zeit zwicken kann. Hier ist, was ich bisher:Wie kann ich FPS in WebGL aufzeichnen und anzeigen?

 var updateAnimation = function() { 
 

 
      requestAnimFrame(updateAnimation); 
 

 
      var anim = global.animation; 
 
      var e = global.events; 
 

 
      //Set current time 
 
      anim.animationCurrentTime = Date.now(); 
 
      //Set start time 
 
      if (anim.animationStartTime === undefined) { 
 
       anim.animationStartTime = anim.animationCurrentTime; 
 
      } 
 

 
      //Clear the animationStage 
 
      webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT); 
 

 

 

 
      //Draw scene 
 
      drawScene(); 
 

 

 
      //Set previous time as current time to use in next frame 
 
      anim.animationLastTime = anim.animationCurrentTime; 
 
     } 
 

 
     global.document.animationStage = document.getElementById("animation-scene"); 
 

 
     webgl = setupScene(global.document.animationStage); 
 

 
     setupShaders(); 
 
     setupAllBuffers(); 
 
     setupEvents(); 
 
     setupLight(); 
 
     setupTextures(); 
 

 
     initScene(); 
 
     }
<header> 
 
    <h1 style="text-align: center">Applied Computer Graphics and Vision</h1> 
 
    <p>Instructions<span> 
 
    <br /> 
 
    <br /> 
 
    Rotation - \t Click and drag in the direction of rotation <br /> 
 
    Increase/Decrease Orbit Radius - Up and Down Keys <br /> 
 
    Increase/Decrease Orbit Speed - Left and Right Keys <br /> 
 
    Translation Of X - Shift plus mouse drag <br /> 
 
    Translation Of Y - Alt plus mouse drag <br /> 
 
    Translation Of Z - Mouse scroll 
 
    </span></p> 
 
</header> 
 

 
<canvas style="float:left" ; id="animation-scene"></canvas> 
 
<canvas id="myCanvas" width="1400" height="800"></canvas> 
 
<script> 
 
\t /* Sets */ 
 
    var area = document.getElementById('animation-scene'); 
 
    area.setAttribute('height', window.innerHeight); 
 
    area.setAttribute('width', window.innerWidth); 
 
</script> 
 
</body> 
 
</html>

Jede Hilfe oder Ratschläge wäre toll. Ich kenne die Grundidee, die Anzahl der gerenderten Frames zählen zu müssen, und sobald eine Sekunde vergangen ist, speichere das in der fps-Variablen, aber bin mir nicht sicher, wie ich das über meine Update-Animationsfunktion implementieren soll.

Ich habe auch Methoden, die die aktuelle/Startzeit für die Szene innerhalb der Update-Animation-Funktion setzt.

+0

einen Blick auf https://github.com/mrdoob/stats.js/ – gaitat

Antwort

0

Eine Möglichkeit wäre, die Delta-Zeit zwischen 2 Frames zu berechnen und den Durchschnitt der letzten Delta-Zeiten zu berechnen. Dazu müssen Sie die Delta-Zeiten in einem Array speichern. Im folgenden Ausschnitt sind 100-mal gespeichert:

var lastTime = Date.now(); 
var times = []; 
var timeSum = 0; 
var actIndex = 0; 
var maxTimes = 100; 

function getFPS() { 

    var currentTime = Date.now(); 
    var deltaMS  = currentTime - lastTime; 
    lastTime  = currentTime; 
    timeSum   = timeSum + deltaMS; 
    if (times.length < maxTimes) { 
     times.push(deltaMS); 
    } else { 
     timeSum   = timeSum - times[actIndex]; 
     times[actIndex] = deltaMS; 
     actIndex  = actIndex < maxTimes-1 ? actIndex+1 : 0; 
    } 
    return 1000 * times.length/timeSum; 
} 

den Code-Snippet Siehe:

var lastTime = Date.now(); 
 
    var times = []; 
 
    var timeSum = 0; 
 
    var actIndex = 0; 
 
    var maxTimes = 100; 
 

 
    function getFPS() { 
 
     
 
     var currentTime = Date.now(); 
 
     var deltaMS  = currentTime - lastTime; 
 
     lastTime  = currentTime; 
 
     timeSum   = timeSum + deltaMS; 
 
     if (times.length < maxTimes) { 
 
      times.push(deltaMS); 
 
     } else { 
 
      timeSum   = timeSum - times[actIndex]; 
 
      times[actIndex] = deltaMS; 
 
      actIndex  = actIndex < maxTimes-1 ? actIndex+1 : 0; 
 
     } 
 
     return 1000 * times.length/timeSum; 
 
    } 
 

 

 
var renderer, scene, camera, controls; 
 

 
function init() { 
 

 
    // renderer 
 
    renderer = new THREE.WebGLRenderer(); 
 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 
    renderer.setClearColor(0x707070, 1); 
 
    document.body.appendChild(renderer.domElement); 
 

 
    // scene 
 
    scene = new THREE.Scene(); 
 
    
 
    // camera 
 
    camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000); 
 
    camera.position.set(2, 2, 2); 
 

 
    // controls 
 
    controls = new THREE.OrbitControls(camera); 
 
    
 
    // materials 
 
    var mat0 = new THREE.MeshBasicMaterial({color: 0xff0000}); 
 
    var mat1 = new THREE.MeshBasicMaterial({color: 0x00ff00}); 
 
    var mat2 = new THREE.MeshBasicMaterial({color: 0x0000ff}); 
 
    var mat3 = new THREE.MeshBasicMaterial({color: 0xffff00}); 
 
    var mat4 = new THREE.MeshBasicMaterial({color: 0xff00ff}); 
 
    var mat5 = new THREE.MeshBasicMaterial({color: 0x00ffff}); 
 
    var materials = [mat0, mat1, mat2, mat3, mat4, mat5]; 
 
    
 
    // geometry 
 
    var geometry = new THREE.BoxGeometry(1, 1, 1); 
 
    var mesh = new THREE.Mesh(geometry, materials); 
 
    
 
    // mesh 
 
    scene.add(mesh); 
 

 
    lastTime = Date.now(); 
 
} 
 

 
function animate() { 
 

 
    document.getElementById("fps_val").innerHTML = getFPS().toFixed(1); 
 

 
    requestAnimationFrame(animate); 
 
    renderer.render(scene, camera); 
 
} 
 

 
init(); 
 
animate();
body { 
 
    margin: 0; 
 
    overflow: hidden; 
 
} 
 

 
canvas { 
 
    width: 100%; 
 
    height: 100% 
 
} 
 

 
#fps_val { 
 
    position : absolute; 
 
    top : 5%; 
 
    left : 5%; 
 
}
<script src="https://threejs.org/build/three.min.js"></script> 
 
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> 
 

 
<span id="fps_val">0</span>

1

Egoshooter Anzeige ist ziemlich einfach und hat wirklich nichts mit WebGL zu tun, außer es ist gemeinsam zu wissen wollen. Hier ist eine kleine FPS-Anzeige

const fpsElem = document.querySelector("#fps"); 
 

 
let then = 0; 
 
function render(now) { 
 
    now *= 0.001;       // convert to seconds 
 
    const deltaTime = now - then;   // compute time since last frame 
 
    then = now;       // remember time for next frame 
 
    const fps = 1/deltaTime;    // compute frames per second 
 
    fpsElem.textContent = fps.toFixed(1); // update fps display 
 
    
 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render);
<div>fps: <span id="fps"></span></div>

sollten Sie wahrscheinlich Date.now() nicht für die Berechnung FPS verwenden als Date.now() nur Millisekunden zurück. requestAnimationFrame wird bereits die Zeit in Mikrosekunden seit dem Laden der Seite übergeben.

Auch Sie nicht wirklich "auf die Leinwand". Verwenden Sie einfach ein anderes HTML-Element, das von der Zeichenfläche getrennt ist. Wenn Sie sie zu überlappen wollen, dann CSS verwenden, um sie überlappen

const gl = document.querySelector("#c").getContext("webgl"); 
 
const fpsElem = document.querySelector("#fps"); 
 

 
let then = 0; 
 
function render(now) { 
 
    now *= 0.001;       // convert to seconds 
 
    const deltaTime = now - then;   // compute time since last frame 
 
    then = now;       // remember time for next frame 
 
    const fps = 1/deltaTime;    // compute frames per second 
 
    fpsElem.textContent = fps.toFixed(1); // update fps display 
 
    
 
    drawScene(now); 
 
    
 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render); 
 

 
function drawScene(time) { 
 
    gl.disable(gl.SCISSOR_TEST); 
 
    gl.clearColor(1, 0, 0, 1); 
 
    gl.clear(gl.COLOR_BUFFER_BIT); 
 
    
 
    const halfWidth = gl.canvas.width/2; 
 
    const halfHeight = gl.canvas.height/2 
 
    const x = halfWidth - f(time) * halfWidth; 
 
    const y = halfHeight - f(time * 1.17) * halfHeight; 
 
    const w = (halfWidth - x) * 2; 
 
    const h = (halfHeight - y) * 2; 
 
    gl.scissor(x, y, w, h); 
 
    gl.enable(gl.SCISSOR_TEST); 
 
    gl.clearColor(f(time * 1.1), f(time * 1.3), f(time * 1.2), 1); 
 
    gl.clear(gl.COLOR_BUFFER_BIT); 
 
} 
 

 
function f(v) { 
 
    return Math.sin(v) * .5 + .5; 
 
}
#container { 
 
    position: relative; /* needed so child elements use this as their base */ 
 
} 
 
#hud { 
 
    position: absolute; 
 
    left: 5px; 
 
    top: 5px; 
 
    background: rgba(0, 0, 0, 0.5); /* 50% opaque black */ 
 
    color: white; 
 
    padding: .5em; 
 
    font-family: monospace; 
 
    border-radius: .5em; 
 
} 
 
<div id="container"> 
 
    <canvas id="c"></canvas> 
 
    <div id="hud">fps: <span id="fps"></span></div> 
 
</div>

Verwandte Themen