- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
作为对自己的挑战,我正在使用 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
}
就这样我得到了一些相当高的数字
在绘图中添加 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 进程使用率仅略有增加
所以看起来大部分时间基本上都花在处理 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
}
似乎已经下降了一点点。
看起来也许你应该 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/
非常简单的问题 - 是否可以通过 Chromium 创建 google chrome 扩展,并让在不同操作系统上运行 Chrome 的人使用相同的扩展? 我正在Ubuntu上开发。 最佳答案 是的,完
我了解 chrome.bookmarks API(记录在 http://goo.gl/tIb6V6 )旨在用于开发访问/操作我的 Chrome 书签的 Chrome 扩展程序(当然要在 Chrome
在比较开源浏览器 Firefox 和 Chromium 的扩展、附加组件和列表时,我试图找到一些有趣的数据。 我感兴趣的是多宿主扩展(两个浏览器列表上都可用的扩展)。 但是当浏览 Chromium 扩
使用新的 chrome.notifications API,我无法从我的扩展程序中获取通知以显示。即使是最基本的通知也无法为我显示,但我没有收到任何错误,并且回调函数已正确执行。 list .json
我正在构建一个在 Chrome 上运行的信息亭媒体,可以播放带音频的视频。我知道默认情况下,chrome 只允许自动播放带有静音 Prop 的视频。 而且我知道我可以通过 chrome://flags
我从来没有真正写过 真实 Chrome 扩展程序。不久前我做了一个只是一个链接下拉列表,但这并不重要。无论如何,与其先回到关于编写 Chrome 扩展程序的大量教程中,不如先确保我的想法是可行的。 我
主要目的是在单个容器中运行多个 chrome 浏览器(9 个浏览器)。 我有一个集线器和节点设置,其中包含多个浏览器的容器,可在单个 chrome 节点容器中运行。我使用以下 docker 命令创建了
我想写一个小的 chrome 扩展程序,它应该从网页 A(当前网页)获取信息,将选项卡更新到网页 B,然后将代码注入(inject)网页 B。不幸的是,以下代码正在将网页更新到 B 但注入(injec
是否可以打开 Chrome 开发者工具来检查 Chrome 应用? 最佳答案 所有可调试目标都列在 chrome://inspect/ 下。请参阅“应用程序”标签。 关于google-chrome -
我正在为 Google Chrome 开发一个应用程序,我想知道如何收费。 问题是我住在巴西,在这个链接上它告诉我它不支持 Chrome 网上应用店付款。如果没有 Chrome 网上商店付款,我可以通
我刚刚更新到 Chrome 32.0.1700.76 m(在 Win7 上)并且开发人员工具已更改。 特别令人痛苦的是用于检查页面元素的放大镜图标消失了。也没有提到它的快捷方式列表。 任何人都知道这已
我在 chrome-extension API (chrome.webrequest) 中遇到问题。 我的 list .json { "name": "tesst", "version": "
我已经制作了 chrome 主机来在我的扩展程序和我的进程之间传递 native 消息,我的进程在 chrome 启动时启动,但在我关闭 chrome 时不关闭,我应该向主机的 list 添加参数还是
文档对此非常不清楚。我知道如果您自己托管您的扩展程序,您可以通过增加版本号来自动更新您的扩展程序。但是,我不知道您是否可以在仍发布到 chrome 网上商店的同时进行自托管。 我不敢相信 Google
我最近一直在使用 Selenium WebDriver。我还专门与 chromedriver 合作。每当我打开一个新的 chrome 窗口 (driver.get(url)) 时,Chrome 都会以
我指的是chrome://flags 我很想知道是否可以通过自定义 chrome 扩展启用或禁用特定的 chrome 标志? 例如-我想启用 Enable Media Source API on e
当我在 chrome 开发者仪表板上向我的扩展程序上传更新时, 它无法这样做,它显示, An error occurred: Failed to process your item. Chrome W
我正在尝试编写一个需要用户身份验证的 chrome 扩展。 Google's tutorial建议我需要先上传到网上商店才能获得 key : Login to the Google APIs Cons
我已经开发了一个 Chrome 扩展程序并且我已经打包了它。 我将我的扩展程序发送给一些人试用,但 Chrome 开始阻止它在商店中找不到的扩展程序。 有没有办法安装我的扩展程序而不会被 Chrome
某些 Chrome 扩展不适用于 Chromium。例如:http://code.google.com/chrome/extensions/samples.html#5d81304a17cf7ac28
我是一名优秀的程序员,十分优秀!