Skip to content

perf: Render ground-aligned particles without sorting#2838

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

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

Conversation

@stephanmeesters

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 by prepending Billboard && to the sort condition in PointGroupClass::Render, yielding an ~8% performance gain in busy scenes and preventing hard-edge visual artifacts where ground particles cut into one another.

  • The sort condition in Render (line 933) is correctly updated to skip sorting when Billboard is false.
  • The identical sort condition inside RenderVolumeParticle (line 1845) was not updated, leaving that path sorting ground-aligned volume particles unnecessarily when rendered at depth > 1.

Confidence Score: 4/5

Safe to merge with one fix: the sort-skip optimization must also be applied to RenderVolumeParticle to keep both render paths consistent.

The optimization in Render is correct and well-reasoned. However, the identical sort condition in RenderVolumeParticle was not updated, so ground-aligned volume particles rendered at depth > 1 will still go through the sorting path — the opposite of the PR's intent. The fix is a one-line change mirroring what was done in Render.

pointgr.cpp — the RenderVolumeParticle function (line 1845) needs the same Billboard && guard applied to its sort condition.

Important Files Changed

Filename Overview
Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp Adds Billboard && guard to the sort condition in Render, skipping sorting for ground-aligned particles. The parallel sort condition in RenderVolumeParticle (line 1845) was not updated, leaving that path inconsistent with the new behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Particle Render Request] --> B{depth > 1?}
    B -- No --> C[Render]
    B -- Yes --> D[RenderVolumeParticle]

    C --> E{Billboard?}
    E -- No --> F[sort = false\nSkip sorting NEW]
    E -- Yes --> G{Translucent & sorting enabled?}
    G -- Yes --> H[sort = true\nSortingRenderer path]
    G -- No --> I[sort = false\nDirect draw path]

    D --> J{Billboard?}
    J -- No --> K[sort = still checks shader only\n Not updated]
    J -- Yes --> L{Translucent & sorting enabled?}
    L -- Yes --> M[sort = true\nSortingRenderer path]
    L -- No --> N[sort = false\nDirect draw path]
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[Particle Render Request] --> B{depth > 1?}
    B -- No --> C[Render]
    B -- Yes --> D[RenderVolumeParticle]

    C --> E{Billboard?}
    E -- No --> F[sort = false\nSkip sorting NEW]
    E -- Yes --> G{Translucent & sorting enabled?}
    G -- Yes --> H[sort = true\nSortingRenderer path]
    G -- No --> I[sort = false\nDirect draw path]

    D --> J{Billboard?}
    J -- No --> K[sort = still checks shader only\n Not updated]
    J -- Yes --> L{Translucent & sorting enabled?}
    L -- Yes --> M[sort = true\nSortingRenderer path]
    L -- No --> N[sort = false\nDirect draw path]
Loading

Comments Outside Diff (2)

  1. Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp, line 1844-1845 (link)

    P1 Incomplete optimization in RenderVolumeParticle

    The sort condition in RenderVolumeParticle (line 1845) was not updated with the Billboard && guard introduced in Render. Any ground-aligned (non-billboard) volume particles with depth > 1 will still be sorted, since RenderVolumeParticle only delegates to Render when depth <= 1. The two code paths will diverge in behavior for the same particle emitter depending on the depth setting.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp
    Line: 1844-1845
    
    Comment:
    **Incomplete optimization in `RenderVolumeParticle`**
    
    The `sort` condition in `RenderVolumeParticle` (line 1845) was not updated with the `Billboard &&` guard introduced in `Render`. Any ground-aligned (non-billboard) volume particles with `depth > 1` will still be sorted, since `RenderVolumeParticle` only delegates to `Render` when `depth <= 1`. The two code paths will diverge in behavior for the same particle emitter depending on the depth setting.
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp, line 1840-1845 (link)

    P1 The same Billboard && guard should be applied here to keep RenderVolumeParticle consistent with the updated Render path.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp
    Line: 1840-1845
    
    Comment:
    The same `Billboard &&` guard should be applied here to keep `RenderVolumeParticle` consistent with the updated `Render` path.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp:1844-1845
**Incomplete optimization in `RenderVolumeParticle`**

The `sort` condition in `RenderVolumeParticle` (line 1845) was not updated with the `Billboard &&` guard introduced in `Render`. Any ground-aligned (non-billboard) volume particles with `depth > 1` will still be sorted, since `RenderVolumeParticle` only delegates to `Render` when `depth <= 1`. The two code paths will diverge in behavior for the same particle emitter depending on the depth setting.

### Issue 2 of 2
Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp:1840-1845
The same `Billboard &&` guard should be applied here to keep `RenderVolumeParticle` consistent with the updated `Render` path.

```suggestion
		DX8Wrapper::Set_Material(PointMaterial);
		DX8Wrapper::Set_Shader(Shader);
		DX8Wrapper::Set_Texture(0,Texture);

		// Enable sorting if the primitives are translucent and alpha testing is not enabled.
		// However, do not apply sorting for ground-aligned (i.e. non-billboard) particles.
		// This is for performance reasons and because ground-aligned particles do not generally benefit from back-to-front sorting.
		const bool sort = Billboard &&
		                  Shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO &&
		                  Shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE &&
		                  WW3D::Is_Sorting_Enabled();
```

Reviews (3): Last reviewed commit: "perf: Render ground-aligned particles wi..." | 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?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant