我们正在编写一个用于流视频的Web客户端,一种类型的流使用专有库,因此我们无法使用支持标准网址的当前插件或HTML标记。 我有几年的OpenGL经验,所以我决定试用WebGL来渲染原始数据帧。
使用js Image()加载png文件非常快。但使用原始RGBA数据进行渲染非常慢。
我将原始数据放在Uint8Array()中并使用接受宽度高度的gl.texImage2D(),而PNG渲染使用接受图像且没有宽度高度的gl.texImage2D()版本。
我会假设原始数据会更快,因为它不必加载和解码png文件,但它似乎是倒退。
我的背景主要是C ++,并且对桌面OpenGL有相当多的经验。 HTML5和javascript对我来说还是一个新手。
为什么WebGL渲染Image()(1024x1024)要快得多,甚至原始数据(32x32)的小图像要慢得多?有没有办法加快速度?我在最新版本的Firefox上运行它。
编辑: 问题实际上是将数据从插件传递给javascript。我正在使用Date.getTime()进行分析,但显然这不是一个好方法,因为创建数组之前和之后的时间和从插件获取数据是相同的。我已经切换到从本地HTTP服务器获取数据,这在获取和呈现原始数据时表现出了很大的性能提升。
答案 0 :(得分:3)
嗯,让我们进行测试
var canvas = document.getElementById("c");
var gl = canvas.getContext("webgl");
var work = document.getElementById("w");
var fps = document.getElementById("f");
var imageData = new Uint8Array(canvas.width * canvas.height * 4);
var program = webglUtils.createProgramFromScripts(
gl, ["vshader", "fshader"], ["a_position"]);
gl.useProgram(program);
var verts = [
1, 1,
-1, 1,
-1, -1,
1, 1,
-1, -1,
1, -1,
];
var vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
var adjust = 1;
var workAmount = adjust;
var oneFrame = 1 / 50; // shoot for 50fps since timing is poor
var then = Date.now() * 0.001;
var frameCount = 0;
var maxIndex = canvas.width * canvas.height;
function doStuff() {
var now = Date.now() * 0.001;
var deltaTime = now - then;
then = now;
++frameCount;
if (deltaTime < oneFrame) {
workAmount += adjust;
} else {
workAmount = Math.max(workAmount - adjust, adjust);
}
fps.innerHTML = (1 / deltaTime).toFixed(1);
work.innerHTML = workAmount;
var color = (frameCount & 1) ? 255 : 128;
for (var i = 0; i < workAmount; ++i) {
var index = (Math.random() * maxIndex | 0) * 4;
imageData[index + 0] = color;
imageData[index + 1] = color;
imageData[index + 2] = color;
imageData[index + 3] = 255;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0,
gl.RGBA, gl.UNSIGNED_BYTE, imageData);
}
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(doStuff);
}
doStuff();
&#13;
body, document {
font-family: monospace;
}
#c {
width: 128px;
height: 128px;
border: 1px solid red;
}
#outer {
position: relative;
}
#info {
position: absolute;
left: 10px;
top: 10px;
background-color: white;
padding: 0.5em;
}
&#13;
<div id="outer">
<canvas id="c" width="1024" height="1024"></canvas>
<div id="info">
<div>fps : <span id="f"></span></div>
<div>work: <span id="w"></span></div>
</div>
</div>
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script id="vshader" type="whatever">
attribute vec4 a_position;
varying vec2 v_texcoord;
void main() {
gl_Position = a_position;
v_texcoord = a_position.xy * 0.5 + 0.5;
}
</script>
<script id="fshader" type="whatever">
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_sampler;
void main() {
gl_FragColor = texture2D(u_sampler, v_texcoord);
}
</script>
&#13;
在我的2014 MBP上,我得到大约20个1024x1024 RGBA / UNSIGNED_BYTE在Chrome上以50fps上传一帧,在Firefox上大致相同
你得到了什么?你确定你的瓶颈是纹理上传而不是其他东西吗?
答案 1 :(得分:0)
缓慢可能来自(至少)3件事:
WebGL必须使用texImage2D进行错误检查。也许浏览器知道Image中的数据始终有效,因此跳过此检查。
WebGL可能需要在幕后进行数据转换;例如,如果您使用预乘alpha;那么WebGL可能需要用原始数据进行转换;而Image元素已经是预乘alpha(最有可能)。
浏览器在创建TypeArrays时仍然非常缓慢。如果您每帧都在创建一个新的TypeArray,这会降低性能。