-
[004] 이미지 로딩 및 렌더링Programming/Dev 2023. 2. 2. 22:19
Direct2D 이전 게시글에서는 데이터 에디터로 만든 파일을 클라이언트에서 읽어오는 작업에 대해 작성했다.
이번에는 파일에서 이미지 데이터를 읽어서 화면에 렌더링하기까지의 과정에 대해 작성할 것이다.
void NytLoader::Load(std::ifstream& fs, NytProperty& root) { NytDataType type{ Read<BYTE>(fs) }; std::string name{ Read<std::string>(fs) }; std::any data{}; switch (type) { case NytDataType::GROUP: break; case NytDataType::INT: { data = Read<int>(fs); break; } case NytDataType::FLOAT: { data = Read<float>(fs); break; } case NytDataType::STRING: data = Read<std::string>(fs); break; case NytDataType::IMAGE: { data = Read<NytImage>(fs); break; } default: assert(false); } int childNodeCount{ Read<int>(fs) }; root.m_childNames.reserve(childNodeCount); root.m_childNames.push_back(name); root.m_childProps[name] = NytProperty{ type, data }; for (int i = 0; i < childNodeCount; ++i) { Load(fs, root.m_childProps[name]); } }
우선, 데이터 로딩 함수를 조금 더 이쁘게 고쳤다.
Read라는 템플릿 함수를 만들어서 파일 스트림에서 해당 자료형을 읽어오도록 했다.
template<> std::string NytLoader::Read(std::ifstream& fs) { char length{}; char buffer[50]{}; fs.read(&length, sizeof(char)); fs.read(buffer, length); return std::string{ buffer }; }
template<> NytImage NytLoader::Read(std::ifstream& fs) { int length{ Read<int>(fs) }; std::unique_ptr<BYTE> buffer{ new BYTE[length] }; fs.read(reinterpret_cast<char*>(buffer.get()), length); ComPtr<IWICBitmapDecoder> decoder; ComPtr<IWICFormatConverter> converter; ComPtr<IWICBitmapFrameDecode> frameDecode; ComPtr<IWICStream> stream; ComPtr<ID2D1Bitmap> bitmap; HRESULT hr{ E_FAIL }; hr = m_WICIFactory->CreateStream(&stream); hr = stream->InitializeFromMemory(buffer.get(), length); hr = m_WICIFactory->CreateDecoderFromStream(stream.Get(), NULL, WICDecodeMetadataCacheOnLoad, &decoder); hr = m_WICIFactory->CreateFormatConverter(&converter); hr = decoder->GetFrame(0, &frameDecode); hr = converter->Initialize(frameDecode.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut); auto renderTarget{ NytApp::GetInstance()->GetRenderTarget() }; hr = renderTarget->CreateBitmapFromWicBitmap(converter.Get(), NULL, &bitmap); assert(SUCCEEDED(hr)); return NytImage{ bitmap }; }
`std::string`과 `NytImage`에 대해서는 템플릿 특수화를 이용하여 함수를 따로 작성하였다.
`NytImage`는 이 프로젝트에서 이미지 데이터를 대표할 클래스이다.
데이터에 저장되어있는 이미지 데이터와 그 길이를 읽은 뒤 해당 데이터를 이용하여 `ID2D1Bitmap` 객체를 생성한다.
생성한 객체는 `NytImage`로 랩핑되어 반환된다.
void NytImage::Render(const ComPtr<ID2D1HwndRenderTarget>& renderTarget) const { auto size{ m_bitmap->GetSize() }; renderTarget->DrawBitmap(m_bitmap.Get(), RECTF{ 0.0f, 0.0f, size.width, size.height }); }
void LoginScene::Render(const ComPtr<ID2D1HwndRenderTarget>& renderTarget) const { WndManager::GetInstance()->Render(renderTarget); renderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); auto paimon{ m_prop->Get<NytImage>("Group1/paimon") }; paimon.Render(renderTarget); }
불러온 이미지를 화면에 띄우기 위해 위와 같이 코드를 작성해보았다.
아직 `NytImage` 클래스에 특별한 기능은 없다.
페이몬 화면에 잘 그려지는 것을 확인할 수 있다!
'Programming > Dev' 카테고리의 다른 글
[006] 게임오브젝트 렌더링 (0) 2023.03.05 [005] Direct2D → DirectX12로 변경 (0) 2023.02.19 [003] 데이터 로딩 (0) 2023.01.28 [002] 데이터 에디터 (0) 2023.01.24 [001] 프레임워크 (2) 2022.12.08