Erstellen von Tiefenpuffer-GeräteressourcenCreate depth buffer device resources

Hier erfahren Sie, wie Sie die zum Unterstützen von Tiefentests für Schattenvolumen erforderlichen Direct3D-Geräteressourcen erstellen.Learn how to create the Direct3D device resources necessary to support depth testing for shadow volumes. Teil 1 von Exemplarische Vorgehensweise: Implementieren von Schattenvolumen mithilfe von Tiefenpuffern in Direct3D 11.Part 1 of Walkthrough: Implement shadow volumes using depth buffers in Direct3D 11.

Erforderliche RessourcenResources you'll need

Zum Rendern einer Tiefenkarte für Schattenvolumen benötigen Sie die folgenden geräteabhängigen Direct3D-Ressourcen:Rendering a depth map for shadow volumes requires the following Direct3D device-dependent resources:

  • Eine Ressource (Puffer) für die TiefenkarteA resource (buffer) for the depth map
  • Eine Tiefenschablonenansicht und eine Shaderressourcenansicht für die RessourceA depth stencil view and shader resource view for the resource
  • Ein Vergleichs-SamplerstatusobjektA comparison sampler state object
  • Konstantenpuffer für POV-BeleuchtungsmatrizenConstant buffers for light POV matrices
  • Einen Viewport zum Rendern der Schattenkarte (normalerweise ein quadratischer Viewport)A viewport for rendering the shadow map (typically a square viewport)
  • Ein Renderstatusobjekt zum Aktivieren von Frontface-CullingA rendering state object to enable front face culling
  • Außerdem benötigen Sie ein Renderstatusobjekt, um wieder zum Backface-Culling zu wechseln, falls Sie noch keines verwenden.You will also need a rendering state object to switch back to back face culling, if you don't already use one.

Beachten Sie, dass die Erstellung dieser Ressourcen in eine geräteabhängige Ressourcenerstellungsroutine eingebunden werden muss. Auf diese Weise kann Ihr Renderer die Ressourcen neu erstellen, wenn (beispielsweise) ein neuer Gerätetreiber installiert wird oder der Benutzer Ihre App auf einen Monitor verschiebt, der an einen anderen Grafikadapter angeschlossen ist.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.

Überprüfen unterstützter FeaturesCheck feature support

Vor dem Erstellen der tiefen Zuordnung wird die checkfeaturesupport -Methode auf dem Direct3D-Gerät, Request D3D11 _ Feature _ d3d9 _ Shadow- _ Unterstützungaufgerufen und eine D3D11 _ Feature _ Data _ d3d9 _ Shadow- _ Unterstützungs Struktur bereitgestellt.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

Wenn diese Funktion nicht unterstützt wird, versuchen Sie nicht, Shader zu laden, die für das Shadermodell 4 Ebene 9 x kompiliert wurden und _ Beispiel Vergleichsfunktionen aufrufen.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. Eine fehlende Unterstützung für dieses Feature bedeutet in vielen Fällen, dass es sich bei der GPU um ein älteres Gerät mit einem Treiber handelt, der nicht zur Unterstützung von mindestens WDDM 1.2 aktualisiert wurde.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. Wenn das Gerät mindestens die Featureebene 10 0 unterstützt, _ können Sie stattdessen einen Beispiel-Vergleichs-Shader für das Shadermodell 4 _ 0 laden.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.

Erstellen des TiefenpuffersCreate depth buffer

Versuchen Sie als Erstes, die Tiefenkarte in einem Tiefenformat mit einer höheren Genauigkeit zu erstellen.First, try creating the depth map with a higher-precision depth format. Richten Sie zuerst die entsprechenden Eigenschaften der Shaderressourcenansicht ein.Set up matching shader resource view properties first. Falls die Erstellung der Ressource fehlschlägt (z. B. weil zu wenig Gerätespeicher verfügbar ist oder ein Format von der Hardware nicht unterstützt wird), können Sie es mit einem Format mit geringerer Genauigkeit probieren und die Eigenschaften entsprechend ändern.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.

Dieser Schritt ist optional, wenn Sie nur ein tiefen Format mit niedriger Genauigkeit benötigen, z. b. beim Rendern auf mittlerer Auflösung Direct3D auf Featureebene von 9 _ 1-Geräten.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
    );

Erstellen Sie anschließend die Ressourcenansichten.Then create the resource views. Legen Sie den Mip-Slice für die Ansicht der Tiefenschablone auf null und die Mip-Ebenen für die Shaderressourcenansicht auf 1 fest.Set the mip slice to zero on the depth stencil view and set mip levels to 1 on the shader resource view. Beide verfügen über eine Textur Dimension von TEXTURE2D, und beide müssen ein entsprechendes DXGI- _ Formatverwenden.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
    );

Erstellen eines VergleichsstatusCreate comparison state

Erstellen Sie jetzt das Vergleichs-Samplerstatusobjekt.Now create the comparison sampler state object. Funktionsebene 9 _ 1 unterstützt nur den D3D11-Vergleich, der _ _ kleiner ist _ .Feature level 9_1 only supports D3D11_COMPARISON_LESS_EQUAL. Die Filterungsoptionen werden ausführlicher unter Unterstützen von Schattenkarten auf unterschiedlicher Hardware erläutert. Oder Sie setzen einfach Punktfilterung ein, um schnellere Schattenkarten zu erhalten.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.

Beachten Sie, dass Sie den D3D11 _ Texture _ Address-Grenz Adress Modus angeben können, der _ auf Featureebene 9 _ 1-Geräten funktioniert.Note that you can specify the D3D11_TEXTURE_ADDRESS_BORDER address mode and it will work on feature level 9_1 devices. Dies gilt für Pixelshader, die vor dem Tiefentest nicht testen, ob sich das Pixel im Ansichtsfrustum der Beleuchtung befindet.This applies to pixel shaders that don't test whether the pixel is in the light's view frustum before doing the depth test. Wenn Sie für jeden Rand 0 oder 1 angeben, können Sie steuern, ob Pixel außerhalb des Lichtkegels den Tiefentest bestehen – was bedeutet, ob sie beleuchtet werden oder sich im Schatten befinden.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.

Auf Featureebene _ 9 1 müssen die folgenden erforderlichen Werte festgelegt werden: minlod ist auf NULL festgelegt, maxlod ist auf D3D11 _ float32 _ Maxund MaxAnisotropy auf 0 (null) festgelegt.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
        )
    );

Erstellen von RenderstatusCreate render states

Erstellen Sie jetzt einen Renderstatus, den Sie zum Aktivieren von Frontface-Culling verwenden können.Now create a render state you can use to enable front face culling. Beachten Sie, dass auf Featureebene 9 _ 1 Geräte depthclipable auf truefestgelegt ist.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
        )
    );

Erstellen Sie einen Renderstatus, den Sie zum Aktivieren von Backface-Culling verwenden können.Create a render state you can use to enable back face culling. Falls Ihr Rendercode Backface-Culling bereits aktiviert, können Sie diesen Schritt überspringen.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
        )
    );

Erstellen von KonstantenpuffernCreate constant buffers

Denken Sie daran, einen Konstantenpuffer für das Rendering aus der Perspektive der Beleuchtung zu erstellen.Don't forget to create a constant buffer for rendering from the light's point of view. Mit diesem Konstantenpuffer können Sie die Beleuchtungsposition für den Shader angeben.You can also use this constant buffer to specify the light position to the shader. Verwenden Sie für punktuelles Licht eine perspektivische Matrix und für gerichtetes Licht (z. B. Sonnenlicht) eine orthogonale Matrix.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
        )
    );

Füllen Sie den Konstantenpuffer mit Daten.Fill the constant buffer data. Aktualisieren Sie den Konstantenpuffer einmal während der Initialisierung und dann noch einmal, wenn sich die Lichtwerte seit dem vorherigen Frame geändert haben.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
    );

Erstellen eines ViewportsCreate a viewport

Sie benötigen einen separaten Viewport zum Rendern der Schattenkarte.You need a separate viewport to render to the shadow map. Der Viewport ist keine geräteabhängige Ressource. Sie können ihn auch an einer anderen Stelle im Code erstellen.The viewport isn't a device-based resource; you're free to create it elsewhere in your code. Wenn Sie den Viewport zusammen mit der Schattenkarte erstellen, ist es einfacher, die Dimensionen von Viewport und Schattenkarte deckungsgleich zu halten.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;

Im nächsten Teil dieser exemplarischen Vorgehensweise erfahren Sie, wie Sie die Schattenkarte durch Rendern in den Tiefenpuffer erstellen.In the next part of this walkthrough, learn how to create the shadow map by rendering to the depth buffer.