Skip to content

Fix alpha render ordering for glass - #5362

Open
FileEX wants to merge 2 commits into
multitheftauto:masterfrom
FileEX:bugfix/alpha-rendering-order
Open

Fix alpha render ordering for glass#5362
FileEX wants to merge 2 commits into
multitheftauto:masterfrom
FileEX:bugfix/alpha-rendering-order

Conversation

@FileEX

@FileEX FileEX commented Sep 11, 2026

Copy link
Copy Markdown
Member

This has been an annoying bug for years, making it impossible to create large glass windows in models. Instead, developers have been forced to use small windows (as tut explained in his guide) or render the glass as material line 3D through scripts.

Flags such as draw_last and no_zbuffer_write have not properly fixed this issue over the years, and the underlying bug has remained.

My investigation

More info The bug is caused by the way GTA handles its `m_alphaList`, which is the list that models with the `draw_last` flag are added to.

The list also contains vehicles and many other objects, such as vegetation and fences. It is sorted by distance, with the closest entities being rendered first. The problem is that the distance is calculated from the center of the entity (pivot point) to the camera. This causes issues with large glass windows.

For example, a vehicle may be visible behind a large glass window, but because the distance from the center of the glass window to the camera is greater than the distance from the vehicle to the camera, the vehicle is rendered before the glass. This results in the vehicle disappearing behind the glass.
image

The no_zbuffer_write flag can appear to help in this situation because the glass no longer occludes the vehicle. However, this causes the vehicle to be rendered completely in front of the glass, which looks bad
image.

Initial approach

Initially, I tried to fix the rendering order by changing how the distance is calculated. Instead of calculating the distance from the center of the entity, I calculated it from the closest point of its bounding box to the camera. This did actually work for vehicles, bushes... However, it caused a chain reaction of other rendering issues. It introduced problems with the map, buildings could disappear at the wrong time, lod models started flickering, and some models with broken bounding boxes were still rendered incorrectly.

Overall, this approach was unsuccessful.

Final approach

R* was apparently aware of these issues and introduced a separate rendering list specifically for the grasshouse object (3261): m_alphaReallyDrawLastList.

This list is rendered literally after the entire scene has been rendered. This allows things such as shadows/lights on the ground, and rendered grass to remain visible through the glass. Unfortunately, this functionality was hardcoded specifically for model ID 3261 instead of being exposed through a dedicated model flag.

This PR adds a custom draw_after_scene flag to engineSetModelFlag that allows models to be rendered through m_alphaReallyDrawLastList.

Additionally, to prevent similar ordering issues, the distance is calculated using the closest point of the entity's bounding box rather than its center.

This allows large glass windows to be rendered correctly without relying on no_zbuffer_write or script-based glass rendering.
Fixed #3124

Comparisons

More info BEFORE image image

AFTER
image
image

Additional issue

While working on this PR, I also found another bug where the glass becomes brighter/flickers when entering the fade-out phase. I will address this separately in another PR once this one has been merged.

Additionally, m_alphaReallyDrawLastList list has a capacity of 50 elements. PR #4786 will allow it to be expanded.

Tests
glass.zip

@FileEX FileEX added the bugfix Solution to a bug of any kind label Sep 11, 2026
Comment on lines +975 to +976
DWORD engine = *(DWORD*)0xC97B24;
auto fpSet = reinterpret_cast<BOOL(__cdecl*)(DWORD, void*)>(*(DWORD*)(engine + 0x20));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is temporary. It should be cleaned up in another PR, ideally by finishing the RwGlobals definitions.

Comment on lines +1032 to +1034
// TODO fix entity brightness flickering when entering fade out phase
// HookInstallCall(0x732BD7, (DWORD)RenderFadingAtomic); // CVisibilityPlugins::RenderEntity
// HookInstallCall(0x732BDE, (DWORD)RenderFadingClump); // CVisibilityPlugins::RenderEntity

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be fixed in a separate PR, as it requires overloading GetModelInfo to return CModelInfoSA based on the interface. I don't want to introduce too much into this PR and would rather keep the focus mainly on the bugfix.

FileEX

This comment was marked as resolved.

@guibzo

guibzo commented Sep 11, 2026

Copy link
Copy Markdown

does this potentially fixes issues like this? afaik its a pretty common problem that needed some scripting workarounds to work properly

Image

@FileEX

FileEX commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

does this potentially fixes issues like this? afaik its a pretty common problem that needed some scripting workarounds to work properly

Image

Probably

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Solution to a bug of any kind

Projects

None yet

Development

Successfully merging this pull request may close these issues.

alphaTransparent and "draw_last" flag doesn't change anything!

2 participants