Compartilhar via


Como aplicar efeitos a primitivos

Este tópico mostra como aplicar uma série de efeitos a primitivos Direct2D e DirectWrite.

Você pode usar a API de efeitos de Direct2D para aplicar grafos de efeito a primitivos renderizados por Direct2D a uma imagem. O exemplo aqui tem dois retângulos arredondados e o texto "Direct2D". Use Direct2D para desenhar os retângulos e DirectWrite para desenhar o texto.

retângulos com o texto

Usando Direct2D efeitos, você pode fazer com que essa imagem se pareça com a próxima imagem. Aplique os efeitos Gaussian Blur, Point Specular Lighting, Aritmetic Composite e Composite aos primitivos 2D para criar a imagem aqui.

retângulos com o texto

Depois de renderizar os retângulos e o texto em uma superfície intermediária, você pode usá-lo como entrada para objetos ID2D1Effect no grafo de imagem.

Neste exemplo, defina a imagem original como a entrada para o efeito Gaussian Blur e, em seguida, defina a saída do desfoque como a entrada para o efeito iluminação especular de ponto. O resultado desse efeito é composto com a imagem original duas vezes para obter a imagem final que é renderizada para a janela.

Aqui está um diagrama do grafo de imagem.

diagrama de grafo de efeito.

Esse grafo de efeito consiste em quatro objetos ID2D1Effect , cada um representando um efeito interno diferente. Você pode criar e conectar efeitos personalizados da mesma maneira, depois de registrá-los usando ID1D1Factory1::RegisterEffect. O código aqui cria os efeitos, define as propriedades e conecta o grafo de efeito mostrado anteriormente.

  1. Crie o efeito de desfoque gaussiano usando o método ID2D1DeviceContext::CreateEffect e especificando o CLSID adequado. Os CLSIDs para os efeitos internos são definidos em d2d1effects.h. Em seguida, defina o desvio padrão do desfoque usando o método ID2D1Effect::SetValue .

    // Create the Gaussian Blur Effect
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1GaussianBlur, &gaussianBlurEffect)
        );
    
    // Set the blur amount
    DX::ThrowIfFailed(
        gaussianBlurEffect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, sc_gaussianBlurStDev)
        );
    

    O efeito desfoque gaussiano desfoca todos os canais da imagem, incluindo o canal alfa.

  2. Crie o efeito de iluminação especular e defina as propriedades. A posição da luz é um vetor de três valores de ponto flutuante, portanto, você deve declará-la como uma variável separada e passá-la para o método SetValue .

    // Create the Specular Lighting Effect
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1PointSpecular, &specularLightingEffect)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_LIGHT_POSITION, sc_specularLightPosition)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_SPECULAR_EXPONENT, sc_specularExponent)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_SURFACE_SCALE, sc_specularSurfaceScale)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_SPECULAR_CONSTANT, sc_specularConstant)
        );
    

    O efeito de iluminação especular usa o canal alfa da entrada para criar um mapa de altura para a iluminação.

  3. Há dois efeitos compostos diferentes que você pode usar o efeito composto e a composição aritmética. Esse grafo de efeito usa ambos.

    Crie o efeito composto e defina o modo como D2D1_COMPOSITE_MODE_SOURCE_IN, que gera a interseção das imagens de origem e de destino.

    O efeito composto aritmético compõe as duas imagens de entrada com base em uma fórmula definida pelo W3C (World Wide Web Consortium) para o padrão SVG (Elementos Gráficos vetoriais escalonáveis). Crie uma composição aritmética e defina os coeficientes para a fórmula.

    // Create the Composite Effects
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1Composite, &compositeEffect)
        );
    
    DX::ThrowIfFailed(
        compositeEffect->SetValue(D2D1_COMPOSITE_PROP_MODE, D2D1_COMPOSITE_MODE_SOURCE_IN)
        );
    
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1ArithmeticComposite, &m_arithmeticCompositeEffect)
        );
    
    DX::ThrowIfFailed(
        m_arithmeticCompositeEffect->SetValue(D2D1_ARITHMETICCOMPOSITE_PROP_COEFFICIENTS, sc_arithmeticCoefficients)
        );
    

    Os coeficientes para o efeito composto aritmético são mostrados aqui.

    D2D1_VECTOR_4F sc_arithmeticCoefficients   = D2D1::Vector4F(0.0f, 1.0f, 1.0f, 0.0f);
    

    Nesse grafo de efeito, ambos os efeitos compostos assumem a saída dos outros efeitos e da superfície intermediária como entradas e compõe-os.

  4. Por fim, conecte os efeitos para formar o grafo definindo as entradas para as imagens e bitmaps adequados.

    O primeiro efeito, desfoque gaussiano, recebe sua entrada da superfície intermediária para a qual você renderiza os primitivos. Defina a entrada usando o método ID2D1Effect::SetInput e especificando o índice de um objeto ID2D1Image . O desfoque gaussiano e os efeitos de iluminação especular têm apenas uma única entrada. O efeito de iluminação especular usa o canal alfa desfocado do desfoque gaussiano

    Os efeitos compostos compostos e aritméticos têm várias entradas. Para garantir que as imagens sejam montadas na ordem certa, você deve especificar o índice correto para cada imagem de entrada.

    // Connect the graph.
    // Apply a blur effect to the original image.
    gaussianBlurEffect->SetInput(0, m_inputImage.Get());
    
    // Apply a specular lighting effect to the result.
    specularLightingEffect->SetInputEffect(0, gaussianBlurEffect.Get());
    
    // Compose the original bitmap under the output from lighting and blur.
    compositeEffect->SetInput(0, m_inputImage.Get());
    compositeEffect->SetInputEffect(1, specularLightingEffect.Get());
    
    // Compose the original bitmap under the output from lighting and blur.
    m_arithmeticCompositeEffect->SetInput(0, m_inputImage.Get());
    m_arithmeticCompositeEffect->SetInputEffect(1, compositeEffect.Get());
    
  5. Passe o objeto de efeito composto aritmético para o método ID2DDeviceContext::D rawImage e processa e desenha a saída do grafo.

        // Draw the output of the effects graph.
        m_d2dContext->DrawImage(
            m_arithmeticCompositeEffect.Get(),
            D2D1::Point2F(
                (size.width - sc_inputBitmapSize.width) / 2,
                (size.height - sc_inputBitmapSize.height) / 2 + sc_offset
                )
            );