Visão geral de máscaras da opacidade
Este tópico descreve como usar bitmaps e pincéis para definir máscaras de opacidade. Ele contém as seguintes seções:
- Pré-requisitos
- O que é uma máscara de opacidade?
- Usar um Bitmap como uma Máscara de Opacidade com o método FillOpacityMask
- Usar um pincel como uma máscara de opacidade com o método FillGeometry
- Aplicar uma Máscara de Opacidade a uma camada
- Tópicos relacionados
Pré-requisitos
Essa visão geral pressupõe que você esteja familiarizado com operações básicas de desenho Direct2D, conforme descrito no passo a passo Criar um aplicativo Direct2D simples. Você também deve estar familiarizado com os diferentes tipos de pincéis, conforme descrito na Visão geral de pincéis.
O que é uma máscara de opacidade?
Uma máscara de opacidade é uma máscara, descrita por um pincel ou bitmap, que é aplicada a outro objeto para tornar esse objeto parcial ou completamente transparente. Uma máscara de opacidade usa informações de canal alfa para especificar como os pixels de origem do objeto são misturados ao destino de destino final. As partes transparentes da máscara indicam as áreas em que a imagem subjacente está oculta, enquanto as partes opacas da máscara indicam onde o objeto mascarado está visível.
Há várias maneiras de aplicar uma máscara de opacidade:
- Use o método ID2D1RenderTarget::FillOpacityMask . O método FillOpacityMask pinta uma região retangular de um destino de renderização e aplica uma máscara de opacidade, definida por um bitmap. Use esse método quando a máscara de opacidade for um bitmap e você quiser preencher uma região retangular.
- Use o método ID2D1RenderTarget::FillGeometry . O método FillGeometry pinta o interior da geometria com o ID2D1BitmapBrush especificado e aplica uma máscara de opacidade, definida por um pincel. Use esse método quando quiser aplicar uma máscara de opacidade a uma geometria ou quiser usar um pincel como uma máscara de opacidade.
- Use um ID2D1Layer para aplicar uma máscara de opacidade. Use essa abordagem quando quiser aplicar uma máscara de opacidade a um grupo de conteúdo de desenho, não apenas a uma única forma ou imagem. Para obter detalhes, consulte a Visão geral das camadas.
Usar um Bitmap como uma Máscara de Opacidade com o método FillOpacityMask
O método FillOpacityMask pinta uma região retangular de um destino de renderização e aplica uma máscara de opacidade, definida por um ID2D1Bitmap. Use esse método quando você tiver um bitmap que deseja usar como uma máscara de opacidade para uma região retangular.
O diagrama a seguir mostra um efeito da aplicação da máscara de opacidade (um ID2D1Bitmap com uma imagem de uma flor) a um ID2D1BitmapBrush com uma imagem de uma planta de samambaia. A imagem resultante é um bitmap de uma planta recortada na forma de flor.
Os exemplos de código a seguir mostram como isso é feito.
O primeiro exemplo carrega o bitmap a seguir, m_pBitmapMask, para uso como uma máscara de bitmap. A ilustração a seguir mostra a saída produzida. Observe que, embora a parte opaca do bitmap pareça preta, as informações de cor no bitmap não têm efeito sobre a máscara de opacidade; somente as informações de opacidade de cada pixel no bitmap são usadas. Os pixels totalmente opacos neste bitmap foram coloridos em preto apenas para fins ilustrativos.
Neste exemplo, o ID2D1Bitmap é carregado por um método auxiliar, LoadResourceBitmap, definido em outro lugar no exemplo.
if (SUCCEEDED(hr))
{
hr = LoadResourceBitmap(
m_pRenderTarget,
m_pWICFactory,
L"BitmapMask",
L"Image",
&m_pBitmapMask
);
}
O próximo exemplo define o pincel, m_pFernBitmapBrush, ao qual a máscara de opacidade é aplicada. Este exemplo usa um ID2D1BitmapBrush que contém uma imagem de uma samambaia, mas você pode usar um ID2D1SolidColorBrush, ID2D1LinearGradientBrush ou ID2D1RadialGradientBrush . A ilustração a seguir mostra a saída produzida.
if (SUCCEEDED(hr))
{
D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp =
D2D1::BitmapBrushProperties(
D2D1_EXTEND_MODE_CLAMP,
D2D1_EXTEND_MODE_CLAMP,
D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
);
hr = m_pRenderTarget->CreateBitmapBrush(
m_pFernBitmap,
propertiesXClampYClamp,
&m_pFernBitmapBrush
);
}
Agora que a máscara de opacidade e o pincel estão definidos, você pode usar o método FillOpacityMask no método de renderização do aplicativo. Ao chamar o método FillOpacityMask , você deve especificar o tipo de máscara de opacidade que está usando: D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL e D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE. Para obter os significados desses três tipos, consulte D2D1_OPACITY_MASK_CONTENT.
Observação
Começando com Windows 8, a D2D1_OPACITY_MASK_CONTENT não é necessária. Consulte o método ID2D1DeviceContext::FillOpacityMask , que não tem nenhum parâmetro D2D1_OPACITY_MASK_CONTENT .
O próximo exemplo define o modo de suavização do destino de renderização como D2D1_ANTIALIAS_MODE_ALIASED para que a máscara de opacidade funcione corretamente. Em seguida, ele chama o método FillOpacityMask e passa a ele a máscara de opacidade (m_pBitmapMask), o pincel ao qual a máscara de opacidade é aplicada (m_pFernBitmapBrush), o tipo de conteúdo dentro da máscara de opacidade (D2D1_OPACITY_MASK_CONTENT_GRAPHICS) e a área a ser pintada. A ilustração a seguir mostra a saída produzida.
D2D1_RECT_F rcBrushRect = D2D1::RectF(5, 5, 155, 155);
// D2D1_ANTIALIAS_MODE_ALIASED must be set for FillOpacityMask to function properly
m_pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
m_pRenderTarget->FillOpacityMask(
m_pBitmapMask,
m_pFernBitmapBrush,
D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
&rcBrushRect
);
m_pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
O código foi omitido neste exemplo.
Usar um pincel como uma máscara de opacidade com o método FillGeometry
A seção anterior descreveu como usar um ID2D1Bitmap como uma máscara de opacidade. Direct2D também fornece o método ID2D1RenderTarget::FillGeometry, que permite especificar opcionalmente o pincel como uma máscara de opacidade ao preencher um ID2D1Geometry. Isso permite que você crie máscaras de opacidade de gradientes (usando ID2D1LinearGradientBrush ou ID2D1RadialGradientBrush) e bitmaps (usando ID2D1Bitmap).
O método FillGeometry usa três parâmetros:
- O primeiro parâmetro, um ID2D1Geometry, define a forma a ser pintada.
- O segundo parâmetro, um ID2D1Brush, especifica o pincel usado para pintar a geometria. Esse parâmetro deve ser um ID2D1BitmapBrush que tenha seus modos x e y-extend definidos como D2D1_EXTEND_MODE_CLAMP.
- O terceiro parâmetro, um ID2D1Brush, especifica um pincel a ser usado como a máscara de opacidade. Esse pincel pode ser um ID2D1LinearGradientBrush, ID2D1RadialGradientBrush ou um ID2D1BitmapBrush. (Tecnicamente, você pode usar um ID2D1SolidColorBrush, mas usar um pincel de cor sólida como uma máscara de opacidade não produz resultados interessantes.)
As seções a seguir descrevem como usar objetos ID2D1LinearGradientBrush e ID2D1RadialGradientBrush como máscaras de opacidade.
Usar um pincel de gradiente linear como uma máscara de opacidade
O diagrama a seguir mostra o efeito de aplicar um pincel de gradiente linear a um retângulo que é preenchido com um bitmap de flores.
As etapas a seguir descrevem como recriar esse efeito.
Defina o conteúdo a ser mascarado. O exemplo a seguir cria um ID2D1BitmapBrush, m_pLinearFadeFlowersBitmap. Os modos de extensão x e y para m_pLinearFadeFlowersBitmap são definidos como D2D1_EXTEND_MODE_CLAMP para que possam ser usados com uma máscara de opacidade pelo método FillGeometry .
if (SUCCEEDED(hr)) { // Create the bitmap to be used by the bitmap brush. hr = LoadResourceBitmap( m_pRenderTarget, m_pWICFactory, L"LinearFadeFlowers", L"Image", &m_pLinearFadeFlowersBitmap ); } if (SUCCEEDED(hr)) { D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = D2D1::BitmapBrushProperties( D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR );
C++ if (SUCCEEDED(hr)) { hr = m_pRenderTarget->CreateBitmapBrush( m_pLinearFadeFlowersBitmap, propertiesXClampYClamp, &m_pLinearFadeFlowersBitmapBrush ); }
C++ }
Defina a máscara de opacidade. O próximo exemplo de código cria um pincel de gradiente linear diagonal (m_pLinearGradientBrush) que desaparece de preto totalmente opaco na posição 0 para branco completamente transparente na posição 1.
if (SUCCEEDED(hr))
{
ID2D1GradientStopCollection *pGradientStops = NULL;
static const D2D1_GRADIENT_STOP gradientStops[] =
{
{ 0.f, D2D1::ColorF(D2D1::ColorF::Black, 1.0f) },
{ 1.f, D2D1::ColorF(D2D1::ColorF::White, 0.0f) },
};
hr = m_pRenderTarget->CreateGradientStopCollection(
gradientStops,
2,
&pGradientStops);
if (SUCCEEDED(hr))
{
hr = m_pRenderTarget->CreateLinearGradientBrush(
D2D1::LinearGradientBrushProperties(
D2D1::Point2F(0, 0),
D2D1::Point2F(150, 150)),
pGradientStops,
&m_pLinearGradientBrush);
}
pGradientStops->Release();
}
- Use o método FillGeometry . O exemplo final usa o método FillGeometry para o pincel de conteúdo para preencher um ID2D1RectangleGeometry (m_pRectGeo) com um ID2D1BitmapBrush (m_pLinearFadeFlowersBitmap) e aplica uma máscara de opacidade (m_pLinearGradientBrush).
m_pRenderTarget->FillGeometry(
m_pRectGeo,
m_pLinearFadeFlowersBitmapBrush,
m_pLinearGradientBrush
);
O código foi omitido neste exemplo.
Usar um pincel de gradiente radial como uma máscara de opacidade
O diagrama a seguir mostra o efeito visual da aplicação de um pincel de gradiente radial a um retângulo que é preenchido com um bitmap de folhagem.
O primeiro exemplo cria um ID2D1BitmapBrush, m_pRadialFadeFlowersBitmapBrush. Para que ele possa ser usado com uma máscara de opacidade pelo método FillGeometry , os modos de extensão x e y para m_pRadialFadeFlowersBitmapBrush são definidos como D2D1_EXTEND_MODE_CLAMP.
if (SUCCEEDED(hr))
{
// Create the bitmap to be used by the bitmap brush.
hr = LoadResourceBitmap(
m_pRenderTarget,
m_pWICFactory,
L"RadialFadeFlowers",
L"Image",
&m_pRadialFadeFlowersBitmap
);
}
if (SUCCEEDED(hr))
{
D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp =
D2D1::BitmapBrushProperties(
D2D1_EXTEND_MODE_CLAMP,
D2D1_EXTEND_MODE_CLAMP,
D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
);
C++ |
---|
|
C++ |
---|
|
O próximo exemplo define o pincel de gradiente radial que será usado como a máscara de opacidade.
if (SUCCEEDED(hr))
{
ID2D1GradientStopCollection *pGradientStops = NULL;
static const D2D1_GRADIENT_STOP gradientStops[] =
{
{ 0.f, D2D1::ColorF(D2D1::ColorF::Black, 1.0f) },
{ 1.f, D2D1::ColorF(D2D1::ColorF::White, 0.0f) },
};
hr = m_pRenderTarget->CreateGradientStopCollection(
gradientStops,
2,
&pGradientStops);
if (SUCCEEDED(hr))
{
hr = m_pRenderTarget->CreateRadialGradientBrush(
D2D1::RadialGradientBrushProperties(
D2D1::Point2F(75, 75),
D2D1::Point2F(0, 0),
75,
75),
pGradientStops,
&m_pRadialGradientBrush);
}
pGradientStops->Release();
}
O exemplo de código final usa o ID2D1BitmapBrush (m_pRadialFadeFlowersBitmapBrush) e a máscara de opacidade (m_pRadialGradientBrush) para preencher um ID2D1RectangleGeometry (m_pRectGeo).
m_pRenderTarget->FillGeometry(
m_pRectGeo,
m_pRadialFadeFlowersBitmapBrush,
m_pRadialGradientBrush
);
O código foi omitido neste exemplo.
Aplicar uma Máscara de Opacidade a uma camada
Ao chamar PushLayer para efetuar push de um ID2D1Layer para um destino de renderização, você pode usar a estrutura D2D1_LAYER_PARAMETERS para aplicar um pincel como uma máscara de opacidade. O exemplo de código a seguir usa um ID2D1RadialGradientBrush como uma máscara de opacidade.
HRESULT DemoApp::RenderWithLayerWithOpacityMask(ID2D1RenderTarget *pRT)
{
HRESULT hr = S_OK;
// Create a layer.
ID2D1Layer *pLayer = NULL;
hr = pRT->CreateLayer(NULL, &pLayer);
if (SUCCEEDED(hr))
{
pRT->SetTransform(D2D1::Matrix3x2F::Translation(300, 250));
// Push the layer with the content bounds.
pRT->PushLayer(
D2D1::LayerParameters(
D2D1::InfiniteRect(),
NULL,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::IdentityMatrix(),
1.0,
m_pRadialGradientBrush,
D2D1_LAYER_OPTIONS_NONE),
pLayer
);
pRT->DrawBitmap(m_pBambooBitmap, D2D1::RectF(0, 0, 190, 127));
pRT->FillRectangle(
D2D1::RectF(25.f, 25.f, 50.f, 50.f),
m_pSolidColorBrush
);
pRT->FillRectangle(
D2D1::RectF(50.f, 50.f, 75.f, 75.f),
m_pSolidColorBrush
);
pRT->FillRectangle(
D2D1::RectF(75.f, 75.f, 100.f, 100.f),
m_pSolidColorBrush
);
pRT->PopLayer();
}
SafeRelease(&pLayer);
return hr;
}
Para obter mais informações sobre como usar camadas, consulte a Visão geral das camadas.
Tópicos relacionados