渲染到纹理 - ClearRenderTargetView() 有效,但 none 对象渲染到纹理(渲染到屏幕工作正常)

Rendering to texture - ClearRenderTargetView() works, but none objects are rendered to texture (rendering to screen works fine)

我尝试将场景渲染为纹理,然后应该显示在屏幕的一角。

虽然我可以这样做:

  1. 渲染场景(我的 Engine::render() 方法将设置着色器并进行绘制调用)- 工作正常
  2. 将渲染目标更改为纹理。
  3. 再次渲染场景 - 不起作用。 context->ClearRenderTargetView(texture->getRenderTargetView(), { 1.0f, 0.0f, 0.0f, 1.0f } ) 将我的纹理设置为红色(对于场景在步骤 1 中。我使用了不同的颜色),但是 none 对象正在其上渲染。
  4. 将渲染目标更改回原始。
  5. 最后一次渲染场景,角落处的矩形具有我在步骤 3 中渲染的纹理。- 工作正常。我也看到了场景,角落里的小矩形。问题是,它只是红色(我猜是第 3 步中的渲染出了点问题)。

结果(应该是"image in image"而不是红色矩形):

步骤 2.-4 的代码:

context->OMSetRenderTargets(1, &textureRenderTargetView, depthStencilView); 
float bg[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
context->ClearRenderTargetView(textureRenderTargetView, bg); //backgroundColor - red, green, blue, alpha
render();
context->OMSetRenderTargets(1, &myRenderTargetView, depthStencilView); //bind  render target back to previous value (not to texture)

render() 方法没有改变(它在步骤 1 中起作用,为什么当我渲染到纹理时它不起作用?)并以 swapChain->Present(0, 0).

我知道 ClearRenderTargetView 会影响我的纹理(没有它,它不会将颜色更改为红色)。但是其余的渲染要么不输出到它,要么有另一个问题。

我是不是漏掉了什么?

我根据this tutorial为其创建纹理、着色器资源视图和渲染目标(也许我的D3D11_TEXTURE2D_DESC有错误?):

D3D11_TEXTURE2D_DESC textureDesc;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;

//1. create render target

ZeroMemory(&textureDesc, sizeof(textureDesc));

//setup the texture description
//we will need to have this texture bound as a render target AND a shader resource
textureDesc.Width = size.getX();
textureDesc.Height = size.getY();
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;

//create the texture
device->CreateTexture2D(&textureDesc, NULL, &textureRenderTarget);

//2. create render target view

//setup the description of the render target view.
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;

//create the render target view
device->CreateRenderTargetView(textureRenderTarget, &renderTargetViewDesc, &textureRenderTargetView);

//3. create shader resource view

//setup the description of the shader resource view.
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;

//create the shader resource view.
device->CreateShaderResourceView(textureRenderTarget, &shaderResourceViewDesc, &texture);

深度缓冲区:

D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = sampleCount;
descDepth.SampleDesc.Quality = maxQualityLevel;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;

这里是交换链:

DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = numerator; //60
sd.BufferDesc.RefreshRate.Denominator = denominator; //1
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = *hwnd;
sd.SampleDesc.Count = sampleCount; //1 (and 0 for quality) to turn off multisampling
sd.SampleDesc.Quality = maxQualityLevel;
sd.Windowed = fullScreen ? FALSE : TRUE;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //allow full-screen switchin

// Set the scan line ordering and scaling to unspecified.
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// Discard the back buffer contents after presenting.
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

我以这种方式创建默认渲染目标视图:

//create a render target view
ID3D11Texture2D* pBackBuffer = NULL;
result = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
ERROR_HANDLE(SUCCEEDED(result), L"The swapChain->GetBuffer() failed.", MOD_GRAPHIC);

//Create the render target view with the back buffer pointer.
result = device->CreateRenderTargetView(pBackBuffer, NULL, &myRenderTargetView);

根据@Gnietschow 的建议,经过一些调试后,我发现了一个错误:

D3D11 ERROR: ID3D11DeviceContext::OMSetRenderTargets:

The RenderTargetView at slot 0 is not compatable with the DepthStencilView. DepthStencilViews may only be used with RenderTargetViews if the effective dimensions of the Views are equal, as well as the Resource types, multisample count, and multisample quality.

The RenderTargetView at slot 0 has (w:1680,h:1050,as:1), while the Resource is a Texture2D with (mc:1,mq:0).

The DepthStencilView has (w:1680,h:1050,as:1), while the Resource is a Texture2D with (mc:8,mq:16).

所以基本上,我的渲染目标(纹理)没有使用抗锯齿,而我的 buffer/depth 缓冲区使用了抗锯齿。

我必须在 DXGI_SWAP_CHAIN_DESCD3D11_TEXTURE2D_DESC 中将 SampleDesc.Count 更改为 1 并将 SampleDesc.Quality 更改为 0 以匹配来自我渲染的纹理。换句话说,我必须在渲染到纹理时关闭抗锯齿。

我想知道,为什么渲染到纹理不支持抗锯齿? 当我将 SampleDesc.CountSampleDesc.Quality 设置为我的标准值时(816,渲染场景时它们在我的 GPU 上工作正常)对于我的纹理渲染目标,device->CreateTexture2D(...) 失败并显示 "invalid parameter"(即使我到处都使用相同的值) .