Compartir a través de


Representar el mapa de sombras en el búfer de profundidad

Represente desde el punto de vista de la luz para crear un mapa de profundidad bidimensional que represente el volumen de sombras. El mapa de profundidad enmascara el espacio que se representará en sombra. Parte 2 de Tutorial: Implementación de volúmenes de sombras mediante búferes de profundidad en Direct3D 11.

Borrar el búfer de profundidad

Limpie siempre el búfer de profundidad antes de renderizar en él.

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 profundidad

Para el paso de representación de sombras, especifique un búfer de profundidad, pero no especifique un destino de representación.

Especifique la ventanilla de luz, un sombreador de vértices y establezca los búferes de constantes de espacio de luz. Use la selección frontal de la cara para este paso para optimizar los valores de profundidad colocados en el búfer de sombras.

Tenga en cuenta que, en la mayoría de los dispositivos, puede especificar nullptr para el sombreador de píxeles (o omitir la especificación de un sombreador de píxeles por completo). Pero algunos controladores pueden producir una excepción al llamar a draw en el dispositivo Direct3D con un conjunto de sombreador de píxeles NULL. Para evitar esta excepción, puede establecer un sombreador de píxeles mínimo para el paso de representación de sombras. La salida de este sombreador se desecha; puede invocar a descartar en cada píxel.

Represente los objetos que pueden proyectar sombras, pero no se moleste en representar geometría que no pueda proyectar una sombra (como un piso en una habitación o los objetos eliminados del proceso de sombras por motivos de optimización).

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 cono de visión: Asegúrate de que tu implementación calcula un cono de visión ajustado para obtener la mayor precisión del búfer de profundidad. Consulte Técnicas comunes para mejorar mapas de profundidad de sombra para obtener más sugerencias sobre la técnica de sombras.

Sombreador de vértices para el pase de sombra

Use una versión simplificada del sombreador de vértices para representar solo la posición del vértice en el espacio de luz. No incluya ninguna normal de iluminación, transformaciones secundarias, y similares.

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á a agregar sombras mediante representación con pruebas de profundidad.