News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

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 1 Guest are viewing this topic.

victor_18993

I have been working on a new 32-bit graphics renderer for Simutrans Standard.

The goal is to modernize the graphics pipeline while keeping compatibility with the existing game and current paksets. Existing 16-bit graphics still work as they do today, but the new renderer can use full 32-bit colour internally, giving us much more room for better shading, transparency, lighting and future higher-quality graphics.

The project is still under development and has NOT been integrated into SVN.

The current version already runs with GDI, SDL2 and SDL3 and has been tested with pak64, pak128 and pak192.comic. The classic 16-bit renderer is still preserved as well.

I have published the current development version here so that anyone interested can review the code, screenshots, documentation and validation results:


https://github.com/Dkijas/simutrans-true32-renderer

The repository also contains the patch against the current development base, build instructions and technical notes.

At this stage I would especially appreciate feedback from maintainers, developers and anyone interested in the graphics side of Simutrans.

There is still work to do before any possible integration into the official trunk, so for now this should be considered a public work-in-progress and review project.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

I've now been able to reproduce and isolate this properly.
There were actually two separate Windows GDI issues involved: one in resize-event delivery, and another where
WindowSize mixed logical and physical pixels when Windows scaling was above 100%.
Both now have tested candidate fixes. I've verified them at 150% scaling with resize, maximize and restore, and the original corruption no longer appears.
I've published the fixes and the test evidence in the public lab repository for review:
https://github.com/Dkijas/simutrans-true32-renderer
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Great,
that's what I've been waiting for—I'm I am scraping with my feet.

Is there a version of makeobj yet that handles 32-bit graphics?

victor_18993

Hi Makie, for now we first need to agree that this renderer is what is wanted—a 32-bit renderer that is backwards-compatible with 16-bit so we don't break existing add-ons (this is essential). The architecture is already designed and I'm still testing, looking for potential bugs.

Then there would be the community discussion to see if the proposal is suitable for Standard.

Don't worry, Makeobj will definitely have to be updated to a version that supports both the future and current formats. As soon as the scope is finalized, I will present the Makeobj proposal.

I know you're very eager for this leap to 32-bit without image compression, but it's important that it's finalized properly. The Japanese community is also waiting for this to be settled, from what I've talked with them, since they would likely handle the port to OTRP and I would do the port adapted for Extended so James can review it.

My idea is for this project to be cross-cutting, just like SDL3 was, which has been quickly incorporated into OTRP and Extended.

Thank you very much for the comment, and I would really appreciate hearing what you artists expect from a real leap to 32-bit without image compression.
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 September 06, 2026, 08:16:29 AMand I would really appreciate hearing what you artists expect from a real leap to 32-bit without image compression.
It s not a image compression it is a lost of color information. Color gradients become stepwise. That can be mask with dithering, but then there is a lost of resolution and sharpness. The graphics are becoming crumbly.

In pak128.german all graphics are available as 32/24-bit graphics.
All i have to do is use a 32bit capable makeobj and run over the thousands of graphics and the map should be softer and the colors more nuanced.
Just how clearly visible that becomes—and whether the effort is worth it—can only be seen in a real test.

pak192.comic will not benefit, i think.
But pak128 and pak128.german should look much more better.
pak64 has too few pixels, so no significant differences are to be expected.

victor_18993

That's great if you have all the images because you can migrate quickly; I framed it as a system that will allow coexistence.

Yes, exactly, I misspoke—it's not image compression, it's how it's processed in Makeobj and then displayed by the renderer in Simutrans. This project is indeed about that: not losing detail, being able to implement shadows and depth, and adding more detail to the graphics.

Ultimately, for me it's not just about improving the graphics and giving Simutrans a bit of a visual refresh for the user, but also about providing a better tool for everyone making add-ons—so what you're already creating in 32-bit is displayed in Simutrans with depth, shadows, and details that we can't offer today with the current renderer.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

poppo

In my opinion, we need to decide how to treat special colors for 24bit colors.

Player color has only 8 variations of brightness, and we can only set the player color from about 28 colors.
The number of special colors are too less, with the 24bit well-resolution graphic.
(And more, we also need to check the variation and how to define light colors in the night)

24bits (32bits) is not hard task for pak makers because most image editing software supports 24(32) bits PNG file.

victor_18993

Poppo, I think that's one of the issues to address. I'd like to have the input of Prissi and the rest of the maintainers to get a broader view.


Thank you very much for your contribution.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Quote from: poppo on September 06, 2026, 09:19:28 AMIn my opinion, we need to decide how to treat special colors for 24bit colors.
Look at this discussion:
https://forum.simutrans.com/index.php/topic,23978.msg213136.html
More special colors lead to many lighting pixel in old graphics.
Who has fought against glowing ghost pixels knows, this is a real nuisance.
All the old PNG files would then have to be reworked.

A good solution is a mask graphic specified separately.
Then at least 24 bits are available for all all kinds of special colors.
And if a mask graphic is specified then the old special colors should be ignored.


victor_18993

QuoteLook at this discussion:
https://forum.simutrans.com/index.php/topic,23978.msg213136.html
More special colors lead to many lighting pixel in old graphics.
Who has fought against glowing ghost pixels knows, this is a real nuisance.
All the old PNG files would then have to be reworked.

A good solution is a mask graphic specified separately.
Then at least 24 bits are available for all all kinds of special colors.
And if a mask graphic is specified then the old special colors should be ignored.



I'm already looking into evolving MakeObj so the prototype can be used for testing; this might help serve as a testing platform to unblock agreement on the special color specifications, for example, or test how the graphics look.

I'll let you know as soon as I update the repository.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

A small update on the RGBA32 / true32 work.

The project has moved forward quite a lot since the last update. The experimental runtime can now load the new XR32 image data while keeping the normal IMG data as a fallback, so old content and older Simutrans versions remain compatible.

The main pieces are now working together:
  • true RGBA32 rendering
  • legacy IMG fallback
  • player colours and special colour semantics
  • day/night changes
  • transparency and antialiased semantic edges
  • native zoom for XR32 images
  • substantially reduced memory usage and first-draw/zoom costs

The native zoom was probably the hardest part. Player colours cannot simply be averaged when an image is scaled, so this needed a new runtime representation that keeps the different colour contributions separate. That design is now implemented and has passed the current pixel-level validation without mismatches.

We have now consolidated the work into a single candidate and are cleaning the remaining laboratory code. It is still experimental and not yet an SVN candidate: there is one runtime path that still needs explicit test coverage, and broader compiler/platform testing is still pending. Makeobj production integration will also come later.

Once the current cleanup is complete, I think we have accumulated enough progress to publish a new laboratory GitHub pre-release, so people can start testing it with real saves, paksets and hardware while we continue preparing the eventual Standard candidate.

So the project has moved from "can true 32-bit graphics work in Simutrans?" to mainly "is the implementation clean, sufficiently covered and portable enough for upstream review?"
I'll keep posting updates as those last stages are completed.



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

victor_18993

[Experimental] True 32-bit (ARGB8888) renderer - Windows test build, feedback wanted

An experimental prototype of a true 32-bit ARGB8888 screen renderer for Simutrans
Standard is available for testing. It is NOT integrated into Standard, it is not an
official release, and it is not a stable version.

Download (Windows x86_64, SDL2):
https://github.com/Dkijas/simutrans-true32-renderer/releases/tag/rgba32-revised-4-r12261-testing-1

What it does: the screen framebuffer and the per-player image caches become ARGB8888
instead of RGB565, so day/night shading, transparency, blending, player colours,
outlines and zoom filtering work with 8 bits per channel instead of 5/6/5. Pakset
image data, savegames and the network protocol are unchanged.

The archive contains two executables built from the same source tree:

    simutrans-rgba32.exe  the 32-bit renderer - the one to test
    simutrans-16bit.exe    the ordinary 16-bit renderer - for comparison

Comparing the two on the same world is the most useful thing you can do.

How to run it:

    1. Extract into a folder of its own, NOT over your normal installation.
    2. Copy in a pakset (pak64, pak128, ...). None is bundled - please use your own.
    3. Use COPIES of any savegames you try.
    4. Run:  simutrans-rgba32.exe -singleuser
      -singleuser keeps settings, saves and screenshots inside that folder
      instead of your Documents\Simutrans.

What would help most:

    - zoom: scroll over a large map at every zoom level, watching tile edges
    - info windows: tile, station, convoy, depot, line - especially at zoom
      levels other than the default one
    - transparency: underground view, cursors, transparent building mode
    - player colours with more than one player, and day/night transitions
    - long sessions, an hour or more on a busy map
    - save and reload, compared against simutrans-16bit.exe on the same save

A note on XR32: the build can read an optional extra node in a pak file, but no
public pakset contains one and the makeobj that would write them is not part of
this candidate. Your usual paksets bring no new XR32 content, so there is no XR32
visual improvement to look for here. Testing the 32-bit renderer with ordinary
paksets is the useful test.

Reporting: https://github.com/Dkijas/simutrans-true32-renderer/issues
There is a "Bug / regression" template. Please include the pakset and version, your
Windows version, the steps from a fresh start, and - this matters more than usual,
because most of the changed code is clipping and zoom - the zoom level and which
window was open. A screenshot and a minimal savegame help.

This is a candidate, not a proposal to merge. It can and probably will change based
on what testing and the discussion here turn up.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

I had a look at the code. It seems, the only difference is the output being 32 bit, but the images pixels still RBG565 bit? It's a bit lost in the include files.

For 32 bit, I think the darkening needs to be handled in the images on the fly with lazy caching, like zoom, and not using lookup tables which are impractically large compared to cache size. With 16 bit 128kB, bit with 4*(2^24) => 64MB, not fitting most caches anymore and thus almost slower than a calculation. Moreover, modern processor have a lot of parallel bytewise operations, so bytewise darkening could be very optimised by the compiler. If all fails, one could use a 256 bit table for darkening one channel after the other, but that sounds again slow (It will fit in the Level 1 cache ...)


makie

Quote from: prissi on Today at 03:55:56 AMFor 32 bit, I think the darkening needs to be handled in the images on the fly with lazy caching, like zoom, and not using lookup tables which are impractically large compared to cache size. With 16 bit 128kB, bit with 4*(2^24) => 64MB, not fitting most caches anymore and thus almost slower than a calculation. Moreover, modern processor have a lot of parallel bytewise operations, so bytewise darkening could be very optimised by the compiler. If all fails, one could use a 256 bit table for darkening one channel after the other, but that sounds again slow (It will fit in the Level 1 cache ...)
Why was darkening handled via a lookup table in 16-bit colors? Presumably to avoid having to check for each of for the various special colors.

Darkening itself is very simple isn't it? Just simply subtract a value from each color. Arithmetic operations on modern CPUs are very fast, whereas memory accesses are slow.

In the future, we want to have even more special colors. These should be encoded in a separate graphic plane.

The question is: is there a need for handling a special color for this pixel? Is there a special color at this tile at all? If no then do darkening with subtraction.

QuoteIf all fails, one could use a 256 bit table for darkening one channel after the other, but that sounds again slow (It will fit in the Level 1 cache ...)
That doesn't work. To identify a special color, all three colors must be compared.

From my point of view, the old-style special colors should be separated into a own graphics layer during loading. That is necessary for 32-bit colors anyway.

Edit supplement:

If there is a wish for a lookup table, then the index should be a program internal sequential number, so that the table keep small and convert all spezial colors in this index. That would also keep the graphics layer for special colors small.
------
I don't have Windows, only Linux.