News:

The Forum Rules and Guidelines
Our forum has Rules and Guidelines. Please, be kind and read them ;).

Simutrans 32-bit graphics — work in progress and open for review

Started by victor_18993, September 05, 2026, 06:37:54 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

victor_18993

Hi everyone,

I've published **RGBA32 revised-10** as a new public testing release:

https://github.com/Dkijas/simutrans-true32-renderer/releases/tag/rgba32-revised-10-r12322-testing-1

This version has been rebased onto **r12322**, just after the Simutrans 125.0 release, so it is now much closer to the current codebase.

The main goal is still the same: **keep full compatibility with existing 16-bit paksets while allowing 32-bit RGBA artwork on top**.

Since revised-9, this build includes the XR32 asset pipeline, 1x/2x MRES support, CRC/bounds checks and the partial-transparency fixes. Windows SDL2, Windows SDL3 and Linux test builds are included, together with a small XR32 test kit and the source patches.

This is still an **experimental testing build**, not trunk and not an official Simutrans release.

The main open issue is still antialiased edges involving special colours such as company colours and lights. That will probably need explicit metadata from the artwork/exporter rather than trying to guess it inside Makeobj.

If anyone wants to test it, I'd be very interested in screenshots, visual regressions, crashes or cases where legacy paksets behave differently from normal Simutrans.

Thanks to everyone who has helped with testing and feedback so far.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Quote from: victor_18993 on October 02, 2026, 03:55:19 PMThe main open issue is still antialiased edges involving special colours such as company colours and lights. That will probably need explicit metadata from the artwork/exporter rather than trying to guess it inside Makeobj.
I don't understand; please explain.

victor_18993

Quote from: makie on October 02, 2026, 04:02:33 PMI don't understand; please explain.
Sure. What I mean is this:

Simutrans recognises company colours and light colours because some exact RGB values have a special meaning.

For example, if a pixel is exactly a company-colour value, the game knows that it has to replace it with the selected player's colour.

The problem appears at antialiased edges.

Imagine a company-coloured area next to a normal grey area. Blender or another graphics program creates intermediate pixels between them to make the edge smooth. Those pixels are no longer the exact Simutrans company colour — they are mixtures of the company colour and grey.

So when Simutrans reads the image, it can recognise the central company-colour pixels, but it cannot know that those intermediate edge pixels were also intended to belong partly to the company colour. To the game they just look like ordinary RGB colours.

The same problem exists around night lights.

We tested trying to guess this automatically in Makeobj, but it is not reliable enough. Different artwork can produce the same intermediate RGB colour for completely different reasons.

That is why I mentioned metadata from the exporter. For example, Blender could export the normal RGBA image plus a small mask saying:

"these pixels belong to company colour 1"
"these pixels belong to this light"

Then Simutrans would know the intended meaning even on smooth/antialiased edges.

Exact special-colour pixels already work correctly. This is only about preserving their meaning through the partially blended pixels around their edges.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Quote from: victor_18993 on October 02, 2026, 08:37:44 PMSo when Simutrans reads the image, it can recognise the central company-colour pixels, but it cannot know that those intermediate edge pixels were also intended to belong partly to the company colour. To the game they just look like ordinary RGB colours.
Yes
QuoteWe tested trying to guess this automatically in Makeobj, but it is not reliable enough. Different artwork can produce the same intermediate RGB colour for completely different reasons.
Please don't do it.

You try to generate the special colors via Blender automatically. My be this is possible or not. This is a special problem to Blender. Please do not integrate a solution to this problem in Makeobj.

The workflow of Pumuckl999s and my and may be some other graphic designer is:

Step 1: Create the the picture regardless of special colors.
Step 2: Eliminate the accidentally created special colors by replacing it to nearby color.
Step 3: Set special colors at the desired position manual.

If in future special colors are in separate plane there is no need for Step 2 and also there is no antialiased edges. See it as a mask, it is pixel exakt and no antialiasing. Maybe sdl3 or the graphics card do it for scaling. This is then after darkening for the night and handle the player colors.

The graphic stock contain no anti-aliased special colors.

prissi

I think too, either the old way as before (since we have already 32 bit PNGs anyway) or a new entry, with a second image name after a semicolon ";" with the mask. (Or even for. But I think atleast for the player colors, unsing red and green for masking with player colors 1 and player color 2 should be straight forward.) Maybe even a third image with the night appearance? So at dawn, the images are blended, which gives all the freedom for a night image.

victor_18993

Thanks, this makes sense.

I agree that Makeobj should not try to guess antialiased special colours from the final RGB image. The better direction is to keep that information explicit in the artwork/export pipeline, for example with separate masks/layers for player colours and lights.

I'm going to prototype that approach for XR32, while keeping legacy paksets fully compatible. I'll also look at the optional separate night image idea as a possible second step.

Thanks for the feedback — it matches very well with what the tests were already showing.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

Hi everyone,

I've published a new public testing build of the 32-bit renderer work:

Revised-11 testing-1
https://github.com/Dkijas/simutrans-true32-renderer/releases/tag/rgba32-revised-11-r12322-testing-1

This version is mainly about solving one of the trickiest parts of the 32-bit work: special colours around anti-aliased edges.

Until now, we were trying to infer things such as player colours and lights from the final rendered image. That works in simple cases, but starts to become unreliable once Blender, anti-aliasing and semi-transparent edge pixels are involved.

Revised-11 changes the approach.

Instead of asking Makeobj to guess the meaning of those pixels, the artwork can now provide the visual image and the semantic information separately.

That gives us a much cleaner pipeline for things such as:

- player/company colours
- lights
- multiple lights affecting the same pixel
- anti-aliased edges
- linear-light composition
- normal RGBA transparency

The important part is that this does not replace the normal image. The visible artwork stays exactly that: the artwork. The extra data simply tells Simutrans what some pixels mean.

For artists, the public test kit includes simple examples for manual 2D work and Blender, so you can see how the idea works without needing the internal test material I used during development.

Compatibility has also been an important part of this work.

Old pak files continue to work with the revised renderer, and the existing old test paks are unchanged. I also tested the new semantic paks with the older builds that were actually part of the compatibility tests.

Windows and Linux Makeobj builds generate the same pak bytes, and the renderer results match between the tested Windows and Linux builds.

There is one known performance issue in testing-1:

For 32-bit images without semantic masks, rebuilding the zoom cache is currently around 10–12% slower than revised-10. This happens when the zoom level changes, not every frame during normal gameplay.

I already have that isolated as a separate optimisation task, so I decided not to delay this testing build or mix an untested optimisation into it. If the fix is good, it can go into testing-2.

A few other notes:

- macOS and Android have not been runtime-tested for this version.
- The Blender exporter changes are still prototype patches, not yet part of the published Blender Kit.
- Object Studio can validate semantic masks, but it does not yet have a full editing UI for them.
- The Renfe S453 artwork I used for some internal accuracy tests is not included in the release.

At this point I'd really like feedback from pakset artists and testers.

In particular, I'm interested in whether this workflow feels understandable from an artist's point of view, and whether you see any visual regressions with existing paksets.

If you test it, please mention your OS, build used, pakset and what you were testing. Screenshots are very welcome if something looks wrong.

Thanks again to everyone who commented on the earlier versions. The move away from colour-guessing and toward explicit semantic data came directly from those discussions, and I think revised-11 is a much stronger direction because of it.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

Do you mean a mask per each player color? I think using the old player colors at (maybe 15%) PC0 TO (80%) PC7 and similar for the second player color. This way, the colors would stay the same for 16 bit and 32 bit paks, as surely users would (and should) be able to mix paks visially.

When talking about blender, rendering night images would be rather trivial and remove the need for special night colors althougether, allowing for an easy automated work flow. And even for handdrawn paks, adding a nigh image can easily done using the base image and then enabling all kind on night effects.

Not everyone uses blender, especially the Japanese community uses pixels a lot. Having so many extra maps woudl be prone to errors. But a single extra night map seems rather straight forward.

And for paks without night images or old paks, night images could be generated on load time, leading to unified handling of the night for all images, leaving only the player colors for special treatment.

So something like
Image[...]=IMG.a.b[,x,y][;Night-IMG.a.b[,x,y]|-][;PC1-IMG.a.b,x,y|-][;PC2-IMG.a.b,x,y]shoudl be even manageable for handdrawn images and give even more flexibility.

victor_18993

Quote from: prissi on Today at 09:46:58 AMDo you mean a mask per each player color? I think using the old player colors at (maybe 15%) PC0 TO (80%) PC7 and similar for the second player color. This way, the colors would stay the same for 16 bit and 32 bit paks, as surely users would (and should) be able to mix paks visially.
When talking about blender, rendering night images would be rather trivial and remove the need for special night colors althougether, allowing for an easy automated work flow. And even for handdrawn paks, adding a nigh image can easily done using the base image and then enabling all kind on night effects.
Not everyone uses blender, especially the Japanese community uses pixels a lot. Having so many extra maps woudl be prone to errors. But a single extra night map seems rather straight forward.
And for paks without night images or old paks, night images could be generated on load time, leading to unified handling of the night for all images, leaving only the player colors for special treatment.
So something like
Image[...]=IMG.a.b[,x,y][;Night-IMG.a.b[,x,y]|-][;PC1-IMG.a.b,x,y|-][;PC2-IMG.a.b,x,y]shoudl be even manageable for handdrawn images and give even more flexibility.
Thanks, I think I understand the direction you mean now.

For player colours, yes: my current prototype stores explicit semantic information rather than trying to recover the player colour from the final anti-aliased RGB pixels. Keeping the traditional PC0–PC7 / second-player colour behaviour also sounds important to me, especially so that 16-bit and 32-bit objects can still be mixed without looking inconsistent.

Your night-image suggestion is particularly interesting.

If I understand it correctly, instead of carrying increasingly complex semantic information for lights, a 32-bit object could optionally provide:

- the normal/day image,
- a night image,
- and player-colour information.

For older paks, or objects without a night image, Simutrans could generate the night representation at load time using the traditional behaviour.

That would give the renderer a much more uniform model while also making the Blender workflow considerably simpler, since the artist can simply render the actual night appearance instead of encoding every light semantically.

It also seems much friendlier for hand-drawn graphics than having several different semantic maps.

I don't want to change revised-11 now that the testing build is published, but I think this is worth investigating as the next architecture step.

I'll make a small isolated prototype and compare the two approaches, particularly memory/pak size, day/night transitions, old-pak compatibility, player colours and the manual pixel-art workflow before proposing anything for trunk.

Thanks — this is exactly the kind of feedback I was hoping to get from the testing release.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Quote from: victor_18993 on Today at 10:00:07 AMYour night-image suggestion is particularly interesting.
The question that arises for me is: Can i create a night image from a day image, using GIMP for example, in the same way Simutrans does?
Adding lighting effects to a night image in GIMP is easy. Where I see a problem is in achieving a consistent map at night when using night images from various sources—old ones, new ones, or ones from a different pakset.


victor_18993

QuoteQuote from: makie on 4/10/2026, 12:29:13
I miss a compiled makeobj.

I'm uploading the compiled version of Makeobj now, I'll let you know, 


cheers.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

Hi prissi,

I finished the public testing build of the DAY + optional NIGHT prototype based on revised-11:

https://github.com/Dkijas/simutrans-true32-renderer/releases/tag/xr32-prissi-night-image-prototype-01-r12322-testing-1

The short version is: your idea works well, but the measurements point to a hybrid approach rather than replacing the legacy path.

For new XR32 content:
- DAY + optional NIGHT works well;
- traditional player colours are preserved;
- the legacy dusk transition can be matched correctly;
- artists gain much more freedom for lights and night effects.

For old content:
- keeping the existing legacy path is clearly better;
- generating NIGHT images at load time is too expensive in memory and cache rebuild time.

The current measured cost for native DAY/NIGHT content is roughly:
- +75–93% XR32 image memory
- +20–47% cache rebuild cost
- +2–12% pak size
- no measurable per-frame difference in the tests

I also published makeobj for Windows and Linux x86_64, and both produce byte-identical test paks.

Before taking this any further, I think there are three design decisions worth discussing:

1. image identity / merging, because the current merge logic can associate the wrong extra XR32 data;
2. whether the extra NIGHT image memory cost is acceptable;
3. whether the pak format should use an explicit marker rather than relying on filename syntax.

So I would treat this as a public architecture prototype for discussion, not as revised-12 yet.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)