diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
index 9ff4754aec9..dd4050fce15 100644
--- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
+++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
@@ -43,6 +43,8 @@ set(WW3D2_SRC
distlod.cpp
distlod.h
dllist.h
+ DX8Backend.cpp
+ DX8Backend.h
dx8caps.cpp
dx8caps.h
#dx8fvf.cpp
@@ -90,6 +92,7 @@ set(WW3D2_SRC
htree.h
#htreemgr.cpp
#htreemgr.h
+ IRenderBackend.h
intersec.cpp
intersec.h
intersec.inl
@@ -155,6 +158,8 @@ set(WW3D2_SRC
proto.h
proxy.h
rddesc.h
+ RenderBackend.cpp
+ RenderBackend.h
#render2d.cpp
#render2d.h
render2dsentence.cpp
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp
new file mode 100644
index 00000000000..c6fd25950c2
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp
@@ -0,0 +1,321 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+// TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend forwarding adapter.
+// Every method in this file is a one-line trampoline to the existing
+// DX8Wrapper static API. Keep it that way — if behavior needs to change it
+// should change in DX8Wrapper, not here.
+
+#include "DX8Backend.h"
+
+#include "dx8wrapper.h"
+#include "vector3.h"
+#include "matrix4.h"
+#include "matrix3d.h"
+#include "light.h"
+#include "lightenvironment.h"
+
+DX8Backend::DX8Backend()
+{
+}
+
+DX8Backend::~DX8Backend()
+{
+}
+
+// -- Device state queries ----------------------------------------------------
+
+bool DX8Backend::Is_Device_Lost() const
+{
+ return DX8Wrapper::Is_Device_Lost();
+}
+
+bool DX8Backend::Has_Stencil()
+{
+ return DX8Wrapper::Has_Stencil();
+}
+
+WW3DFormat DX8Backend::Get_Back_Buffer_Format()
+{
+ return DX8Wrapper::getBackBufferFormat();
+}
+
+SurfaceClass * DX8Backend::Get_Back_Buffer(unsigned int num)
+{
+ return DX8Wrapper::_Get_DX8_Back_Buffer(num);
+}
+
+void DX8Backend::Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit)
+{
+ DX8Wrapper::Set_Gamma(gamma, bright, contrast, calibrate, uselimit);
+}
+
+// -- Frame lifecycle ---------------------------------------------------------
+
+void DX8Backend::Begin_Scene()
+{
+ DX8Wrapper::Begin_Scene();
+}
+
+void DX8Backend::End_Scene(bool flip_frame)
+{
+ DX8Wrapper::End_Scene(flip_frame);
+}
+
+void DX8Backend::Flip_To_Primary()
+{
+ DX8Wrapper::Flip_To_Primary();
+}
+
+void DX8Backend::Clear(bool clear_color, bool clear_z_stencil,
+ const Vector3 & color,
+ float dest_alpha, float z, unsigned int stencil)
+{
+ DX8Wrapper::Clear(clear_color, clear_z_stencil, color, dest_alpha, z, stencil);
+}
+
+void DX8Backend::Set_Viewport(const RenderBackendViewport & viewport)
+{
+ D3DVIEWPORT8 vp;
+ vp.X = viewport.x;
+ vp.Y = viewport.y;
+ vp.Width = viewport.width;
+ vp.Height = viewport.height;
+ vp.MinZ = viewport.min_z;
+ vp.MaxZ = viewport.max_z;
+ DX8Wrapper::Set_Viewport(&vp);
+}
+
+// -- Vertex / index buffers --------------------------------------------------
+
+void DX8Backend::Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream)
+{
+ DX8Wrapper::Set_Vertex_Buffer(vb, stream);
+}
+
+void DX8Backend::Set_Vertex_Buffer(const DynamicVBAccessClass & vba)
+{
+ DX8Wrapper::Set_Vertex_Buffer(vba);
+}
+
+void DX8Backend::Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset)
+{
+ DX8Wrapper::Set_Index_Buffer(ib, index_base_offset);
+}
+
+void DX8Backend::Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset)
+{
+ DX8Wrapper::Set_Index_Buffer(iba, index_base_offset);
+}
+
+void DX8Backend::Set_Index_Buffer_Index_Offset(unsigned int offset)
+{
+ DX8Wrapper::Set_Index_Buffer_Index_Offset(offset);
+}
+
+// -- State: shaders, materials, textures ------------------------------------
+
+void DX8Backend::Set_Shader(const ShaderClass & shader)
+{
+ DX8Wrapper::Set_Shader(shader);
+}
+
+void DX8Backend::Get_Shader(ShaderClass & shader)
+{
+ DX8Wrapper::Get_Shader(shader);
+}
+
+void DX8Backend::Set_Material(const VertexMaterialClass * material)
+{
+ DX8Wrapper::Set_Material(material);
+}
+
+void DX8Backend::Set_Texture(unsigned int stage, TextureBaseClass * texture)
+{
+ DX8Wrapper::Set_Texture(stage, texture);
+}
+
+void DX8Backend::Apply_Render_State_Changes()
+{
+ DX8Wrapper::Apply_Render_State_Changes();
+}
+
+void DX8Backend::Apply_Default_State()
+{
+ DX8Wrapper::Apply_Default_State();
+}
+
+void DX8Backend::Invalidate_Cached_Render_States()
+{
+ DX8Wrapper::Invalidate_Cached_Render_States();
+}
+
+// -- Transforms --------------------------------------------------------------
+
+void DX8Backend::Set_Transform(TransformKind transform, const Matrix4x4 & m)
+{
+ DX8Wrapper::Set_Transform(static_cast(transform), m);
+}
+
+void DX8Backend::Set_Transform(TransformKind transform, const Matrix3D & m)
+{
+ DX8Wrapper::Set_Transform(static_cast(transform), m);
+}
+
+void DX8Backend::Get_Transform(TransformKind transform, Matrix4x4 & m)
+{
+ DX8Wrapper::Get_Transform(static_cast(transform), m);
+}
+
+void DX8Backend::Set_World_Identity()
+{
+ DX8Wrapper::Set_World_Identity();
+}
+
+void DX8Backend::Set_View_Identity()
+{
+ DX8Wrapper::Set_View_Identity();
+}
+
+bool DX8Backend::Is_World_Identity()
+{
+ return DX8Wrapper::Is_World_Identity();
+}
+
+bool DX8Backend::Is_View_Identity()
+{
+ return DX8Wrapper::Is_View_Identity();
+}
+
+void DX8Backend::Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar)
+{
+ DX8Wrapper::Set_Projection_Transform_With_Z_Bias(matrix, znear, zfar);
+}
+
+// -- Lighting and fog --------------------------------------------------------
+
+void DX8Backend::Set_Light(unsigned int index, const LightClass & light)
+{
+ DX8Wrapper::Set_Light(index, light);
+}
+
+void DX8Backend::Set_Ambient(const Vector3 & color)
+{
+ DX8Wrapper::Set_Ambient(color);
+}
+
+const Vector3 & DX8Backend::Get_Ambient() const
+{
+ return DX8Wrapper::Get_Ambient();
+}
+
+void DX8Backend::Set_Fog(bool enable, const Vector3 & color, float start, float end)
+{
+ DX8Wrapper::Set_Fog(enable, color, start, end);
+}
+
+bool DX8Backend::Get_Fog_Enable() const
+{
+ return DX8Wrapper::Get_Fog_Enable();
+}
+
+void DX8Backend::Set_Light_Environment(LightEnvironmentClass * light_env)
+{
+ DX8Wrapper::Set_Light_Environment(light_env);
+}
+
+LightEnvironmentClass * DX8Backend::Get_Light_Environment() const
+{
+ return DX8Wrapper::Get_Light_Environment();
+}
+
+// -- Draw calls --------------------------------------------------------------
+
+void DX8Backend::Draw_Triangles(unsigned short start_index,
+ unsigned short polygon_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count)
+{
+ DX8Wrapper::Draw_Triangles(start_index, polygon_count, min_vertex_index, vertex_count);
+}
+
+void DX8Backend::Draw_Triangles(unsigned int buffer_type,
+ unsigned short start_index,
+ unsigned short polygon_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count)
+{
+ DX8Wrapper::Draw_Triangles(buffer_type, start_index, polygon_count, min_vertex_index, vertex_count);
+}
+
+void DX8Backend::Draw_Strip(unsigned short start_index,
+ unsigned short index_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count)
+{
+ DX8Wrapper::Draw_Strip(start_index, index_count, min_vertex_index, vertex_count);
+}
+
+// -- Programmable pipeline ---------------------------------------------------
+
+void DX8Backend::Set_Vertex_Shader(unsigned long vertex_shader)
+{
+ DX8Wrapper::Set_Vertex_Shader(static_cast(vertex_shader));
+}
+
+void DX8Backend::Set_Pixel_Shader(unsigned long pixel_shader)
+{
+ DX8Wrapper::Set_Pixel_Shader(static_cast(pixel_shader));
+}
+
+void DX8Backend::Set_Vertex_Shader_Constant(int reg, const void * data, int count)
+{
+ DX8Wrapper::Set_Vertex_Shader_Constant(reg, data, count);
+}
+
+void DX8Backend::Set_Pixel_Shader_Constant(int reg, const void * data, int count)
+{
+ DX8Wrapper::Set_Pixel_Shader_Constant(reg, data, count);
+}
+
+// -- Render targets ----------------------------------------------------------
+
+TextureClass * DX8Backend::Create_Render_Target(int width, int height, WW3DFormat format)
+{
+ return DX8Wrapper::Create_Render_Target(width, height, format);
+}
+
+void DX8Backend::Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture)
+{
+ DX8Wrapper::Set_Render_Target_With_Z(texture, ztexture);
+}
+
+bool DX8Backend::Is_Render_To_Texture()
+{
+ return DX8Wrapper::Is_Render_To_Texture();
+}
+
+void DX8Backend::Set_Shadow_Map(int idx, ZTextureClass * ztex)
+{
+ DX8Wrapper::Set_Shadow_Map(idx, ztex);
+}
+
+ZTextureClass * DX8Backend::Get_Shadow_Map(int idx)
+{
+ return DX8Wrapper::Get_Shadow_Map(idx);
+}
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h
new file mode 100644
index 00000000000..916f6b76954
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h
@@ -0,0 +1,123 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+// TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend is the reference
+// implementation of IRenderBackend that forwards every virtual method to the
+// existing DX8Wrapper static facade. It adds zero new rendering logic and
+// performs zero behavior changes — it is pure adaptation so the rest of the
+// engine can start talking to an IRenderBackend pointer while still running
+// on the established DX8 path. See RENDER_BACKEND.md.
+
+#pragma once
+
+#include "IRenderBackend.h"
+
+class DX8Backend : public IRenderBackend
+{
+public:
+ DX8Backend();
+ virtual ~DX8Backend();
+
+ // -- Device state queries -------------------------------------------------
+
+ virtual bool Is_Device_Lost() const;
+ virtual bool Has_Stencil();
+ virtual WW3DFormat Get_Back_Buffer_Format();
+ virtual SurfaceClass * Get_Back_Buffer(unsigned int num);
+ virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit);
+
+ // -- Frame lifecycle ------------------------------------------------------
+
+ virtual void Begin_Scene();
+ virtual void End_Scene(bool flip_frame);
+ virtual void Flip_To_Primary();
+ virtual void Clear(bool clear_color, bool clear_z_stencil,
+ const Vector3 & color,
+ float dest_alpha, float z, unsigned int stencil);
+ virtual void Set_Viewport(const RenderBackendViewport & viewport);
+
+ // -- Vertex / index buffers -----------------------------------------------
+
+ virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream);
+ virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba);
+ virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset);
+ virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset);
+ virtual void Set_Index_Buffer_Index_Offset(unsigned int offset);
+
+ // -- State: shaders, materials, textures ---------------------------------
+
+ virtual void Set_Shader(const ShaderClass & shader);
+ virtual void Get_Shader(ShaderClass & shader);
+ virtual void Set_Material(const VertexMaterialClass * material);
+ virtual void Set_Texture(unsigned int stage, TextureBaseClass * texture);
+ virtual void Apply_Render_State_Changes();
+ virtual void Apply_Default_State();
+ virtual void Invalidate_Cached_Render_States();
+
+ // -- Transforms -----------------------------------------------------------
+
+ virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m);
+ virtual void Set_Transform(TransformKind transform, const Matrix3D & m);
+ virtual void Get_Transform(TransformKind transform, Matrix4x4 & m);
+ virtual void Set_World_Identity();
+ virtual void Set_View_Identity();
+ virtual bool Is_World_Identity();
+ virtual bool Is_View_Identity();
+ virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar);
+
+ // -- Lighting and fog -----------------------------------------------------
+
+ virtual void Set_Light(unsigned int index, const LightClass & light);
+ virtual void Set_Ambient(const Vector3 & color);
+ virtual const Vector3 & Get_Ambient() const;
+ virtual void Set_Fog(bool enable, const Vector3 & color, float start, float end);
+ virtual bool Get_Fog_Enable() const;
+ virtual void Set_Light_Environment(LightEnvironmentClass * light_env);
+ virtual LightEnvironmentClass * Get_Light_Environment() const;
+
+ // -- Draw calls -----------------------------------------------------------
+
+ virtual void Draw_Triangles(unsigned short start_index,
+ unsigned short polygon_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count);
+ virtual void Draw_Triangles(unsigned int buffer_type,
+ unsigned short start_index,
+ unsigned short polygon_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count);
+ virtual void Draw_Strip(unsigned short start_index,
+ unsigned short index_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count);
+
+ // -- Programmable pipeline ------------------------------------------------
+
+ virtual void Set_Vertex_Shader(unsigned long vertex_shader);
+ virtual void Set_Pixel_Shader(unsigned long pixel_shader);
+ virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count);
+ virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count);
+
+ // -- Render targets -------------------------------------------------------
+
+ virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format);
+ virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture);
+ virtual bool Is_Render_To_Texture();
+ virtual void Set_Shadow_Map(int idx, ZTextureClass * ztex);
+ virtual ZTextureClass * Get_Shadow_Map(int idx);
+};
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h
new file mode 100644
index 00000000000..80e9f4fdb60
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h
@@ -0,0 +1,224 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+// TheSuperHackers @refactor bobtista 10/04/2026 Introduce IRenderBackend
+// abstract interface so WW3D2 rendering can be re-targeted to modern backends
+// (bgfx, Diligent, etc.) while the existing DX8 path stays functional as the
+// reference implementation. See Core/Libraries/Source/WWVegas/WW3D2/RENDER_BACKEND.md.
+
+#pragma once
+
+#include "ww3dformat.h"
+
+// -----------------------------------------------------------------------------
+// Forward declarations
+// -----------------------------------------------------------------------------
+//
+// Kept lightweight deliberately. IRenderBackend.h must be includable without
+// dragging in the full WW3D2 header graph, so callers only pay for the types
+// they actually use.
+//
+// All W3D classes passed through this interface are referenced by pointer or
+// reference; none of them need a full definition in this header.
+
+class ShaderClass;
+class VertexMaterialClass;
+class TextureBaseClass;
+class TextureClass;
+class ZTextureClass;
+class SurfaceClass;
+class VertexBufferClass;
+class IndexBufferClass;
+class DynamicVBAccessClass;
+class DynamicIBAccessClass;
+class LightClass;
+class LightEnvironmentClass;
+class Matrix4x4;
+class Matrix3D;
+class Vector3;
+
+// -----------------------------------------------------------------------------
+// POD types owned by the interface
+// -----------------------------------------------------------------------------
+
+enum TransformKind
+{
+ // Values chosen so they can be mapped directly to D3DTS_* inside the
+ // DX8Backend without a branch. A modern backend ignores these indices
+ // and uses whichever matrix storage is convenient for it.
+ RB_TRANSFORM_VIEW = 2, // D3DTS_VIEW
+ RB_TRANSFORM_PROJECTION = 3, // D3DTS_PROJECTION
+ RB_TRANSFORM_WORLD = 256 // D3DTS_WORLD
+};
+
+struct RenderBackendViewport
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ float min_z;
+ float max_z;
+};
+
+// -----------------------------------------------------------------------------
+// IRenderBackend — abstract W3D-facing rendering interface
+// -----------------------------------------------------------------------------
+//
+// This interface exposes the *high-level* subset of DX8Wrapper's public API:
+// the calls that take and return W3D types (ShaderClass, TextureBaseClass,
+// Matrix4x4, etc.) and are backend-neutral by construction. The low-level
+// D3D8-specific entry points on DX8Wrapper (Set_DX8_Render_State,
+// _Create_DX8_Texture, _Get_D3D_Device8, etc.) are NOT exposed here and
+// remain reachable only through DX8Wrapper's static methods. Code that
+// needs them is DX8-only and must be migrated during later phases.
+//
+// **Method names intentionally match the existing DX8Wrapper names** so
+// that migrating callers is a mechanical `DX8Wrapper::X(...)` →
+// `g_renderBackend->X(...)` rewrite with minimal diff noise.
+//
+// **This header is included from VC6-compiled translation units** (the
+// DX8 reference path and the tools). Keep it C++98-compatible:
+// - No , no , no or other STL in signatures
+// - No `override`, `= default`, `= delete`, `auto`, `constexpr`
+// - `nullptr` is OK (the project has a VC6 shim)
+// - POD structs for parameter bundles
+// - Forward-declare W3D types rather than including their headers
+//
+// Implementations (DX8Backend.cpp, future BgfxBackend.cpp, etc.) can use
+// whatever C++ features the project's main build allows.
+
+class IRenderBackend
+{
+public:
+ virtual ~IRenderBackend() {}
+
+ // -------------------------------------------------------------------------
+ // Device state queries
+ // -------------------------------------------------------------------------
+
+ virtual bool Is_Device_Lost() const = 0;
+ virtual bool Has_Stencil() = 0;
+ virtual WW3DFormat Get_Back_Buffer_Format() = 0;
+ virtual SurfaceClass * Get_Back_Buffer(unsigned int num) = 0;
+ virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) = 0;
+
+ // -------------------------------------------------------------------------
+ // Frame lifecycle
+ // -------------------------------------------------------------------------
+
+ virtual void Begin_Scene() = 0;
+ virtual void End_Scene(bool flip_frame) = 0;
+ virtual void Flip_To_Primary() = 0;
+ virtual void Clear(bool clear_color, bool clear_z_stencil,
+ const Vector3 & color,
+ float dest_alpha, float z, unsigned int stencil) = 0;
+ virtual void Set_Viewport(const RenderBackendViewport & viewport) = 0;
+
+ // -------------------------------------------------------------------------
+ // Vertex / index buffers
+ // -------------------------------------------------------------------------
+
+ virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) = 0;
+ virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba) = 0;
+ virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) = 0;
+ virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) = 0;
+ virtual void Set_Index_Buffer_Index_Offset(unsigned int offset) = 0;
+
+ // -------------------------------------------------------------------------
+ // State: shaders, materials, textures
+ // -------------------------------------------------------------------------
+
+ virtual void Set_Shader(const ShaderClass & shader) = 0;
+ virtual void Get_Shader(ShaderClass & shader) = 0;
+ virtual void Set_Material(const VertexMaterialClass * material) = 0;
+ virtual void Set_Texture(unsigned int stage, TextureBaseClass * texture) = 0;
+
+ virtual void Apply_Render_State_Changes() = 0;
+ virtual void Apply_Default_State() = 0;
+ virtual void Invalidate_Cached_Render_States() = 0;
+
+ // -------------------------------------------------------------------------
+ // Transforms
+ // -------------------------------------------------------------------------
+
+ virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m) = 0;
+ virtual void Set_Transform(TransformKind transform, const Matrix3D & m) = 0;
+ virtual void Get_Transform(TransformKind transform, Matrix4x4 & m) = 0;
+ virtual void Set_World_Identity() = 0;
+ virtual void Set_View_Identity() = 0;
+ virtual bool Is_World_Identity() = 0;
+ virtual bool Is_View_Identity() = 0;
+ virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix,
+ float znear, float zfar) = 0;
+
+ // -------------------------------------------------------------------------
+ // Lighting and fog
+ // -------------------------------------------------------------------------
+
+ virtual void Set_Light(unsigned int index, const LightClass & light) = 0;
+ virtual void Set_Ambient(const Vector3 & color) = 0;
+ virtual const Vector3 & Get_Ambient() const = 0;
+ virtual void Set_Fog(bool enable, const Vector3 & color, float start, float end) = 0;
+ virtual bool Get_Fog_Enable() const = 0;
+ virtual void Set_Light_Environment(LightEnvironmentClass * light_env) = 0;
+ virtual LightEnvironmentClass * Get_Light_Environment() const = 0;
+
+ // -------------------------------------------------------------------------
+ // Draw calls
+ // -------------------------------------------------------------------------
+
+ virtual void Draw_Triangles(unsigned short start_index,
+ unsigned short polygon_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count) = 0;
+
+ virtual void Draw_Triangles(unsigned int buffer_type,
+ unsigned short start_index,
+ unsigned short polygon_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count) = 0;
+
+ virtual void Draw_Strip(unsigned short start_index,
+ unsigned short index_count,
+ unsigned short min_vertex_index,
+ unsigned short vertex_count) = 0;
+
+ // -------------------------------------------------------------------------
+ // Programmable pipeline (GPU vertex / pixel shaders)
+ // -------------------------------------------------------------------------
+ //
+ // These correspond to DX8's programmable shader slots. Modern backends
+ // will re-interpret the handles internally; the interface treats the
+ // shader id as an opaque unsigned long.
+
+ virtual void Set_Vertex_Shader(unsigned long vertex_shader) = 0;
+ virtual void Set_Pixel_Shader(unsigned long pixel_shader) = 0;
+ virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count) = 0;
+ virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count) = 0;
+
+ // -------------------------------------------------------------------------
+ // Render targets
+ // -------------------------------------------------------------------------
+
+ virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format) = 0;
+ virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture) = 0;
+ virtual bool Is_Render_To_Texture() = 0;
+ virtual void Set_Shadow_Map(int idx, ZTextureClass * ztex) = 0;
+ virtual ZTextureClass * Get_Shadow_Map(int idx) = 0;
+};
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp
new file mode 100644
index 00000000000..0ec35c51022
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp
@@ -0,0 +1,48 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+// TheSuperHackers @refactor bobtista 10/04/2026 Render backend global
+// owner. Holds the single g_renderBackend pointer and constructs/destroys
+// the concrete backend instance. See RENDER_BACKEND.md.
+
+#include "RenderBackend.h"
+#include "DX8Backend.h"
+
+IRenderBackend * g_renderBackend = nullptr;
+
+void Init_Render_Backend()
+{
+ if (g_renderBackend != nullptr)
+ {
+ return;
+ }
+
+ // Phase 1: the DX8 backend is the only option. Phase 2 will introduce
+ // a compile-time flag to pick between DX8, bgfx, and Diligent.
+ g_renderBackend = new DX8Backend();
+}
+
+void Shutdown_Render_Backend()
+{
+ if (g_renderBackend == nullptr)
+ {
+ return;
+ }
+ delete g_renderBackend;
+ g_renderBackend = nullptr;
+}
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h
new file mode 100644
index 00000000000..ee4627d5717
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h
@@ -0,0 +1,42 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2026 TheSuperHackers
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+// TheSuperHackers @refactor bobtista 10/04/2026 Backend-agnostic access point
+// for the global IRenderBackend instance. Engine-side code should include
+// this header (not IRenderBackend.h or DX8Backend.h directly) to use the
+// render backend. See RENDER_BACKEND.md.
+
+#pragma once
+
+#include "IRenderBackend.h"
+
+// The active rendering backend. Set by Init_Render_Backend() during
+// WW3D device initialization and cleared by Shutdown_Render_Backend()
+// during device teardown. Never null between those two calls.
+extern IRenderBackend * g_renderBackend;
+
+// Create the render backend. Called by DX8Wrapper::Do_Onetime_Device_Dependent_Inits
+// after the D3D device has been successfully created.
+//
+// Phase 1 always creates a DX8Backend. Phase 2 will add a compile-time
+// option to select between DX8Backend, BgfxBackend, and DiligentBackend.
+void Init_Render_Backend();
+
+// Destroy the render backend. Called by DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns
+// before the D3D device is released.
+void Shutdown_Render_Backend();
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 1e420b66798..cce9691c305 100644
--- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -56,6 +56,7 @@
#include "dx8vertexbuffer.h"
#include "dx8indexbuffer.h"
#include "dx8renderer.h"
+#include "RenderBackend.h"
#include "ww3d.h"
#include "camera.h"
#include "wwstring.h"
@@ -387,6 +388,11 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Inits()
TextureLoader::Init();
Set_Default_Global_Render_States();
+
+ // TheSuperHackers @refactor bobtista 10/04/2026 Construct the global
+ // IRenderBackend instance now that the D3D device is ready. See
+ // Core/Libraries/Source/WWVegas/WW3D2/RENDER_BACKEND.md.
+ Init_Render_Backend();
}
inline DWORD F2DW(float f) { return *((unsigned*)&f); }
@@ -447,6 +453,11 @@ void DX8Wrapper::Invalidate_Cached_Render_States()
void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns()
{
+ // TheSuperHackers @refactor bobtista 10/04/2026 Tear down the render
+ // backend before the D3D device is released so any backend-owned
+ // resources get released first. See RENDER_BACKEND.md.
+ Shutdown_Render_Backend();
+
/*
** Shutdown ww3d systems
*/