Creare risorse dispositivo per il buffer profonditàCreate depth buffer device resources

Scoprire come creare le risorse dispositivo Direct3D necessarie per supportare il testing della profondità dei volumi d’ombra.Learn how to create the Direct3D device resources necessary to support depth testing for shadow volumes. Parte 1 dell’Esercitazione: Implementare volumi d’ombra tramite buffer profondità in Direct3D 11.Part 1 of Walkthrough: Implement shadow volumes using depth buffers in Direct3D 11.

Risorse necessarieResources you'll need

Per il rendering di una mappa di profondità per i volumi d'ombra sono necessarie le risorse dipendenti da dispositivo Direct3D seguenti:Rendering a depth map for shadow volumes requires the following Direct3D device-dependent resources:

  • Un (buffer) di risorse per la mappa di profonditàA resource (buffer) for the depth map
  • Una visualizzazione depth stencil e una visualizzazione risorse shader per la risorsaA depth stencil view and shader resource view for the resource
  • Un oggetto stato campionatore di confrontoA comparison sampler state object
  • Buffer costanti per le matrici del punto di vista della fonte di luceConstant buffers for light POV matrices
  • Un riquadro di visualizzazione per il rendering della mappa delle ombreggiature (in genere un riquadro visualizzazione quadrato)A viewport for rendering the shadow map (typically a square viewport)
  • Un oggetto stato di rendering per abilitare il front-face cullingA rendering state object to enable front face culling
  • Avrai anche bisogno di un oggetto stato di rendering per tornare al back-face culling, se già non ne usi uno.You will also need a rendering state object to switch back to back face culling, if you don't already use one.

Tieni presente che la creazione di queste risorse deve essere inclusa in una routine di creazione delle risorse dipendenti dal dispositivo, in modo che il tuo renderer possa ricrearle se viene installato un nuovo driver di dispositivo, ad esempio, oppure se l'utente sposta la tua app su un monitor collegato a una diversa scheda grafica.Note that creation of these resources needs to be included in a device-dependent resource creation routine, that way your renderer can recreate them if (for example) a new device driver is installed, or the user moves your app to a monitor attached to a different graphics adapter.

Verificare il supporto della funzionalitàCheck feature support

Prima di creare la mappa di profondità, chiamare il metodo CheckFeatureSupport sul dispositivo Direct3D, richiedere il supporto per l' ** _ _ _ ombreggiatura _ della funzionalità d3d11 d3d9**e fornire una struttura di ** _ _ _ _ _ supporto d3d9 per i dati delle funzionalità d3d11** .Before creating the depth map, call the CheckFeatureSupport method on the Direct3D device, request D3D11_FEATURE_D3D9_SHADOW_SUPPORT, and provide a D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT structure.

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

Se questa funzionalità non è supportata, non provare a caricare gli shader compilati per Shader Model 4 Level 9 _ che chiamano funzioni di confronto di esempio.If this feature is not supported, do not try to load shaders compiled for shader model 4 level 9_x that call sample comparison functions. In molti casi la mancanza di supporto per questa funzionalità indica che la GPU è un dispositivo legacy con un driver non aggiornato per supportare almeno WDDM 1.2.In many cases, lack of support for this feature means that the GPU is a legacy device with a driver that isn't updated to support at least WDDM 1.2. Se il dispositivo supporta almeno il livello di funzionalità 10 _ 0, è possibile caricare uno shader di confronto di esempio compilato per il modello di Shader 4 _ 0.If the device supports at least feature level 10_0 then you can load a sample comparison shader compiled for shader model 4_0 instead.

Creare il buffer profonditàCreate depth buffer

Prova innanzitutto a creare la mappa di profondità con un formato di profondità di maggiore precisione.First, try creating the depth map with a higher-precision depth format. Configura prima di tutto le proprietà corrispondenti per la visualizzazione risorse shader.Set up matching shader resource view properties first. Se la creazione della risorsa non riesce, ad esempio a causa di memoria insufficiente del dispositivo o di un formato non supportato dall'hardware, prova un formato con precisione inferiore e modifica le proprietà di conseguenza.If the resource creation fails, for example due to low device memory or a format that the hardware doesn't support, try a lower-precision format and change properties to match.

Questo passaggio è facoltativo se è necessario solo un formato di profondità a bassa precisione, ad esempio quando si esegue il rendering in dispositivi Direct3D a risoluzione media di livello 9 _ 1.This step is optional if you only need a low-precision depth format, for example when rendering on medium-resolution Direct3D feature level 9_1 devices.

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

Crea quindi le visualizzazioni delle risorse.Then create the resource views. Imposta la sezione MIP su zero nella visualizzazione depth stencil e i livelli MIP su 1 nella visualizzazione risorse shader.Set the mip slice to zero on the depth stencil view and set mip levels to 1 on the shader resource view. Entrambi hanno una dimensione di trama di TEXTURE2D ed entrambi devono usare un ** _ formato DXGI**corrispondente.Both have a texture dimension of TEXTURE2D, and both need to use a matching 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
    );

Creare lo stato di confrontoCreate comparison state

Creiamo ora l'oggetto stato campionatore di confronto.Now create the comparison sampler state object. Il livello di funzionalità 9 _ 1 supporta solo il _ confronto d3d11 _ meno _ uguale.Feature level 9_1 only supports D3D11_COMPARISON_LESS_EQUAL. Le scelte per i filtri sono spiegate in maggiore dettaglio in Supportare le mappe delle ombreggiature in un’ampia gamma di hardware. Puoi anche semplicemente selezionare il filtro a punti per ottenere mappe delle ombreggiature più veloci.Filtering choices are explained more in Supporting shadow maps on a range of hardware - or you can just pick point filtering for faster shadow maps.

Si noti che è possibile specificare la _ modalità di indirizzo del bordo dell'indirizzo della trama d3d11 _ e che funzionerà _ su dispositivi di livello 2 di funzionalità _ .Note that you can specify the D3D11_TEXTURE_ADDRESS_BORDER address mode and it will work on feature level 9_1 devices. Questo vale per i pixel shader che non verificano se il pixel si trova nel frustum di vista della fonte di luce prima di eseguire il test di profondità.This applies to pixel shaders that don't test whether the pixel is in the light's view frustum before doing the depth test. Specificando 0 o 1 per ogni bordo, puoi stabilire se i pixel all'esterno del frustum superano o meno il test di profondità e quindi se sono illuminati o in ombra.By specifying 0 or 1 for each border, you can control whether pixels outside the light's view frustum pass or fail the depth test, and therefore whether they are lit or in shadow.

A livello di funzionalità 9 _ 1 è necessario impostare i valori obbligatori seguenti: MinLOD è impostato su zero, MaxLOD è impostato su d3d11 _ FLOAT32 _ Maxe MaxAnisotropy è impostato su zero.On feature level 9_1, the following required values must be set: MinLOD is set to zero, MaxLOD is set to D3D11_FLOAT32_MAX, and MaxAnisotropy is set to zero.

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

Creare gli stati di renderingCreate render states

Creiamo ora uno stato di rendering utilizzabile per abilitare il front-face culling.Now create a render state you can use to enable front face culling. Si noti che per i dispositivi con livello di funzionalità 9 _ 1 è necessario impostare DepthClipEnable su true.Note that feature level 9_1 devices require DepthClipEnable set to 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
        )
    );

Crea uno stato di rendering utilizzabile per abilitare il back-face culling.Create a render state you can use to enable back face culling. Se il tuo codice di rendering prevede già l'attivazione del back-face culling, puoi ignorare questo passaggio.If your rendering code already turns on back face culling, then you can skip this step.

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

Creare buffer costantiCreate constant buffers

Non dimenticarti di creare un buffer costante per il rendering dal punto di vista della fonte di luce.Don't forget to create a constant buffer for rendering from the light's point of view. Puoi anche usare questo buffer costante per specificare la posizione della fonte di luce per lo shader.You can also use this constant buffer to specify the light position to the shader. Usa una matrice prospettica per luci puntiformi e una matrice ortogonale per luci direzionali (come la luce solare).Use a perspective matrix for point lights, and use an orthogonal matrix for directional lights (such as sunlight).

DX::ThrowIfFailed(
    m_deviceResources->GetD3DDevice()->CreateBuffer(
        &viewProjectionConstantBufferDesc,
        nullptr,
        &m_lightViewProjectionBuffer
        )
    );

Completa i dati dei buffer costanti.Fill the constant buffer data. Aggiorna i buffer costanti una volta durante l'inizializzazione e di nuovo se i valori della fonte di luce sono cambiati rispetto al frame precedente.Update the constant buffers once during initialization, and again if the light values have changed since the previous frame.

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

Creare un riquadro di visualizzazioneCreate a viewport

Hai bisogno di un riquadro di visualizzazione separato per il rendering nella mappa delle ombreggiature.You need a separate viewport to render to the shadow map. Il riquadro di visualizzazione non è una risorsa basata su dispositivo e sei libero di crearlo in altre posizioni nel codice.The viewport isn't a device-based resource; you're free to create it elsewhere in your code. La creazione del riquadro di visualizzazione insieme alla mappa delle ombreggiature può essere utile per fare in modo che la dimensione del riquadro di visualizzazione rimanga congruente con la dimensione della mappa delle ombreggiature.Creating the viewport along with the shadow map can help make it more convenient to keep the dimension of the viewport congruent with the shadow map dimension.

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

Nella prossima parte di questa esercitazione imparerai a creare la mappa delle ombreggiature tramite il rendering nel buffer di intensità.In the next part of this walkthrough, learn how to create the shadow map by rendering to the depth buffer.