Skip to content

bugfix: Render ground-aligned particles without sorting#2838

Open
stephanmeesters wants to merge 4 commits into
TheSuperHackers:mainfrom
stephanmeesters:perf/ground-aligned-particles-nosort
Open

bugfix: Render ground-aligned particles without sorting#2838
stephanmeesters wants to merge 4 commits into
TheSuperHackers:mainfrom
stephanmeesters:perf/ground-aligned-particles-nosort

Conversation

@stephanmeesters

@stephanmeesters stephanmeesters commented Jun 28, 2026

Copy link
Copy Markdown

A performance gain (about 8%) could be achieved in a busy scene, see animated gif below, by not sorting particles that are "ground-aligned". (tested in release mode, windowed, stats averaged in 60 secs window)

The reasoning is that ground-aligned particles generally do not have much benefit from back to front sorting, as they are effectively on the ground with nothing behind them, and other nearby ground-aligned particles are at about the same height.

In testing this actually appeared to resolve some rendering issues as ground particles would sometimes cut into nearby particles leaving hard edges (see the before image).

sorting-renderer.webm

Todo

  • Do some more testing, in campaign etc

@greptile-apps

greptile-apps Bot commented Jun 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR skips back-to-front sorting for ground-aligned (non-billboard) particles in PointGroupClass::Render, delivering an ~8% performance gain in busy scenes and eliminating hard-edge blending artifacts where ground particles clipped into billboards. RenderVolumeParticle is intentionally left unchanged; a new @info comment explains the rationale for keeping sorting active there.

  • Render() fixBillboard && is prepended to the sort condition so non-billboard particles always bypass the sorting index buffer, removing both the sort overhead and the artifact-causing depth-ordering conflict with billboard particles.
  • RenderVolumeParticle() unchanged — sorting is retained for volumetric particles (billboard and ground-aligned alike), with a comment asserting that stacked layers require correct ordering for accurate alpha-blending; this is the subject of an ongoing discussion thread.

Confidence Score: 4/5

The Render() change is safe to merge — the Billboard guard is a straightforward, well-tested condition that only affects the index buffer selection for ground-aligned particles.

The core fix in Render() is clean and the author has done broad testing including campaign mode. The only open question — whether ground-aligned volumetric particles in RenderVolumeParticle also benefit from skipping sorting — is actively being discussed in an existing thread and remains unresolved, which warrants a small amount of caution before merging.

Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp — specifically the sort condition inside the RenderVolumeParticle depth loop, which is the subject of the ongoing review thread.

Important Files Changed

Filename Overview
Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp Adds Billboard && guard to sort condition in Render() — clean, well-justified change. RenderVolumeParticle() receives only a comment; the comment's assertion about ground-aligned volumetric layers is under active discussion in a previous thread.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PointGroupClass::Render] --> B{Billboard?}
    B -- false\nground-aligned --> C[sort = false\nskip sorting index buffer]
    B -- true\nbillboard --> D{Shader translucent?\nAlpha test disabled?\nSorting enabled?}
    D -- No --> C
    D -- Yes --> E[sort = true\nuse sorting index buffer]
    C --> F[Render with Quads/Tris]
    E --> G[Render with SortingQuads/SortingTris]

    H[PointGroupClass::RenderVolumeParticle\ndepth > 1] --> I{Shader translucent?\nAlpha test disabled?\nSorting enabled?}
    I -- No --> J[sort = false]
    I -- Yes --> K[sort = true\nBillboard AND ground-aligned]
    J --> L[Render layer with Quads/Tris]
    K --> M[Render layer with SortingQuads/SortingTris]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[PointGroupClass::Render] --> B{Billboard?}
    B -- false\nground-aligned --> C[sort = false\nskip sorting index buffer]
    B -- true\nbillboard --> D{Shader translucent?\nAlpha test disabled?\nSorting enabled?}
    D -- No --> C
    D -- Yes --> E[sort = true\nuse sorting index buffer]
    C --> F[Render with Quads/Tris]
    E --> G[Render with SortingQuads/SortingTris]

    H[PointGroupClass::RenderVolumeParticle\ndepth > 1] --> I{Shader translucent?\nAlpha test disabled?\nSorting enabled?}
    I -- No --> J[sort = false]
    I -- Yes --> K[sort = true\nBillboard AND ground-aligned]
    J --> L[Render layer with Quads/Tris]
    K --> M[Render layer with SortingQuads/SortingTris]
Loading

Reviews (7): Last reviewed commit: "Technical justification" | Re-trigger Greptile

@stephanmeesters stephanmeesters force-pushed the perf/ground-aligned-particles-nosort branch from fdcebaf to 45a97a7 Compare June 28, 2026 11:41
@stephanmeesters

Copy link
Copy Markdown
Author

@greptileai It should not apply to RenderVolumeParticle as these are layered particles that require sorting

@greptile-apps

greptile-apps Bot commented Jun 28, 2026

Copy link
Copy Markdown

The current PR diff only modifies Render(), so RenderVolumeParticle is unaffected — its sorting logic remains unchanged. However, your note raises an important concern for future maintainability: someone could mistakenly apply the same Billboard skip to RenderVolumeParticle to "keep parity," breaking layered particle rendering.

To guard against that, it would be worth adding a short comment in RenderVolumeParticle's sorting block explicitly documenting why the ground-aligned skip does NOT apply there. Can you point me to where RenderVolumeParticle computes its sort variable so I can suggest the right comment in context?

@xezon

xezon commented Jun 28, 2026

Copy link
Copy Markdown

In testing this actually appeared to resolve some rendering issues as ground particles would sometimes cut into nearby particles leaving hard edges

This is very nice. An annoying visual issue.

Does it now always fix this issue or does it depend on "random" sorting order?

@xezon xezon added Bug Something is not working right, typically is user facing Major Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Gen Relates to Generals ZH Relates to Zero Hour Rendering Is Rendering related labels Jun 28, 2026
Comment thread Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp Outdated
@stephanmeesters

Copy link
Copy Markdown
Author

Does it now always fix this issue or does it depend on "random" sorting order?

In theory, yes:

Particles do not write to the depth buffer (except for ALPHA_TEST particles), which means they do not clip through each other, unless you use a sorting renderer that sorts each triangle by Z and then draws them in order.

The sorted particles are drawn last in a frame so all of the ground-aligned particles should now appear behind the sorted particles.

The ground-aligned particles are now drawn in the order of how they are in the particle manager list so that should be consistent as well (no flickering etc).

(also, ALPHA_TEST particles are never sorted and are always billboarded.)

@xezon

xezon commented Jun 30, 2026

Copy link
Copy Markdown

Ok cool

@xezon xezon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tested. Looking good.

@xezon

xezon commented Jun 30, 2026

Copy link
Copy Markdown

The bot is complaining about RenderVolumeParticle

@stephanmeesters

Copy link
Copy Markdown
Author

Clarified the comment and changed from perf to bugfix as primary contribution, added an info comment to RenderVolumeParticle according to Greptile's suggestion

@stephanmeesters stephanmeesters changed the title perf: Render ground-aligned particles without sorting bugfix: Render ground-aligned particles without sorting Jun 30, 2026
Comment thread Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp Outdated
Comment thread Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp Outdated
@stephanmeesters stephanmeesters force-pushed the perf/ground-aligned-particles-nosort branch from 4e257f0 to f42e0d5 Compare July 1, 2026 10:55
Comment thread Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp
@stephanmeesters

Copy link
Copy Markdown
Author

Volume particles that are ground-aligned have the stack pointing straight up (it's called ground aligned but they are flat in XY plane), and billboarded volume particles I observed earlier also have visible stack layers, so these layers don't point straight at the camera in normal circumstances

@stephanmeesters stephanmeesters force-pushed the perf/ground-aligned-particles-nosort branch from 9878e85 to 0c4ff29 Compare July 1, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Gen Relates to Generals Major Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Rendering Is Rendering related ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants