Directx 从Direct3D纹理和曲面执行回读
我需要弄清楚如何将D3D纹理和曲面的数据返回到系统内存中。做这些事情最快的方法是什么?如何做 另外,如果我只需要一个子矩形,那么如何在不必将整个内容读回系统内存的情况下只读回该部分呢 简言之,我正在寻找如何将以下内容复制到系统内存的简明描述:Directx 从Direct3D纹理和曲面执行回读,directx,textures,gpgpu,geometry-surface,Directx,Textures,Gpgpu,Geometry Surface,我需要弄清楚如何将D3D纹理和曲面的数据返回到系统内存中。做这些事情最快的方法是什么?如何做 另外,如果我只需要一个子矩形,那么如何在不必将整个内容读回系统内存的情况下只读回该部分呢 简言之,我正在寻找如何将以下内容复制到系统内存的简明描述: a纹理 纹理的子集 a表面 曲面的子集 aD3DUSAGE\u渲染目标纹理 D3DUSAGE\U RENDERTARGET纹理的子集 这是Direct3D 9,但如果您能回答D3D较新版本的问题,我们将不胜感激。最重要的部分是从视频内存中的某个表面(“默认
这是Direct3D 9,但如果您能回答D3D较新版本的问题,我们将不胜感激。最重要的部分是从视频内存中的某个表面(“默认池”)读取数据。这通常用于渲染目标 让我们先来看看简单的部分:
surfaceinter
是指向COM对象的智能指针(它在赋值或析构函数时释放对象)。大大简化了错误处理。这与VisualC++中的<>代码>
上面的代码读取整个曲面。如果你想有效地阅读其中的一部分,那么我认为最快的方法大概是:
编辑:更新以匹配编辑的问题。谢谢。这确实为我指明了正确的道路。发布后不久,我确实在MSDN中发现了这样一条评论:您无法锁定D3DUSAGE_RENDERTARGET,必须使用GetRenderTargetData。真倒霉不过,如果有一个更干净、更吝啬的代码示例就好了。:-)没有像素复制代码肯定会更好。用实际的D3D名称替换非D3D类型SurfacePointer如何?LPDIRECT3DSURFACE9或IDirect3DSurface9*以及如果我想从默认池中获取纹理,但它不是rendertarget,该怎么办。锁定不起作用,我无法对非渲染目标曲面使用GetRenderTargetData()。有时可以创建中间渲染目标,但如果原始纹理采用某些格式(如D3DFORMAT_L8),则无法使用此格式创建渲染目标。所以看起来不可能得到这样的纹理。我说得对吗?
bool GfxDeviceD3D9::ReadbackImage( /* params */ )
{
HRESULT hr;
IDirect3DDevice9* dev = GetD3DDevice();
SurfacePointer renderTarget;
hr = dev->GetRenderTarget( 0, &renderTarget );
if( !renderTarget || FAILED(hr) )
return false;
D3DSURFACE_DESC rtDesc;
renderTarget->GetDesc( &rtDesc );
SurfacePointer resolvedSurface;
if( rtDesc.MultiSampleType != D3DMULTISAMPLE_NONE )
{
hr = dev->CreateRenderTarget( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &resolvedSurface, NULL );
if( FAILED(hr) )
return false;
hr = dev->StretchRect( renderTarget, NULL, resolvedSurface, NULL, D3DTEXF_NONE );
if( FAILED(hr) )
return false;
renderTarget = resolvedSurface;
}
SurfacePointer offscreenSurface;
hr = dev->CreateOffscreenPlainSurface( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DPOOL_SYSTEMMEM, &offscreenSurface, NULL );
if( FAILED(hr) )
return false;
hr = dev->GetRenderTargetData( renderTarget, offscreenSurface );
bool ok = SUCCEEDED(hr);
if( ok )
{
// Here we have data in offscreenSurface.
D3DLOCKED_RECT lr;
RECT rect;
rect.left = 0;
rect.right = rtDesc.Width;
rect.top = 0;
rect.bottom = rtDesc.Height;
// Lock the surface to read pixels
hr = offscreenSurface->LockRect( &lr, &rect, D3DLOCK_READONLY );
if( SUCCEEDED(hr) )
{
// Pointer to data is lt.pBits, each row is
// lr.Pitch bytes apart (often it is the same as width*bpp, but
// can be larger if driver uses padding)
// Read the data here!
offscreenSurface->UnlockRect();
}
else
{
ok = false;
}
}
return ok;
}