Forza Painter FH6 hands you an EXE, and the repo root still ships five batch files
Vinyl Painter Import Tool for FH6. Featuring GPU-accelerated generation & import. Based on forza-painter
At a glance
- What is it?
- A Windows tool that turns images into Forza Horizon 6 Vinyl Group geometry, with a bundled OpenCL generator and an importer that writes into a live game process. The documentation covers blur and layer counts carefully and says nothing at all about rules.
- Who is it for?
- Use this if you are prepared to read the numbers rather than the pitch, because the preset table, the 40 percent GPU idle figure and the four-layer boundary offset are all documented precisely enough to plan around. Skip the parallel setting unless you actually have a queue, since a single queued image gains nothing from it.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 29 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The EXE is the product, and five batch files sit next to it
Distribution is a single file. The documentation says normal users do not need Python, a virtual environment, batch files or manual memory addresses, and it tells them to take `forza-painter-fh6-v1.9.6.exe` from the releases page and run it. It goes further and warns against downloading GitHub's automatic source archive unless you are contributing. The repository root does not agree with that story. Five batch files live there: a file whose name begins with a number and an instruction to drag an image onto it, plus check_environment.bat, clean_runtime_data.bat, install_dependencies.bat and start_app.bat. Alongside them are requirements.txt, a second requirements-preview.txt, pytest.ini, and directories named bin, config, docs, experiments, scripts, src and tests. The EXE path is clearly the supported one, and the batch files are the developer path left in view rather than hidden.
requirements.txt names three packages and no GPU library
The Python dependency list is three lines long: psutil at 5.9.0 or newer, pywin32 at 306 or newer, and pillow at 10.4.0 or newer. Read together those three describe the integration surface rather than the numerics. psutil watches processes, pywin32 reaches the Windows API and process memory, and pillow handles the PNG, JPG and BMP input. There is no OpenCL binding, no array library and no machine learning framework anywhere in the list, even though the project describes itself as GPU-accelerated and the feature table credits a bundled GPU and OpenCL generator. The work therefore happens outside Python, in a binary shipped with the project, which is also why a bin directory exists and why an end user is handed a compiled executable rather than a package to install. A second requirements file covers the preview path, so the two dependency sets are split by role rather than merged.
Blurriness has two causes and the advice points at the wrong one first
The word blurry gets two different explanations in this project and the order of advice is worth noticing. The prominent note says that if the result looks blurry you should raise Random samples first, that values above 200000 usually make a major quality difference, and that higher values are clearer but take much longer. The separate note about layer counts says something more mechanical: importing a 500-layer JSON into a 3000-layer template will look blurry. Those are not the same fault. One is a generator sampling problem, the other is a mismatch between the geometry you produced and the geometry the template expects. The preset table shows where the two collide, since the recommended default of balanced runs 1800 layers at 120000 samples, which sits below the 200000 threshold the blur advice points at, while the slow preset at 2500 and 220000 is the first one inside it.
The layer count you type is not the number in the filename
The importer asks you to enter the exact template layer count, and that number is not the one in the JSON filename. Generated files are written beside the source image with the layer count in the name, such as image.500.json, image.1000.json and image.3000.json, and the guidance is to prefer the highest-layer JSON that matches your template. The reason a direct match fails is an offset: the game needs four extra boundary layers to save the cover and apply bounds correctly. A 1000-layer JSON should therefore be paired with at least a 1004-layer template, and a 3000-layer template yields about 2996 drawable shapes. Working the arithmetic backwards, the number you type is always the template's count and never the count in the file name, which is the step where most of the blur reports appear to originate.
Parallel images exists because the GPU idles 40 percent of every layer
The concurrency setting is explained by the generator's internal shape rather than by a desire for speed. Each run alternates a single-threaded CPU phase that picks candidate shapes with a GPU phase that scores them, so one image on its own leaves the GPU idle for roughly 40 percent of every layer, and running several images at once fills those gaps. The published figures are one at baseline, two at about 1.5 times and three at about 1.9 times, measured on a single card, an RX 9070 XT. Two caveats are stated plainly. A single queued image takes the same time at any setting, so the control does nothing unless a queue exists, and above one the per-layer estimate is replaced by an image counter with the image name prefixed to each log line. Each parallel job is a separate generator process holding its own copy of the image on the GPU.
The importer writes into a live game process and never mentions rules
What the import actually does is worth stating without interpretation. You start the game, keep Vinyl Group Editor open, load a template of many simple sphere layers and ungroup it. Then in the app you open Import, click Refresh and select `forzahorizon6.exe`, enter the template layer count, add the generated JSON or use Use generated JSON, leave the advanced address fields empty and click Import JSON. The feature table describes the step as auto-locating and verifying the editable layer table before writing, and the quick start says to run the app as administrator if Windows blocks process access. Locating that table is slow enough to have its own warning: version 1.4.1 and later try multiple template locators and can spend up to five minutes finding the safe layer table. No part of the documentation mentions bans, anti-cheat, competitive rules or terms of service.
The EXE checks for updates at startup and can open an external market
Two network behaviours are on by default and neither is buried. The feature table lists an update check that runs on startup and shows changelog notes when a new version is available, so opening the tool is itself a request outbound. Separately, a preset market entry opens https://painter6.com from inside the application to browse shared images, presets and JSON packages, and the notes call the in-app banner the newer route to the same destination. That means the tool both pulls version information and can send you to a site hosting content uploaded by other people. Worth noting against the rest of the design, which is otherwise built around local files: generated JSON is written beside the source image, and the layer template is yours, ungrouped, in your own save.
Two license files at the root and no statement of coverage
The repository carries two license files side by side, LICENSE and LICENSE.custom-importer, while the project records no license at all in its repository metadata. Which of the two files covers which part of the code is not stated anywhere in the documentation, and there is no note saying the custom importer is a separate work with separate terms or that one file merely duplicates the other. The documentation does point at a license file in its closing line, so a licence exists and is meant to be found; the ambiguity is about scope rather than about permission. Two files is also consistent with the shape of the tool, since the regular importer and the experimental full-shape and type-code path arrived in different releases, 1.8.0 and 1.8.1, and the presence of a file named for the custom importer suggests the authors treated them as separable pieces.
Editorial conclusion
Use this if you are prepared to read the numbers rather than the pitch, because the preset table, the 40 percent GPU idle figure and the four-layer boundary offset are all documented precisely enough to plan around. Skip the parallel setting unless you actually have a queue, since a single queued image gains nothing from it. Before you import anything, read the section on layer counts, since that single number is the most common cause of a blurry result. And settle the rules question yourself: the documentation describes selecting the game executable, running as administrator and writing to a layer table, and says nothing about whether any of that is permitted.
Frequently asked questions
How do I use forza-painter-fh6?
Download forza-painter-fh6-v1.9.6.exe from Releases into a writable folder, double-click it, and run it as administrator if Windows blocks process access. In the game open Create Vinyl Group or Vinyl Group Editor, load a sphere template and Ungroup it. Then generate JSON in the app, open Import, enter the exact template layer count and import.
Is Forza Painter bannable?
The README does not address bans, anti-cheat or terms of service anywhere. What it does document is that you select forzahorizon6.exe on the Import page, that the tool auto-locates and verifies an editable layer table before writing, that it may run as administrator, and that finding that table can take up to five minutes. Whether any of that is permitted is a question for the game's own rules, not for this repository.
Why does my imported Forza vinyl look blurry?
Two separate causes. Importing a 500-layer JSON into a 3000-layer template looks blurry because the geometry does not match, and a low sample count looks blurry because the generator did not search enough. The notes suggest raising Random samples above 200000 for the second case, and matching the layer count for the first.
Why does forza-painter-fh6 ask for a layer count the JSON filename already states?
The game needs four extra boundary layers to save the cover and apply bounds correctly. A 1000-layer JSON should use at least a 1004-layer template, and a 3000-layer template can import about 2996 drawable shapes, so the number you type is the template's count rather than the count in image.3000.json.
What does the Parallel images setting do in forza-painter-fh6?
The generator alternates a single-threaded CPU phase with a GPU phase, leaving the GPU idle for roughly 40 percent of every layer, so queued images fill the gaps. Two images give about 1.5 times throughput and three about 1.9 times, measured on an RX 9070 XT. It only helps when more than one image is queued, and each job is a separate process with its own copy on the GPU.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bvzrays-forza-painter-fh6)