Representar el mapa de sombras en el búfer de profundidadRender the shadow map to the depth buffer

Representa desde el punto de vista de la luz para crear un mapa de profundidad de dos dimensiones representando el volumen de sombra.Render from the point of view of the light to create a two-dimensional depth map representing the shadow volume. El mapa de profundidad enmascara el espacio que se va a representar en la sombraThe depth map masks the space that will be rendered in shadow. Parte 2 de Tutorial: implementar volúmenes de sombra con búferes de profundidad en Direct3D 11.Part 2 of Walkthrough: Implement shadow volumes using depth buffers in Direct3D 11.

Borra el búfer de profundidadClear the depth buffer

Siempre borra el búfer de profundidad antes de representarlo.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);

Representar el mapa de sombras en el búfer de profundidadRender the shadow map to the depth buffer

Para el pase (o transferencia) de representación de sombras, especifica un búfer de profundidad pero no especifiques un destino de representación.For the shadow rendering pass, specify a depth buffer but do not specify a render target.

Especifica la ventanilla de luz y un sombreador de vértices, y establece los búferes de constantes del espacio de luz.Specify the light viewport, a vertex shader, and set the light space constant buffers. Usa la selección (culling) de la cara anterior para este pase a fin de optimizar los valores de profundidad en el búfer de sombras.Use front face culling for this pass to optimize the depth values placed in the shadow buffer.

Observa que en la mayoría de dispositivos, puedes especificar nullptr para el sombreador de píxeles (o saltear completamente la especificación de un sombreador de píxeles).Note that on most devices, you can specify nullptr for the pixel shader (or skip specifying a pixel shader entirely). Sin embargo algunos controladores pueden generar una excepción cuando llamas a draw en el dispositivo de Direct3D con un sombreador de píxeles nulo establecido.But some drivers may throw an exception when you call draw on the Direct3D device with a null pixel shader set. Para evitar esta excepción, puedes establecer un sombreador de píxeles mínimo para el pase de representación de sombras.To avoid this exception, you can set a minimal pixel shader for the shadow rendering pass. El resultado de este sombreador se descarta; puede llamar a discard en cada píxel.The output of this shader is thrown away; it can call discard on every pixel.

Representa los objetos que pueden arrojar sombras, pero no te preocupes en representar geometría que no pueda dar sombra (como el piso de una habitación u objetos quitados del pase de sombras por motivos de optimización).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
        );
}

Optimizar el frustum de vista: asegúrate de que tu implementación calcule un frustum de vista ajustado para que obtengas la mayor precisión posible de tu búfer de profundidad.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. Consulta Técnicas habituales para mejorar los mapas de profundidad de sombras para ver más sugerencias sobre la técnica de sombras.See Common Techniques to Improve Shadow Depth Maps for more tips on shadow technique.

Sombreador de vértices para el pase de sombrasVertex shader for shadow pass

Usa una versión simplificada de tu sombreador de vértices para representar solo la posición de vértice en el espacio de luz.Use a simplified version of your vertex shader to render just the vertex position in light space. No incluyas ninguna normal de iluminación ni transformaciones secundarias, 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;
}

En la siguiente parte de este tutorial, aprenderás a agregar sombras mediante la representación con pruebas de profundidad.In the next part of this walkthrough, learn how to add shadows by rendering with depth testing.