Создание ресурсов устройства буфера глубины
Научитесь создавать ресурсы устройств Direct3D, необходимые для поддержки тестирования глубины для теневых томов. Пошаговое руководство. Реализация теневых объемов с помощью буферов глубины в Direct3D 11, часть 1.
Необходимые ресурсы
Для прорисовки карты глубины для теневых томов требуются следующие аппаратно-зависимые ресурсы Direct3D:
- Ресурс (буфер) для карты глубины
- Представление набора элементов глубины и представление ресурсов шейдера для ресурса
- Объект сравнения состояний дискретизатора
- Буферы констант для матриц освещения точки обзора
- Окно просмотра для прорисовки карты теней (обычно прямоугольное окно просмотра)
- Объект состояния прорисовки для включения выбора передней поверхности
- Объект состояния прорисовки (если он уже не используется) также потребуется вам для возвращения к выбору задней поверхности.
Отметим, что создание таких ресурсов должно быть включено в программу создания аппаратно-зависимых ресурсов. При этом ваше средство визуализации сможет, например, заново создавать их, когда устанавливается новый драйвер устройства или когда пользователь переносит ваше приложение на монитор, связанный с другим графическим адаптером.
Проверка поддержки функции
Перед созданием карты глубины вызовите метод CheckFeatureSupport на устройстве Direct3D, запросите D3D11_FEATURE_D3D9_SHADOW_SUPPORT и укажите структуру D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT .
D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT isD3D9ShadowSupported;
ZeroMemory(&isD3D9ShadowSupported, sizeof(isD3D9ShadowSupported));
pD3DDevice->CheckFeatureSupport(
D3D11_FEATURE_D3D9_SHADOW_SUPPORT,
&isD3D9ShadowSupported,
sizeof(D3D11_FEATURE_D3D9_SHADOW_SUPPORT)
);
if (isD3D9ShadowSupported.SupportsDepthAsTextureWithLessEqualComparisonFilter)
{
// Init shadow map resources
Если эта функция не поддерживается, не пытайтесь загружать шейдеры, скомпилированные для модели шейдера уровня 4, 9_x которые вызывают функции сравнения образцов. Во многих случаях отсутствие поддержки этой функции означает, что GPU — это устаревшее устройство, и его драйвер не обновлен для поддержки по крайней мере WDDM 1.2. Если устройство поддерживает по крайней мере уровень функций 10_0, вы можете загрузить пример шейдера сравнения, скомпилированный для модели шейдера 4_0.
Создание буфера глубины
Сначала попробуйте создать карту глубины с максимально точным форматом глубины. Задайте соответствующие свойства представления ресурса шейдера. Если создать ресурс не удалось, например из-за недостаточной памяти устройства или потому, что формат не поддерживается оборудованием, попытайтесь применить менее точный формат и измените свойства соответствующим образом.
Этот шаг необязателен, если вам нужен только формат глубины с низкой точностью, например при отрисовке на устройствах уровня функций Direct3D среднего разрешения 9_1.
D3D11_TEXTURE2D_DESC shadowMapDesc;
ZeroMemory(&shadowMapDesc, sizeof(D3D11_TEXTURE2D_DESC));
shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
shadowMapDesc.MipLevels = 1;
shadowMapDesc.ArraySize = 1;
shadowMapDesc.SampleDesc.Count = 1;
shadowMapDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
shadowMapDesc.Height = static_cast<UINT>(m_shadowMapDimension);
shadowMapDesc.Width = static_cast<UINT>(m_shadowMapDimension);
HRESULT hr = pD3DDevice->CreateTexture2D(
&shadowMapDesc,
nullptr,
&m_shadowMap
);
Затем создайте представления ресурсов. Задайте нулевое значение для MIP-среза в представлении трафарета глубины и значение 1 для уровней MIP в представлении ресурса шейдера. Оба имеют размер текстуры TEXTURE2D, и оба должны использовать соответствующий DXGI_FORMAT.
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
ZeroMemory(&depthStencilViewDesc, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
hr = pD3DDevice->CreateDepthStencilView(
m_shadowMap.Get(),
&depthStencilViewDesc,
&m_shadowDepthView
);
hr = pD3DDevice->CreateShaderResourceView(
m_shadowMap.Get(),
&shaderResourceViewDesc,
&m_shadowResourceView
);
Создание состояния сравнения
Теперь создайте объект сравнения состояний дискретизатора. Уровень компонентов 9_1 поддерживает только D3D11_COMPARISON_LESS_EQUAL. Возможности фильтрации подробнее объясняются в документе Поддержка карт теней на разном оборудовании. Можно также выбрать точечную фильтрацию для ускорения работы карт теней.
Обратите внимание, что можно указать D3D11_TEXTURE_ADDRESS_BORDER адресный режим, и он будет работать на устройствах с уровнем компонентов 9_1. Это применимо к шейдерам, которые не проверяют, находится ли пиксель в конусе представления освещения, перед выполнением теста глубины. Указывая значения 0 или 1 для каждой границы, вы можете контролировать, проходят или не проходят пиксели вне конуса освещения тест на глубину, то есть освещены они или находятся в тени.
На уровне компонентов 9_1 необходимо задать следующие обязательные значения: Значение MinLOD равно нулю, MaxLOD — D3D11_FLOAT32_MAX, а MaxAnisotropy — нулю.
D3D11_SAMPLER_DESC comparisonSamplerDesc;
ZeroMemory(&comparisonSamplerDesc, sizeof(D3D11_SAMPLER_DESC));
comparisonSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
comparisonSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
comparisonSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
comparisonSamplerDesc.BorderColor[0] = 1.0f;
comparisonSamplerDesc.BorderColor[1] = 1.0f;
comparisonSamplerDesc.BorderColor[2] = 1.0f;
comparisonSamplerDesc.BorderColor[3] = 1.0f;
comparisonSamplerDesc.MinLOD = 0.f;
comparisonSamplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
comparisonSamplerDesc.MipLODBias = 0.f;
comparisonSamplerDesc.MaxAnisotropy = 0;
comparisonSamplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
comparisonSamplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
// Point filtered shadows can be faster, and may be a good choice when
// rendering on hardware with lower feature levels. This sample has a
// UI option to enable/disable filtering so you can see the difference
// in quality and speed.
DX::ThrowIfFailed(
pD3DDevice->CreateSamplerState(
&comparisonSamplerDesc,
&m_comparisonSampler_point
)
);
Создание состояний прорисовки
Теперь создайте состояние прорисовки, которое можно использовать для выбора передней поверхности. Обратите внимание, что для устройств уровня компонентов 9_1 требуется параметр DepthClipEnable , равный true.
D3D11_RASTERIZER_DESC drawingRenderStateDesc;
ZeroMemory(&drawingRenderStateDesc, sizeof(D3D11_RASTERIZER_DESC));
drawingRenderStateDesc.CullMode = D3D11_CULL_BACK;
drawingRenderStateDesc.FillMode = D3D11_FILL_SOLID;
drawingRenderStateDesc.DepthClipEnable = true; // Feature level 9_1 requires DepthClipEnable == true
DX::ThrowIfFailed(
pD3DDevice->CreateRasterizerState(
&drawingRenderStateDesc,
&m_drawingRenderState
)
);
Создайте состояние прорисовки, которое можно использовать для выбора задней поверхности. Если ваш код прорисовки уже включает выбор задней поверхности, этот шаг можно пропустить.
D3D11_RASTERIZER_DESC shadowRenderStateDesc;
ZeroMemory(&shadowRenderStateDesc, sizeof(D3D11_RASTERIZER_DESC));
shadowRenderStateDesc.CullMode = D3D11_CULL_FRONT;
shadowRenderStateDesc.FillMode = D3D11_FILL_SOLID;
shadowRenderStateDesc.DepthClipEnable = true;
DX::ThrowIfFailed(
pD3DDevice->CreateRasterizerState(
&shadowRenderStateDesc,
&m_shadowRenderState
)
);
Создание буферов констант
Не забудьте создать буфер констант для прорисовки с точки зрения освещения. Этот буфер констант можно также использовать, чтобы указывать шейдеру позицию источника освещения. Используйте матрицу перспективы для точечных источников света и ортогональную матрицу для направленных источников света (например, для солнечного света).
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&viewProjectionConstantBufferDesc,
nullptr,
&m_lightViewProjectionBuffer
)
);
Заполните данные буфера констант. Обновляйте буферы констант один раз при инициализации и затем снова, если значения освещения были изменены по сравнению с предыдущим кадром.
{
XMMATRIX lightPerspectiveMatrix = XMMatrixPerspectiveFovRH(
XM_PIDIV2,
1.0f,
12.f,
50.f
);
XMStoreFloat4x4(
&m_lightViewProjectionBufferData.projection,
XMMatrixTranspose(lightPerspectiveMatrix)
);
// Point light at (20, 15, 20), pointed at the origin. POV up-vector is along the y-axis.
static const XMVECTORF32 eye = { 20.0f, 15.0f, 20.0f, 0.0f };
static const XMVECTORF32 at = { 0.0f, 0.0f, 0.0f, 0.0f };
static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f };
XMStoreFloat4x4(
&m_lightViewProjectionBufferData.view,
XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up))
);
// Store the light position to help calculate the shadow offset.
XMStoreFloat4(&m_lightViewProjectionBufferData.pos, eye);
}
context->UpdateSubresource(
m_lightViewProjectionBuffer.Get(),
0,
NULL,
&m_lightViewProjectionBufferData,
0,
0
);
Создание окна просмотра
Для прорисовки на карте глубины требуется отдельное окно просмотра. Окно просмотра не является аппаратно-зависимым ресурсом. Вы можете создать его в любом месте кода. Создание окна просмотра вместе с картой теней делает более удобным согласование размеров окна просмотра с размерами карты теней.
// Init viewport for shadow rendering
ZeroMemory(&m_shadowViewport, sizeof(D3D11_VIEWPORT));
m_shadowViewport.Height = m_shadowMapDimension;
m_shadowViewport.Width = m_shadowMapDimension;
m_shadowViewport.MinDepth = 0.f;
m_shadowViewport.MaxDepth = 1.f;
В следующей части этого руководства вы научитесь создавать карту теней путем прорисовки в буфер глубины.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по