Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Визуализация с точки зрения света для создания двумерной карты глубины, отображающей объем тени. Карта глубины маскирует пространство, которое будет отображаться в тени. Часть 2 пошагового руководства : Реализация теневых объемов с использованием буферов глубины в Direct3D 11.
Очистка буфера глубины
Всегда очищайте буфер глубины перед рендерингом.
context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
context->ClearDepthStencilView(m_shadowDepthView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
Отрендерьте теневую карту в буфер глубины
Для прохода отрисовки тени укажите буфер глубины, но не указывайте целевой объект отрисовки.
Укажите окно просмотра света, шейдер вершин и задайте буферы констант света. Используйте отсечение лицевой стороны для этого прохода, чтобы оптимизировать значения глубины, помещенные в теневой буфер.
Обратите внимание, что на большинстве устройств можно указать nullptr для шейдера пикселей (или пропустить указание шейдера пикселей полностью). Но некоторые драйверы могут выбросить исключение при вызове команды рисования на устройстве Direct3D с установленным на NULL пиксельным шейдером. Чтобы избежать этого исключения, можно задать минимальный пиксельный шейдер для прохода рендеринга теней. Выходные данные этого шейдера отбрасываются; он может вызывать отмену для каждого пикселя.
Отрисовка объектов, которые могут бросать тени, но не старайтесь отрисовывать геометрию, которая не может бросать тень (например, пол в комнате или объекты, удаленные из теневого прохода по целям оптимизации).
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: Убедитесь, что реализация вычисляет жесткое представление 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;
}
В следующей части этого пошагового руководства вы узнаете, как добавить тени путем отрисовки с помощью тестирования глубины.