Comment appliquer des effets à des primitives
Cette rubrique montre comment appliquer une série d’effets aux primitives Direct2D et DirectWrite.
Vous pouvez utiliser l’API d’effets Direct2D pour appliquer des graphiques d’effets à des primitives rendues par Direct2D à une image. L’exemple comporte ici deux rectangles arrondis et le texte « Direct2D ». Utilisez Direct2D pour dessiner les rectangles et DirectWrite pour dessiner le texte.
À l’aide des effets Direct2D, vous pouvez faire en sorte que cette image ressemble à l’image suivante. Appliquez les effets Flou gaussien, Éclairage spéculaire point, Composite arithmétique et Composite aux primitives 2D pour créer l’image ici.
Après avoir rendu les rectangles et le texte sur une surface intermédiaire, vous pouvez l’utiliser comme entrée pour les objets ID2D1Effect dans le graphique d’image.
Dans cet exemple, définissez l’image d’origine comme entrée sur l’effet de flou gaussien , puis définissez la sortie du flou comme entrée pour l’effet Éclairage spéculaire point. Le résultat de cet effet est ensuite composé avec l’image d’origine à deux reprises pour obtenir l’image finale rendue dans la fenêtre.
Voici un diagramme du graphique d’image.
Ce graphe d’effets se compose de quatre objets ID2D1Effect , chacun représentant un effet intégré différent. Vous pouvez créer et connecter des effets personnalisés de la même façon, après les avoir inscrits à l’aide de ID1D1Factory1::RegisterEffect. Le code crée ici les effets, définit les propriétés et connecte le graphique d’effets présenté précédemment.
Créez l’effet de flou gaussien à l’aide de la méthode ID2D1DeviceContext::CreateEffect et en spécifiant le CLSID approprié. Les CLSID pour les effets intégrés sont définis dans d2d1effects.h. Vous définissez ensuite l’écart type du flou à l’aide de la méthode 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) );
L’effet de flou gaussien brouille tous les canaux de l’image, y compris le canal alpha.
Créez l’effet d’éclairage spéculaire et définissez les propriétés. La position de la lumière étant un vecteur de 3 valeurs à virgule flottante, vous devez la déclarer en tant que variable distincte et la transmettre à la méthode 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) );
L’effet d’éclairage spéculaire utilise le canal alpha de l’entrée pour créer une carte de hauteur pour l’éclairage.
Il existe deux effets composites différents que vous pouvez utiliser l’effet composite et le composite arithmétique. Ce graphique d’effets utilise les deux.
Créez l’effet composite et définissez le mode sur D2D1_COMPOSITE_MODE_SOURCE_IN, qui génère l’intersection des images source et de destination.
L’effet composite arithmétique compose les deux images d’entrée basées sur une formule définie par le World Wide Web Consortium (W3C) pour la norme SVG (Scalable Vector Graphics). Créez un composite arithmétique et définissez les coefficients de la formule.
// 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) );
Les coefficients de l’effet composite arithmétique sont présentés ici.
D2D1_VECTOR_4F sc_arithmeticCoefficients = D2D1::Vector4F(0.0f, 1.0f, 1.0f, 0.0f);
Dans ce graphique d’effet, les deux effets composites prennent la sortie des autres effets et la surface intermédiaire comme entrées et les composites.
Enfin, vous connectez les effets pour former le graphique en définissant les entrées sur les images et bitmaps appropriées.
Le premier effet, flou gaussien, reçoit son entrée de la surface intermédiaire vers laquelle vous avez rendu les primitives. Vous définissez l’entrée à l’aide de la méthode ID2D1Effect::SetInput et en spécifiant l’index d’un objet ID2D1Image . Le flou gaussien et les effets d’éclairage spéculaire n’ont qu’une seule entrée. L’effet d’éclairage spéculaire utilise le canal alpha flou du flou gaussien
Les effets composites et arithmétiques ont plusieurs entrées. Pour vous assurer que les images sont rassemblées dans le bon ordre, vous devez spécifier l’index correct pour chaque image d’entrée.
// 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());
Passez l’objet d’effet composite arithmétique dans la méthode ID2DDeviceContext::D rawImage , puis traite et dessine la sortie du graphique.
// 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 ) );