Geometry Realization Sample

This topic contains the following sections.

Goal

  • To show the benefits and costs of using opacity masks and meshes as an alternative to traditional geometry rendering.
  • To provide a self-contained package that can be used in other applications to provide the functionality that is mentioned in the previous item.

Description

In Direct2D, geometries are device-independent resources which make them infinitely scalable on all targets. They are truly rendered as vectors. This also leads to increased processing at the time of actual geometry rendering. There are many applications that do not require their scenes to be target agnostic. In such scenarios, caching of geometric data can lead to a performance improvement.

This sample caters to the following scenarios in which geometric caching can be used:

  • Filled or stroked geometry.
  • Aliased or anti-aliased geometry.
  • Hardware vs. software performance

The sample shows a scene where many objects that are basically geometries are being animated. It produces the output shown in the following screen shot.

Screen shot of many objects that are being animated

The key concepts being demonstrated:

Using Opacity Masks and A8 Targets for Improving Performance for Anti-aliased Geometries

An opacity mask is a bitmap whose only purpose is to supply the coverage information that is represented by the alpha channel. In other words, it controls the transparency of the content that is being rendered.

Direct2D enables an application to fill a Bitmap (where alpha is treated as a mask) with a Brush, in the same manner as the ID2D1RenderTarget::FillGeometry call. The alpha channel of the bitmap is used to represent the coverage of the geometry at each pixel, and this is filled appropriately with the brush, and then modulated by the opacity brush. Typically an application will generate this AlphaMask bitmap by drawing to an intermediate render target that is created by using ID2D1RenderTarget::CreateCompatibleRenderTarget.

Using Meshes to Improve Performance for Aliased Geometries

ID2D1Mesh is used to represent a set of render target vertices that can be drawn by Direct2D by using FillMesh. These render target vertices are simple X/Y positions that form a list of triangles. The representation of meshes is closest to what is stored on the video card. Every geometry is tessellated and the list of render target vertices that form the triangles are stored on the video card before they are rendered. Because the representation of a mesh is already in that form, they are rendered very fast. This fast rendering gives a performance improvement. Meshes can only be used when the rendering mode is set to aliased.

User Scenario

The most likely scenario will be the one in which an application draws many of the same complex paths. In such a scenario, the geometry can be cached one time and redrawn multiple times. For example, a 2D slot machine game shows the same item multiple times with different colors.

However, one should take a note of the following facts about realizations:

  • Anti-aliased realizations can consume lots of memory.
    • This varies with the area of the underlying bitmaps.
    • The effect is lessened somewhat (by a factor of 4) by using alpha-only bitmaps.
  • A performance benefit is only present when you use a hardware render target.
  • A transform can be changed dynamically, but it results in decreased quality.
    • Opacity masks become "blocky" when zoomed in.
    • Faceting becomes clear in Beziers when meshes are zoomed in.

Details

Options

This sample can be run with multiple settings to change rendering modes and scene complexity.

The following table summarizes the various options:

ControlBehavior
Up ArrowIncreases the number of primitives rendered.
Down ArrowDecreases the number of primitives rendered.
SpacebarPauses/resumes the animation.
'T' key Toggles between hardware and software rendering.
'R' key Toggles between rendering geometry with and without realizations.
'A' keyToggles between antialiasing modes.
Mouse WheelZooms in and out while hovering the mouse pointer over an area of the application. The focus follows the mouse when zooming in. Realizations are not regenerated.

 

The goal of the sample is not to show how to implement a zoom, but to show that realizations have a limitation and cannot be zoomed in infinitely. You can re-create realizations at a higher zoom level to avoid significant loss of quality. But this sample does not show that case.

Implementation Details

One goal of this sample is to provide you with a pre-baked realization package.

The realization package is split into two interfaces: IGeometryRealizationFactory and IGeometryRealization.

The intent is that the user would create one realization factory per resource domain—that is, one per render target and its compatible render targets. The factory keeps track of resources shared between realizations, such as opacity mask atlases. However, the package does not support atlasing.

From the realization factory the user creates an IGeometryRealization, specifying how this realization is to be used—whether it will be stroked, filled, or both, and if stroked, what parameters to use. This realization will then contain all the sub-resources needed to render in these contexts. If the resource is used in a context that was not specified at creation time, an error is returned. The one exception to this rule is the world transform. If the world transform on the RT differs from the one specified at creation time, then the realization is transformed appropriately to make up the difference. For example, if the realization is created by using a 2x2 scale transform when the current world transform is a 3x3 scale, then the realization will be scaled up by 3/2 x 3/2. This produces a geometry with the same size as its unrealized counterpart, but with decreased quality (the nature of this degradation depends on the kind of realization).

When users want to change the realization in some way (for example, to account for a new world transformation), they can call IGeometryRealization::Update. This reuses existing resources when it is possible.

In pseudo-code, the package resembles the following example:

GeometryRealizationFactory::CreateGeometryRealization
{
    if (alisased)
    {
        if (filled)
        {     
            // Create mesh

            // Tessellate geometry into mesh
        }
        
        if (stroked)
        {
            // Widen geometry

            // Create mesh

            // Tessellate widened geometry into mesh
        }

        // Store creation-time world transform and inverse
    }

    if (antialiased)
    {
        if (filled)
        {     
            // Get bounds of geometry

            // Create bitmap render target with size = size of computed bounds and with
            // alpha-only pixel format.

            // Render geometry into RENDER TARGET
           
            // Store creation-time world transform + translation to position
            // bitmap and inverse.

        }
        
        if (stroked)
        {
            // Widen geometry

            // Get bounds of widened geometry

            // Create bitmap RENDER TARGET with size = size of computed bounds and with
            // alpha-only pixel format.

            // Render geometry into RENDER TARGET
           
            // Store creation-time world transform + translation to position
            // bitmap and inverse
        }
    }
};

GeometryRealizationFactory::Fill
{
    // 
    // Determine if the target is HW/SW.

    if (inSoftware || renderMode == ForceUnealized)
    {
        m_pRENDER TARGET->FillGeometry(m_unrealizedGeometry);
    }
    else
    {
        //
        // Get RENDER TARGET transform
        //
        // Set RENDER TARGET transform = inverse(creationTransform) * currentTransform 
        //
        // Get RENDER TARGET antialias mode
        //
        if (AAmode == aliased)
        {
            m_pRENDER TARGET->FillMesh();
        }
        else
        {
            m_pRENDER TARGET->FillOpacityMask();
        }

        // Reset RENDER TARGET transform
    }
}

Requirements

Minimum supported clientWindows 7 or Windows Vista with Service Pack 2 (SP2) and Platform Update for Windows Vista
Minimum supported serverWindows Server 2008 R2 or Windows Server 2008 with Service Pack 2 (SP2) and Platform Update for Windows Server 2008
Windows SDKWindows Software Development Kit (SDK) for Windows 7

 

Downloading the Sample

This sample is available in the following locations.

LocationPath/URL
Windows SDK\Program Files\Microsoft SDKs\Windows\v7.0\Samples\Multimedia\Direct2D\GeometryRealizationSample
Code GalleryDownload from MSDN Code Gallery

 

Building the Sample

Building the Sample Using the Command Prompt

  1. Open the Command Prompt window and browse to the sample directory.
  2. Type msbuild GeometryRealizationSample.sln.

Building the Sample Using Visual Studio 2008 (Preferred Method)

  1. Open Windows Explorer and browse to the sample directory.
  2. Double-click the icon for the .sln (solution) file to open the file in Visual Studio.
  3. In the Build menu, select Build Solution. The application will be built in the default \Debug or \Release directory.

 

 

Send comments about this topic to Microsoft

Build date: 1/22/2012

Community Additions

Show: