Skip to content

feat(texturefilter): Extend texture filtering to support; none, point, bilinear, trilinear and anisotropic filtering#2423

Merged
xezon merged 2 commits intoTheSuperHackers:mainfrom
Mauller:Mauller/feat-improve-filtering-support
Mar 18, 2026
Merged

feat(texturefilter): Extend texture filtering to support; none, point, bilinear, trilinear and anisotropic filtering#2423
xezon merged 2 commits intoTheSuperHackers:mainfrom
Mauller:Mauller/feat-improve-filtering-support

Conversation

@Mauller
Copy link

@Mauller Mauller commented Mar 8, 2026

merge by rebase

This PR cleans up the texture filtering class and extends its functionality.

This can be squash merged, i seperated it into commits to make it easier to follow the changes when reviewing.

By default the game was stuck with Bilinear filtering, as they never added options to allow texture filtering to be altered within the game. This PR cleans up the original code and extends the support for more filtering modes.

At the moment this does nothing new. we still need to add the external code to set a different filtering mode, so the game still defaults to bilinear mode.

But now we have the following modes:

No filtering - Point filtering when minifying or maximising textures, mipmaps have no filtering
Point Filtering - The same as no filtering but mip maps now have point filtering
Bilinear - Default, Minifying and maximising now has linear filtering, mipmaps retain point filtering
Trilinear - The same as Bilinear but mipmaps now gain linear filtering
Anisotropic - Minifying and maximising now has anisotropic filtering and mip maps retain linear filtering.

Anisotropic filtering is defaulted to 2x which is the minimum and has a new static function to change the filtering mode.


If you want to test the changes, alter the int WW3D::TextureFilter variable in ww3d.cpp

@Mauller Mauller self-assigned this Mar 8, 2026
@Mauller Mauller added Enhancement Is new feature or request Gen Relates to Generals ZH Relates to Zero Hour labels Mar 8, 2026
@greptile-apps
Copy link

greptile-apps bot commented Mar 8, 2026

Greptile Summary

This PR refactors TextureFilterClass::_Init_Filters to support five explicit texture filtering modes — None, Point, Bilinear, Trilinear, and Anisotropic — replacing the old #ifdef _XBOX / non-Xbox split with a clean switch-based dispatch. A new _Set_Max_Anisotropy helper and AnisotropicFilterMode enum (2×–16×) provide the infrastructure for future UI-driven filter selection. Both ww3d.cpp variants correctly update the TextureFilter default from the magic literal 0 to the named TEXTURE_FILTER_BILINEAR constant, which is important because two new enum entries were prepended.

Key changes:

  • Old FILTER_TYPE_BEST pre-initialization (anisotropic defaults) is always overridden by the switch, so it serves only as a belt-and-suspenders safe default.
  • Hardware capability checks now gate each filter level individually (linear for bilinear/trilinear, anisotropic for anisotropic) with graceful point-filter fallbacks.
  • Stage propagation loop simplified from [i-1] source references to a direct [0] source, which is cleaner and avoids an implicit assumption that all stages were set in order.
  • D3DTSS_MAXANISOTROPY is now only written when anisotropic mode is actually selected, rather than unconditionally for every stage on every _Init_Filters call.

Confidence Score: 4/5

  • Safe to merge — no functional regressions introduced; the new infrastructure is dormant until an external caller is wired up.
  • The logic is sound and all hardware capability fallback paths are handled. The only deductions are minor: data-oriented init blocks are not column-aligned per project style, and the new _Set_Max_Anisotropy loop omits braces inconsistently with the rest of the file. No runtime bugs or security issues were found.
  • No files require special attention, though the style suggestions in texturefilter.cpp are worth a quick pass before merge.

Important Files Changed

Filename Overview
Core/Libraries/Source/WWVegas/WW3D2/texturefilter.cpp Major refactor replacing #ifdef Xbox/non-Xbox split with a clean switch-based dispatch for five filter modes; logic and hardware capability fallbacks are correct, _Set_Max_Anisotropy helper extracted cleanly, and stage propagation loop simplified from [i-1] to [0] references.
Core/Libraries/Source/WWVegas/WW3D2/texturefilter.h Adds TEXTURE_FILTER_NONE and TEXTURE_FILTER_POINT to TextureFilterMode enum and introduces a new AnisotropicFilterMode enum with 2×/4×/8×/16× levels; #pragma once is already present, public API surface is clean.
Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp Default TextureFilter initialization changed from the magic literal 0 to the named TEXTURE_FILTER_BILINEAR enum constant, which is the correct value now that the enum has two new leading entries.
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp Same single-line fix as its Generals counterpart — default TextureFilter updated from 0 to the named TEXTURE_FILTER_BILINEAR constant.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[_Init_Filters called with filter_type] --> B[Pre-init stage 0\nFILTER_TYPE_NONE = POINT\nFILTER_TYPE_FAST = LINEAR bilinear\nFILTER_TYPE_BEST = ANISOTROPIC]

    B --> SW{switch filter_type}

    SW -- default --> DEF[DEBUG_CRASH\nFALLTHROUGH]
    DEF --> NONE

    SW -- TEXTURE_FILTER_NONE --> NONE[FAST = POINT / mip NONE\nBEST = POINT / mip NONE]
    SW -- TEXTURE_FILTER_POINT --> POINT[FAST = POINT / mip POINT\nBEST = POINT / mip POINT]

    SW -- TEXTURE_FILTER_BILINEAR --> BIL_CAP{Caps: MINFLINEAR\n& MAGFLINEAR?}
    BIL_CAP -- Yes --> BIL_OK[BEST = LINEAR / mip POINT]
    BIL_CAP -- No --> BIL_FB[BEST = POINT / mip POINT]

    SW -- TEXTURE_FILTER_TRILINEAR --> TRI_CAP{Caps: MINFLINEAR\n& MAGFLINEAR?}
    TRI_CAP -- Yes --> TRI_LIN[BEST min/mag = LINEAR]
    TRI_CAP -- No --> TRI_PT[BEST min/mag = POINT]
    TRI_LIN & TRI_PT --> TRI_MIP{Caps: MIPFLINEAR?}
    TRI_MIP -- Yes --> TRI_OK[mip = LINEAR]
    TRI_MIP -- No --> TRI_FB[mip = POINT\nbecomes Bilinear]

    SW -- TEXTURE_FILTER_ANISOTROPIC --> ANI_CAP{Caps: MAGFANISO\n& MINFANISO?}
    ANI_CAP -- Yes --> ANI_OK[BEST = ANISOTROPIC\n_Set_Max_Anisotropy 2X]
    ANI_CAP -- No --> ANI_FB[BEST = POINT]
    ANI_OK & ANI_FB --> ANI_MIP{Caps: MIPFLINEAR?}
    ANI_MIP -- Yes --> ANI_LIN[mip = LINEAR]
    ANI_MIP -- No --> ANI_PT[mip = POINT]

    NONE & POINT & BIL_OK & BIL_FB & TRI_OK & TRI_FB & ANI_LIN & ANI_PT --> PROP

    PROP[Propagate stage 0 values\nto stages 1..MAX_TEXTURE_STAGES\nAniso stages -> LINEAR fallback]
    PROP --> DEF2[Set FILTER_TYPE_DEFAULT = FILTER_TYPE_BEST\nfor all stages]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: Core/Libraries/Source/WWVegas/WW3D2/texturefilter.cpp
Line: 107-120

Comment:
**Column alignment in data-oriented init blocks**

These three groups are data-oriented initialization blocks that the project style guide asks to be column-aligned for readability. The `=` signs should be aligned within each block. The same pattern recurs throughout the new switch cases (e.g. `TEXTURE_FILTER_NONE`, `TEXTURE_FILTER_POINT`, etc.).

```suggestion
	// TheSuperHackers @info Init zero stage filter defaults, point filtering is the lowest type for non mip filtering
	_MinTextureFilters[0][FILTER_TYPE_NONE] = D3DTEXF_POINT;
	_MagTextureFilters[0][FILTER_TYPE_NONE] = D3DTEXF_POINT;
	_MipMapFilters[0][FILTER_TYPE_NONE]     = D3DTEXF_NONE;

	// Bilinear
	_MinTextureFilters[0][FILTER_TYPE_FAST] = D3DTEXF_LINEAR;
	_MagTextureFilters[0][FILTER_TYPE_FAST] = D3DTEXF_LINEAR;
	_MipMapFilters[0][FILTER_TYPE_FAST]     = D3DTEXF_POINT;

	// Anisotropic - MipMap interlayer filtering only goes up to linear
	_MinTextureFilters[0][FILTER_TYPE_BEST] = D3DTEXF_ANISOTROPIC;
	_MagTextureFilters[0][FILTER_TYPE_BEST] = D3DTEXF_ANISOTROPIC;
	_MipMapFilters[0][FILTER_TYPE_BEST]     = D3DTEXF_LINEAR;
```

The same alignment applies to the equivalent blocks inside each switch case.

**Rule Used:** Align columns in data-oriented blocks (like lookup... ([source](https://app.greptile.com/review/custom-context?memory=e61e83cf-a14f-4759-bed8-3bab008b25b5))

**Learnt From**
[TheSuperHackers/GeneralsGameCode#2067](https://github.com/TheSuperHackers/GeneralsGameCode/pull/2067#discussion_r2704192059)

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: Core/Libraries/Source/WWVegas/WW3D2/texturefilter.cpp
Line: 280-284

Comment:
**`for` loop body should use braces**

Every other loop in this file wraps its body in braces (see the stage-propagation loop at line 225 and the `_Set_Default_*` helpers). Adding braces here keeps the style consistent and allows a precise debugger breakpoint on the body line.

```suggestion
	for (int stage = 0; stage < MAX_TEXTURE_STAGES; ++stage) {
		DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAXANISOTROPY, mode);
	}
```

**Rule Used:** Always place if/else/for/while statement bodies on... ([source](https://app.greptile.com/review/custom-context?memory=16b9b669-b823-49be-ba5b-2bd30ff3ba6d))

**Learnt From**
[TheSuperHackers/GeneralsGameCode#2067](https://github.com/TheSuperHackers/GeneralsGameCode/pull/2067#discussion_r2706274626)

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "feat(texturefilter):..."

@Mauller Mauller force-pushed the Mauller/feat-improve-filtering-support branch 2 times, most recently from 67a9d46 to 57753f7 Compare March 8, 2026 12:39
@Mauller Mauller force-pushed the Mauller/feat-improve-filtering-support branch from 57753f7 to 2df4a8a Compare March 8, 2026 12:57
@xezon xezon changed the title feat(texturefilter): Extend texture filtering to support; none, point, bilinear, trilinear and anisitropic filtering feat(texturefilter): Extend texture filtering to support; none, point, bilinear, trilinear and anisotropic filtering Mar 17, 2026
Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

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

Reviewing the individual commits was certainly easier than the combined blob. Can we perhaps have 2 commits, one just for refactors and the other for the improvements? Would that make a clean and easy diff?

Also, can we then set the Anisotropic filtering for our new Very High graphics setting?

@Mauller
Copy link
Author

Mauller commented Mar 17, 2026

Reviewing the individual commits was certainly easier than the combined blob. Can we perhaps have 2 commits, one just for refactors and the other for the improvements? Would that make a clean and easy diff?

Also, can we then set the Anisotropic filtering for our new Very High graphics setting?

I was considering this to just be squash merged, but i can look at squashing all the cleanup into a chore commit then the feature into a feat commit.

Yes we can set the defaults for the options to whatever we want for these filtering modes.
We will need to get the options.ini code plumbed in first then the game options defaults can be tweaked to set the filtering modes too.

@Mauller Mauller force-pushed the Mauller/feat-improve-filtering-support branch 2 times, most recently from 6894a9e to 561b981 Compare March 18, 2026 18:23
@Mauller
Copy link
Author

Mauller commented Mar 18, 2026

Just a rebase before i condense the commits

@Mauller Mauller force-pushed the Mauller/feat-improve-filtering-support branch from 561b981 to c470563 Compare March 18, 2026 18:36
@Mauller
Copy link
Author

Mauller commented Mar 18, 2026

Updated the commits for a cleaner merge by rebase

@xezon xezon merged commit 8bf736a into TheSuperHackers:main Mar 18, 2026
23 checks passed
@xezon xezon deleted the Mauller/feat-improve-filtering-support branch March 18, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Is new feature or request Gen Relates to Generals ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants