如何在openGL中制作一步一步的显示动画?

Posted

技术标签:

【中文标题】如何在openGL中制作一步一步的显示动画?【英文标题】:How to make a step by step display animation in openGL? 【发布时间】:2012-10-21 21:13:59 【问题描述】:

我正在做一个 reprap 打印机项目来读取 GCode 文件并将其解释为图形。 现在我很难一步一步地绘制整个对象的动画。 我需要画很多短线来组成一个完整的对象。 例如:

|-----|
|     |
|     |
|-----|

方块由许多短线组成,每条线由如下代码生成:

glPushMatrix();
.....
for(int i=0; i< instruction[i].size(),i++)
  ....
   glBegin(GL_LINES);
     glVertex3f(oldx, oldy, oldz);
     glVertex3f(x, y, z);
   glEnd();

glPopMatrix();

现在我想制作一个步进动画来展示这个正方形是如何制作的。每次绘制新线时我都尝试刷新屏幕,但它不起作用,整个正方形立即出现。有人知道怎么做吗?

【问题讨论】:

【参考方案1】:

典型的 OpenGL 实现会将大量调用排队,以将它们批量处理成突发的活动,以充分利用可用的通信带宽和 GPU 时间资源。

您想要做的基本上与双缓冲渲染相反,即在每个绘图步骤立即可见的地方进行渲染。一种方法是渲染到单个缓冲窗口并在每一步之后调用glFinish()。主要缺点:在使用合成窗口管理器等的现代系统上可能无法正常工作。

我推荐的另一种方法是使用单独的缓冲区进行增量绘制,并不断刷新主帧缓冲区。关键主题是Frame Buffer ObjectRender To Texture

首先,您创建一个 FBO(大量教程以及 *** 上的答案)。 FBO 基本上是一种抽象,您可以将目标缓冲区(如纹理或渲染缓冲区)连接到它,并且可以将其绑定为绘图调用的目标。

那么如何解决您的问题呢?首先,您不应该通过延迟绘图循环来制作动画。这有几个原因,但主要问题是,您因此失去了程序的交互性。相反,您在动画中的哪一步维护一个(全局)计数器。我们就叫它step

int step = 0;

然后在您的绘图功能中,您必须分阶段进行:1)纹理更新 2)屏幕刷新

第一阶段包括将帧缓冲区对象绑定为渲染目标。为此,目标纹理必须是未绑定的

glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, animFBO);
glViewport(0, 0, fbo.width, fbo.height);
set_animFBO_projection();

现在的诀窍是,您只清除一次 animFBO,即在创建之后,然后再也不清除。现在您根据动画步骤绘制线条

draw_lines_for_step(step);

并增加计步器(可以作为复合语句执行此操作,但更明确)

step++;

更新动画 FBO 后,是时候更新屏幕了。首先解绑animFBO

glBindFramebuffer(GL_FRAMEBUFFER, 0);

我们现在位于主要的屏幕帧缓冲区

glViewport(0, 0, window.width, window.height);
set_window_projection(); //most likely a glMatrixMode(GL_PROJECTION); glOrtho(0, 1, 0, 1, -1, 1);

现在绑定 FBO 附加纹理并将其绘制到一个完整的视口四边形

glBindTexture(GL_TEXTURE_2D, animFBOTexture);
draw_full_viewport_textured_quad();

最后做缓冲区交换以显示动画步骤迭代

SwapBuffers();

【讨论】:

【参考方案2】:

您应该在每次绘制调用后调用 SwapBuffer 方法。 确保你没有搞砸矩阵堆栈,你可能需要一些东西来“暂停”渲染,比如断点。

【讨论】:

交换缓冲区调用很可能会破坏后台缓冲区的内容,因此无法继续绘制。 SwapBuffer 不起作用,不知道是坐标文件太大还是其他原因。程序一直处于运行状态,屏幕上什么也没有显示....但还是谢谢!【参考方案3】:

如果您只想让线条一个接一个地出现,并且不必对效率或良好的编程风格挑剔,请尝试以下方法:

(在您的绘图程序中)

if (timer &gt; 100)

//draw the next line

timer = 0;

else

timer++;

//draw all the other lines (you have to remember wich one already appeared)

//for example using a boolean array "lineDrawn[10]"

计时器是一个整数,它告诉您绘制场景的频率。如果你把它变大,当你运行你的程序时,屏幕上的东西会变得更慢。

当然,这只有在你有一个绘图例程时才有效。如果没有,我强烈建议使用一个。

->到处都有很多教程,例如

http://nehe.gamedev.net/tutorial/creating_an_opengl_window_%28win32%29/13001/

祝你好运!

PS:我认为您的做法几乎相同,但没有计时器。这就是为什么所有东西都画得如此之快,以至于你认为它同时出现。

【讨论】:

以上是关于如何在openGL中制作一步一步的显示动画?的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅强烈推荐一款强大的 Android OpenGL ES 调试工具 GAPID并展示实战操作演练一步一步看如何使用GAPID调试工具

求一步一步教PHP留言板制作方法

一步一步的django学习---003

在 Silverlight 中实现登录和注册表单动画

带你一步一步的解析ARouter 源码

需要一步一步的 WCF 作为 Windows 服务