我刚刚开始使用webgl。我跟着youtube上的一个简单的初学者教程学习。现在,我正在尝试创建一个简单的2D游戏。
在这个游戏中,我想渲染一个简单的图片库存。当我这样做时,我的fps在10秒后下降到2。如果我删除库存渲染的代码,它保持在60。
我知道我的问题出在第82行的 game/js/engine/inventory/inventory.js
. 在那里,我用一个看教程做的sprite类渲染35张图片。我想是因为我看了一个简单的教程,其中渲染图像的代码没有优化,可能不是最好的方法。这个sprite类位于 game/js/engine/material.js:127
. 在sprite类中,我设置了简单的变量,这些变量可以被解析到我的顶点和片段着色器中。
在设置方法中,我为我的图像设置了所有的参数。
gl.useProgram(this.material.program);
this.gl_tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.gl_tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image);
gl.bindTexture(gl.TEXTURE_2D, null);
this.uv_x = this.size.x / this.image.width;
this.uv_y = this.size.y / this.image.height;
this.tex_buff = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.tex_buff);
gl.bufferData(gl.ARRAY_BUFFER, Sprite.createRenderRectArray(0, 0, this.uv_x, this.uv_y), gl.STATIC_DRAW);
this.geo_buff = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.geo_buff);
gl.bufferData(gl.ARRAY_BUFFER, Sprite.createRectArray(0, 0, this.size.x, this.size.y), gl.STATIC_DRAW);
gl.useProgram(null);
在渲染方法中,我首先绑定了纹理,然后绑定了一个tex坐标缓冲区、一个地理缓冲区和一些世界的偏移量。然后,我为我的世界绑定了一个tex坐标缓冲区、一个地理缓冲区和一些偏移量。最后,我绘制数组。
let frame_x = Math.floor(frames.x) * this.uv_x;
let frame_y = Math.floor(frames.y) * this.uv_y;
let oMat = new M3x3().transition(position.x, position.y);
gl.useProgram(this.material.program);
this.material.set("u_color", 1, 1, 1, 1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.gl_tex);
this.material.set("u_image", 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.tex_buff);
this.material.set("a_texCoord");
gl.bindBuffer(gl.ARRAY_BUFFER, this.geo_buff);
this.material.set("a_position");
this.material.set("u_texeloffset", 0.5 / (this.image.width * scale.x), 0.5 / (this.image.height * scale.y));
this.material.set("u_frame", frame_x, frame_y);
this.material.set("u_world", worldSpaceMatrix.getFloatArray());
this.material.set("u_object", oMat.getFloatArray());
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 6);
gl.useProgram(null);
Github。https:/github.comDJ1TJOO2DGame:
有谁知道我怎样才能解决这个问题吗?或者说有什么更好的方法来渲染库存?
如果你找到任何其他方法来改进我的webgl或javascript,请告诉我。
是否有更好的方法来渲染一个库存?
在我的脑海中,有几种方法可以优化。
如果只用HTML来制作库存,可能会更快一些
认真的。你还可以获得简单的国际字体渲染,造型,CSS的响应能力等等... ... 很多游戏都是这样做的。
一般来说,使用纹理图集(一个有很多不同图像的单一纹理),然后为你的库存的所有部分生成顶点到顶点缓冲区,会更快。然后用一个绘制调用来绘制所有的部件。例如,这就是如何 亲爱的ImGUI 工程,以使 所有这些惊人的图形用户界面. 它本身并不绘制任何东西,只是为纹理图集生成一个带有位置和纹理坐标的顶点缓冲区。
做#2,除了不在每一帧生成整个顶点缓冲区,只更新变化的部分。
比如说,你的清单上写着...。
[gold ] 123
[silver] 54
[copper] 2394
让我们假设你总是画 [gold ]
, [silver]
和 [copper]
但只有数字会改变。你可以生成包含每个字母所有位置的顶点缓冲区作为精灵,然后为每个值生成6个字符占位符。你只需要在数字发生变化时通过记住它们在顶点缓冲区中的位置来更新它们。对于任何你不想画的数字,你可以直接把它的顶点移到屏幕外。
将库存绘制成一个纹理(或部分纹理)。然后在屏幕上绘制纹理。只更新纹理中发生变化的部分。
这基本上是 浏览器本身的功能. 根据不同的CSS设置,页面的部分被划分为纹理。当一些HTML或CSS发生变化时,只有那些发生变化的纹理会被重新渲染,然后所有的纹理都被绘制出来,重新合成页面。