Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 优化重叠矩形的绘制_Javascript_Algorithm_Math_Webgl_Spatial Index - Fatal编程技术网

Javascript 优化重叠矩形的绘制

Javascript 优化重叠矩形的绘制,javascript,algorithm,math,webgl,spatial-index,Javascript,Algorithm,Math,Webgl,Spatial Index,我有大量的矩形,有些与其他矩形重叠;每个矩形都有一个绝对z顺序和一种颜色。(每个“矩形”实际上是粒子效果、网格或纹理的轴对齐边界框,可能是半透明的。但是,抽象地思考彩色矩形更容易,只要你不尝试在其他矩形后面剔除矩形,因此我将在问题描述中使用它:) 改变“颜色”的成本相当高;连续绘制两个蓝色矩形比绘制两个不同颜色的矩形要快得多 绘制不在屏幕上的矩形的成本也相当高,应该避免 如果两个矩形不重叠,则它们相对于彼此绘制的顺序并不重要。只有当它们重叠时,z顺序才是重要的 例如: 1(红色)和4(红色)可

我有大量的矩形,有些与其他矩形重叠;每个矩形都有一个绝对z顺序和一种颜色。(每个“矩形”实际上是粒子效果、网格或纹理的轴对齐边界框,可能是半透明的。但是,抽象地思考彩色矩形更容易,只要你不尝试在其他矩形后面剔除矩形,因此我将在问题描述中使用它:)

改变“颜色”的成本相当高;连续绘制两个蓝色矩形比绘制两个不同颜色的矩形要快得多

绘制不在屏幕上的矩形的成本也相当高,应该避免

如果两个矩形不重叠,则它们相对于彼此绘制的顺序并不重要。只有当它们重叠时,z顺序才是重要的

例如:

1(红色)和4(红色)可以画在一起。2(蓝色)和5(蓝色)也可以画在一起,3(绿色)和7(绿色)也可以画在一起。但8(红色)必须在6(蓝色)之后绘制。所以要么我们把三个红色画在一起,把蓝色画成两组,要么我们把所有蓝色画在一起,把红色画成两组

一些矩形可能会偶尔移动。(并非所有矩形;已知某些矩形是静态的;已知其他矩形是移动的。)

我将在JavaScript/webGL中绘制此场景

如何以合理的顺序绘制矩形以最小化颜色变化,并在JavaScript剔除代码与允许GPU剔除代码之间进行良好的权衡

(仅仅计算出哪些矩形重叠,哪些是可见的是昂贵的。我有一个很好的方法,这大大加快了我的场景绘制速度(与只为整个场景发出绘制操作相比);现在的问题是如何最大限度地减少OpenGL状态更改和连接属性数组)

更新我创建了一个非常简单的测试应用程序来说明问题,并作为演示解决方案的基础:

源代码位于github上,可以很容易地进行分叉:

事实证明,很难制作一个状态变化足够大的小测试应用程序来真正重现我在整个游戏中看到的问题。在某种程度上,您必须将状态更改视为一个给定的过程,因为状态更改可能会非常昂贵。同样重要的是如何加速空间索引(演示中的四叉树)和总体方法

选择颜色,而不是盒子! 在任何时候,一个或多个箱子都可以喷漆,也就是说,下一个箱子可以喷漆,而不会带来问题(尽管可能会因为与最近喷漆的箱子颜色不同而带来成本)

每一点上的问题都是:下一步我们应该选择什么颜色?不必考虑选择单个可绘制的框进行绘制,因为一旦选择了下一个要绘制的特定框,您就可以绘制当时可以绘制的相同颜色的所有可用框。这是因为绘制长方体不会给问题添加约束,它只会移除约束;如果在不改变当前颜色的情况下选择不绘制可绘制的盒子,则无法降低解决方案的成本,因为您以后必须绘制该盒子,并且可能需要更改颜色。这也意味着,我们以何种顺序绘制相同颜色的可绘制盒子并不重要,因为我们将在盒子绘制操作的单个“块”中一次性绘制所有盒子

依赖关系图 首先构建一个“位于下方”依赖关系图,其中每个彩色矩形由一个顶点表示,如果矩形v与矩形u重叠并位于其下方,则从v到u有一条弧(箭头)。我的第一个想法是通过找到传递闭包来构建“必须在之前绘制”依赖关系图,但实际上我们不需要这样做,因为下面所有的算法都关心顶点是否可绘制。可绘制顶点是没有前导的顶点(在圆弧中),采用传递闭包不会改变顶点在圆弧中是否为0

此外,当一个给定颜色的盒子只有与它的祖先相同颜色的盒子时,它将被画在同一个“块”中——因为所有这些祖先都可以在它之前画,而不改变颜色

加速 为了减少计算量,请注意,只要某一特定颜色的所有可绘制框没有不同颜色的后代,绘制此颜色不会为其他框打开任何可绘制的新机会,所以当我们考虑下一种颜色的时候,我们不需要考虑这种颜色——我们可以把它留到后来,没有增加成本的风险。事实上,最好等到以后再画这种颜色,因为到那时这种颜色的其他盒子可能已经可以画了。如果至少有一个颜色的可绘制框具有不同颜色的后代,则称该颜色为“有用”。当我们到了没有剩余有用颜色的时候(即,当所有剩余的盒子只重叠相同颜色的盒子,或者根本没有盒子),我们就完成了:只需为每个剩余颜色的盒子上漆,按任何顺序挑选颜色

算法 这些观察结果提出了两种可能的算法:

  • 一种快速但可能次优的贪婪算法:选择绘制下一个颜色,以生成最新的可绘制顶点。(这只会自动考虑有用的颜色)
  • < > >强>一个较慢的、精确的DP或递归算法:对于每一个可能有用的颜色C,考虑通过绘制所有可着色的C颜色框的依赖图:

    设f(g)为绘制依存关系图g中所有方框所需的最小颜色变化次数。然后

    f(g)=1+mi
    For all rectangles, back to front:
      If this rectangle has been marked as drawn, skip to the next one
      Set a screen-sized unseen surface to all black
      Call this rectangle's color "the color"
      For rectangles starting with this one and proceeding toward the front
        If (this rectangle's color is the color and
            all the pixels of this rectangle on the unseen are black) then
          Add this rectangle to the to-draw list
        Draw a white rectangle with this rectangle's shape on the unseen surface
        If the unseen surface is more than half white, break
      For all rectangles on the to-draw list:
        Draw the rectangle
        Mark it as drawn