我想知道如何优化我的画圆方法。在将顶点发送到opengl之前,我寻求如何尽快生成顶点。
void DrawCircle(float x, float y, float radius, Color color, float thickness)
{
int numOfPoints = 100;
for (float i = 0; i < numOfPoints; ++i) {
float pi2 = 6.28318530718;
float angle = i / numOfPoints * pi2;
FillRect(
cos(angle) * radius + x,
sin(angle) * radius + y,
thickness,
thickness,
color);
}
}
FillRect函数只绘制一个四边形,因此DrawCircle函数绘制100个四边形,这些四边形按cos、sin和半径移动。
FillRect(float x, float y, float w, float h, Color color)
我怎么能以不同的方式画圆呢?
在您的评论中,您提到您正在使用OpenGL进行渲染(假设旧的API),所以使用单独的GL_QUADS
是您的问题。当你做OpenGL调用你的圆的每个单独的“像素”。这通常比渲染本身慢得多。有什么选择来解决这个问题?
>
VBO
这是您的最佳选择,只需创建VBO,其中包含cos(a)、sin(a)
单位圆点,并渲染为单个glDrawArray
调用(应用变换矩阵将单位圆变换到所需的位置和半径)。这应该几乎和单个GL_QUADS
调用一样快。。。(除非每个圆有太多的点)但会丢失厚度(除非组合2个圆和模具…)。在这里:
您可以找到如何在OpenGL中使用VAO/VBO。另请参见如何制作孔(厚度):
GL\u-LINE\u-LOOP
您可以使用粗线条而不是矩形,这样可以将glVertex
调用从每“像素”4个减少到1个。它看起来像这样:
void DrawCircle(float x, float y, float radius, Color color, float thickness)
{
const int numOfPoints = 100;
const float pi2=6.28318530718; // = 2.0*M_PI
const float da=pi2/numOfPoints;
float a;
glColor3f(color.r,color.g,color.b);
glLineWidth(thickness/2.0);
glBegin(GL_LINE_LOOP);
for (a=0;a<pi2;a+=da) glVertex2f(cos(a)*radius + x, sin(a) * radius + y);
glEnd();
glLineWidth(1.0);
}
因为我不知道如何组织颜色
,所以颜色设置可能会更改。此外,glLineWidth
不保证适用于任意厚度。。。
如果你仍然想使用GL_QUADS
,那么至少把它转到GL_QUAD_STRIP
,这将需要一半的glVertex
调用...
void DrawCircle(float x, float y, float radius, Color color, float thickness)
{
const int numOfPoints = 100;
const float pi2=6.28318530718; // = 2.0*M_PI
const float da=pi2/numOfPoints;
float a,r0=radius-0.5*thickness,r1=radius+0.5*thickness,c,s;
int e;
glColor3f(color.r,color.g,color.b);
glBegin(GL_QUAD_STRIP);
for (e=1,a=0.0;e;a+=da)
{
if (a>=pi2) { e=0; a=pi2; }
c=cos(a); s=sin(a);
glVertex2f(c*r0 + x, s * r0 + y);
glVertex2f(c*r1 + x, s * r1 + y);
}
glEnd();
}
着色器
您甚至可以创建着色器,将圆的中心、厚度和半径作为输入(作为统一体),并通过围绕圆渲染单个四边形bbox来使用它。然后,内部碎片着色器丢弃圆周长以外的所有碎片。大概是这样的:
实现#2是最简单的。使用#1需要一些工作,但如果你知道如何使用VBO,就不会太多。#3也不太复杂,但如果你没有任何着色器的经验,可能会造成问题...
由于您明确要求优化生成顶点坐标的方法,我将为此提出一个解决方案。然而,看看一些基准测量(见下面的演示链接),我不相信这真的是任何性能问题的原因...
您可以使用旋转矩阵递归地计算以(0,0)为中心的圆上的顶点:
// Init
X(0) = radius;
Y(0) = 0;
// Loop body
X(n+1) = cos(a) * X(n) - sin(a) * Y(n);
Y(n+1) = sin(a) * X(n) + cos(a) * Y(n);
这将替换循环中的cos
和sin
计算,而只使用少量浮点乘法、加法
void DrawCircle(float x, float y, float radius, Color color, float thickness) {
int numOfPoints = 100;
float pi2 = 6.28318530718;
float fSize = numOfPoints;
float alpha = 1 / fSize * pi2;
// matrix coefficients
const float cosA = cos(alpha);
const float sinA = sin(alpha);
// initial values
float curX = radius;
float curY = 0;
for (size_t i = 0; i < numOfPoints; ++i) {
FillRect(curX + x, curY + y, thickness, thickness, color);
// recurrence formula
float ncurX = cosA * curX - sinA * curY;
curY = sinA * curX + cosA * curY;
curX = ncurX;
}
}
现场演示
使用独占递归的缺点是,每次迭代都会累积微小的计算错误。如演示所示,在100次迭代中,错误是微不足道的。
问题内容: 我一直在使用一个简单的动画上。但是,当观看动画时,我会遇到难以置信的震荡。我应该采取什么步骤来优化此代码? 不知道这是否重要,但是我正在使用OpenJDK 1.8.0_121版本。 任何帮助表示赞赏。 问题答案: 在与Yago进行了精彩的讨论之后,我发现问题围绕多个领域展开,很大程度上归因于Java将更新与操作系统和硬件同步的能力,有些是您可以控制的,有些是无法控制的。 受到Yago的
如何清理linux不需要的软件包
有时候你会遇到循环,或者递归函数,它们会花费很长的执行时间,可能是你的产品的瓶颈。在你尝试使循环变得快一点之前,花几分钟考虑是否有可能把它整个移除掉,有没有一个不同的算法?你可以在计算时做一些其他的事情吗?如果你不能找到一个方法去绕开它,你可以优化这个循环了。这是很简单的,move stuff out。最后,这不仅需要智慧而且需要理解每一种语句和表达式的开销。这里是一些建议: 删除浮点运算操作。
这样一堆 if 合理吗?后面还会加判断,会更多。 再拆分的话感觉不太好,有更好的方法吗?
本文向大家介绍js如何性能优化?相关面试题,主要包含被问及js如何性能优化?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 减少HTTP请求 使用内容发布网络(CDN) 添加本地缓存 压缩资源文件 将CSS样式表放在顶部,把javascript放在底部(浏览器的运行机制决定) 避免使用CSS表达式 减少DNS查询 使用外部javascript和CSS 避免重定向 图片lazyLoad
本文向大家介绍MySQL如何优化索引,包括了MySQL如何优化索引的使用技巧和注意事项,需要的朋友参考一下 1. MySQL如何使用索引 索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后遍历整个表以找到相关的行。表越大,花费越多。如果表中有相关列的索引,MySQL可以快速确定要在数据文件中间查找的位置,而不必查看所有数据。这比顺序读取每一行要快得多。 大多数MyS