Recording DirectX and OpenGL Rendered Animations(翻译)
记录DirectX和OpenGL渲染的动画简介
当我们创建游戏和仿真模拟时,有时我们有必要记录渲染的内容。在某些情况下渲染过于复杂和耗时,这是不可避免的。
在DirectX中,库函数D3DXSaveSurfaceToFile()保存表面为一张图片文件。对OpenGL,我们用glReadPixels()来读渲染的图像像素然后手动的保存它们为一张图片文件。然而这些表面只是针对单帧记录的,对记录一段连续帧没有简单的方法存在。换句话说,没有库函数来记录我们的完整存在渲染动画效果。
在这方面,本文提出了几类,这有助于创造电影DirectX的方法和动画。用类CDxToMovie和 CGLToMovie电影可以选择性地或连续的从DirectX和OpenGL渲染帧来创建。一般来说,一个典型的电影创作过程涉及复杂的任务,例如读图的内容,选择帧速率设置,编解码器的设置,初始化媒体流,写媒体流等(详细讨论关于如何创建位图图像序列的电影,请参考这篇文章 Create Movie from HBitmap)。类CDxToMovie和CGLToMovie这里介绍的抽象出所有不必要的复杂性和易于使用的界面,提供简单方法解释如下
从DirectX渲染序列记录一个电影
类CDxToMovie可以记录DirectX渲染序列成电影文件。该类用到DirectX 9.0接口例如LPDIRECT3DSURFACE9,因此你应该用DirectX 9.0 SDK 或者其他的兼容的地方使用这个类 。
开始从本文中的DirectX代码拷贝文件DxToMovie.h,RenderTarget.h,AviFile.h和AviFile.cpp到你的工程目录下然后添加他们到你的工程中,然后添加vfw.lib,一旦添加到你的工程中,你可以通过#include "DxToMovie.h"访问。CDxToMovie构造函数接受不同的参数如输出电影文件名,电影帧的宽度和高度的要求,每像素比特数等…如下所示,

真正记录的功能是通过函数CDxToMovie::StartRecordingMovie()和CDxToMovie::PauseRecordingMovie().这两个函数必须每一帧都要在 IDirect3DDevice9::BeginScene() 和
IDirect3DDevice9::EndScene()之间。如下所示
g_pd3dDevice
->
BeginScene();
![]()
//
Capture the Rendering onto CDxToMovie's Render Target
g_MovieRecorder.StartRecordingMovie(g_pd3dDevice);
//
Render as usual
..
g_pd3dDevice
->
Clear(
0
,NULL,D3DCLEAR_TARGET
|
D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(
0
,
0
,
200
),
1
,
0
);
g_pd3dDevice
->
SetStreamSource(
0
,g_pVB,
0
,
sizeof
(CUSTOMVERTEX));
g_pd3dDevice
->
SetFVF(D3DFVF_CUSTOMVERTEX);
g_pd3dDevice
->
DrawPrimitive(D3DPT_TRIANGLELIST,
0
,
1
);
g_MovieRecorder.PauseRecordingMovie(g_pd3dDevice);
![]()
//
Copy the CDxToMovie's Render Target content back onto BackBuffer's Surface
g_pd3dDevice
->
StretchRect(g_MovieRecorder.RecordingSurface(),
NULL,pBackSurface,
0
,D3DTEXF_NONE);
![]()
g_pd3dDevice
->
EndScene();
在上面的代码段中,
g_MovieRecorder.StartRecordingMovie(g_pd3dDevice)
将所有随后的渲染在CDxToMovie的内部渲染目标直到 g_MovieRecorder.PauseRecordingMovie(g_pd3dDevice)被调用。所有的渲染工作在CDxToMovie的内部渲染目标上做,你的程序back surface将没有任何有效的内容显示在你的应用程序窗口。这不要紧,如果你的申请不只是创作这部电影没有任何动画直接呈现在屏幕上。然而,如果你记录电影从一个互动游戏会话上,它会变坏屏幕不更新到最新的渲染的内容(因为通过重新渲染目标,CDxToMovie内容被偷了)。为了避免它,你可以选择性地复制回CDxToMovie内部的渲染目标的内容到你的应用程序的back surface 使用方法IDirect3DDevice9:StretchRect(),其次是常见的g_pd3dDevice - > EndScene()和g_pd3dDevice - >Present()的要求会更新内容的呈现在屏幕上背缓冲区,使屏幕上更新。
如果你想避免一些帧被选择性记录在这部电影,只是不要叫g_MovieRecorder.StartRecordingMovie和g_MovieRecorder.PauseRecordingMovie()(相应的 g_pd3dDevice - > StretchRect())对那些帧,并会直接渲染动画在屏幕上(没有被重定向到CDxToMovie内部的渲染目标)。
演示代码提供这个项目提供了一个简单的应用程序,使得DirectX屏幕上的一个三角形的动作,鼠标移动窗户上,这将simulatenously被渲染成电影文件和记录(名叫output.avi)。跑演示的可执行程序,确保你有MPG4编解码器的计算机上安装,目录有写权限去创建输出电影文件。详情请设置解码器和平衡,请参考这篇文章 Create Movie from HBitmap
Recording a Movie from OpenGL Rendered Sequence
先暂时不翻译了,以后再翻。
注:第一次翻译,水平比较差,还望各位看客见谅。
Reference: Recording DirectX and OpenGL Rendered Animations