# ShaderFit Client module for Blockland v21. While a world is drawing, it watches the frame rate and changes the shadow map to match. A low frame rate steps the map down. A stretch of high frame rate steps it back up. The map also stays inside the size this 32-bit process can allocate. Shader source is not modified. ## Install Place `ShaderFit.dll` in the game's `modules` folder, then quit and start Blockland from Steam. A DLL that is already loaded stays mapped until that restart. The module only changes rendering on this client. ## What it follows The shader quality setting chooses a shadow resolution and a cascade count. ShaderFit remembers that pair. Automatic changes are a temporary limit on top of it. Choosing a different quality replaces the remembered pair and clears the limit. Each presented frame updates a smoothed frame rate. A frame longer than a quarter second is ignored, so a hitch does not look like a low rate. Scaling waits one second after shadows start, and then waits 2.5 seconds after every change. Shadows have to be in use. Scaling pauses when shaders are off, when the shader name is `minimum`, or when the shadow size or cascade count is 0. It starts again when shadows are back. ## Stepping down and up Under 50 fps for one second, the resolution is cut in half. The floor is 1024. At 1024, the next step removes one cascade. It will not go below one cascade. Over 70 fps for eight seconds, one cascade is restored, up to the count from the quality setting. After the cascades are back, the resolution doubles, up to the cap for this adapter. The frame rate gained by a step down is not treated as spare room. The map is raised only when the rate would still be about 65 fps after giving that gain back. If a raise drops the rate under 50 within the following second, the step is undone and another raise is blocked for 45 seconds. Each change rebuilds the shadow map and writes a console line with the frame rate, resolution, and cascade count. ## How large a map can be The shadow map is one 16-bit depth array: width times height times cascades times 2 bytes. The cap is the largest power of two that fits all of these: - under 2 GB - under a quarter of dedicated video memory - inside `GL_MAX_TEXTURE_SIZE` - at least 1024 8192 with 4 cascades is 512 MB. 16384 with 4 cascades is exactly 2 GB. This process runs out of memory at that size, so it is not chosen. If a rebuild larger than 8192 still turns shaders off, ShaderFit turns them back on at 8192. An unknown adapter is not used as a reason to shrink the quality setting. Once an OpenGL context exists, the cap is taken from the current renderer, dedicated memory, and the maximum texture size. Before that, a vendor guess is used: NVIDIA 8192, AMD 4096, and Intel from the amount of dedicated memory. ## Console variables - `$ShaderFit::Vendor` - `$ShaderFit::Renderer` - `$ShaderFit::DedicatedMB` - `$ShaderFit::ShadowCap` - `$ShaderFit::FrameRate` The first shadow rebuild also logs the vendor, renderer name, dedicated memory, and cap. ## Build Blockland is a 32-bit program, so the DLL has to be built with a 32-bit MinGW toolchain (`i686-w64-mingw32`). Put that toolchain's `bin` directory first on `PATH` so CMake finds that `gcc` and `mingw32-make`. `find_package(TSFUNCS)` needs a tsfuncs 1.0.1 package: `tsfuncs-config.cmake` next to `include/` and `lib/`. MinHook's cmake package lives under that package's `lib/minhook`. Pass the package directory as `CMAKE_PREFIX_PATH`. From this repo: ``` cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_PREFIX_PATH=C:/path/to/tsfuncs -S . -B build cmake --build build ``` The result is `build/ShaderFit.dll`. CMake is set so the filename has no `lib` prefix. The link line is tsfuncs, MinHook, `psapi`, `opengl32`, and `dxgi`, with static libgcc and libstdc++. Source is `src/main.cpp` and `CMakeLists.txt`. The current DLL is attached to the v1.0.0 release.