如何将附近的像素数据发送到 Direct3D 11 中的像素着色器?
How do I send nearby pixel data to a Pixel-Shader in Direct3D 11?
我一直在阅读这些教程(我只允许使用 2 个链接):https:// code.msdn.microsoft.com/Direct3D-Tutorial-Win32-829979ef
并通读 Direct3D 11 图形管道:https://msdn.microsoft.com/en-us/library/windows/desktop/ff476882%28v=vs.85%29.aspx
我目前有一个用 HLSL 编码的像素(又名片段)着色器,由以下代码组成:
//Pixel Shader input.
struct psInput
{
float4 Position: SV_POSITION;
float4 Color: COLOR;
};
//Pixel (aka. Fragment) Shader.
float4 PS(psInput input): SV_TARGET
{
return input.Color;
}
我(认为我)想做的是对像素着色器中的每个像素进行多重采样并访问附近的像素数据,以便我可以执行某种自定义抗锯齿,如 FXAA (http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf) .根据我的理解,我需要为每个渲染使用 PSSetShaderResources 将纹理传递给 HLSL,但除此之外我不知道。所以,我的问题是:
如何将附近的像素数据发送到 Direct3D 11 中的像素着色器?
能够做这种事情也对我理解 c++ 和 HLSL 如何在我在教程中找到的标准“将一些 float4 传递给着色器”之外的彼此交互方面非常有益。貌似这是D3D开发中最关键的一个方面,但是我在网上找不到很多例子。
我考虑过传统的 MSAA(多重采样抗锯齿),但我找不到任何关于如何在 D3D 11 中成功实现它的信息,除此之外我需要使用“BitBlt”(位块转移)模型交换链第一。 (参见 DXGI_SAMPLE_DESC1 和 DXGI_SAMPLE_DESC;只有计数为 1 且质量为 0(无 AA)才会导致绘制。)此外,我想知道如何对一般情况执行上述操作了解我的项目的其他方面是否需要它。不过,也欢迎回答有关如何在 D3D 11 中执行 MSAA 的问题。
请仅使用 D3D 11 和 HLSL 代码。
要像 FXAA 一样进行自定义抗锯齿,您需要将场景渲染到屏幕外渲染目标:
-使用绑定标志 D3D11_BIND_RENDER_TARGET
和 D3D11_BIND_SHADER_RESOURCE
创建一个 ID3D11Texture2D
-为第一步创建的纹理创建一个ID3D11ShaderResourceView
和一个ID3D11RenderTargetView
。
-将场景渲染到步骤 2
中创建的 ID3D11RenderTargetView
-将后台缓冲区设置为渲染目标并将在第 2 步中创建的 ID3D11ShaderResourceView
绑定到正确的像素着色器插槽。
-Render a fullscreen triangle covering the entire screen you'll be able to sample the texture containing the scene in the pixel shader (use the Load()函数)
当您尝试进行传统 MSAA 时,您是否记得设置 MultisampleEnable in the rasterizer state?
我再次回答我自己的问题,有点(从未使用过 FXAA...)。我在这里提供我的答案是为了对那些追随我脚步的人好。
原来我错过了 MSAA 的深度模板视图。您希望禁用 MSAA 的 SampleCount 为 1U,2XMSAA 为 2U,4XMSAA 为 4U,8XMSAA 为 8U,等等(使用 ID3D11Device::CheckMultisampleQualityLevels 到 "probe" 以获得可行的 MSAA 级别...)您几乎总是想要为禁用的 MSAA 使用质量级别 0U,为启用的 MSAA 使用 1U。
下面是我的工作 MSAA 代码(您应该可以填写其余部分)。请注意,我使用了 DXGI_FORMAT_D24_UNORM_S8_UINT 和 D3D11_DSV_DIMENSION_TEXTURE2DMS,并且深度纹理和深度模板视图的格式值相同,SampleCount 和 SampleQuality 值也相同。
祝你好运!
unsigned int SampleCount = 1U;
unsigned int SampleQuality = (SampleCount > 1U ? 1U : 0U);
//Create swap chain.
IDXGIFactory2* dxgiFactory2 = nullptr;
d3dResult = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
if (dxgiFactory2)
{
//DirectX 11.1 or later.
d3dResult = D3DDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&D3DDevice1));
if (SUCCEEDED(d3dResult))
{
D3DDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&D3DDeviceContext1));
}
DXGI_SWAP_CHAIN_DESC1 swapChain;
ZeroMemory(&swapChain, sizeof(swapChain));
swapChain.Width = width;
swapChain.Height = height;
swapChain.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChain.SampleDesc.Count = SampleCount;
swapChain.SampleDesc.Quality = SampleQuality;
swapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChain.BufferCount = 2U;
d3dResult = dxgiFactory2->CreateSwapChainForHwnd(D3DDevice, w32Window, &swapChain, nullptr, nullptr, &SwapChain1);
if (SUCCEEDED(d3dResult))
{
d3dResult = SwapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&SwapChain));
}
dxgiFactory2->Release();
}
else
{
//DirectX 11.0.
DXGI_SWAP_CHAIN_DESC swapChain;
ZeroMemory(&swapChain, sizeof(swapChain));
swapChain.BufferCount = 2U;
swapChain.BufferDesc.Width = width;
swapChain.BufferDesc.Height = height;
swapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChain.BufferDesc.RefreshRate.Numerator = 60U;
swapChain.BufferDesc.RefreshRate.Denominator = 1U;
swapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChain.OutputWindow = w32Window;
swapChain.SampleDesc.Count = SampleCount;
swapChain.SampleDesc.Quality = SampleQuality;
swapChain.Windowed = true;
d3dResult = dxgiFactory->CreateSwapChain(D3DDevice, &swapChain, &SwapChain);
}
//Disable Alt + Enter and Print Screen shortcuts.
dxgiFactory->MakeWindowAssociation(w32Window, DXGI_MWA_NO_PRINT_SCREEN | DXGI_MWA_NO_ALT_ENTER);
dxgiFactory->Release();
if (FAILED(d3dResult))
{
return false;
}
//Create render target view.
ID3D11Texture2D* backBuffer = nullptr;
d3dResult = SwapChain->GetBuffer(0U, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer));
if (FAILED(d3dResult))
{
return false;
}
d3dResult = D3DDevice->CreateRenderTargetView(backBuffer, nullptr, &RenderTargetView);
backBuffer->Release();
if (FAILED(d3dResult))
{
return false;
}
//Create depth stencil texture.
ID3D11Texture2D* DepthStencilTexture = nullptr;
D3D11_TEXTURE2D_DESC depthTextureLayout;
ZeroMemory(&depthTextureLayout, sizeof(depthTextureLayout));
depthTextureLayout.Width = width;
depthTextureLayout.Height = height;
depthTextureLayout.MipLevels = 1U;
depthTextureLayout.ArraySize = 1U;
depthTextureLayout.Usage = D3D11_USAGE_DEFAULT;
depthTextureLayout.CPUAccessFlags = 0U;
depthTextureLayout.MiscFlags = 0U;
depthTextureLayout.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthTextureLayout.SampleDesc.Count = SampleCount;
depthTextureLayout.SampleDesc.Quality = SampleQuality;
depthTextureLayout.BindFlags = D3D11_BIND_DEPTH_STENCIL;
d3dResult = D3DDevice->CreateTexture2D(&depthTextureLayout, nullptr, &DepthStencilTexture);
if (FAILED(d3dResult))
{
return false;
}
//Create depth stencil.
D3D11_DEPTH_STENCIL_DESC depthStencilLayout;
depthStencilLayout.DepthEnable = true;
depthStencilLayout.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilLayout.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilLayout.StencilEnable = true;
depthStencilLayout.StencilReadMask = 0xFF;
depthStencilLayout.StencilWriteMask = 0xFF;
depthStencilLayout.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilLayout.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilLayout.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilLayout.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
ID3D11DepthStencilState* depthStencilState;
D3DDevice->CreateDepthStencilState(&depthStencilLayout, &depthStencilState);
D3DDeviceContext->OMSetDepthStencilState(depthStencilState, 1U);
//Create depth stencil view.
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewLayout;
ZeroMemory(&depthStencilViewLayout, sizeof(depthStencilViewLayout));
depthStencilViewLayout.Format = depthTextureLayout.Format;
depthStencilViewLayout.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
depthStencilViewLayout.Texture2D.MipSlice = 0U;
d3dResult = D3DDevice->CreateDepthStencilView(DepthStencilTexture, &depthStencilViewLayout, &DepthStencilView);
DepthStencilTexture->Release();
if (FAILED(d3dResult))
{
return false;
}
//Set output-merger render targets.
D3DDeviceContext->OMSetRenderTargets(1U, &RenderTargetView, DepthStencilView);
我一直在阅读这些教程(我只允许使用 2 个链接):https:// code.msdn.microsoft.com/Direct3D-Tutorial-Win32-829979ef
并通读 Direct3D 11 图形管道:https://msdn.microsoft.com/en-us/library/windows/desktop/ff476882%28v=vs.85%29.aspx
我目前有一个用 HLSL 编码的像素(又名片段)着色器,由以下代码组成:
//Pixel Shader input.
struct psInput
{
float4 Position: SV_POSITION;
float4 Color: COLOR;
};
//Pixel (aka. Fragment) Shader.
float4 PS(psInput input): SV_TARGET
{
return input.Color;
}
我(认为我)想做的是对像素着色器中的每个像素进行多重采样并访问附近的像素数据,以便我可以执行某种自定义抗锯齿,如 FXAA (http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf) .根据我的理解,我需要为每个渲染使用 PSSetShaderResources 将纹理传递给 HLSL,但除此之外我不知道。所以,我的问题是:
如何将附近的像素数据发送到 Direct3D 11 中的像素着色器?
能够做这种事情也对我理解 c++ 和 HLSL 如何在我在教程中找到的标准“将一些 float4 传递给着色器”之外的彼此交互方面非常有益。貌似这是D3D开发中最关键的一个方面,但是我在网上找不到很多例子。
我考虑过传统的 MSAA(多重采样抗锯齿),但我找不到任何关于如何在 D3D 11 中成功实现它的信息,除此之外我需要使用“BitBlt”(位块转移)模型交换链第一。 (参见 DXGI_SAMPLE_DESC1 和 DXGI_SAMPLE_DESC;只有计数为 1 且质量为 0(无 AA)才会导致绘制。)此外,我想知道如何对一般情况执行上述操作了解我的项目的其他方面是否需要它。不过,也欢迎回答有关如何在 D3D 11 中执行 MSAA 的问题。
请仅使用 D3D 11 和 HLSL 代码。
要像 FXAA 一样进行自定义抗锯齿,您需要将场景渲染到屏幕外渲染目标:
-使用绑定标志 D3D11_BIND_RENDER_TARGET
和 D3D11_BIND_SHADER_RESOURCE
ID3D11Texture2D
-为第一步创建的纹理创建一个ID3D11ShaderResourceView
和一个ID3D11RenderTargetView
。
-将场景渲染到步骤 2
中创建的ID3D11RenderTargetView
-将后台缓冲区设置为渲染目标并将在第 2 步中创建的 ID3D11ShaderResourceView
绑定到正确的像素着色器插槽。
-Render a fullscreen triangle covering the entire screen you'll be able to sample the texture containing the scene in the pixel shader (use the Load()函数)
当您尝试进行传统 MSAA 时,您是否记得设置 MultisampleEnable in the rasterizer state?
我再次回答我自己的问题,有点(从未使用过 FXAA...)。我在这里提供我的答案是为了对那些追随我脚步的人好。
原来我错过了 MSAA 的深度模板视图。您希望禁用 MSAA 的 SampleCount 为 1U,2XMSAA 为 2U,4XMSAA 为 4U,8XMSAA 为 8U,等等(使用 ID3D11Device::CheckMultisampleQualityLevels 到 "probe" 以获得可行的 MSAA 级别...)您几乎总是想要为禁用的 MSAA 使用质量级别 0U,为启用的 MSAA 使用 1U。
下面是我的工作 MSAA 代码(您应该可以填写其余部分)。请注意,我使用了 DXGI_FORMAT_D24_UNORM_S8_UINT 和 D3D11_DSV_DIMENSION_TEXTURE2DMS,并且深度纹理和深度模板视图的格式值相同,SampleCount 和 SampleQuality 值也相同。
祝你好运!
unsigned int SampleCount = 1U;
unsigned int SampleQuality = (SampleCount > 1U ? 1U : 0U);
//Create swap chain.
IDXGIFactory2* dxgiFactory2 = nullptr;
d3dResult = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
if (dxgiFactory2)
{
//DirectX 11.1 or later.
d3dResult = D3DDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&D3DDevice1));
if (SUCCEEDED(d3dResult))
{
D3DDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&D3DDeviceContext1));
}
DXGI_SWAP_CHAIN_DESC1 swapChain;
ZeroMemory(&swapChain, sizeof(swapChain));
swapChain.Width = width;
swapChain.Height = height;
swapChain.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChain.SampleDesc.Count = SampleCount;
swapChain.SampleDesc.Quality = SampleQuality;
swapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChain.BufferCount = 2U;
d3dResult = dxgiFactory2->CreateSwapChainForHwnd(D3DDevice, w32Window, &swapChain, nullptr, nullptr, &SwapChain1);
if (SUCCEEDED(d3dResult))
{
d3dResult = SwapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&SwapChain));
}
dxgiFactory2->Release();
}
else
{
//DirectX 11.0.
DXGI_SWAP_CHAIN_DESC swapChain;
ZeroMemory(&swapChain, sizeof(swapChain));
swapChain.BufferCount = 2U;
swapChain.BufferDesc.Width = width;
swapChain.BufferDesc.Height = height;
swapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChain.BufferDesc.RefreshRate.Numerator = 60U;
swapChain.BufferDesc.RefreshRate.Denominator = 1U;
swapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChain.OutputWindow = w32Window;
swapChain.SampleDesc.Count = SampleCount;
swapChain.SampleDesc.Quality = SampleQuality;
swapChain.Windowed = true;
d3dResult = dxgiFactory->CreateSwapChain(D3DDevice, &swapChain, &SwapChain);
}
//Disable Alt + Enter and Print Screen shortcuts.
dxgiFactory->MakeWindowAssociation(w32Window, DXGI_MWA_NO_PRINT_SCREEN | DXGI_MWA_NO_ALT_ENTER);
dxgiFactory->Release();
if (FAILED(d3dResult))
{
return false;
}
//Create render target view.
ID3D11Texture2D* backBuffer = nullptr;
d3dResult = SwapChain->GetBuffer(0U, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer));
if (FAILED(d3dResult))
{
return false;
}
d3dResult = D3DDevice->CreateRenderTargetView(backBuffer, nullptr, &RenderTargetView);
backBuffer->Release();
if (FAILED(d3dResult))
{
return false;
}
//Create depth stencil texture.
ID3D11Texture2D* DepthStencilTexture = nullptr;
D3D11_TEXTURE2D_DESC depthTextureLayout;
ZeroMemory(&depthTextureLayout, sizeof(depthTextureLayout));
depthTextureLayout.Width = width;
depthTextureLayout.Height = height;
depthTextureLayout.MipLevels = 1U;
depthTextureLayout.ArraySize = 1U;
depthTextureLayout.Usage = D3D11_USAGE_DEFAULT;
depthTextureLayout.CPUAccessFlags = 0U;
depthTextureLayout.MiscFlags = 0U;
depthTextureLayout.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthTextureLayout.SampleDesc.Count = SampleCount;
depthTextureLayout.SampleDesc.Quality = SampleQuality;
depthTextureLayout.BindFlags = D3D11_BIND_DEPTH_STENCIL;
d3dResult = D3DDevice->CreateTexture2D(&depthTextureLayout, nullptr, &DepthStencilTexture);
if (FAILED(d3dResult))
{
return false;
}
//Create depth stencil.
D3D11_DEPTH_STENCIL_DESC depthStencilLayout;
depthStencilLayout.DepthEnable = true;
depthStencilLayout.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilLayout.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilLayout.StencilEnable = true;
depthStencilLayout.StencilReadMask = 0xFF;
depthStencilLayout.StencilWriteMask = 0xFF;
depthStencilLayout.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilLayout.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilLayout.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilLayout.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilLayout.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
ID3D11DepthStencilState* depthStencilState;
D3DDevice->CreateDepthStencilState(&depthStencilLayout, &depthStencilState);
D3DDeviceContext->OMSetDepthStencilState(depthStencilState, 1U);
//Create depth stencil view.
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewLayout;
ZeroMemory(&depthStencilViewLayout, sizeof(depthStencilViewLayout));
depthStencilViewLayout.Format = depthTextureLayout.Format;
depthStencilViewLayout.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
depthStencilViewLayout.Texture2D.MipSlice = 0U;
d3dResult = D3DDevice->CreateDepthStencilView(DepthStencilTexture, &depthStencilViewLayout, &DepthStencilView);
DepthStencilTexture->Release();
if (FAILED(d3dResult))
{
return false;
}
//Set output-merger render targets.
D3DDeviceContext->OMSetRenderTargets(1U, &RenderTargetView, DepthStencilView);