Restituer le plan d’ombres dans le tamponRender the shadow map to the depth buffer

Générez le rendu du point de vue de la lumière pour créer un mappage de profondeur en deux dimensions qui représente le volume de l’ombre.Render from the point of view of the light to create a two-dimensional depth map representing the shadow volume. Le mappage de profondeur masque l’espace qui sera rendu dans l’ombre.The depth map masks the space that will be rendered in shadow. Partie 2 de la Procédure pas à pas : implémenter des volumes d’ombre à l’aide de tampons de profondeur dans Direct3D 11.Part 2 of Walkthrough: Implement shadow volumes using depth buffers in Direct3D 11.

Effacer le tampon de profondeurClear the depth buffer

Effacez toujours le tampon de profondeur avant d’y générer un rendu.Always clear the depth buffer before rendering to it.

context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
context->ClearDepthStencilView(m_shadowDepthView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

Restituer le plan d’ombres dans le tamponRender the shadow map to the depth buffer

Pour la passe de rendu d’ombre, spécifiez un tampon de profondeur mais ne spécifiez pas de cible de rendu.For the shadow rendering pass, specify a depth buffer but do not specify a render target.

Spécifiez la fenêtre d’affichage de la lumière, un nuanceur de vertex et définissez les tampons constants de l’espace lumineux.Specify the light viewport, a vertex shader, and set the light space constant buffers. Utilisez l’élimination de la face avant pour cette passe pour optimiser les valeurs de profondeur placées dans le tampon de l’ombre.Use front face culling for this pass to optimize the depth values placed in the shadow buffer.

Notez que sur la plupart des périphériques, vous pouvez spécifier nullptr pour le nuanceur de pixels (ou évitez totalement de spécifier un nuanceur de pixels).Note that on most devices, you can specify nullptr for the pixel shader (or skip specifying a pixel shader entirely). Mais certains pilotes risquent de lever une exception quand vous appelez le dessin sur le périphérique Direct3D avec un jeu de nuanceurs de pixels null.But some drivers may throw an exception when you call draw on the Direct3D device with a null pixel shader set. Pour éviter cette exception, vous pouvez définir un nuanceur de pixels minimal pour la passe de rendu d’ombre.To avoid this exception, you can set a minimal pixel shader for the shadow rendering pass. Le résultat de ce nuanceur est rejeté. Il peut appeler la fonction ignore à chaque pixel.The output of this shader is thrown away; it can call discard on every pixel.

Générez le rendu des objets pouvant projeter des ombres, mais ne vous embêtez pas à générer le rendu de la géométrie qui ne peut pas en projeter (comme un sol dans une salle ou des objets supprimés de la passe d’ombre pour des raisons d’optimisation).Render the objects that can cast shadows, but don't bother rendering geometry that can't cast a shadow (like a floor in a room, or objects removed from the shadow pass for optimization reasons).

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

Optimiser la vue frustum : Assurez-vous que votre implémentation calcule un frustum d’affichage étroit afin que vous obteniez la plus grande précision de votre mémoire tampon de profondeur.Optimize the view frustum: Make sure your implementation computes a tight view frustum so that you get the most precision out of your depth buffer. Voir Techniques courantes pour améliorer les mappages de profondeur d’ombre pour obtenir plus de conseils sur la technique d’ombrage.See Common Techniques to Improve Shadow Depth Maps for more tips on shadow technique.

Nuanceur de vertex pour la passe d’ombreVertex shader for shadow pass

Utilisez une version simplifiée de votre nuanceur de vertex pour générer uniquement le rendu de la position du vertex dans l’espace lumineux.Use a simplified version of your vertex shader to render just the vertex position in light space. N’incluez pas de normales d’éclairage, de transformations secondaires, etc.Don't include any lighting normals, secondary transformations, and so on.

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

Dans la partie suivante de cette procédure pas à pas, découvrez comment ajouter des ombres en générant le rendu avec un test de profondeur.In the next part of this walkthrough, learn how to add shadows by rendering with depth testing.