Javascript three.js Points材质性能降低-大精灵/形状降低性能

Javascript three.js Points材质性能降低-大精灵/形状降低性能,javascript,performance,three.js,webgl,Javascript,Performance,Three.js,Webgl,我正在处理一个大约有60000个顶点的点云 如果我渲染云“查看它很小”,性能是可以的,但当我“放大”并在屏幕上看到大精灵/平面/点时,性能会下降 使用PointsMaterial或RawShaderMaterial、Points对象或instancedBufferGeometry网格时会发生这种情况 看起来,当渲染覆盖大部分画布的单个大型形状时,性能会下降 如果点具有透明纹理,则性能会下降 我记得在处理过程中渲染大的重叠透明图像时遇到了类似的问题。这与Three.js没有直接关系,更多的是与We

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

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

使用
PointsMaterial
RawShaderMaterial
Points
对象或
instancedBufferGeometry
网格时会发生这种情况

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

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


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

这与Three.js没有直接关系,更多的是与WebGL有关,更普遍的是与GPU有关。。。您将观察到OpenGL或DirectX的类似行为。简单的回答是:你的GPU需要计算然后画一些东西,这需要时间

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

  • GPU必须绘制的像素越多,所需时间就越长,这意味着如果一个简单的点精灵覆盖整个画布区域,则绘制所需时间将比绘制3或4像素宽的点精灵所需时间更长

  • 由于您尝试绘制“云”,我怀疑您禁用了深度测试,以允许通过透明度在前一个精灵的上方绘制所有精灵。这意味着GPU必须在画布上绘制相同的像素多次,每次都使用混合方程,用于覆盖画布一部分的每个精灵

  • 如果每个精灵都有纹理,则添加到点1。二,。纹理处理,纹理过滤,mipmap等


  • 您必须自己测试主要瓶颈所在的位置。有时,您无能为力,必须在硬件限制范围内,通过减少精灵数量等方式进行创作。

    这与Three.js没有直接关系,更多的是与WebGL,更普遍的是与GPU没有直接关系。。。您将观察到OpenGL或DirectX的类似行为。简单的回答是:你的GPU需要计算然后画一些东西,这需要时间

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

  • GPU必须绘制的像素越多,所需时间就越长,这意味着如果一个简单的点精灵覆盖整个画布区域,则绘制所需时间将比绘制3或4像素宽的点精灵所需时间更长

  • 由于您尝试绘制“云”,我怀疑您禁用了深度测试,以允许通过透明度在前一个精灵的上方绘制所有精灵。这意味着GPU必须在画布上绘制相同的像素多次,每次都使用混合方程,用于覆盖画布一部分的每个精灵

  • 如果每个精灵都有纹理,则添加到点1。二,。纹理处理,纹理过滤,mipmap等


  • 您必须自己测试主要瓶颈所在的位置。有时,您无能为力,必须在硬件限制范围内,通过减少精灵数量等方式进行创作。

    正如Sedenion提到的,您很可能会受到填充率限制。这意味着你画的像素太多了

    GPU只能画得这么快。一个普通的非玩家GPU只能以每秒60帧的速度绘制6-10个满是像素的屏幕。如果绘制的像素数超过该值,则即使这些像素中有一个是简单像素,它也会运行得太慢(换句话说,即使您有简单的着色器)。对于普通3D场景,通常启用深度测试。通过先绘制最接近的对象,深度缓冲区将防止绘制后面的对象,这有助于加快绘制速度。对于精灵,通常不使用深度测试。这意味着绘制每个精灵的每个像素,即使它们重叠。如果将绘制的像素数相加,您会发现绘制的像素太多

    下面是一个简单的示例,它仅以纯色绘制一个2048x2048
    ,没有纹理。一个非常简单的着色器。向右拖动滑块以绘制更多点。在我的2014款Macbook Pro中,它只能在该尺寸下绘制约12个点,然后才能以60 fps的速度运行。不同的GPU将能够或多或少地绘制图形

    const vs=`
    void main(){
    gl_位置=vec4(0,0,0,1);
    gl_PointSize=4000.0;
    }
    `
    常数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]);
    设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(即target.value);
    });
    函数updateValue(值){
    numPointsElem.textContent=值;
    numPixElem.textContent=frmt(值*点大小*点大小);
    numPoints=值;
    };
    更新值(1);
    然后设=0;
    函数渲染(现在){
    常数deltaTime=现在-那时;
    然后=现在;
    常数fps=1000/增量时间;
    fpsElem.textContent=fps.toFixed(1);
    总账启用(总账混合);
    gl.blendFunc(gl.ONE,gl.ONE减去SRCα);
    总账使用程序(programInfo.program);
    总图数组(总图点、0、numPoints);
    请求动画帧(渲染);
    }
    请求动画帧(渲染);
    功能frmt(五){
    return[].map.call(v.toString(),a=>a).reverse().map((a,n)=>{return a+(n%3===0&&n>1?',':'';}).reverse().join('');
    }
    html{框大小:边框框;}
    *,*:在,*:在{b