Поддержка карт теней на различном оборудованииSupport shadow maps on a range of hardware

Более высокое качество отображения теней на быстрых устройствах и быстрое отображение на менее мощных устройствах.Render higher-fidelity shadows on faster devices and faster shadows on less powerful devices. Пошаговое руководство. Реализация теневых объемов с помощью буферов глубины в Direct3D 11, часть 4.Part 4 of Walkthrough: Implement shadow volumes using depth buffers in Direct3D 11.

Типы фильтров сравненияComparison filter types

Линейную фильтрацию используйте только на устройствах, где допустимо снижение производительности.Only use linear filtering if the device can afford the performance penalty. Как правило, устройства с уровнем функций Direct3D 9 _ 1 не имеют достаточных возможностей для линейной фильтрации теней.Generally, Direct3D feature level 9_1 devices don't have enough power to spare for linear filtering on shadows. На таких устройствах используйте точечную фильтрацию.Use point filtering instead on these devices. Если используется линейная фильтрация, настройте пиксельный шейдер так, чтобы он обрабатывал переход границ тени.When you use linear filtering, adjust the pixel shader so that it blends the shadow edges.

Создайте сравнительный образец для точечной фильтрации:Create the comparison sampler for point filtering:

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
        )
    );

Затем создайте образец для линейной фильтрации:Then create a sampler for linear filtering:

comparisonSamplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
DX::ThrowIfFailed(
    pD3DDevice->CreateSamplerState(
        &comparisonSamplerDesc,
        &m_comparisonSampler_linear
        )
    );

Выберите образец:Choose a sampler:

ID3D11PixelShader* pixelShader;
ID3D11SamplerState** comparisonSampler;
if (m_useLinear)
{
    pixelShader = m_shadowPixelShader_linear.Get();
    comparisonSampler = m_comparisonSampler_linear.GetAddressOf();
}
else
{
    pixelShader = m_shadowPixelShader_point.Get();
    comparisonSampler = m_comparisonSampler_point.GetAddressOf();
}

// Attach our pixel shader.
context->PSSetShader(
    pixelShader,
    nullptr,
    0
    );

context->PSSetSamplers(0, 1, comparisonSampler);
context->PSSetShaderResources(0, 1, m_shadowResourceView.GetAddressOf());

Обработайте границы тени с помощью линейной фильтрации:Blend shadow edges with linear filtering:

// Blends the shadow area into the lit area.
float3 light = lighting * (ambient + DplusS(N, L, NdotL, input.view));
float3 shadow = (1.0f - lighting) * ambient;
return float4(input.color * (light + shadow), 1.f);

Размер буфера тенейShadow buffer size

Крупные карты теней выглядят менее угловато, но занимают больше графической памяти.Larger shadow maps won't look as blocky but they take up more space in graphics memory. Попробуйте в своей игре карты теней разных размеров и сравните результаты на разных устройствах с разными размерами экранов.Experiment with different shadow map sizes in your game and observe the results in different types of devices and different display sizes. Чтобы добиться лучшего результата при меньшей загрузке графической памяти, попробуйте применить оптимизацию, например реализовать каскадные карты теней.Consider an optimization like cascaded shadow maps to get better results with less graphics memory. См. раздел Распространенные методики улучшения карт глубины теней.See Common Techniques to Improve Shadow Depth Maps.

Глубина буфера тенейShadow buffer depth

Более высокая точность буфера теней дает более достоверные результаты проверки глубины и позволяет избежать конфликта z-буфера и других проблем.Greater precision in the shadow buffer will give more accurate depth test results, which helps avoid issues like z-buffer fighting. Но, как и большие карты теней, при повышенной точности буфера используется больше памяти.But like larger shadow maps, greater precision takes up more memory. Экспериментируйте с различными типами точности глубины в формате "игра-DXGI", _ _ R24G8 _ тип _ и формат DXGI _ R16 _ без типов, и следите за скоростью и качеством на различных уровнях функций.Experiment with different depth precision types in your game - DXGI_FORMAT_R24G8_TYPELESS versus DXGI_FORMAT_R16_TYPELESS - and observe the speed and quality on different feature levels.

Оптимизация предварительно скомпилированных шейдеровOptimizing precompiled shaders

Приложения универсальной платформы Windows (UWP) могут использовать динамическую компиляцию шейдеров, но быстрее использовать динамическое связывание шейдеров.Universal Windows Platform (UWP) apps can use dynamic shader compilation, but it's faster to use dynamic shader linking. Можно также использовать директивы компилятора и блоки #ifdef для создания различных версий шейдеров.You can also use compiler directives and #ifdef blocks to create different versions of shaders. Для этого нужно открыть файл проекта Visual Studio в текстовом редакторе и добавить несколько записей <FxcCompiler> для HLSL (каждая с соответствующими определениями препроцессора).This is done by opening the Visual Studio project file in a text editor and adding multiple <FxcCompiler> entries for the HLSL (each with the appropriate preprocessor definitions). Обратите внимание, что это требует различных имен файлов. в этом случае Visual Studio присоединяет _ Point и _ линейный к разным версиям шейдера.Note that this necessitates different filenames; in this case, Visual Studio appends _point and _linear to the different versions of the shader.

В записи файла проекта для версии с линейной фильтрацией шейдера определяется LINEAR:The project file entry for the linear filtered version of the shader defines LINEAR:

<FxCompile Include="Content\ShadowPixelShader.hlsl">
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
  <DisableOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</DisableOptimizations>
  <EnableDebuggingInformation Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</EnableDebuggingInformation>
  <DisableOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DisableOptimizations>
  <DisableOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DisableOptimizations>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(OutDir)%(Filename)_linear.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(OutDir)%(Filename)_linear.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)%(Filename)_linear.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)%(Filename)_linear.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)%(Filename)_linear.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)%(Filename)_linear.cso</ObjectFileOutput>
  <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">LINEAR</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">LINEAR</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">LINEAR</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">LINEAR</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">LINEAR</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">LINEAR</PreprocessorDefinitions>
</FxCompile>

В записи файла проекта для версии с линейной фильтрацией не задаются определения препроцессора:The project file entry for the linear filtered version of the shader does not include preprocessor definitions:

<FxCompile Include="Content\ShadowPixelShader.hlsl">
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
  <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
  <DisableOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</DisableOptimizations>
  <EnableDebuggingInformation Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</EnableDebuggingInformation>
  <DisableOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DisableOptimizations>
  <DisableOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DisableOptimizations>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(OutDir)%(Filename)_point.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(OutDir)%(Filename)_point.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)%(Filename)_point.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)%(Filename)_point.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)%(Filename)_point.cso</ObjectFileOutput>
  <ObjectFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)%(Filename)_point.cso</ObjectFileOutput>
</FxCompile>