Magic_Game/core/base/render.cpp

292 lines
6.5 KiB
C++
Raw Normal View History

// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "render.h"
#include "time.h"
#include "base.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")
#pragma comment(lib, "windowscodecs.lib")
namespace easy2d
{
namespace render
{
_D2D_Resource D2D = { 0 };
void Initialize(HWND hwnd)
{
if (D2D.Factory)
return;
ThrowIfFailed(
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&D2D.Factory
)
);
ThrowIfFailed(
CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
reinterpret_cast<void**>(&D2D.WICImagingFactory)
)
);
ThrowIfFailed(
DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&D2D.DWriteFactory)
)
);
auto stroke_style = D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_LINE_JOIN_MITER,
2.0f,
D2D1_DASH_STYLE_SOLID,
0.0f
);
ThrowIfFailed(
D2D.Factory->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&D2D.MiterStrokeStyle
)
);
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
ThrowIfFailed(
D2D.Factory->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&D2D.BevelStrokeStyle
)
);
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
ThrowIfFailed(
D2D.Factory->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&D2D.RoundStrokeStyle
)
);
CreateDeviceResources(hwnd);
}
void CreateDeviceResources(HWND hwnd)
{
if (!D2D.HwndRenderTarget)
{
RECT rc;
::GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9>ԴӦ<D4B4><D3A6> Direct2D <20><EFBFBD><E8B1B8>ʧʱ<CAA7>ؽ<EFBFBD>
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Direct2D <20><>ȾĿ<C8BE><C4BF>
ThrowIfFailed(
D2D.Factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd,
size,
D2D1_PRESENT_OPTIONS_NONE),
&D2D.HwndRenderTarget
)
);
}
if (!D2D.SolidColorBrush)
{
ThrowIfFailed(
D2D.HwndRenderTarget->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&D2D.SolidColorBrush
)
);
}
if (!D2D.TextRenderer)
{
ThrowIfFailed(
ITextRenderer::Create(
&D2D.TextRenderer,
D2D.Factory,
D2D.HwndRenderTarget,
D2D.SolidColorBrush
)
);
}
}
void Uninitialize()
{
SafeRelease(D2D.TextRenderer);
SafeRelease(D2D.SolidColorBrush);
SafeRelease(D2D.HwndRenderTarget);
SafeRelease(D2D.MiterStrokeStyle);
SafeRelease(D2D.BevelStrokeStyle);
SafeRelease(D2D.RoundStrokeStyle);
SafeRelease(D2D.WICImagingFactory);
SafeRelease(D2D.DWriteFactory);
SafeRelease(D2D.Factory);
}
//-------------------------------------------------------
// GraphicsDevice
//-------------------------------------------------------
GraphicsDevice instance;
GraphicsDevice::GraphicsDevice()
: fps_text_format_(nullptr)
, fps_text_layout_(nullptr)
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
{
}
GraphicsDevice::~GraphicsDevice()
{
SafeRelease(fps_text_format_);
SafeRelease(fps_text_layout_);
}
void GraphicsDevice::BeginDraw(HWND hwnd)
{
render::CreateDeviceResources(hwnd);
render::D2D.HwndRenderTarget->BeginDraw();
render::D2D.HwndRenderTarget->Clear(clear_color_);
}
void GraphicsDevice::EndDraw()
{
HRESULT hr = render::D2D.HwndRenderTarget->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
// <20><><EFBFBD><EFBFBD> Direct3D <20><EFBFBD><E8B1B8>ִ<EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ε<EFBFBD><CEB5><EFBFBD>ʱ<EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD>Դ
hr = S_OK;
SafeRelease(fps_text_format_);
SafeRelease(fps_text_layout_);
SafeRelease(render::D2D.TextRenderer);
SafeRelease(render::D2D.SolidColorBrush);
SafeRelease(render::D2D.HwndRenderTarget);
}
ThrowIfFailed(hr);
}
void GraphicsDevice::SetBackgroundColor(const Color& color)
{
clear_color_ = color;
}
void GraphicsDevice::DrawDebugInfo()
{
static int render_times_ = 0;
static time::TimePoint last_render_time_ = time::Now();
int duration = (time::Now() - last_render_time_).Milliseconds();
if (!fps_text_format_)
{
ThrowIfFailed(
render::D2D.DWriteFactory->CreateTextFormat(
L"",
nullptr,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
20,
L"",
&fps_text_format_
)
);
ThrowIfFailed(
fps_text_format_->SetWordWrapping(
DWRITE_WORD_WRAPPING_NO_WRAP
)
);
}
++render_times_;
if (duration >= 100)
{
wchar_t fps_text[12] = {};
int len = swprintf_s(fps_text, L"FPS: %.1f", 1000.f / duration * render_times_);
last_render_time_ = time::Now();
render_times_ = 0;
SafeRelease(fps_text_layout_);
ThrowIfFailed(
render::D2D.DWriteFactory->CreateTextLayout(
fps_text,
static_cast<UINT32>(len),
fps_text_format_,
0,
0,
&fps_text_layout_
)
);
}
if (fps_text_layout_)
{
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
render::D2D.SolidColorBrush->SetOpacity(1.0f);
render::D2D.TextRenderer->SetTextStyle(
D2D1::ColorF(D2D1::ColorF::White),
TRUE,
D2D1::ColorF(D2D1::ColorF::Black, 0.4f),
1.5f,
D2D1_LINE_JOIN_ROUND
);
fps_text_layout_->Draw(nullptr, render::D2D.TextRenderer, 10, 0);
}
}
}
}