Прорисовка карты теней в буфер глубины
Выполняя прорисовку с точки зрения освещения, вы можете создать двумерную карту глубин, представляющую объемную тень. Карта глубин маскирует пространство, которое будет прорисовано с затенением. Пошаговое руководство. Реализация теневых объемов с помощью буферов глубины в Direct3D 11, часть 2.
Очистка буфера глубины
Всегда очищайте буфер глубины перед прорисовкой в него.
context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
context->ClearDepthStencilView(m_shadowDepthView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
Прорисовка карты теней в буфер глубины
Для прохода прорисовки теней задайте буфер глубины, но не указывайте цель прорисовки.
Задайте окно просмотра освещения, шейдер вершин и буферы констант для светового пространства. При этом проходе используйте выбор передней грани, чтобы оптимизировать значения глубины, помещаемые в буфер теней.
Обратите внимание, что в большинстве устройств вы можете задать nullptr для построителя текстуры (или вовсе не задавать построитель текстуры). Но некоторые драйверы могут генерировать исключение при вызове операции рисования на устройстве Direct3D с пустым указателем на построитель текстуры. Чтобы такого исключения не возникало, вы можете задать минимальный пиксельный шейдер для прохода прорисовки теней. Выходное значение этого шейдера будет игнорироваться; он может вызывать discard для каждого пикселя.
Прорисовывайте объекты, которые могут отбрасывать тени, но не тратьте усилия на прорисовку геометрических элементов, которые не способны отбрасывать тень (например, пол в комнате или объекты, исключенные из прохода прорисовки теней в целях оптимизации).
void ShadowSceneRenderer::RenderShadowMap()
{
auto context = m_deviceResources->GetD3DDeviceContext();
// Render all the objects in the scene that can cast shadows onto themselves or onto other objects.
// Only bind the ID3D11DepthStencilView for output.
context->OMSetRenderTargets(
0,
nullptr,
m_shadowDepthView.Get()
);
// Note that starting with the second frame, the previous call will display
// warnings in VS debug output about forcing an unbind of the pixel shader
// resource. This warning can be safely ignored when using shadow buffers
// as demonstrated in this sample.
// Set rendering state.
context->RSSetState(m_shadowRenderState.Get());
context->RSSetViewports(1, &m_shadowViewport);
// Each vertex is one instance of the VertexPositionTexNormColor struct.
UINT stride = sizeof(VertexPositionTexNormColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());
// Attach our vertex shader.
context->VSSetShader(
m_simpleVertexShader.Get(),
nullptr,
0
);
// Send the constant buffers to the Graphics device.
context->VSSetConstantBuffers(
0,
1,
m_lightViewProjectionBuffer.GetAddressOf()
);
context->VSSetConstantBuffers(
1,
1,
m_rotatedModelBuffer.GetAddressOf()
);
// In some configurations, it's possible to avoid setting a pixel shader
// (or set PS to nullptr). Not all drivers are tolerant of this, so to be
// safe set a minimal shader here.
//
// Direct3D will discard output from this shader because the render target
// view is unbound.
context->PSSetShader(
m_textureShader.Get(),
nullptr,
0
);
// Draw the objects.
context->DrawIndexed(
m_indexCountCube,
0,
0
);
}
Оптимизируйте представление frustum: Убедитесь, что реализация вычисляет ограниченный обзор, чтобы обеспечить наибольшую точность буфера глубины. Другие советы по работе с тенями см. в разделе о распространенных методиках улучшения карт глубин теней.
Шейдер вершин для прохода прорисовки теней
Используйте упрощенную версию шейдера вершин, чтобы прорисовать только положение вершины в световом пространстве. Не включайте в него световые нормали, вторичные преобразования и т. д.
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f);
// Transform the vertex position into projected space.
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
return output;
}
В следующей части этого пошагового руководства вы научитесь добавлять тени при помощи прорисовки с проверкой глубины.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по