gpt4 book ai didi

javascript - Chrome 和 Windows 的非最佳 WebGL 性能

转载 作者:搜寻专家 更新时间:2023-11-01 04:40:56 25 4
gpt4 key购买 nike

作为对自己的挑战,我正在使用 javascript 进行基本的 minecraft 重制,并使用 <canvas> 支持的 WebGL 库。标签。我在 youtube 上有一个演示视频 here .为了使世界易于编辑,我将世界几何体分成 block (16^3) 个区域,这意味着我需要为每个渲染 block 绘制调用。这就是问题所在。这不是显卡的性能问题,我的 Nvidia GeForce 980 甚至没有打开风扇,GPU 报告在最大时钟速度的一半时利用率仅为 25%,因此实际上更准确的数字是12.5% 的利用率。问题出在 CPU 上。


GPU Process在 google chrome 任务管理器中,我的 CPU 中的核心饱和度高出 15%。这是 GL 的调用记录器所说的:

GL drawElements: [4, 7680, 5123, 0]
GL drawElements: [4, 6144, 5123, 0]
GL drawElements: [4, 7866, 5123, 0]
GL drawElements: [4, 6618, 5123, 0]
GL drawElements: [4, 6144, 5123, 0]
GL drawElements: [4, 4608, 5123, 0]
GL uniformMatrix4fv: [[object WebGLUniformLocation], false, mat4(0.9999874830245972, -0.000033332948078168556, 0.004999868106096983, 0, 0, 0.9999777674674988, 0.006666617467999458, 0, -0.0049999793991446495, -0.00666653411462903, 0.999965250492096, 0, -127.43840026855469, -129.25619506835938, -113.50281524658203, 1)]
GL uniform2fv: [[object WebGLUniformLocation], vec2(-8, -7)]
GL drawElements: [4, 7680, 5123, 0]
GL drawElements: [4, 6144, 5123, 0]
GL drawElements: [4, 6210, 5123, 0]
GL drawElements: [4, 8148, 5123, 0]
GL drawElements: [4, 6144, 5123, 0]
GL drawElements: [4, 4608, 5123, 0]
GL uniformMatrix4fv: [[object WebGLUniformLocation], false, mat4(0.9999874830245972, -0.000033332948078168556, 0.004999868106096983, 0, 0, 0.9999777674674988, 0.006666617467999458, 0, -0.0049999793991446495, -0.00666653411462903, 0.999965250492096, 0, -127.51840209960938, -129.36285400390625, -97.50337219238281, 1)]
GL uniform2fv: [[object WebGLUniformLocation], vec2(-8, -6)]
GL drawElements: [4, 7680, 5123, 0]
GL drawElements: [4, 6144, 5123, 0]
GL drawElements: [4, 7842, 5123, 0]
GL drawElements: [4, 6144, 5123, 0]
GL drawElements: [4, 4608, 5123, 0]

我能够连续调用 drawElements 的原因是因为我使用的是 WebGL 扩展 OES_vertex_array_object所以这些调用不会被记录器记录下来,所以你看不到它们。

我有很多关于状态变化的故事非常昂贵,但因为我调用了很多 drawElements背靠背这应该不是问题?我还了解到,使用我的硬件类型的人可以通过考虑这些状态变化轻松地进行 4096 绘制调用。也许这是一个问题,因为 webgl 本身未从 ANGLE gl 到 Google Chrome 使用的 direct3D 调用进行优化。

还有一点要注意:如果我将几何构造大小从 16^3 调整为 16x16x128,将绘制调用计数减少 8,那么如果没有创建世界几何,我能够以稳定的 60FPS 运行游戏。如果有则游戏无法玩。

编辑:更多测试...所以我决定制作一个最小的 webgl 程序,结果证明它是一个非常酷的屏幕保护程序。在这里:

<html>
<body style="margin:0px">
<canvas id="gl" style="width:100%;height:100%;">

</canvas>
</body>

<script type="vertex" id="vertex">
attribute vec2 pos;

uniform mat4 matrix;

uniform float time;
uniform vec2 translate;

varying vec3 color;

void main (){
gl_Position = matrix * vec4(pos + translate, (sin(time) + 1.5) * -10.0, 1.0);

color = vec3((sin(time) + 1.0) / 2.0);
}
</script>

<script type="frag", id="frag">
precision mediump float;

varying vec3 color;

void main (){
gl_FragColor = vec4(color, 1.0);
}
</script>

<script>
var canvas = document.getElementById("gl");
var gl = canvas.getContext("webgl");

canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;

gl.viewport(0, 0, canvas.width, canvas.height);

var vertShader = gl.createShader(gl.VERTEX_SHADER);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertShader, "attribute vec2 pos;uniform mat4 matrix;uniform float time;uniform vec2 translate;varying vec3 color;void main(){gl_Position=matrix*vec4(pos+translate,(sin(time)+1.5)*-10.0,1.0);color=vec3((sin(time)+1.0)/2.0);}");
gl.shaderSource(fragShader, "precision mediump float;varying vec3 color;void main(){gl_FragColor=vec4(color, 1.0);}");
gl.compileShader(vertShader);
gl.compileShader(fragShader);

var shader = gl.createProgram();
gl.attachShader(shader, vertShader);
gl.attachShader(shader, fragShader);
gl.linkProgram(shader);
gl.useProgram(shader);

gl.enableVertexAttribArray(0);

var u_time = gl.getUniformLocation(shader, "time");
var u_matrix = gl.getUniformLocation(shader, "matrix");
var u_translate = gl.getUniformLocation(shader, "translate");

(function (){
var nearView = 0.1;
var farView = 100;
var f = 1 / Math.tan(60 / 180 * Math.PI / 2);
var nf = nearView - farView;
var aspectRatio = canvas.width / canvas.height;

gl.uniformMatrix4fv(u_matrix, false, [
f / aspectRatio, 0, 0, 0,
0, f, 0, 0,
0, 0, (farView + nearView) / nf, -1,
0, 0, (2 * farView * nearView) / nf, 0
]);
})();

var buf = gl.createBuffer();
gl.bindBuffer (gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1, -1,
1, 1,
-1, 1,
-1, -1,
1, 1,
1, -1,
]), gl.STATIC_DRAW);

gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);

var time = 0;

var translations = [];

for (var i = 0; i < 4096; i++){
translations.push(Math.random() * 10 - 5, Math.random() * 10 - 5);
}

var renderLoop = function (){
gl.clear(gl.CLEAR_COLOR_BIT | gl.CLEAR_DEPTH_BIT);

for (var i = 0; i < 4096; i++){

gl.uniform1f(u_time, time + i / 100);
gl.uniform2f(u_translate, translations[i * 2], translations[i * 2 + 1])

gl.drawArrays(gl.TRIANGLES, 0, 6);
}

window.requestAnimationFrame(renderLoop);
}

window.setInterval(function (){
time += 0.01;
}, 10);

window.requestAnimationFrame(renderLoop);
</script>

程序绘制了一堆正方形。在这种情况下,它是 4096 进行那么多的绘制调用。性能比我的主要项目好,但仍不是最佳的。 gpu 进程使用 ~13% 的 CPU,我以某种方式维持了售出的 60 FPS。当然,我所做的最多就是进行一些统一调用。我的真实项目使用了 5 个着色器程序,显然要处理更多的信息。我将尝试使用我用来渲染主游戏的 api 来编写它。也许还有改进的余地。

最佳答案

你有多少 block ?你说每个 block 是 16^3。所以这是 4096 个立方体或最多 49152 个三 Angular 形(如果通过某种魔法你可以显示每个立方体的每个面,我猜你不能)

我真的不知道怎么回答你的问题。我想首先要测试的是一个空程序运行多少 CPU

function render() {
requestAnimationFrame(render);
}

requestAnimationFrame(render);

我看几乎没有时间做那个。

那么,最小的 WebGL 程序怎么样

var gl = document.createElement("canvas").getContext("webgl");
document.body.appendChild(gl.canvas);

function resize(canvas) {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
}
}

function render() {
resize(gl.canvas);
gl.clearColor(Math.random(), 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { 
width: 100%;
height: 100%;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0
}
  

就这样我得到了一些相当高的数字

enter image description here

在绘图中添加 100 个 49k 多边形的球体(类似于您的 100 个 block )

"use strict";
// using twgl.js because I'm lazy
twgl.setAttributePrefix("a_");
var m4 = twgl.m4;
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

var shapes = [
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
twgl.primitives.createSphereBufferInfo(gl, 1, 157, 157),
];

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

// Shared values
var lightWorldPosition = [1, 8, -10];
var lightColor = [1, 1, 1, 1];
var camera = m4.identity();
var view = m4.identity();
var viewProjection = m4.identity();

var tex = twgl.createTexture(gl, {
min: gl.NEAREST,
mag: gl.NEAREST,
src: [
255, 255, 255, 255,
192, 192, 192, 255,
192, 192, 192, 255,
255, 255, 255, 255,
],
});

var randColor = function() {
var color = [Math.random(), Math.random(), Math.random(), 1];
color[Math.random() * 3 | 0] = 1; // make at least 1 bright
return color;
};

var r = function() {
return Math.random() * 2 - 1;
};

var objects = [];
var numObjects = 100;
for (var ii = 0; ii < numObjects; ++ii) {
var world = m4.translation([r(), r(), r()]);
var uniforms = {
u_lightWorldPos: lightWorldPosition,
u_lightColor: lightColor,
u_diffuseMult: randColor(),
u_specular: [1, 1, 1, 1],
u_shininess: 50,
u_specularFactor: 1,
u_diffuse: tex,
u_viewInverse: camera,
u_world: world,
u_worldInverseTranspose: m4.transpose(m4.inverse(world)),
u_worldViewProjection: m4.identity(),
};
objects.push({
ySpeed: rand(0.1, 0.3),
zSpeed: rand(0.1, 0.3),
uniforms: uniforms,
programInfo: programInfo,
bufferInfo: shapes[ii % shapes.length],
});
}

var showRenderingArea = false;

function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);

gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

var eye = [Math.cos(time) * 8, 0, Math.sin(time) * 8];
var target = [0, 0, 0];
var up = [0, 1, 0];

m4.lookAt(eye, target, up, camera);
m4.inverse(camera, view);

var projection = m4.perspective(
30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 100);
m4.multiply(view, projection, viewProjection);


objects.forEach(function(obj, ndx) {

var uni = obj.uniforms;
var world = uni.u_world;
m4.multiply(uni.u_world, viewProjection, uni.u_worldViewProjection);

gl.useProgram(obj.programInfo.program);
twgl.setBuffersAndAttributes(gl, obj.programInfo, obj.bufferInfo);
twgl.setUniforms(obj.programInfo, uni);
twgl.drawBufferInfo(gl, gl.TRIANGLES, obj.bufferInfo);
});
}

var renderContinuously = function(time) {
render(time);
requestAnimationFrame(renderContinuously);
}
requestAnimationFrame(renderContinuously);
* {
box-sizing: border-box;
-moz-box-sizing: border-box;
}
html, body {
margin: 0px;
width: 100%;
height: 100%;
font-family: monospace;
}
canvas {
width: 100%;
height: 100%;
}
#c {
position: fixed;
}
<canvas id="c"></canvas>
<script src="//twgljs.org/dist/twgl-full.min.js"></script>
<script id="vs" type="notjs">
uniform mat4 u_worldViewProjection;
uniform vec3 u_lightWorldPos;
uniform mat4 u_world;
uniform mat4 u_viewInverse;
uniform mat4 u_worldInverseTranspose;

attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

void main() {
v_texCoord = a_texcoord;
v_position = (u_worldViewProjection * a_position);
v_normal = (u_worldInverseTranspose * vec4(a_normal, 0)).xyz;
v_surfaceToLight = u_lightWorldPos - (u_world * a_position).xyz;
v_surfaceToView = (u_viewInverse[3] - (u_world * a_position)).xyz;
gl_Position = v_position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

uniform vec4 u_lightColor;
uniform vec4 u_diffuseMult;
uniform sampler2D u_diffuse;
uniform vec4 u_specular;
uniform float u_shininess;
uniform float u_specularFactor;

vec4 lit(float l ,float h, float m) {
return vec4(1.0,
abs(l),//max(l, 0.0),
(l > 0.0) ? pow(max(0.0, h), m) : 0.0,
1.0);
}

void main() {
vec4 diffuseColor = texture2D(u_diffuse, v_texCoord) * u_diffuseMult;
vec3 a_normal = normalize(v_normal);
vec3 surfaceToLight = normalize(v_surfaceToLight);
vec3 surfaceToView = normalize(v_surfaceToView);
vec3 halfVector = normalize(surfaceToLight + surfaceToView);
vec4 litR = lit(dot(a_normal, surfaceToLight),
dot(a_normal, halfVector), u_shininess);
vec4 outColor = vec4((
u_lightColor * (diffuseColor * litR.y +
u_specular * litR.z * u_specularFactor)).rgb,
diffuseColor.a);
gl_FragColor = outColor;
}
</script>

我的 GPU 进程使用率仅略有增加

enter image description here

所以看起来大部分时间基本上都花在处理 WebGL 上了。换句话说,问题似乎不是您的代码?

让我们尝试一些可能的优化(没有 alpha,没有抗锯齿)

var gl = document.createElement("canvas").getContext("webgl", {alpha: false, antialias: false});
document.body.appendChild(gl.canvas);

function resize(canvas) {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
}
}

function render() {
resize(gl.canvas);
gl.clearColor(Math.random(), 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { 
width: 100%;
height: 100%;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0
}

似乎已经下降了一点点。

enter image description here

看起来也许你应该 file a bug并询问为什么 Chrome 需要 2 个进程中的 20% 来显示 Canvas

注意:在 Chrome 的防御中,Firefox 也使用了大约相同数量的处理器能力(1 个处理器上 30-40%)。

另一方面,Safari 仅将 7% 用于最小的 WebGL 程序。

关于javascript - Chrome 和 Windows 的非最佳 WebGL 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31106321/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com