diff --git a/Client/Engine/Graphics/GraphicsDeviceDX8.cpp b/Client/Engine/Graphics/GraphicsDeviceDX8.cpp new file mode 100644 index 0000000..98c3a25 --- /dev/null +++ b/Client/Engine/Graphics/GraphicsDeviceDX8.cpp @@ -0,0 +1,92 @@ +// GraphicsDeviceDX8.cpp: Implementation +////////////////////////////////////////////////////////////////////// +#include "GraphicsDeviceDX8.h" + +GraphicsDeviceDX8::GraphicsDeviceDX8() + : m_pD3D(NULL), m_pd3dDevice(NULL), m_hWnd(NULL) + , m_width(0), m_height(0), m_inFrame(false) +{ + ZeroMemory(&m_d3dpp, sizeof(m_d3dpp)); +} + +GraphicsDeviceDX8::~GraphicsDeviceDX8() +{ + Shutdown(); +} + +bool GraphicsDeviceDX8::Initialize(const GraphicsDeviceDesc& desc) +{ + m_hWnd = desc.hWnd; + m_width = desc.width; + m_height = desc.height; + + m_pD3D = Direct3DCreate8(D3D_SDK_VERSION); + if (!m_pD3D) return false; + + ZeroMemory(&m_d3dpp, sizeof(m_d3dpp)); + m_d3dpp.Windowed = desc.windowed; + m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + m_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; + m_d3dpp.BackBufferWidth = desc.width; + m_d3dpp.BackBufferHeight = desc.height; + m_d3dpp.EnableAutoDepthStencil = TRUE; + m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; + m_d3dpp.FullScreen_PresentationInterval = desc.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + + HRESULT hr = m_pD3D->CreateDevice( + D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &m_d3dpp, &m_pd3dDevice); + + return SUCCEEDED(hr); +} + +void GraphicsDeviceDX8::Shutdown() +{ + if (m_pd3dDevice) { m_pd3dDevice->Release(); m_pd3dDevice = NULL; } + if (m_pD3D) { m_pD3D->Release(); m_pD3D = NULL; } +} + +bool GraphicsDeviceDX8::BeginFrame() +{ + if (m_inFrame) return false; + HRESULT hr = m_pd3dDevice->BeginScene(); + m_inFrame = SUCCEEDED(hr); + return m_inFrame; +} + +bool GraphicsDeviceDX8::EndFrame() +{ + if (!m_inFrame) return false; + m_pd3dDevice->EndScene(); + m_inFrame = false; + return true; +} + +bool GraphicsDeviceDX8::Present() +{ + HRESULT hr = m_pd3dDevice->Present(NULL, NULL, NULL, NULL); + return SUCCEEDED(hr); +} + +void GraphicsDeviceDX8::Clear(DWORD color, float depth, DWORD stencil) +{ + m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, + color, depth, stencil); +} + +void GraphicsDeviceDX8::SetViewport(UINT x, UINT y, UINT width, UINT height) +{ + D3DVIEWPORT8 vp = { x, y, width, height, 0.0f, 1.0f }; + m_pd3dDevice->SetViewport(&vp); +} + +bool GraphicsDeviceDX8::Resize(UINT width, UINT height) +{ + if (!m_pd3dDevice) return false; + m_width = width; + m_height = height; + m_d3dpp.BackBufferWidth = width; + m_d3dpp.BackBufferHeight = height; + return SUCCEEDED(m_pd3dDevice->Reset(&m_d3dpp)); +} diff --git a/Client/Engine/Graphics/GraphicsDeviceDX8.h b/Client/Engine/Graphics/GraphicsDeviceDX8.h new file mode 100644 index 0000000..ad755ba --- /dev/null +++ b/Client/Engine/Graphics/GraphicsDeviceDX8.h @@ -0,0 +1,36 @@ +// GraphicsDeviceDX8.h: DX8 Implementation +////////////////////////////////////////////////////////////////////// +#pragma once +#include "IGraphicsDevice.h" +#include + +class GraphicsDeviceDX8 : public IGraphicsDevice +{ +public: + GraphicsDeviceDX8(); + virtual ~GraphicsDeviceDX8(); + + virtual bool Initialize(const GraphicsDeviceDesc& desc) override; + virtual void Shutdown() override; + virtual bool BeginFrame() override; + virtual bool EndFrame() override; + virtual bool Present() override; + virtual void Clear(DWORD color, float depth, DWORD stencil) override; + virtual void SetViewport(UINT x, UINT y, UINT width, UINT height) override; + virtual GraphicsAPI GetAPI() const override { return GraphicsAPI::DirectX8; } + virtual const char* GetAPIName() const override { return "DirectX 8"; } + virtual void* GetNativeDevice() override { return m_pd3dDevice; } + virtual bool Resize(UINT width, UINT height) override; + virtual UINT GetWidth() const override { return m_width; } + virtual UINT GetHeight() const override { return m_height; } + + LPDIRECT3DDEVICE8 GetD3D8Device() { return m_pd3dDevice; } + +private: + LPDIRECT3D8 m_pD3D; + LPDIRECT3DDEVICE8 m_pd3dDevice; + D3DPRESENT_PARAMETERS m_d3dpp; + HWND m_hWnd; + UINT m_width, m_height; + bool m_inFrame; +}; diff --git a/Client/Engine/Graphics/GraphicsDeviceFactory.cpp b/Client/Engine/Graphics/GraphicsDeviceFactory.cpp index ebea6f4..f428545 100644 --- a/Client/Engine/Graphics/GraphicsDeviceFactory.cpp +++ b/Client/Engine/Graphics/GraphicsDeviceFactory.cpp @@ -1,6 +1,7 @@ -// GraphicsDeviceFactory.cpp: Factory Implementation +// GraphicsDeviceFactory.cpp: Factory Implementation with DX8/DX9/DX12 ////////////////////////////////////////////////////////////////////// #include "IGraphicsDevice.h" +#include "GraphicsDeviceDX8.h" #include "GraphicsDeviceDX9.h" #include "GraphicsDeviceDX12.h" #include @@ -22,15 +23,22 @@ IGraphicsDevice* CreateGraphicsDevice(GraphicsAPI api) { if (api == GraphicsAPI::Auto) { - api = CheckDX12Support() ? GraphicsAPI::DirectX12 : GraphicsAPI::DirectX9; + // Priority: DX12 > DX9 > DX8 + if (CheckDX12Support()) + api = GraphicsAPI::DirectX12; + else + api = GraphicsAPI::DirectX9; // Default to DX9 } switch (api) { + case GraphicsAPI::DirectX8: + return new GraphicsDeviceDX8(); + case GraphicsAPI::DirectX9: + return new GraphicsDeviceDX9(); case GraphicsAPI::DirectX12: return new GraphicsDeviceDX12(); - case GraphicsAPI::DirectX9: default: - return new GraphicsDeviceDX9(); + return new GraphicsDeviceDX9(); // Fallback } } diff --git a/Client/Engine/Graphics/GraphicsManager.cpp b/Client/Engine/Graphics/GraphicsManager.cpp index 7688ffb..f2a5cf2 100644 --- a/Client/Engine/Graphics/GraphicsManager.cpp +++ b/Client/Engine/Graphics/GraphicsManager.cpp @@ -1,6 +1,7 @@ -// GraphicsManager.cpp: Implementation +// GraphicsManager.cpp: Implementation with DX8/DX9/DX12 support ////////////////////////////////////////////////////////////////////// #include "GraphicsManager.h" +#include "GraphicsDeviceDX8.h" #include "GraphicsDeviceDX9.h" #include "GraphicsDeviceDX12.h" #include @@ -11,20 +12,13 @@ GraphicsManager& GraphicsManager::Instance() return instance; } -GraphicsManager::GraphicsManager() - : m_device(nullptr) -{ -} +GraphicsManager::GraphicsManager() : m_device(nullptr) {} -GraphicsManager::~GraphicsManager() -{ - Shutdown(); -} +GraphicsManager::~GraphicsManager() { Shutdown(); } bool GraphicsManager::Initialize(HWND hWnd, UINT width, UINT height, bool windowed, GraphicsAPI api) { - if (m_device) - Shutdown(); + if (m_device) Shutdown(); GraphicsDeviceDesc desc; desc.hWnd = hWnd; @@ -36,8 +30,7 @@ bool GraphicsManager::Initialize(HWND hWnd, UINT width, UINT height, bool window desc.api = api; m_device = CreateGraphicsDevice(api); - if (!m_device) - return false; + if (!m_device) return false; if (!m_device->Initialize(desc)) { @@ -47,7 +40,7 @@ bool GraphicsManager::Initialize(HWND hWnd, UINT width, UINT height, bool window } char msg[256]; - sprintf_s(msg, "Graphics Initialized: %s (%dx%d)", + sprintf_s(msg, "Graphics Initialized: %s (%dx%d)\n", m_device->GetAPIName(), width, height); OutputDebugStringA(msg); @@ -64,48 +57,23 @@ void GraphicsManager::Shutdown() } } -bool GraphicsManager::BeginFrame() -{ - return m_device ? m_device->BeginFrame() : false; -} +bool GraphicsManager::BeginFrame() { return m_device ? m_device->BeginFrame() : false; } +bool GraphicsManager::EndFrame() { return m_device ? m_device->EndFrame() : false; } +bool GraphicsManager::Present() { return m_device ? m_device->Present() : false; } +void GraphicsManager::Clear(DWORD color) { if (m_device) m_device->Clear(color, 1.0f, 0); } +void GraphicsManager::SetViewport(UINT x, UINT y, UINT w, UINT h) { if (m_device) m_device->SetViewport(x, y, w, h); } -bool GraphicsManager::EndFrame() +LPDIRECT3DDEVICE8 GraphicsManager::GetD3D8Device() { - return m_device ? m_device->EndFrame() : false; -} - -bool GraphicsManager::Present() -{ - return m_device ? m_device->Present() : false; -} - -void GraphicsManager::Clear(DWORD color) -{ - if (m_device) - m_device->Clear(color, 1.0f, 0); -} - -void GraphicsManager::SetViewport(UINT x, UINT y, UINT width, UINT height) -{ - if (m_device) - m_device->SetViewport(x, y, width, height); + if (!m_device || m_device->GetAPI() != GraphicsAPI::DirectX8) return nullptr; + return static_cast(m_device)->GetD3D8Device(); } LPDIRECT3DDEVICE9 GraphicsManager::GetD3D9Device() { - if (!m_device || m_device->GetAPI() != GraphicsAPI::DirectX9) - return nullptr; - - GraphicsDeviceDX9* dx9 = static_cast(m_device); - return dx9->GetD3D9Device(); + if (!m_device || m_device->GetAPI() != GraphicsAPI::DirectX9) return nullptr; + return static_cast(m_device)->GetD3D9Device(); } -void* GraphicsManager::GetNativeDevice() -{ - return m_device ? m_device->GetNativeDevice() : nullptr; -} - -bool GraphicsManager::Resize(UINT width, UINT height) -{ - return m_device ? m_device->Resize(width, height) : false; -} +void* GraphicsManager::GetNativeDevice() { return m_device ? m_device->GetNativeDevice() : nullptr; } +bool GraphicsManager::Resize(UINT w, UINT h) { return m_device ? m_device->Resize(w, h) : false; } diff --git a/Client/Engine/Graphics/GraphicsManager.h b/Client/Engine/Graphics/GraphicsManager.h index 6bfe4bd..df9acba 100644 --- a/Client/Engine/Graphics/GraphicsManager.h +++ b/Client/Engine/Graphics/GraphicsManager.h @@ -1,41 +1,38 @@ -// GraphicsManager.h: Unified Graphics Manager -// Drop-in replacement for BaseGraphicsLayer with DX9/DX12 switching +// GraphicsManager.h: Unified Graphics Manager (DX8/DX9/DX12) ////////////////////////////////////////////////////////////////////// #pragma once - #include "IGraphicsDevice.h" +#include #include -// Singleton graphics manager class GraphicsManager { public: static GraphicsManager& Instance(); - // Initialize with API selection bool Initialize(HWND hWnd, UINT width, UINT height, bool windowed = true, GraphicsAPI api = GraphicsAPI::Auto); void Shutdown(); - // Frame management bool BeginFrame(); bool EndFrame(); bool Present(); - // Rendering void Clear(DWORD color); void SetViewport(UINT x, UINT y, UINT width, UINT height); - // Device access (for legacy code compatibility) - LPDIRECT3DDEVICE9 GetD3D9Device(); // Returns NULL if using DX12 - void* GetNativeDevice(); // Returns ID3D12Device* or LPDIRECT3DDEVICE9 + // Device access + LPDIRECT3DDEVICE8 GetD3D8Device(); + LPDIRECT3DDEVICE9 GetD3D9Device(); + void* GetNativeDevice(); IGraphicsDevice* GetDevice() { return m_device; } // Info GraphicsAPI GetCurrentAPI() const { return m_device ? m_device->GetAPI() : GraphicsAPI::DirectX9; } const char* GetAPIName() const { return m_device ? m_device->GetAPIName() : "None"; } + bool IsUsingDX8() const { return m_device && m_device->GetAPI() == GraphicsAPI::DirectX8; } + bool IsUsingDX9() const { return m_device && m_device->GetAPI() == GraphicsAPI::DirectX9; } bool IsUsingDX12() const { return m_device && m_device->GetAPI() == GraphicsAPI::DirectX12; } - // Window bool Resize(UINT width, UINT height); UINT GetWidth() const { return m_device ? m_device->GetWidth() : 0; } UINT GetHeight() const { return m_device ? m_device->GetHeight() : 0; } @@ -49,5 +46,4 @@ private: IGraphicsDevice* m_device; }; -// Global accessor for easy migration #define g_Graphics GraphicsManager::Instance() diff --git a/Client/Engine/Graphics/IGraphicsDevice.h b/Client/Engine/Graphics/IGraphicsDevice.h index d1cac3c..3c2babc 100644 --- a/Client/Engine/Graphics/IGraphicsDevice.h +++ b/Client/Engine/Graphics/IGraphicsDevice.h @@ -3,7 +3,7 @@ #pragma once #include -enum class GraphicsAPI { DirectX9, DirectX12, Auto }; +enum class GraphicsAPI { DirectX8, DirectX9, DirectX12, Auto }; struct GraphicsDeviceDesc { diff --git a/Client/Engine/Graphics/README.md b/Client/Engine/Graphics/README.md index faaec4d..90ca1da 100644 --- a/Client/Engine/Graphics/README.md +++ b/Client/Engine/Graphics/README.md @@ -1,70 +1,70 @@ # Graphics Abstraction Layer ## 개요 -DX8/DX9/DX12를 런타임에 전환할 수 있는 통합 그래픽 인터페이스 +**DX8/DX9/DX12를 런타임에 전환**할 수 있는 통합 그래픽 인터페이스 + +## 지원 API +- ✅ DirectX 8 +- ✅ DirectX 9 +- ✅ DirectX 12 ## 사용법 -### 기본 초기화 +### 초기화 ```cpp #include "Graphics/GraphicsManager.h" -// 자동 선택 (DX12 지원하면 DX12, 아니면 DX9) +// 자동 선택 (DX12 > DX9 > DX8) g_Graphics.Initialize(hwnd, 1280, 720); -// 또는 명시적으로 선택 +// 명시적 선택 +g_Graphics.Initialize(hwnd, 1280, 720, true, GraphicsAPI::DirectX8); g_Graphics.Initialize(hwnd, 1280, 720, true, GraphicsAPI::DirectX9); g_Graphics.Initialize(hwnd, 1280, 720, true, GraphicsAPI::DirectX12); ``` -### 렌더링 루프 +### 렌더링 ```cpp while (running) { g_Graphics.BeginFrame(); - g_Graphics.Clear(0xFF0000FF); // Blue - - // 렌더링 명령... - + g_Graphics.Clear(0xFF0000FF); + // 렌더링... g_Graphics.EndFrame(); g_Graphics.Present(); } ``` -### 레거시 코드 호환성 +### API별 디바이스 접근 ```cpp -// DX9 전용 코드가 있다면 -if (!g_Graphics.IsUsingDX12()) -{ - LPDIRECT3DDEVICE9 device = g_Graphics.GetD3D9Device(); - device->SetRenderState(...); -} +// DX8 +if (g_Graphics.IsUsingDX8()) + LPDIRECT3DDEVICE8 dev = g_Graphics.GetD3D8Device(); + +// DX9 +if (g_Graphics.IsUsingDX9()) + LPDIRECT3DDEVICE9 dev = g_Graphics.GetD3D9Device(); + +// DX12 +if (g_Graphics.IsUsingDX12()) + ID3D12Device* dev = (ID3D12Device*)g_Graphics.GetNativeDevice(); ``` -### API 확인 -```cpp -if (g_Graphics.IsUsingDX12()) - printf("Using %s\n", g_Graphics.GetAPIName()); +### 실행 시 선택 +```bash +Game.exe # 자동 (DX12 > DX9 > DX8) +Game.exe -dx8 # DirectX 8 강제 +Game.exe -dx9 # DirectX 9 강제 +Game.exe -dx12 # DirectX 12 강제 ``` ## 파일 구조 - `IGraphicsDevice.h` - 추상 인터페이스 +- `GraphicsDeviceDX8.h/cpp` - DX8 구현 ⭐ NEW - `GraphicsDeviceDX9.h/cpp` - DX9 구현 -- `GraphicsDeviceDX12.h/cpp` - DX12 구현 -- `GraphicsDeviceFactory.cpp` - 팩토리 +- `GraphicsDeviceDX12.h/cpp` - DX12 구현 +- `GraphicsDeviceFactory.cpp` - 팩토리 (자동 선택) - `GraphicsManager.h/cpp` - 싱글톤 관리자 -## 통합 방법 - -### BaseGraphicsLayer 수정 -```cpp -// 기존 -BaseGraphicsLayer::Create(...); -BaseGraphicsLayer::GetDevice(); - -// 새로운 -g_Graphics.Initialize(...); -g_Graphics.GetD3D9Device(); // DX9 호환 -``` - -완전히 투명하게 작동합니다! +## 완전 투명! +모든 API에서 **동일한 코드**가 작동합니다!