WarcraftXL: A 1,578-Shader Vulkan Device for the 18-Year-Old WoW 3.3.5a Client

By Indie Kings | October 17, 2026

Updated October 17, 2026: The developer behind the WarcraftXL modding framework pushed a new repository, wxl-vulkan-api, on October 11, 2026: a native Vulkan graphics device that replaces the Direct3D 9 backend inside the 18 year old World of Warcraft 3.3.5a client. It reuses the game's own shaders, all 1,578 of them, translated to SPIR-V from the user's own client, and a sibling repository, wxl-grasswind, handles a smaller trick: making the grass move.

GitHub repository card for WarcraftXL wxl-vulkan-api, a native Vulkan graphics device for the World of Warcraft 3.3.5a client
Image credit: WarcraftXL/GitHub.

What wxl-vulkan-api is

A reader's summary line: one developer wrote an entire Vulkan graphics device for the World of Warcraft 3.3.5a client from 2008, and it loads from inside the game while reusing the client's own shaders. The repository WarcraftXL/wxl-vulkan-api went up on October 11, 2026, is written in C++ and is licensed under GPL-3.0, per its GitHub repository page.

Per the project's README, wxl-vulkan-api is an extension of the WarcraftXL framework and requires the framework's v1.2, which is also in alpha. The extension does not build or load against wxl-core v1.1. One sentence on the current state: both wxl-core v1.2 and wxl-vulkan-api are alpha, so rendering bugs, missing features and the occasional crash are expected, and the README tells users to keep a copy of the client and its WTF folder.

This is one entry in a wider client-modding ecosystem we have covered before, including a retrofit workbench for running later WoW content on old clients and tooling such as WoTLK_MultiTool and Tortoise-WoW. wxl-vulkan-api sits further down the stack than any of those: it reaches directly into the rendering device.

How a 2008 client gets swapped to Vulkan

The 3.3.5a client, build 12340, shipped in 2008 with Direct3D 9 as its graphics backend on Windows. Per the wxl-vulkan-api README, the extension does not rip the engine apart to do this. The engine keeps its own CGxDevice object, built by its own factory, with its window, render states and caches intact.

What changes is the code underneath. The extension replaces the code behind the 42 vtable slots that reach D3D9, and per the README 39 of those slots are reimplemented on Vulkan while 3 are stubs. In practical terms, the client believes it is still talking to D3D9, but the work lands on a Vulkan device instead.

There is no SDK to install. Per the README, the Khronos headers are vendored and every Vulkan entry point is resolved at runtime, so the extension finds its own way onto whatever driver the machine has.

The client's own shaders, translated to SPIR-V

The sharpest technical idea in the project is what it does with shaders. Rather than rewriting the game's rendering from scratch, the extension translates every DX9 shader record the engine loads: 1,578 of 1,578 records translated, per the README, including bone-palette, tree-wind, shadow and G-buffer variants. Those modules run on Vulkan as SPIR-V.

The rest is hand-written GLSL. Per the README, the UI, fixed-function, particle, present and overlay shaders are written by hand, and the hand-written modules are versioned inside the repository.

The translated modules deliberately are not committed. Per the README, they are derived from Blizzard's shader archives, so each user generates them from their own copy of the game with the tools/translate_shaders.py script plus the Khronos Group's glslang compiler. The script reads the .bls shader containers from the client's MPQ archives, translates every record to GLSL, compiles it to SPIR-V and writes the result with a manifest. A full run takes a few minutes, per the README, and should be rerun whenever the client's shaders change.

Requirements, setup and the config knobs

Turning the device on is one line: WXL_VK_DEVICE=native in WarcraftXL.cfg beside the client. If the value is unset, the extension stays inert and the stock D3D9 device runs as before, per the README. Building it means cloning the repository into wxl-core v1.2's extensions folder and building with CMake 3.20 or later against a Win32 C++20 toolchain, with Python 3.8+ and glslang needed once for the shader translation.

Running it needs a legally obtained World of Warcraft 3.3.5a client, wxl-core v1.2 installed in that client, a GPU and driver with Vulkan 1.0 or later, and the 32-bit Vulkan loader, C:\Windows\SysWOW64\vulkan-1.dll, which the README notes is installed by every current NVIDIA, AMD and Intel driver. Without a usable Vulkan driver, 32-bit loader or translated shaders, the device is declined and the log says why, per the README.

The optional knobs, per the README's configuration block:

Config keyWhat it does
WXL_VK_DEVICE=nativeTurns on the native Vulkan device; unset keeps stock D3D9
WXL_VK_ANISOTROPY=16Anisotropic filtering of the world's mipmapped textures; 0 or 1 keeps the engine's own setting
WXL_VK_MIP_BIAS within -1 to 1Mip LOD bias for those textures; below 0 is sharper
WXL_VK_TRANSLATED=0, 1 or 20 runs hand-written pipelines only, 1 lets translated modules fill in, 2 prefers them
WXL_VK_CAPS=10 gives a plain Vulkan 1.0 device without the optional 1.1/1.2 features
WXL_VK_VALIDATION=1Enables the Khronos validation layer, when installed, 32-bit
WXL_VK_STATS=1Detailed per-module counters in the log, roughly once a minute and at exit

The log is specific about performance too. Per the README, the extension reports frames presented, average and maximum frame time, draws received and drawn, pipeline count, and memory reserved and used in MiB with the allocation count, in a periodic line and at device destruction.

The rendering API other extensions can call

The device is not just for itself. Per the README, the extension publishes a rendering API, include/wxl/VkRenderApi.h, so other WarcraftXL extensions can record their own Vulkan work into the frame. The interface is published as wxl.vk.render while the native device runs, and extensions resolve it after load rather than in WXL_Load.

What that API exposes, per the README: insertion points in the frame, compute and full-screen stages; the previous and current depth buffers; a depth pyramid; a G-buffer of the opaque world; shadow replays of the captured world; device capabilities; a memory budget; and frame figures. The header documents every entry point, structure and threading rule, and fields and functions are only ever appended, with extensions told to check structSize before reading anything marked as appended.

It is a small detail with a large consequence: the device becomes infrastructure. A grass-swaying extension, or anything else visual, can hook into real Vulkan stages instead of hacking the client again.

wxl-grasswind: the grass moves

The second repository shows the other end of the same ecosystem. WarcraftXL/wxl-grasswind was created August 8, 2026 and last pushed August 10, 2026, is licensed under GNU GPLv3 and has 5 stars, per its GitHub repository page. Its README needs one line for the pitch: makes the grass move.

Per that README, the stock client's grass is completely static and does not react to anything. The module gives it a bit of life: it sways gently as if caught in the wind, parts when the player walks through it, and settles back behind them.

Per the README, the effect is purely visual with no gameplay impact, runs on the GPU, and carries no noticeable performance cost. The tunables are wind direction and strength, speed, and how much the grass parts when you walk through it. That is the whole story, and the brevity is the point: the same framework that carries an entire rendering device also carries small GPU-side visual extensions one vtable slot below it.

The scope warning

Modifying a World of Warcraft client violates Blizzard Entertainment's terms of service. These tools target the discontinued 2008 3.3.5a client, the build commonly used by private servers, and per their READMEs they ship none of Blizzard's files. Readers use them at their own risk against their own legally obtained client.

FAQ

Does the WoW 3.3.5a client still run Direct3D 9?
Yes, by default. The client shipped in 2008 with D3D9 as its Windows graphics backend, and the stock device keeps running unless WXL_VK_DEVICE=native is set in WarcraftXL.cfg.

How does wxl-vulkan-api switch the game to Vulkan?
It leaves the engine's own CGxDevice in place and replaces the code behind the 42 vtable slots that reach D3D9: 39 reimplemented on Vulkan, 3 stubs, per the project README.

Where do the Vulkan shaders come from?
From the user's own client. All 1,578 DX9 shader records the engine loads are translated to SPIR-V by tools/translate_shaders.py plus glslang, and the translated modules are deliberately not committed because they derive from Blizzard's archives.

What do you need to run it?
A legally obtained 3.3.5a client, wxl-core v1.2, Vulkan 1.0 or later drivers, and the 32-bit Vulkan loader in C:\Windows\SysWOW64\vulkan-1.dll.

Does wxl-grasswind affect gameplay or performance?
No gameplay impact, per its README, and the effect runs on the GPU with no noticeable performance cost. It sways grass in the wind and parts it when the player walks through.

Is it safe to use?
Both wxl-core v1.2 and wxl-vulkan-api are alpha with expected crashes, and modifying the client violates Blizzard's terms of service. Back up the client and WTF folder and use it only on a client you can afford to break.

Bottom Line

WarcraftXL pushed two October projects worth attention: wxl-vulkan-api, an alpha Vulkan device that replaces D3D9 inside the 3.3.5a client with 39 of 42 reaching vtable slots reimplemented and all 1,578 engine shader records translated from the user's own files, and wxl-grasswind, a small GPU extension that makes the grass sway and part. Together they mark the range of the same framework, from a whole rendering device down to foliage motion, on an 18-year-old Windows binary.

Our take:

We think the shader translation is the part other projects will copy. Reusing all 1,578 of the client's own shader records instead of rebuilding the look from scratch is the honest way to keep a 2008 game looking like itself, and it sidesteps the legal trap of redistributing Blizzard's files by making each user generate them locally. The grass module is trivial, but it is exactly the kind of experiment the published VkRenderApi header exists to enable, and that is the sign of a framework thinking ahead.

Sources

Device behavior, vtable replacement (42 slots, 39 reimplemented, 3 stubs), shader translation (1,578 of 1,578 records to SPIR-V, bone-palette, tree-wind, shadow and G-buffer variants), hand-written UI, fixed-function, particle, present and overlay GLSL shaders, translated modules not committed, requirements (legally obtained 3.3.5a build 12340 client, wxl-core v1.2, Vulkan 1.0+, 32-bit SysWOW64 vulkan-1.dll loader, vendored Khronos headers with runtime entry-point resolution), configuration knobs, log content, the published render API (wxl.vk.render, frame/compute/full-screen insertion points, prev and current depth, depth pyramid, opaque-world G-buffer, shadow replays, device capabilities, memory budget, frame figures, appended-only fields with structSize check), and the alpha warning with WTF folder backup advice, per the WarcraftXL/wxl-vulkan-api README.

Static stock grass, wind sway, walk-through parting and settling, purely visual behavior, GPU execution with no noticeable performance cost, and wind direction, strength, speed and parting tunables, per the WarcraftXL/wxl-grasswind README. Repository dates (wxl-vulkan-api created and pushed October 11, 2026; wxl-grasswind created August 8, 2026, last pushed August 10, 2026), languages, licenses (GPL-3.0 and GNU GPLv3) and star count (5), per the two GitHub repository pages.

Share