2009-07-11 143 views
1

我正在写在D3D9一个3D建模应用程序,我想使尽可能广泛的兼容性。这意味着使用少数依赖于硬件的功能,即多重采样。然而,虽然实时渲染不需要完美无瑕,但我确实需要提供漂亮的屏幕捕捉,而没有多重采样,看起来很粗糙和很差。抗锯齿/多重采样在D3D9

为了制造我的截屏,我在内存中创建一个临时的表面,使现场一次,然后将其保存到一个文件中。我的,我怎么能实现抗锯齿捕获的第一个想法是创造我的屏幕外的stencilsurface作为多次采样,但当然DX不允许,由于设备本身已经与D3DMULTISAMPLE_NONE初始化。

要开始了,下面是我究竟如何创建一个抓屏样品。我知道它会更简单,只是保存已渲染帧的后备缓冲,但我需要保存不同尺寸的影像比实际的渲染窗口的能力 - 这就是为什么我做这种方式。为简洁起见,错误检查,恢复状态的代码和释放资源在此处省略。 m_d3ddev是我的LPDIRECT3DDEVICE9。

//Get the current pp 
LPDIRECT3DSWAPCHAIN9 sc; 
D3DPRESENT_PARAMETERS pp; 
m_d3ddev->GetSwapChain(0, &sc); 
sc->GetPresentParameters(&pp); 

//Create a new surface to which we'll render 
LPDIRECT3DSURFACE9 ScreenShotSurface= NULL; 
LPDIRECT3DSURFACE9 newDepthStencil = NULL; 
LPDIRECT3DTEXTURE9 pRenderTexture = NULL; 
m_d3ddev->CreateDepthStencilSurface(_Width, _Height, pp.AutoDepthStencilFormat, pp.MultiSampleType, pp.MultiSampleQuality, FALSE, &newDepthStencil, NULL); 
m_d3ddev->SetDepthStencilSurface(newDepthStencil); 
m_d3ddev->CreateTexture(_Width, _Height, 1, D3DUSAGE_RENDERTARGET, pp.BackBufferFormat, D3DPOOL_DEFAULT, &pRenderTexture, NULL); 
pRenderTexture->GetSurfaceLevel(0,&ScreenShotSurface); 

//Render the scene to the new surface 
m_d3ddev->SetRenderTarget(0, ScreenShotSurface); 
RenderFrame(); 

//Save the surface to a file 
D3DXSaveSurfaceToFile(_OutFile, D3DXIFF_JPG, ScreenShotSurface, NULL, NULL); 

你可以看到调用CreateDepthStencilSurface(),这是我希望我能有即D3DMULTISAMPLE_4_SAMPLES取代pp.MultiSampleType,但没有奏效。

我的下一个想法是创建一个完全不同的LPDIRECT3DDEVICE9作为D3DDEVTYPE_REF,它始终支持D3DMULTISAMPLE_4_SAMPLES(不管视频卡)。然而,我所有的资源(网格,纹理)的已加载到m_d3ddev,我HAL设备,因此,我无法将它们用于REF设备下渲染场景。请注意,资源可以在Direct3d9ex(Vista)下的设备之间共享,但我正在使用XP。由于存在相当多的资源,重新加载所有内容以渲染这一帧,然后卸载它们对于我的应用程序而言效率太低。

我看了看其他的选择抗锯齿的图像捕捉后(即3×3模糊滤镜),但它们都产生很糟糕的结果,所以我很想尝试,并得到一个反锯齿场景右出D3D,如果可能的....

任何智慧或指针将不胜感激......

谢谢!

+0

为什么不检测多采样能力,只是在可用的情况下使用(可能需要禁用性能选项)?我的意思是,这不像你通过做你想做的事来提高兼容性。 – U62 2009-07-11 18:39:10

+0

那么,这是我最后的选择......但我真正想做的是能够提供antialiased图像,无论视频卡的能力。我没有那么在乎实时的质量呈现 (是的,这肯定会提高兼容性 - 因为_always_支持多重采样,所以如果我可以使用该类型设备的参考设备来呈现的截图,它应该冷静但仍有上述问题,所以我希望一些其他的解决办法...) – Metal450 2009-07-11 22:37:27

回答

3

通过渲染到更大的缓冲区和缩小或组合抖动缓冲区的超采样可能是您最好的选择。组合多个抖动缓冲区应该为给定数量的样本提供最佳质量(比简单渲染等分样本数量多倍的分辨率和缩小比常规网格更好),但是会产生额外的多次渲染通道开销。它的优点是不受你渲染目标支持的最大尺寸的限制,并且允许你选择几乎任意级别的AA(尽管如果组合了许多抖动缓冲区,你将不得不关注精度问题)。

opengl.org上的文章“用积累缓冲区进行抗锯齿”介绍了如何修改用于抖动采样(OpenGL,但数学基本相同)的投影矩阵。亚历山大·凯勒和沃尔夫冈·海德里奇的论文“Interleaved Sampling”谈到了技术的扩展,它会以更多的渲染过程为代价提供更好的采样模式。对不起,不提供链接 - 作为一个新用户,我只能为每个答案发布一个链接。谷歌应该为你找到它们。

如果您想要将渲染路线转换为较大的缓冲区并降低采样率,但不希望受限于允许的最大渲染目标尺寸,那么您可以使用偏心投影矩阵生成平铺图像,如here

1

您可以始终呈现宽度和高度两倍(即4倍大小)的纹理,然后对其进行超级取样。

诚然,你仍然会得到问题如果卡不能创建一个纹理4倍后缓冲区的大小...

编辑:有想到的另一种方式。

如果您重复使用视图矩阵中的微小抖动n次,您将能够生成尽可能多的图像,然后再将它们相加,形成一个非常抗锯齿的图像。奖金是,它可以在任何可以渲染图像的机器上运行。尽管如此,它显然比较慢。当你这样做时,仍然是256xAA真的看起来不错!

+0

+1:超级采样是在我脑海中,这是可以做到的w/o GPU支持的唯一的事情。我不确定要改变视图矩阵。我认为你会因透视变化而得到其他的文物。看看会发生什么会很有趣。我想这取决于正在渲染的场景。 – gatorfax 2009-07-15 15:31:47

+0

是的......我也想到了这一点,看起来这可能是我必须走的路。不知怎的,它只是似乎不可思议,它没有内置设施得到更广泛的多重采样的支持,这是不可用的一半以上我已经试过了笔记本电脑! – Metal450 2009-07-22 17:19:50

0

这篇文章http://msdn.microsoft.com/en-us/library/bb172266(VS.85).aspx似乎暗示你可以使用渲染状态标志D3DRS_MULTISAMPLEANTIALIAS来控制这个。您是否可以在启用了抗锯齿功能的情况下创建设备,但使用此渲染状态标志关闭屏幕渲染和关闭屏幕渲染?

虽然我没有尝试过。