Im a big fan of the Hieroglyph 3 Engine http://hieroglyph3.codeplex.com/. Because of that ive written an integration as an overlay that is working with the current version 83062 of Hieroglyph 3.

To render the direct2D content on top of the engine there has to be written one additional class.
The other code for implementation will be written in the App class provided by the engine.

GUIOverlay.h

#ifndef GUIOverlay_h
#define GUIOverlay_h
//--------------------------------------------------------------------------------
#include "Task.h"
#include "SpriteFontLoaderDX11.h"
#include "SpriteRendererDX11.h"

#include "Rendering\D2D1Renderer.h"
//--------------------------------------------------------------------------------
namespace Glyph3
{

    class GUIOverlay : public Task
    {
    public:
        GUIOverlay( RendererDX11& Renderer, D2D1Renderer& RendererD2D1, ResourcePtr RenderTarget );
        virtual ~GUIOverlay();

        virtual void Update( float fTime );
        virtual void QueuePreTasks( RendererDX11* pRenderer );
        virtual void ExecuteTask( PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager );
        virtual void Resize( UINT width, UINT height );

        virtual void SetRenderParams( IParameterManager* pParamManager );
        virtual void SetUsageParams( IParameterManager* pParamManager );

        virtual std::wstring GetName();

    protected:
        Vector4f                m_vColor;
        int                        m_iViewport;

        ResourcePtr                m_RenderTarget;

        SpriteFontPtr            m_pSpriteFont;
        SpriteRendererDX11*        m_pSpriteRenderer;
       
    private:
        ResourcePtr _direct2DTexture;

    };
};
//--------------------------------------------------------------------------------
#endif // GUIOverlay_h

GUIOverlay.cpp

#include "GUIOverlay.h"
#include "Entity3D.h"
#include "Node3D.h"
#include "Texture2dConfigDX11.h"
#include "Log.h"
#include "IParameterManager.h"
#include "PipelineManagerDX11.h"
#include "Texture2dDX11.h"
//--------------------------------------------------------------------------------
using namespace Glyph3;
//--------------------------------------------------------------------------------
GUIOverlay::GUIOverlay( RendererDX11& Renderer, D2D1Renderer& RendererD2D1, ResourcePtr RenderTarget )
{
    m_RenderTarget = RenderTarget;

    m_vColor.MakeZero();

    ResourceDX11* pResource = Renderer.GetResourceByIndex( m_RenderTarget->m_iResource );

    if ( pResource->GetType() == RT_TEXTURE2D )
    {
        Texture2dDX11* pTexture = (Texture2dDX11*)pResource;
        D3D11_TEXTURE2D_DESC desc = pTexture->GetActualDescription();

        // Create a view port to use on the scene.  This basically selects the
        // entire floating point area of the render target.
        D3D11_VIEWPORT viewport;
        viewport.Width = static_cast< float >( desc.Width );
        viewport.Height = static_cast< float >( desc.Height );
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;

        m_iViewport = Renderer.CreateViewPort( viewport );
    }

    // Create the text rendering classes.
    _direct2DTexture = Renderer.LoadTexture(RendererD2D1.GetTexture());

    m_pSpriteRenderer = new SpriteRendererDX11();
    m_pSpriteRenderer->Initialize();
}
//--------------------------------------------------------------------------------
GUIOverlay::~GUIOverlay()
{
    SAFE_DELETE( m_pSpriteRenderer );
}
//--------------------------------------------------------------------------------
void GUIOverlay::Update( float fTime )
{
}
//--------------------------------------------------------------------------------
void GUIOverlay::QueuePreTasks( RendererDX11* pRenderer )
{
    // Queue this view into the renderer for processing.
    pRenderer->QueueTask( this );
}
//--------------------------------------------------------------------------------
void GUIOverlay::ExecuteTask( PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager )
{
    Matrix4f mat = Matrix4f::Identity();

    // Set the parameters for rendering this view
    pPipelineManager->ClearRenderTargets();
    pPipelineManager->OutputMergerStage.DesiredState.RenderTargetViews.SetState( 0, m_RenderTarget->m_iResourceRTV );
    pPipelineManager->ApplyRenderTargets();

    pPipelineManager->RasterizerStage.DesiredState.ViewportCount.SetState( 1 );
    pPipelineManager->RasterizerStage.DesiredState.Viewports.SetState( 0, m_iViewport );
    pPipelineManager->RasterizerStage.DesiredState.RasterizerState.SetState( 0 );

    // Set default states for these stages
    pPipelineManager->OutputMergerStage.DesiredState.DepthStencilState.SetState( 0 );
    pPipelineManager->OutputMergerStage.DesiredState.BlendState.SetState( 0 );

    m_pSpriteRenderer->Render( pPipelineManager, pParamManager, _direct2DTexture, mat);
}
//--------------------------------------------------------------------------------
void GUIOverlay::Resize( UINT width, UINT height )
{
    RendererDX11::Get()->ResizeViewport( m_iViewport, width, height );
}
//--------------------------------------------------------------------------------
void GUIOverlay::SetRenderParams( IParameterManager* pParamManager )
{
 } //-------------------------------------------------------------------------------- void GUIOverlay::SetUsageParams( IParameterManager* pParamManager ) { } //-------------------------------------------------------------------------------- std::wstring GUIOverlay::GetName() { return( L"GUIOverlay" ); }

Include the headers

#include "Rendering\D2D1Renderer.h"
#include "Objects\Stage.h"
#include "GUIOverlay.h"

Needed variables

D2D1Renderer* _rendererD2D1;
D2::Stage* _stage;
GUIOverlay* _guiOverlayView;

Needed methods

bool InitializeD2D1Renderer(int width, int height);

Initializing the D2D1Renderer and the Stage-Object

bool App::InitializeD2D1Renderer(int width, int height) {
    _rendererD2D1 = new D2D1Renderer();
  
    if(!_rendererD2D1->Initialize(m_pRenderer11->CreateSharedSurface(width, height))) {
        return false;
    }
  
    _stage = new D2::Stage();
    _rendererD2D1->addD2D1FrameRenderListener(_stage);

    return true;
}

Initialize the D2D1Renderer inside the ConfigureEngineCompoents()-Method

bool App::ConfigureEngineComponents()
{
    ...

    if ( !InitializeD2D1Renderer(width, height) ) {
        return false;
    }

    return true;
}

Update the D2D1Renderer each frame

void App::Update()
{
    // Update the timer to determine the elapsed time since last frame.  This can
    // then used for animation during the frame.
    m_pTimer->Update();

    // Send an event to everyone that a new frame has started.  This will be used
    // in later examples for using the material system with render views.
    EvtManager.ProcessEvent( EvtFrameStartPtr( new EvtFrameStart( m_pTimer->Elapsed() ) ) );

    _rendererD2D1->Update();

    // Update the scene, and then render all cameras within the scene.
    m_pScene->Update( m_pTimer->Elapsed() );
    m_pScene->Render( m_pRenderer11 );

    // Perform the rendering and presentation for the window.
    m_pRenderer11->Present( m_pWindow->GetHandle(), m_pWindow->GetSwapChain() );
}

The WindowProc Method of the App class has to be overwritten.

virtual LRESULT WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);

Register the interaction-model on the windows message loop.

LRESULT App::WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    _stage->HandleWindowMessage(hwnd, msg, wparam, lparam);
   //if App is a sublass of RenderApplication use:
   //return RenderApplication::WindowProx(hwnd, msg, wparam, lparam)
   return Application::WindowProc(hwnd, msg, wparam, lparam);
}

If the mouse buttons are not working it is necessary to register the mouse for rawInput support.

void App::InitializeRawInput() {
    RAWINPUTDEVICE Rid[1];

    Rid[0].usUsagePage = 1;
    Rid[0].usUsage = 2;
    Rid[0].dwFlags = 0;
    Rid[0].hwndTarget = NULL;

    if(RegisterRawInputDevices(Rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
        MessageBox(NULL, L"Failed to Register Input Devices!", L"ALERT", MB_OK);
        exit(1);
    }
}

Initialize the GUIOverlay

void App::Initialize()
{
    //... init camera

    //if the App class is a subclass of RenderApplication we can use:
    //_guiOverlayView = new GUIOverlay( *m_pRenderer11, *_rendererD2D1, m_BackBuffer );
    //else in the case it is a subclass of Application we can use:
    _guiOverlayView = new GUIOverlay( *m_pRenderer11, *_rendererD2D1, m_pRenderer11->GetSwapChainResource( m_pWindow->GetSwapChain()));
    m_pCamera->SetOverlayView( _guiOverlayView );
}

NOTICE: The Config of the SwapChain format of the DirectX11 device has to be  DXGI_FORMAT_B8G8R8A8_UNORM

To solve this problem we can overwrite the ConfigureRenderingEngineComponents method of the RenderApplication from which our App class derived from.

bool App::ConfigureRenderingEngineComponents( UINT width, UINT height, D3D_FEATURE_LEVEL desiredLevel, D3D_DRIVER_TYPE driverType )
{
    // Create the renderer and initialize it for the desired device
    // type and feature level.

    m_pRenderer11 = new RendererDX11();

    if ( !m_pRenderer11->Initialize( driverType, desiredLevel ) )
    {
        Log::Get().Write( L"Could not create hardware device, trying to create the reference device..." );

        if ( !m_pRenderer11->Initialize( D3D_DRIVER_TYPE_REFERENCE, D3D_FEATURE_LEVEL_11_0 ) )
        {
            MessageBox( 0, L"Could not create a hardware or software Direct3D 11 device - the program will now abort!", L"Hieroglyph 3 Rendering", MB_ICONEXCLAMATION | MB_SYSTEMMODAL );
            RequestTermination();          
            return( false );
        }

        // If using the reference device, utilize a fixed time step for any animations.
        m_pTimer->SetFixedTimeStep( 1.0f / 10.0f );
    }

    // Create the window.
    m_iWidth = width;
    m_iHeight = height;

    // Create the window wrapper class instance.
    m_pWindow = CreateRenderWindow();
    m_pWindow->SetPosition( 20, 20 );
    m_pWindow->SetSize( m_iWidth, m_iHeight );
    m_pWindow->SetCaption( GetName() );
    m_pWindow->Initialize( this );

    // Create a swap chain for the window.
    SwapChainConfigDX11 Config;
    Config.SetFormat( DXGI_FORMAT_B8G8R8A8_UNORM );
    Config.SetWidth( m_pWindow->GetWidth() );
    Config.SetHeight( m_pWindow->GetHeight() );
    Config.SetOutputWindow( m_pWindow->GetHandle() );
    m_pWindow->SetSwapChain( m_pRenderer11->CreateSwapChain( &Config ) );

    // We'll keep a copy of the swap chain's render target index to
    // use later.
    m_BackBuffer = m_pRenderer11->GetSwapChainResource( m_pWindow->GetSwapChain() );

    SetMultiThreadedMode( true );

    return( true );
}

Its seems to be a a lot of new code but it only differs from the native ConfigureRenderingEngineComponents-method by changing the format to DXGI_FORMAT_B8G8R8A8_UNORM over Config.SetFormat( DXGI_FORMAT_B8G8R8A8_UNORM );


Last edited May 22, 2013 at 10:18 AM by TypeOverride, version 29

Comments

No comments yet.