画了很多圈-优化
Drawing a lot of circles - optimization
我有一个应用程序,当您在屏幕上按下时,该应用程序会在该位置创建一个圆圈并开始变大,直到达到最大大小并被删除。
如何优化我的代码以画很多圈?
Iterator<CircleShape> it = mCircles.iterator();
while (it.hasNext()) {
CircleShape shape = it.next();
if (shape.getScale().x <= shape.getMaxScale()) {
shape.setScale(shape.getScale().x + mGrowSpeed * smoothedDeltaRealTime_ms);
draw(shape);
} else {
it.remove();
}
}
圆是在片段着色器中通过丢弃我不需要的像素创建的:
void main()
{
float d = distance(v_texCoord, vec2(0.5, 0.5));
if (d > 0.5f)
discard;
gl_FragColor = uColor;
}
这是我的应用程序的图片:
首先你应该尝试分析你的瓶颈在哪里。我认为片段着色器仍然很重,但可以稍微优化一下。
您正在比较使用通常较慢的平方根的距离。尝试做
vec2 vector = v_texCoord - vec2(0.5, 0.5);
if(vector.x*vector.x + vector.y*vector.y > 0.5*0.5) // or 0.25
在这种情况下,如果您不使用深度缓冲区,它可能会对您有所帮助。如果您不使用它,我假设您按照从最旧(最宽)到最新的顺序绘制圆圈。这意味着它实际上会为每个圆圈绘制所有片段,然后新的将在旧的圆圈上重新绘制。您可以启用深度缓冲区,并且当您增加圆圈的大小时,您也可以将其进一步放在 z
坐标中。现在将绘制顺序从最新更改为最旧,这样背景中的那些圆就不会绘制在前一个圆已经显示的位置。也不要忘记清除深度缓冲区。
还有一些其他潜在的优化,例如在您的情况下,您可能只在表示尺寸增加的圆圈周围绘制笔划,而不清除颜色缓冲区。但这意味着实际创建用于绘制具有定义宽度的笔画圆的顶点,这至少会增加顶点部分的负载,但会严重降低光栅化和绘制的片段数量。在这种方法中,您将需要一个深度缓冲区,但是一旦出现新的圆圈,您还需要推回当前的深度缓冲区……可以通过一次屏幕重绘来完成,但要正确完成这是一项艰巨的任务。
我能想到的另一种方法实际上是为圆心、颜色和半径设置一个统一的数组,可以将其馈送到片段着色器。然后在片段着色器中遍历数组并检查哪个圆表示实际上是您应该在该特定像素处绘制的那个并使用它的颜色(如果无效则简单地丢弃以保留当前背景颜色)。这意味着在整个视图中只绘制一个矩形。没有深度缓冲区,不需要清除颜色缓冲区。这对于片段着色器来说可能很重,但是片段的数量会严重减少,因此它可能会给您带来相当大的性能提升(或没有)。
我有一个应用程序,当您在屏幕上按下时,该应用程序会在该位置创建一个圆圈并开始变大,直到达到最大大小并被删除。
如何优化我的代码以画很多圈?
Iterator<CircleShape> it = mCircles.iterator();
while (it.hasNext()) {
CircleShape shape = it.next();
if (shape.getScale().x <= shape.getMaxScale()) {
shape.setScale(shape.getScale().x + mGrowSpeed * smoothedDeltaRealTime_ms);
draw(shape);
} else {
it.remove();
}
}
圆是在片段着色器中通过丢弃我不需要的像素创建的:
void main()
{
float d = distance(v_texCoord, vec2(0.5, 0.5));
if (d > 0.5f)
discard;
gl_FragColor = uColor;
}
这是我的应用程序的图片:
首先你应该尝试分析你的瓶颈在哪里。我认为片段着色器仍然很重,但可以稍微优化一下。
您正在比较使用通常较慢的平方根的距离。尝试做
vec2 vector = v_texCoord - vec2(0.5, 0.5);
if(vector.x*vector.x + vector.y*vector.y > 0.5*0.5) // or 0.25
在这种情况下,如果您不使用深度缓冲区,它可能会对您有所帮助。如果您不使用它,我假设您按照从最旧(最宽)到最新的顺序绘制圆圈。这意味着它实际上会为每个圆圈绘制所有片段,然后新的将在旧的圆圈上重新绘制。您可以启用深度缓冲区,并且当您增加圆圈的大小时,您也可以将其进一步放在 z
坐标中。现在将绘制顺序从最新更改为最旧,这样背景中的那些圆就不会绘制在前一个圆已经显示的位置。也不要忘记清除深度缓冲区。
还有一些其他潜在的优化,例如在您的情况下,您可能只在表示尺寸增加的圆圈周围绘制笔划,而不清除颜色缓冲区。但这意味着实际创建用于绘制具有定义宽度的笔画圆的顶点,这至少会增加顶点部分的负载,但会严重降低光栅化和绘制的片段数量。在这种方法中,您将需要一个深度缓冲区,但是一旦出现新的圆圈,您还需要推回当前的深度缓冲区……可以通过一次屏幕重绘来完成,但要正确完成这是一项艰巨的任务。
我能想到的另一种方法实际上是为圆心、颜色和半径设置一个统一的数组,可以将其馈送到片段着色器。然后在片段着色器中遍历数组并检查哪个圆表示实际上是您应该在该特定像素处绘制的那个并使用它的颜色(如果无效则简单地丢弃以保留当前背景颜色)。这意味着在整个视图中只绘制一个矩形。没有深度缓冲区,不需要清除颜色缓冲区。这对于片段着色器来说可能很重,但是片段的数量会严重减少,因此它可能会给您带来相当大的性能提升(或没有)。