opengl: How to display a comet and path traced by it?
我正在尝试使用 freeglut 进行一些 opengl 编程。假设一个在 3D 空间中移动的对象(彗星/飞机),我想将其追踪的路径渲染为点云(表示飞机留下的白色轨迹)。
我的问题是,每次调用 glutDispFunc 时,我都需要使用 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) 清除屏幕,以便让飞机移动(我正在使用键盘功能来改变飞机的位置)。但是,我还需要显示大量点,这些点会随着飞机移动而不断累积。我尝试过使用
清除屏幕
1 | glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
随着点数的增加会导致性能严重下降,但可以显示移动平面以及点云。有谁知道如何处理这种情况?
是的,您每次都清除屏幕并重新绘制所有内容。这就是游戏引擎的工作量。
However I also need to display a huge number of points which go on accumulating as the plane moves.I have tried with clear screen using
你可能试图绘制太多的粒子。 100 个粒子(或几百个,但不到一千个)应该足以绘制彗星轨迹。只需 200 (BIG) 个粒子,您就可以制作出令人信服的云。
另外,绘制彗星轨迹不需要积分。使用 alpha 混合,您可以使用三角形轻松绘制半透明的光剑状线条。
类光剑、等离子、类火焰应使用任何带有少量白色的颜色(例如 rgb 255、10、10),并且传统上使用
绘制
这里有几个例子。示例显示您应该使用的三角形网格。数字表示阿尔法。 0 - 完全透明,1 - 完全不透明。必要时,斜线表示三角测量。"|"和"-"表示面边缘:
发光线
1 2 3 4 5 6 7 8 9 10 11 12 13 | 0--0--0--0 | \\| | /| 0--1--1--0 | /| | \\| 0--0--0--0 repeat 0--0 | | 1--1 | | 0--0 to add more segments |
发光的粗线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 0--0--0--0 | \\| | /| 0--1--1--0 | | | | 0--1--1--0 | /| | \\| 0--0--0--0 repeat 0--0 | | 1--1 | | 1--1 | | 0--0 to add more segments. |
您可以将类似的东西用于彗星轨迹。并添加一些小颗粒以产生火花或其他东西。
也不要忘记纹理。使用纹理可以轻松添加更多细节,而不是尝试使用无纹理几何图形绘制所有内容。
--编辑--
aeroplane's white trail
实现任何类型的烟雾...
是的,大多数游戏都是通过擦除屏幕并在每一帧重新绘制它来工作的。但是,也可以减少每帧的工作量。屏幕上除了轨迹还有别的吗?这条路应该有多长?它是否必须随着时间的推移保持恒定的长度(而不是像鼠标轨迹那样随着时间的推移逐渐消失)?
如果您有能力淡出您的踪迹,您可以使用缓冲反馈。此技术在相关屏幕(或对象轨迹)上呈现半透明四边形,其效果是将尾部的最远部分淡化为背景颜色。然后在新位置绘制对象,再次创建尾部最亮的部分。这是一个相当常见的演示/可视化效果,可以创建非常漂亮的尾巴,每帧绘制开销很小。
这可能不是你所需要的(我在你澄清你的需要之前写了这个作为对@SigTerm 答案的评论),但我将把它留在这里,因为其他人可能需要这种"线索"。
如果您还没有使用它们,您应该使用 glDrawArrays 进行绘制,例如,它采用一组点,并且只需一个函数调用即可绘制所有内容。它比直接绘图 API(glBegin 和 glEnd)快得多。你可以这样设置:
1 2 3 4 | float points[100][3]; int pointsCount = 0; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), points); |
然后,每次对象"产生"一个点(例如,每一帧),您可以将其位置添加到数组中:
1 2 3 4 | points[pointsCount][0] = object.x; points[pointsCount][1] = object.y; points[pointsCount][2] = object.z; pointsCount++; |
然后,像这样画它们:
1 | glDrawArrays(GL_POINTS, 0, pointsCount); |
当然,当数组填满时你必须做一些事情,但你明白了。
还有 VBO,可以进一步提高速度,但是是更高级的功能。
编辑:是的,您应该使用此方法重绘所有内容。我会说它仍然不会比 glBegin/End 影响更多的点数。根据此处的答案,您应该能够使用 glBufferData 调整缓冲区的大小,但可能必须将当前数据存储在数组中,并在调整大小后将其传回。