diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp
new file mode 100644
index 00000000000..7ddbe267aef
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp
@@ -0,0 +1,303 @@
+/*
+** 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()
+{
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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();
+}
+
+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);
+}
+
+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();
+}
+
+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);
+}
+
+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);
+}
+
+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/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h
new file mode 100644
index 00000000000..7e1cdbb8a20
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h
@@ -0,0 +1,103 @@
+/*
+** 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. Pure adaptation, no new rendering logic.
+
+#pragma once
+
+#include "IRenderBackend.h"
+
+class DX8Backend : public IRenderBackend
+{
+public:
+ DX8Backend();
+ virtual ~DX8Backend();
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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();
+
+ 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);
+
+ 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;
+
+ 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);
+
+ // The shader id is treated as an opaque unsigned long.
+ 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);
+
+ 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/Backend/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp
new file mode 100644
index 00000000000..70190545323
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp
@@ -0,0 +1,46 @@
+/*
+** 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.
+
+#include "RenderBackend.h"
+#include "DX8Backend.h"
+
+IRenderBackend * g_renderBackend = nullptr;
+
+void Init_Render_Backend()
+{
+ if (g_renderBackend != nullptr)
+ {
+ return;
+ }
+
+ 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/Backend/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h
new file mode 100644
index 00000000000..39386ee5dd0
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h
@@ -0,0 +1,35 @@
+/*
+** 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 backend.
+
+#pragma once
+
+#include "IRenderBackend.h"
+
+// The active rendering backend. Set by Init_Render_Backend() and cleared by
+// Shutdown_Render_Backend(); never null between those two calls.
+extern IRenderBackend * g_renderBackend;
+
+// Create the render backend. Must be called after the render device is ready.
+void Init_Render_Backend();
+
+// Destroy the render backend. Must be called before the render device is released.
+void Shutdown_Render_Backend();
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
index 9ff4754aec9..90b37a4b311 100644
--- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
+++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
@@ -43,6 +43,10 @@ set(WW3D2_SRC
distlod.cpp
distlod.h
dllist.h
+ Backend/DX8Backend.cpp
+ Backend/DX8Backend.h
+ Backend/RenderBackend.cpp
+ Backend/RenderBackend.h
dx8caps.cpp
dx8caps.h
#dx8fvf.cpp
@@ -90,6 +94,7 @@ set(WW3D2_SRC
htree.h
#htreemgr.cpp
#htreemgr.h
+ IRenderBackend.h
intersec.cpp
intersec.h
intersec.inl
diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h
new file mode 100644
index 00000000000..4b80eb18151
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h
@@ -0,0 +1,158 @@
+/*
+** 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 Abstract W3D-facing rendering
+// interface so WW3D2 rendering can be re-targeted to other backends while the
+// existing DX8 path stays as the reference implementation.
+
+#pragma once
+
+#include "ww3dformat.h"
+
+// Forward declarations keep this header includable without pulling in the full
+// WW3D2 header graph. All W3D types below are passed by pointer or reference.
+
+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;
+
+enum TransformKind
+{
+ // Values match D3DTS_* so DX8Backend can map them without a branch.
+ 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;
+};
+
+// Exposes the high-level subset of DX8Wrapper's public API: the calls that take
+// and return W3D types (ShaderClass, TextureBaseClass, Matrix4x4, etc.). The
+// low-level D3D8-specific entry points on DX8Wrapper are not exposed here and
+// remain reachable only through DX8Wrapper's static methods.
+//
+// Method names intentionally match the existing DX8Wrapper names so migrating a
+// caller is a mechanical DX8Wrapper::X(...) -> g_renderBackend->X(...) rewrite.
+
+class IRenderBackend
+{
+public:
+ virtual ~IRenderBackend() {}
+
+ // Optional device lifecycle. DX8Wrapper owns the render device and calls
+ // these after the backend is constructed and before it is destroyed. A
+ // backend that drives its own device creates it in Initialize and releases
+ // it in Shutdown; the DX8 reference backend leaves them as no-ops.
+ virtual void Initialize(void * window, int width, int height) {}
+ virtual void Shutdown() {}
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ // The shader id is treated 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;
+
+ 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/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 1e420b66798..99070bcc382 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 "Backend/RenderBackend.h"
#include "ww3d.h"
#include "camera.h"
#include "wwstring.h"
@@ -387,6 +388,12 @@ 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, then let it
+ // bring up any device of its own.
+ Init_Render_Backend();
+ g_renderBackend->Initialize(_Hwnd, ResolutionWidth, ResolutionHeight);
}
inline DWORD F2DW(float f) { return *((unsigned*)&f); }
@@ -447,6 +454,12 @@ 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.
+ g_renderBackend->Shutdown();
+ Shutdown_Render_Backend();
+
/*
** Shutdown ww3d systems
*/