首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >three.js PointsMaterial性能缓慢-较大的精灵/形状会降低性能

three.js PointsMaterial性能缓慢-较大的精灵/形状会降低性能
EN

Stack Overflow用户
提问于 2017-09-22 07:22:00
回答 2查看 896关注 0票数 0

我正在处理一个大约有60.000个顶点的点云。

如果我渲染云“查看它很小”,性能是可以的,但是当我“放大”时,我在屏幕上看到大的精灵/平面/点,性能下降。

这可以使用PointsMaterialRawShaderMaterialPoints对象或instancedBufferGeometry网格来实现。

看起来,当渲染覆盖大部分画布的单个大形状时,性能会下降。

如果点具有透明纹理,则性能会下降得更糟。

我记得在处理过程中渲染大的重叠透明图像时也有类似的问题。

EN

回答 2

Stack Overflow用户

发布于 2017-09-22 22:07:04

就像Sedenion提到的,你最有可能是被限制了。这意味着你画的像素太多了。

GPU的绘图速度只能这么快。一个普通的非游戏GPU只能以每秒60帧的速度绘制6-10个充满像素的屏幕。如果你绘制更多的像素,它将运行太慢,即使那些是简单的像素(换句话说,即使你有简单的着色器)。对于普通的3D场景,通常会启用深度测试。通过首先绘制最近的东西,深度缓冲区将防止后面的东西被绘制,这有助于加快速度。但是,对于精灵,通常不使用深度测试。这意味着每个精灵中的每个像素都会被绘制,即使它们重叠。如果你把要绘制的像素数加起来,你会发现你很快就画得太多了。

这里有一个简单的例子,它只绘制了一个2048x2048的POINT的纯色,没有纹理。一个非常简单的着色器。向右拖动滑块以绘制更多点。在我2014年的Macbook Pro中,它只能在这个大小下绘制大约12个点,才不能再以60fps的速度运行。不同的GPU将能够或多或少地绘制。

代码语言:javascript
运行
复制
const vs = `
void main() {
  gl_Position = vec4(0, 0, 0, 1);
  gl_PointSize = 4000.0;
}
`
const fs = `
void main() {
  gl_FragColor = vec4(1./256., 0, 0, 1./256.);
}
`;

const gl = document.querySelector("canvas").getContext("webgl");
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);

let numPoints = 1;
const inputElem = document.querySelector('input');
const numPointsElem = document.querySelector('#numpoints');
const fpsElem = document.querySelector('#fps');
const numPixElem = document.querySelector('#numpix');
const pointSizeElem = document.querySelector('#ps');
const pointSize = Math.min(2048, gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE)[1]);
pointSizeElem.textContent = `${pointSize}x${pointSize}`;


inputElem.addEventListener('input', (e) => {
  updateValue(e.target.value);
});

function updateValue(value) {
  numPointsElem.textContent = value;
  numPixElem.textContent = frmt(value * pointSize * pointSize);
  numPoints = value;
};

updateValue(1);

let then = 0;
function render(now) {
  const deltaTime = now - then;
  then = now;
  const fps = 1000 / deltaTime;
  fpsElem.textContent = fps.toFixed(1);
  
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  gl.useProgram(programInfo.program);
  gl.drawArrays(gl.POINTS, 0, numPoints);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function frmt(v) {
  return [].map.call(v.toString(), a => a).reverse().map((a, n) => { return a + (n % 3 === 0 && n > 1 ? ',' : ''); }).reverse().join('');
}
代码语言:javascript
运行
复制
html { box-sizing: border-box; }
*, *:after, *:before { box-sizing: inherit; }
body {  margin: 0; font-family: monospace; }
canvas { width: 100vw; height: 100vh; display: block; }
#ui { 
  padding: 1em;
  position: absolute; 
  top: 0; 
  left: 0; 
  color: white; 
  background: rgba(0,0,0,0.9); 
  width: 100vw;
};
代码语言:javascript
运行
复制
<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
<canvas width="2048" height="2048"></canvas>
<div id="ui">
  <div><input type="range" min="1" max="500" value="1"></div>
  <div>number of points: <span id="numpoints">1</span></div>
  <div>point size: <span id="ps"></span></div>
  <div>number of pixels being drawn per frame: <span id="numpix"></span></div>
  <div>frames per second: <span id="fps"></span></div>
</div>

没有“简单”的解决方案。您需要找到一种方法来以某种方式绘制较少的像素。打开深度测试,并使您的点不混合可能是解决方案上的帮助。启用深度测试后,从前到后对点进行排序也会有所帮助。

票数 4
EN

Stack Overflow用户

发布于 2017-09-22 18:18:10

这与Three.js没有直接关系,更多的是与WebGL有关,更广泛地说是与GPU...您将在OpenGL或DirectX中观察到类似的行为。简单的答案是:你的GPU需要计算然后绘制一些东西,这需要时间。

现在让我们来看看一些细节。我不能保证你的减速问题与我将要解释的内容直接相关,但这是一些线索:

  1. 图形处理器需要绘制的像素越多,花费的时间就越多,这意味着如果一个简单的点-子画面覆盖整个画布区域,那么它将花费更长的时间来绘制,而如果它是3或4个像素宽的话。
  2. 由于您试图绘制“云”,我怀疑您禁用了深度测试,以允许所有的精灵通过透明度在前一个上面绘制。这意味着GPU必须在画布上多次绘制相同的像素,每次使用混合方程,对于覆盖画布一部分的每个精灵。
  3. 如果每个精灵都有纹理,则添加到点1.和2.纹理处理,使用纹理过滤,mipmap等。

你必须自己测试主要的瓶颈在哪里。有时,你无能为力,你必须在硬件限制下,通过减少精灵数量等方式进行合成。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46354608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档