diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp index 2d9ede8547e..3f3b1e40dfa 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp @@ -710,6 +710,9 @@ void W3DDisplay::init() } } + // TheSuperHackers @feature Mauller 13/03/2026 Add native MSAA support, must be set before creating render device + WW3D::Set_MSAA_Mode(WW3D::MULTISAMPLE_MODE_NONE); + renderDeviceError = WW3D::Set_Render_Device( 0, getWidth(), diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index b7e9d5a77ae..6f39aae81ba 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -87,6 +87,7 @@ const int DEFAULT_RESOLUTION_WIDTH = 640; const int DEFAULT_RESOLUTION_HEIGHT = 480; const int DEFAULT_BIT_DEPTH = 32; const int DEFAULT_TEXTURE_BIT_DEPTH = 16; +const D3DMULTISAMPLE_TYPE DEFAULT_MSAA = D3DMULTISAMPLE_NONE; bool DX8Wrapper_IsWindowed = true; @@ -110,6 +111,7 @@ int DX8Wrapper::BitDepth = DEFAULT_BIT_DEPTH; int DX8Wrapper::TextureBitDepth = DEFAULT_TEXTURE_BIT_DEPTH; bool DX8Wrapper::IsWindowed = false; D3DFORMAT DX8Wrapper::DisplayFormat = D3DFMT_UNKNOWN; +D3DMULTISAMPLE_TYPE DX8Wrapper::MultiSampleAntiAliasing = DEFAULT_MSAA; D3DMATRIX DX8Wrapper::old_world; D3DMATRIX DX8Wrapper::old_view; @@ -951,7 +953,6 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int _PresentParameters.BackBufferHeight = ResolutionHeight; _PresentParameters.BackBufferCount = IsWindowed ? 1 : 2; - _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; _PresentParameters.SwapEffect = IsWindowed ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_FLIP; // Shouldn't this be D3DSWAPEFFECT_FLIP? _PresentParameters.hDeviceWindow = _Hwnd; _PresentParameters.Windowed = IsWindowed; @@ -1024,7 +1025,7 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int } /* - ** Time to actually create the device. + ** Set default for depth stencil format if auto Z buffer failed. */ if (_PresentParameters.AutoDepthStencilFormat==D3DFMT_UNKNOWN) { if (BitDepth==32) { @@ -1035,6 +1036,40 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int } } + /* + ** Check the devices support for the requested MSAA mode then setup the multi sample type + */ + if (MultiSampleAntiAliasing > D3DMULTISAMPLE_NONE) { + + HRESULT hrBack = D3DInterface->CheckDeviceMultiSampleType( + CurRenderDevice, + D3DDEVTYPE_HAL, + _PresentParameters.BackBufferFormat, + IsWindowed, + MultiSampleAntiAliasing + ); + + HRESULT hrDepth = D3DInterface->CheckDeviceMultiSampleType( + CurRenderDevice, + D3DDEVTYPE_HAL, + _PresentParameters.AutoDepthStencilFormat, + IsWindowed, + MultiSampleAntiAliasing + ); + + if (FAILED(hrBack) || FAILED(hrDepth)) { + // IF we fail then disable MSAA entirely. + // External code needs to retrieve the configured MSAA mode after device creation + WWDEBUG_SAY(("Requested MSAA Mode Not Supported")); + MultiSampleAntiAliasing = D3DMULTISAMPLE_NONE; + } + } + + _PresentParameters.MultiSampleType = MultiSampleAntiAliasing; + + /* + ** Time to actually create the device. + */ StringClass displayFormat; StringClass backbufferFormat; diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h index 3235047869c..3088d8f6920 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h @@ -590,6 +590,9 @@ class DX8Wrapper static void Set_Texture_Bitdepth(int depth) { WWASSERT(depth==16 || depth==32); TextureBitDepth = depth; } static int Get_Texture_Bitdepth() { return TextureBitDepth; } + static void Set_MSAA_Mode(D3DMULTISAMPLE_TYPE mode) { MultiSampleAntiAliasing = mode; } + static D3DMULTISAMPLE_TYPE Get_MSAA_Mode() { return MultiSampleAntiAliasing; } + static void Set_Swap_Interval(int swap); static int Get_Swap_Interval(); static void Set_Polygon_Mode(int mode); @@ -628,6 +631,7 @@ class DX8Wrapper static int TextureBitDepth; static bool IsWindowed; static D3DFORMAT DisplayFormat; + static D3DMULTISAMPLE_TYPE MultiSampleAntiAliasing; static D3DMATRIX old_world; static D3DMATRIX old_view; diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp index 8472c8eb9eb..7ed105cb3f7 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp @@ -2014,6 +2014,52 @@ int WW3D::Get_Texture_Bitdepth() return DX8Wrapper::Get_Texture_Bitdepth(); } +void WW3D::Set_MSAA_Mode(MultiSampleModeEnum mode) +{ + switch (mode) { + + default: + case MULTISAMPLE_MODE_NONE: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_NONE); + break; + + case MULTISAMPLE_MODE_2X: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_2_SAMPLES); + break; + + case MULTISAMPLE_MODE_4X: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_4_SAMPLES); + break; + + case MULTISAMPLE_MODE_8X: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_8_SAMPLES); + break; + + } +} + +WW3D::MultiSampleModeEnum WW3D::Get_MSAA_Mode() +{ + D3DMULTISAMPLE_TYPE type = DX8Wrapper::Get_MSAA_Mode(); + + switch (type) { + + default: + case D3DMULTISAMPLE_NONE: + return MULTISAMPLE_MODE_NONE; + + case D3DMULTISAMPLE_2_SAMPLES: + return MULTISAMPLE_MODE_2X; + + case D3DMULTISAMPLE_4_SAMPLES: + return MULTISAMPLE_MODE_4X; + + case D3DMULTISAMPLE_8_SAMPLES: + return MULTISAMPLE_MODE_8X; + + } +} + void WW3D::Add_To_Static_Sort_List(RenderObjClass *robj, unsigned int sort_level) { CurrentStaticSortLists->Add_To_List(robj, sort_level); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h b/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h index eafcaa8b75e..94355d16d29 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h @@ -72,6 +72,13 @@ class WW3D { public: + enum MultiSampleModeEnum { + MULTISAMPLE_MODE_NONE, + MULTISAMPLE_MODE_2X, + MULTISAMPLE_MODE_4X, + MULTISAMPLE_MODE_8X + }; + enum PrelitModeEnum { PRELIT_MODE_VERTEX, PRELIT_MODE_LIGHTMAP_MULTI_PASS, @@ -259,6 +266,9 @@ class WW3D static void Set_Texture_Bitdepth(int bitdepth); static int Get_Texture_Bitdepth(); + static void Set_MSAA_Mode(MultiSampleModeEnum mode); + static MultiSampleModeEnum Get_MSAA_Mode(); + static void Set_Mesh_Draw_Mode (MeshDrawModeEnum mode) { MeshDrawMode = mode; } static MeshDrawModeEnum Get_Mesh_Draw_Mode () { return (MeshDrawMode); } diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp index f3daf95e948..e34e4428649 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp @@ -761,6 +761,9 @@ void W3DDisplay::init() } } + // TheSuperHackers @feature Mauller 13/03/2026 Add native MSAA support, must be set before creating render device + WW3D::Set_MSAA_Mode(WW3D::MULTISAMPLE_MODE_NONE); + renderDeviceError = WW3D::Set_Render_Device( 0, getWidth(), diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 19ae5714a21..82a48499509 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -91,6 +91,7 @@ const int DEFAULT_RESOLUTION_WIDTH = 640; const int DEFAULT_RESOLUTION_HEIGHT = 480; const int DEFAULT_BIT_DEPTH = 32; const int DEFAULT_TEXTURE_BIT_DEPTH = 16; +const D3DMULTISAMPLE_TYPE DEFAULT_MSAA = D3DMULTISAMPLE_NONE; bool DX8Wrapper_IsWindowed = true; @@ -114,6 +115,7 @@ int DX8Wrapper::BitDepth = DEFAULT_BIT_DEPTH; int DX8Wrapper::TextureBitDepth = DEFAULT_TEXTURE_BIT_DEPTH; bool DX8Wrapper::IsWindowed = false; D3DFORMAT DX8Wrapper::DisplayFormat = D3DFMT_UNKNOWN; +D3DMULTISAMPLE_TYPE DX8Wrapper::MultiSampleAntiAliasing = DEFAULT_MSAA; D3DMATRIX DX8Wrapper::old_world; D3DMATRIX DX8Wrapper::old_view; @@ -1025,7 +1027,6 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int _PresentParameters.BackBufferHeight = ResolutionHeight; _PresentParameters.BackBufferCount = IsWindowed ? 1 : 2; - _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; //I changed this to discard all the time (even when full-screen) since that the most efficient. 07-16-03 MW: _PresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;//IsWindowed ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_FLIP; // Shouldn't this be D3DSWAPEFFECT_FLIP? _PresentParameters.hDeviceWindow = _Hwnd; @@ -1099,7 +1100,7 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int } /* - ** Time to actually create the device. + ** Set default for depth stencil format if auto Z buffer failed. */ if (_PresentParameters.AutoDepthStencilFormat==D3DFMT_UNKNOWN) { if (BitDepth==32) { @@ -1110,6 +1111,40 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int } } + /* + ** Check the devices support for the requested MSAA mode then setup the multi sample type + */ + if (MultiSampleAntiAliasing > D3DMULTISAMPLE_NONE) { + + HRESULT hrBack = D3DInterface->CheckDeviceMultiSampleType( + CurRenderDevice, + D3DDEVTYPE_HAL, + _PresentParameters.BackBufferFormat, + IsWindowed, + MultiSampleAntiAliasing + ); + + HRESULT hrDepth = D3DInterface->CheckDeviceMultiSampleType( + CurRenderDevice, + D3DDEVTYPE_HAL, + _PresentParameters.AutoDepthStencilFormat, + IsWindowed, + MultiSampleAntiAliasing + ); + + if (FAILED(hrBack) || FAILED(hrDepth)) { + // IF we fail then disable MSAA entirely. + // External code needs to retrieve the configured MSAA mode after device creation + WWDEBUG_SAY(("Requested MSAA Mode Not Supported")); + MultiSampleAntiAliasing = D3DMULTISAMPLE_NONE; + } + } + + _PresentParameters.MultiSampleType = MultiSampleAntiAliasing; + + /* + ** Time to actually create the device. + */ StringClass displayFormat; StringClass backbufferFormat; diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h index 0be59ec7a3a..9537514c7a4 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h @@ -599,6 +599,9 @@ class DX8Wrapper static void Set_Texture_Bitdepth(int depth) { WWASSERT(depth==16 || depth==32); TextureBitDepth = depth; } static int Get_Texture_Bitdepth() { return TextureBitDepth; } + static void Set_MSAA_Mode(D3DMULTISAMPLE_TYPE mode) { MultiSampleAntiAliasing = mode; } + static D3DMULTISAMPLE_TYPE Get_MSAA_Mode() { return MultiSampleAntiAliasing; } + static void Set_Swap_Interval(int swap); static int Get_Swap_Interval(); static void Set_Polygon_Mode(int mode); @@ -637,6 +640,7 @@ class DX8Wrapper static int TextureBitDepth; static bool IsWindowed; static D3DFORMAT DisplayFormat; + static D3DMULTISAMPLE_TYPE MultiSampleAntiAliasing; static D3DMATRIX old_world; static D3DMATRIX old_view; diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp index 9f3a1229197..768df469da4 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp @@ -2017,6 +2017,52 @@ int WW3D::Get_Texture_Bitdepth() return DX8Wrapper::Get_Texture_Bitdepth(); } +void WW3D::Set_MSAA_Mode(MultiSampleModeEnum mode) +{ + switch (mode) { + + default: + case MULTISAMPLE_MODE_NONE: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_NONE); + break; + + case MULTISAMPLE_MODE_2X: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_2_SAMPLES); + break; + + case MULTISAMPLE_MODE_4X: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_4_SAMPLES); + break; + + case MULTISAMPLE_MODE_8X: + DX8Wrapper::Set_MSAA_Mode(D3DMULTISAMPLE_8_SAMPLES); + break; + + } +} + +WW3D::MultiSampleModeEnum WW3D::Get_MSAA_Mode() +{ + D3DMULTISAMPLE_TYPE type = DX8Wrapper::Get_MSAA_Mode(); + + switch (type) { + + default: + case D3DMULTISAMPLE_NONE: + return MULTISAMPLE_MODE_NONE; + + case D3DMULTISAMPLE_2_SAMPLES: + return MULTISAMPLE_MODE_2X; + + case D3DMULTISAMPLE_4_SAMPLES: + return MULTISAMPLE_MODE_4X; + + case D3DMULTISAMPLE_8_SAMPLES: + return MULTISAMPLE_MODE_8X; + + } +} + void WW3D::Add_To_Static_Sort_List(RenderObjClass *robj, unsigned int sort_level) { CurrentStaticSortLists->Add_To_List(robj, sort_level); diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h index ace20e57446..b70c737e066 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.h @@ -72,6 +72,13 @@ class WW3D { public: + enum MultiSampleModeEnum { + MULTISAMPLE_MODE_NONE, + MULTISAMPLE_MODE_2X, + MULTISAMPLE_MODE_4X, + MULTISAMPLE_MODE_8X + }; + enum PrelitModeEnum { PRELIT_MODE_VERTEX, PRELIT_MODE_LIGHTMAP_MULTI_PASS, @@ -259,6 +266,9 @@ class WW3D static void Set_Texture_Bitdepth(int bitdepth); static int Get_Texture_Bitdepth(); + static void Set_MSAA_Mode(MultiSampleModeEnum mode); + static MultiSampleModeEnum Get_MSAA_Mode(); + static void Set_Mesh_Draw_Mode (MeshDrawModeEnum mode) { MeshDrawMode = mode; } static MeshDrawModeEnum Get_Mesh_Draw_Mode () { return (MeshDrawMode); }