Partilhar via


Visão Geral das Realizações de Geometria

Este tópico descreve como usar realizações de geometria Direct2D para melhorar o desempenho de renderização de geometria do seu aplicativo em determinados cenários.

Contém as seguintes secções:

O que são realizações de geometria?

As realizações de geometria, introduzidas no Windows 8.1, são um novo tipo de primitiva de desenho que torna mais fácil para aplicativos Direct2D melhorar o desempenho de renderização de geometria em certos casos. As realizações de geometria são representadas pela interface ID2D1GeometryRealization.

Por que usar realizações de geometria?

Quando Direct2D renderiza um objetoID2D1Geometry, ele deve converter essa geometria em uma forma que o hardware gráfico entende por meio de um processo chamado tessellation. Normalmente, o Direct2D deve tesselar a geometria de cada quadro desenhado, mesmo que a geometria não seja alterada. Se seu aplicativo renderizar a mesma geometria a cada quadro, a retesselação repetida representará um esforço computacional desperdiçado. É mais eficiente computacionalmente armazenar em cache a tesselação, ou até mesmo a rasterização completa, da geometria, e usar essa representação em cache em cada quadro em vez de repetir a tesselação.

Uma maneira comum de os desenvolvedores resolverem esse problema é armazenar em cache a rasterização completa da geometria. Particularmente, é comum criar um novo bitmap, rasterizar a geometria para esse bitmap e, em seguida, inserir esse bitmap na cena conforme necessário. (Essa abordagem é descrita na seção de renderização de geometria da melhoria do desempenho de aplicações Direct2D.) Embora essa abordagem seja muito eficiente computacionalmente, ela tem algumas desvantagens:

  • O bitmap armazenado em cache é sensível a alterações na transformação aplicada à cena. Por exemplo, dimensionar a rasterização pode resultar em artefatos de dimensionamento percetíveis. Mitigar esses artefatos com algoritmos de dimensionamento de alta qualidade pode ser computacionalmente caro.
  • O bitmap armazenado em cache consome uma quantidade significativa de memória, especialmente se for rasterizado em alta resolução.

As realizações de geometria fornecem uma maneira alternativa de armazenar em cache a geometria que evita as desvantagens acima. As realizações de geometria não são representadas por pixels (como é o caso de uma rasterização completa), mas sim por pontos em um plano matemático. Por esta razão, eles são menos sensíveis do que as rasterizações completas à escala e outras manipulações, e consomem significativamente menos memória.

Quando usar realizações de geometria

Considere o uso de realizações de geometria quando seu aplicativo renderiza geometrias complexas cujas formas mudam com pouca frequência, mas que podem estar sujeitas a transformações variáveis.

Por exemplo, considere um aplicativo de mapeamento que mostra um mapa estático, mas que permite ao usuário aumentar e diminuir o zoom. Este aplicativo pode se beneficiar do uso de realizações de geometria. Como as geometrias que estão sendo renderizadas permanecem estáticas, é útil armazená-las em cache para salvar o trabalho de tesselação. Mas como os mapas são dimensionados quando o usuário amplia, armazenar em cache uma rasterização completa não é o ideal, devido ao dimensionamento de artefatos. Cachear realizações de geometria permitiria que a aplicação evitasse o trabalho de re-tesselação, mantendo uma alta qualidade visual durante o dimensionamento.

Por outro lado, considere um aplicativo caleidoscópio com geometria animada que muda continuamente. Este aplicativo provavelmente não se beneficiaria do uso de realizações de geometria. Como as próprias formas mudam de quadro para quadro, não é útil armazenar em cache suas tesselações. A melhor abordagem para este aplicativo é desenhar ID2D1Geometry objetos diretamente.

Criação de realizações geométricas

Um objeto ID2D1GeometryRealization deve ser criado a partir de um objeto ID2D1Geometry existente. Para criar uma realização de geometria, chame o método CreateFilledGeometryRealization ou o método CreateStrokedGeometryRealization e passe o ID2D1Geometry a ser realizado.

Ambos os tipos de realização de geometria são representados pela interface ID2D1GeometryRealization.

Ao criar uma realização de geometria, Direct2D deve achatar quaisquer curvas na geometria fornecida para aproximações poligonais. Você deve fornecer um parâmetro de tolerância de achatamento para o método de criação — isso especifica a distância máxima, em pixels independentes do dispositivo (DIPs), entre a curva verdadeira da geometria e sua aproximação poligonal. Quanto menor a tolerância de achatamento fornecida, maior será a fidelidade do objeto de realização de geometria resultante. Da mesma forma, fornecer uma maior tolerância ao achatamento produz uma realização de geometria de menor fidelidade. Observe que as realizações de geometria de maior fidelidade são mais caras de desenhar do que as de baixa fidelidade, mas elas podem ser dimensionadas ainda mais antes de introduzir artefatos visíveis. Para obter orientação sobre o uso de tolerâncias de achatamento, consulte Realizações de geometria de dimensionamento abaixo.

Observação

Os objetos de realização de geometria estão associados a um dispositivo gráfico específico: são recursos dependentes do dispositivo.

 

Realizações de geometria de desenho

Desenhar realizações de geometria é semelhante a desenhar outras primitivas Direct2D, como bitmaps. Para fazer isso, chame o método DrawGeometryRealization e passe-lhe o objeto de realização de geometria a ser desenhado e o pincel a ser usado. Como acontece com outros métodos de desenho Direct2D, você deve chamar DrawGeometryRealization entre chamadas para BeginDraw e EndDraw.

Realizações de geometria de escala

As realizações de geometria, como outras primitivas de Direct2D, respeitam a transformação definida no contexto do dispositivo. Embora as transformações de translação e rotação não tenham efeito sobre a qualidade visual das realizações de geometria, as transformações de escala podem produzir artefatos visuais.

Em particular, a aplicação de uma escala grande o suficiente para qualquer realização de geometria pode revelar a aproximação poligonal das curvas verdadeiras. A imagem aqui mostra um par de realizações de geometria elíptica (preenchimento e traço) que foram ampliadas demais. Artefatos de achatamento de curvas são visíveis.

um par de representações de geometria elíptica (preenchimento e traço) que foram ampliadas excessivamente. Artefatos de achatamento de curvas são visíveis.

Os aplicativos sensíveis à qualidade visual devem tomar medidas para garantir que isso não aconteça. A forma como você lida com o dimensionamento depende das necessidades do seu aplicativo. A seguir estão várias abordagens recomendadas para vários tipos diferentes de aplicativo.

Usando aplicações de geometria em aplicativos que não são escaláveis

Se seu aplicativo não executar nenhum dimensionamento nas realizações de geometria, é seguro criar as realizações apenas uma vez, usando uma única tolerância de nivelamento. (As transformações sem dimensionamento não afetam a qualidade visual das realizações de geometria renderizada.) Use a função ComputeFlatteningTolerance para calcular a tolerância de nivelamento apropriada para o DPI:

    float dpiX, dpiY;
    deviceContext->GetDpi(&dpiX, &dpiY);

    float flatteningTolerance = D2D1::ComputeFlatteningTolerance(
        D2D1::Matrix3x2F::Identity(),   // apply no additional scaling transform
        dpiX,                           // horizontal DPI
        dpiY                            // vertical DPI
        );

Usando realizações de geometria em aplicativos que são dimensionados por uma pequena quantidade

Se a sua aplicação conseguir ampliar uma realização de geometria em apenas uma pequena quantidade (por exemplo, até 2x ou 3x), então pode ser apropriado simplesmente criar a realização de geometria uma vez, com uma tolerância de achatamento proporcionalmente menor do que a padrão. Isso cria uma realização de maior fidelidade que pode ser ampliada significativamente antes de incorrer em artefactos de escala; a contrapartida é que desenvolver a realização de maior fidelidade requer mais trabalho.

Por exemplo, suponha que saiba que o seu aplicativo nunca irá aumentar uma representação geométrica em mais de 2x. Seu aplicativo pode criar a realização geométrica usando uma tolerância de achatamento que é metade do valor padrão e simplesmente dimensionar a realização conforme for necessário, até ao dobro. Use a funçãoComputeFlatteningTolerance para calcular a tolerância de nivelamento apropriada passando 2.0 como o parâmetro maxZoomFactor:

    float dpiX, dpiY;
    deviceContext->GetDpi(&dpiX, &dpiY);
    
    float flatteningTolerance = D2D1::ComputeFlatteningTolerance(
        D2D1::Matrix3x2F::Identity(),   // apply no additional scaling transform
        dpiX,                           // horizontal DPI
        dpiY,                           // vertical DPI
        2.0f                            // realization can be scaled by an additional 2x
        );

Usando realizações de geometria em aplicativos que são dimensionados em grande quantidade

Se a sua aplicação puder dimensionar uma realização de geometria para cima ou para baixo em proporções significativas (por exemplo, em 10x ou mais), lidar com o dimensionamento de forma adequada torna-se mais complicado.

Para a maioria desses aplicativos, a abordagem recomendada é recriar a realização de geometria com tolerâncias de achatamento progressivamente menores à medida que a cena é ampliada, a fim de manter a fidelidade visual e evitar artefatos de escala. Da mesma forma, à medida que a cena é reduzida, o aplicativo deve recriar as realizações de geometria em tolerâncias de achatamento progressivamente mais altas, a fim de evitar desperdício de detalhes de renderização que não são visíveis. O aplicativo não deve recriar as realizações de geometria toda vez que a escala muda, porque isso derrota o propósito de armazenar em cache o trabalho de tesselação. Em vez disso, o aplicativo deve recriar as realizações de geometria com menos frequência: por exemplo, após cada aumento ou diminuição de 2x na escala.

Cada vez que a escala muda em um aplicativo em resposta à interação do usuário, o aplicativo pode comparar a nova escala com a escala na qual as realizações de geometria foram criadas pela última vez (armazenadas, por exemplo, em um membro m_lastScale). Se os dois valores estiverem próximos (neste caso, dentro de um fator de 2), nenhuma outra ação será tomada. Mas se os dois valores não estiverem próximos, então as realizações de geometria são recriadas. A função ComputeFlatteningTolerance é usada para calcular uma tolerância de achatamento apropriada para a nova escala, e m_lastScale é atualizada para a nova escala.

Além disso, o aplicativo sempre cria realizações usando uma tolerância menor do que o que normalmente seria usado para a nova escala, passando um valor de 2 como o parâmetro maxZoomFactor para ComputeFlatteningTolerance. Isso permite que as novas realizações de geometria sejam ampliadas por um fator adicional de 2 sem incorrer em artefatos de escala.

Observação

A abordagem descrita aqui pode não ser apropriada para todos os aplicativos. Por exemplo, se seu aplicativo permitir que a cena seja dimensionada por fatores muito grandes muito rapidamente (por exemplo, se ela contiver um controle deslizante de "zoom" que pode ser movido de 100% para 1.000.000% no espaço de alguns quadros), essa abordagem pode resultar em excesso de trabalho recriando as realizações de geometria a cada quadro. Uma abordagem alternativa é recriar as representações geométricas somente depois que cada manipulação da escala da cena tiver sido concluída (por exemplo, depois que o usuário tiver completado um gesto de pinça).

 

Visão Geral das Geometrias

Melhorar o desempenho de aplicações Direct2D

Diretrizes gerais para renderizar conteúdo estático complexo

ID2D1DeviceContext1

ID2D1GeometriaRealização

função ComputeFlatteningTolerance