在DirectX渲染目标纹理中访问DirectX& XAML WP8项目类型 [英] Access pixel data in DirectX Render Target Texture for DirectX & XAML WP8 Project type

查看:156
本文介绍了在DirectX渲染目标纹理中访问DirectX& XAML WP8项目类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿所有。我正在进行一个项目,我正在对纹理进行一些图像处理,结果呈现给DirectX& ;;中使用的渲染目标。 XAML项目模板。我的问题在于尝试访问Render Target
纹理中的像素数据(最终结果)。我想把这些数据复制到一个字节数组,然后我可以保存以供日后使用。

Hey all. I am working on a project where I am doing some image processing on a texture with the result being rendered to a Render Target used in the DirectX & XAML project template. My problem lies in trying to access the pixel data in the Render Target texture(the final result). I want to take this data and copy to a byte array which I can then save for later and other stuff.

我开发了一些代码完成这个编译和运行但不幸的是,会导致全部为零,从而保存黑色图像。基本上我使用了copyRenderTarget方法(下面),它使用DirectXContext :: CopyResource
将m_renderTarget DirectX纹理(从模板中的DirectXBase类)复制到另一个

分期
我已定义的纹理。这个分段纹理允许CPU访问纹理数据并从中读取。 

I developed some code to accomplish this which compiles and runs but unfortunately results in all zeros and thus a black image being saved. Basically I used copyRenderTarget method(below) which uses DirectXContext::CopyResource to copy the m_renderTarget DirectX texture(from DirectXBase class in template) to another staging texture I have defined. This staging texture allows the CPU to access the texture data and read from it. 

我在原始输入纹理上使用了相同的方法,并且能够在我的新分段中恢复它纹理正确。我的代码如下所示。任何人都可以看到它有什么问题吗?我需要设置或执行从render
目标中读取的特殊属性吗?有没有人有任何其他建议将m_renderTarget纹理中的纹理数据读入字节数组?任何帮助将不胜感激。 

I have used the same method on the original input texture and am able to recover that in my new staging texture correctly. My code is shown below. Can anyone see anything wrong with it? Is there a special property I need to set or do to read from the render target? Does anyone have any other suggestions to read the texture data in the m_renderTarget texture into a byte array? Any help would be greatly appreciated. 

copyRenderTarget方法

copyRenderTarget Method

HRESULT CubeRenderer::copyRenderTarget(_In_ ID3D11Resource* pSource)
{
	if ( !m_d3dContext || !pSource )
        return E_INVALIDARG;

    D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN;
    pSource->GetType( &resType );

    if ( resType != D3D11_RESOURCE_DIMENSION_TEXTURE2D )
        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );

    
Microsoft::WRL::ComPtr<ID3D11Texture2D> pTexture;
    HRESULT hr = pSource->QueryInterface( __uuidof(ID3D11Texture2D), (void**) &pTexture );
    if ( FAILED(hr) )
        return hr;

    assert( pTexture.Get() );

	//captureTexture_Desc  is of type D3D11_TEXTURE2D_DESC
    pTexture->GetDesc( &captureTexture_Desc );


    // Otherwise, create a staging texture from the non-MSAA source
    captureTexture_Desc.BindFlags = 0;
    captureTexture_Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
    captureTexture_Desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    captureTexture_Desc.Usage = D3D11_USAGE_STAGING;

	hr = m_d3dDevice->CreateTexture2D( &captureTexture_Desc, 0, &(this->captureTexture) );
    if ( FAILED(hr) )
        return hr;

    assert( (this->captureTexture).Get() );

	m_d3dContext->CopyResource( (this->captureTexture).Get(), pSource );

    return S_OK;
}

CaptureImage方法

CaptureImage method

void CubeRenderer :: CaptureImage(Platform :: WriteOnlyArray< int,1U> ^ outputBuffer)
{
//停止Render()方法的布尔值从实际执行写入调用
processingFrame = true;

//尝试通过设置renderTarget纹理来轻松调试单个值来测试此函数
const float midnightBlue [] = {0.098f,0.098f,0.439f,1.000f};
m_d3dContext-> ClearRenderTargetView(m_renderTargetView.Get(),midnightBlue);
m_d3dContext-> Flush();

//将renderTarget纹理资源复制到我的"captureTexture"资源
DX :: ThrowIfFailed(
copyRenderTarget(m_renderTarget.Get())
);
// HRESULT hr = copyRenderTarget(m_cameraTexture.Get());

//映射我的"captureTexture"资源访问像素数据
D3D11_MAPPED_SUBRESOURCE映射;
DX :: ThrowIfFailed(
m_d3dContext-> Map(captureTexture.Get(),0,D3D11_MAP_READ,0,& mapped)
);

//将像素数据强制转换为字节数组
const uint8_t * sptr = reinterpret_cast< const uint8_t *>(mapped.pData);
if(!sptr)
{
m_d3dContext-> Unmap(captureTexture.Get(),0);
return; // E_POINTER;
}
//遍历纹理中的所有像素并复制到输出缓冲区
int counter = 0;
for(UINT row = 0; row< captureTexture_Desc.Height; row ++)
{
UINT rowStart = row * mapped.RowPitch;
for(UINT col = 0; col< captureTexture_Desc.Width; col ++)
{
UINT colStart = col * 4;

byte R = sptr [rowStart + colStart + 0]; //红色
字节G = sptr [rowStart + colStart + 1]; //绿色
字节B = sptr [rowStart + colStart + 2]; //蓝色
字节A = sptr [rowStart + colStart + 3]; // Alpha

outputBuffer [row * captureTexture_Desc.Width + col] =(A<< 24)| (R<< 16)| (G << 8)| B;
// outputBuffer [row + col] = A<< 24 + R<< 16 + G< 8 + B;
}
}

//取消映射纹理&清理
m_d3dContext-> Unmap(captureTexture.Get(),0);

//允许directx再次开始调用draw调用
processingFrame = false;
}

void CubeRenderer::CaptureImage(Platform::WriteOnlyArray<int,1U>^ outputBuffer) { // Boolean value that halts the Render() method from actually executing writing calls processingFrame = true; // Trying to test this function by setting renderTarget texture to easily debugged single value const float midnightBlue[] = { 0.098f, 0.098f, 0.439f, 1.000f }; m_d3dContext->ClearRenderTargetView( m_renderTargetView.Get(), midnightBlue); m_d3dContext->Flush(); // Copy the renderTarget texture resource to my "captureTexture" resource DX::ThrowIfFailed( copyRenderTarget(m_renderTarget.Get()) ); //HRESULT hr = copyRenderTarget(m_cameraTexture.Get()); // Map my "captureTexture" resource to access the pixel data D3D11_MAPPED_SUBRESOURCE mapped; DX::ThrowIfFailed( m_d3dContext->Map( captureTexture.Get(), 0, D3D11_MAP_READ, 0, &mapped ) ); // Cast the pixel data to a byte array essentially const uint8_t* sptr = reinterpret_cast<const uint8_t*>( mapped.pData ); if ( !sptr ) { m_d3dContext->Unmap( captureTexture.Get(), 0 ); return;// E_POINTER; } // Loop through all pixels in texture and copy to output buffer int counter = 0; for( UINT row = 0; row < captureTexture_Desc.Height; row++ ) { UINT rowStart = row * mapped.RowPitch; for( UINT col = 0; col < captureTexture_Desc.Width; col++ ) { UINT colStart = col * 4; byte R = sptr[rowStart + colStart + 0]; // Red byte G = sptr[rowStart + colStart + 1]; // Green byte B = sptr[rowStart + colStart + 2]; // Blue byte A = sptr[rowStart + colStart + 3]; // Alpha outputBuffer[row * captureTexture_Desc.Width + col] = (A << 24) | (R << 16) | (G << 8) | B; //outputBuffer[row + col] = A << 24 + R << 16 + G << 8 + B; } } // Unmap the texture & clean up m_d3dContext->Unmap( captureTexture.Get(), 0 ); // Allow directx to begin calling draw calls again processingFrame = false; }

推荐答案

解决:我找到了上述问题的解决方案。因为我讨厌当人们在网上发布问题而只是说他们没有详细说明如何解决问题时,我将描述我在下面所做的事情。

SOLVED: I figured out the solution for my problem above. Because I hate it when people post an issue online and just say they've figured it out without giving details of how, I'm going to describe what I did below.

当使用渲染目标纹理的DirectXContext :: CopyResource到您的登台纹理时,问题就是一些内部事故。它只会用像素数据的全零来填充分段纹理。用于创建项目模板渲染的代码显示
target:

The issue lied with some internal mishap when using DirectXContext::CopyResource of the render target texture to your staging texture. It would just fill the staging texture with all zeros for the pixel data. The code for creating the project template render target is shown:

	// Create a descriptor for the render target buffer.
	CD3D11_TEXTURE2D_DESC renderTargetDesc(
		DXGI_FORMAT_B8G8R8A8_UNORM,
		static_cast<UINT>(m_renderTargetSize.Width),
		static_cast<UINT>(m_renderTargetSize.Height),
		1,
		1,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE
		);
	renderTargetDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
	


密钥围绕着正在设置的MiscFlags。我猜测这些是设置的,因此可以通过IDrawingSurface访问纹理,并将复制到XAML中的DrawingSurface UIElement的数据显示在屏幕上。如果设置renderTargetDesc.MiscFlags
= 0,它将起作用。所以基本上我创建了另一个渲染目标纹理和渲染目标着色器视图,除了MiscFlag值之外,它们与模板渲染目标变量基本相同。当我希望捕获我的DirectX绘图
和渲染的结果时,我只需切换到我的个人渲染目标着色器视图,其中m_d3dContext-> ClearRenderTargetView(m_renderTargetView.Get(),midnightBlue);和  m_d3dContext-> OMSetRenderTargets(1,m_renderTargetView.GetAddressOf(),m_depthStencilView.Get()
);在我的渲染方法中$



The key revolved around the MiscFlags being set. I'm guessing these were set so the texture could be accessed by the IDrawingSurface and the data copied to your DrawingSurface UIElement in XAML to be shown onscreen. If you set the renderTargetDesc.MiscFlags = 0 it will work. So basically I created another Render Target texture and Render Target Shader view that are essentially identical the template render target variables except for that MiscFlag value. When I wish to capture the result of my DirectX drawing and rendering, I just switch to my personal Render Target shader view for m_d3dContext->ClearRenderTargetView( m_renderTargetView.Get(), midnightBlue); and m_d3dContext->OMSetRenderTargets( 1, m_renderTargetView.GetAddressOf(), m_depthStencilView.Get() ); in my Render method



这篇关于在DirectX渲染目标纹理中访问DirectX&amp; XAML WP8项目类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆