我在游戏中添加了WebGL支持,但是我遇到了一个奇怪的问题:它比Canvas 2D渲染模式运行得更慢,我不明白为什么。
我检查了Firefox PC,Chrome PC和Chrome Android,他们在网络上运行了数百个精灵的WebGL演示,所以我肯定在我的代码中出错了。
Firefox的分析器说整个游戏只使用了7%的资源,渲染部分仅占1.2%。它只是游戏的标题屏幕,只有五个精灵可以画。虽然很慢......
更新:Chrome的分析器表示闲置率仅为4%,程序占93%,渲染率为2.6%。 当使用Canvas 2D时,情况非常不同,76%闲置,16%程序,2.3%绘图功能 肯定是我的WebGL渲染代码中存在问题。
更新:Android Chrome的分析器(在JXD S5110上)总是说程序是~39%,drawArrays是~8%,bufferData是~5%,bindTexture是3%。其他一切都可以忽略不计。
如果一个地雷的功能浪费了所有的资源我会知道该怎么做,但这里的瓶颈似乎是"程序" (浏览器本身?)和webgl方法,我无法编辑的两件事。
请有人查看我的代码并告诉我我做错了什么。
以下是我的着色器
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
attribute vec2 a_texCoord;
uniform vec2 u_resolution;
uniform vec2 u_translation;
uniform vec2 u_rotation;
varying vec2 v_texCoord;
void main()
{
// Rotate the position
vec2 rotatedPosition = vec2(
a_position.x * u_rotation.y + a_position.y * u_rotation.x,
a_position.y * u_rotation.y - a_position.x * u_rotation.x);
// Add in the translation.
vec2 position = rotatedPosition + u_translation;
// convert the rectangle from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
// pass the texCoord to the fragment shader
// The GPU will interpolate this value between points
v_texCoord = a_texCoord;
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
// our texture
uniform sampler2D u_image;
// the texCoords passed in from the vertex shader.
varying vec2 v_texCoord;
void main()
{
// Look up a color from the texture.
gl_FragColor = texture2D(u_image, vec2(v_texCoord.s, v_texCoord.t));
}
</script>
这是我的画布的创建代码及其在WebGL模式下的上下文。 (我使用多个分层画布,以避免在每个帧都画出背景和前景,而它们永远不会改变,这就是画布和上下文在数组中的原因。)
// Get A WebGL context
liste_canvas[c] = document.createElement("canvas") ;
document.getElementById('game_div').appendChild(liste_canvas[c]);
liste_ctx[c] = liste_canvas[c].getContext('webgl',{premultipliedAlpha:false}) || liste_canvas[c].getContext('experimental-webgl',{premultipliedAlpha:false});
var gl = liste_ctx[c] ;
gl.viewport(0, 0, game.res_w, game.res_h);
// setup a GLSL program
gl.vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
gl.fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
gl.program = createProgram(gl, [gl.vertexShader, gl.fragmentShader]);
gl.useProgram(gl.program);
// look up where the vertex data needs to go.
positionLocation = gl.getAttribLocation(gl.program, "a_position");
texCoordLocation = gl.getAttribLocation(gl.program, "a_texCoord");
// provide texture coordinates for the rectangle.
texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable( gl.BLEND ) ;
gl.posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, gl.posBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
在我的图片的.onload功能中,我添加了
var gl = liste_ctx[c] ;
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
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.bindTexture(gl.TEXTURE_2D, null);
这是我的draw_sprite()函数的WebGL部分:
var gl = liste_ctx[c] ;
gl.bindTexture(gl.TEXTURE_2D, sprites[d_sprite].texture);
var resolutionLocation = gl.getUniformLocation(gl.program, "u_resolution");
gl.uniform2f(resolutionLocation, liste_canvas[c].width, liste_canvas[c].height);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.posBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
topleft_x , topleft_y ,
topright_x , topright_y ,
bottomleft_x , bottomleft_y ,
bottomleft_x , bottomleft_y ,
topright_x , topright_y ,
bottomright_x , bottomright_y ]), gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, 6);
我做错了什么?
答案 0 :(得分:1)
使用多个webgl画布让它变得如此之慢的原因是我现在只使用了一个而且效果更好。但它仍然比Canvas 2D慢一点,而且探测器说65%是空闲而它落后于地狱所以我真的不明白......
编辑:我想我明白了。由于我的计算机运行的是WinXP,因此无法启用WebGL的硬件加速,因此浏览器使用软件渲染,这就解释了为什么编程&#39;在Chrome的分析器中是巨大的。但是,硬件加速似乎适用于2D环境,这就是它更快的原因。
答案 1 :(得分:1)
这可能有所帮助:What do the "Not optimized" warnings in the Chrome Profiler mean?
相关链接:
对于“优化太多次”,这意味着功能参数/行为变化太大,因此Chrome不得不重新优化它。