riperiperi / FreeSO

Re-implementation of The Sims Online.
http://freeso.org
Mozilla Public License 2.0
836 stars 97 forks source link

Improve extreme color calculation for DXT compress #276

Closed kaetemi closed 11 months ago

kaetemi commented 11 months ago

Take average color, then use vector math to get the furthest color from the average, then again find the furthest color from the furthest color.

kaetemi commented 11 months ago

Both DXT1a and DXT5 tested and working.

Before: image

After: image

kaetemi commented 11 months ago

Slightly better with weighted colors for distance calculation.

image

riperiperi commented 11 months ago

Thanks for having a look at this issue. Two quick notes before I give it a review later (not at a pc for a while):

EDIT: looks like you fixed indentation after i wrote this message, but before it posted 🥴 i’ll take a look at the code when i can.

kaetemi commented 11 months ago

Previous code does one iteration and checks for both minimum and maximum in that pass in each color individually. (Which leads to completely incorrect color mixes when the endpoints are different colors. E.g. green to blue becomes black to cyan.)

New code does one iteration to find the average, one iteration to find the furthest, and another iteration to find the opposing endpoint.

Both then iterate again to find which of the 4 colors in the endpoint gradient is nearest to each pixel.

Agree a cache would be good eventually. Haven't noticed any performance drop, at least, and looks better. Could put a performance timer on it to verify.

kaetemi commented 11 months ago

Somehow faster on my machine. Ryzen 5 2600.

new code: Total time: 598ms Total blocks: 748286 Time per million blocks: 799ms

old code: Total time: 712ms Total blocks: 747132 Time per million blocks: 952ms

New code (second run): Total time: 641ms Total blocks: 746612 Time per million blocks: 858ms

Old code (second run): Total time: 780ms Total blocks: 754988 Time per million blocks: 1033ms

New code (third run): Total time: 747ms Total blocks: 773352 Time per million blocks: 965ms

Old code (third run): Total time: 851ms Total blocks: 778296 Time per million blocks: 1093ms

kaetemi commented 11 months ago

Alright, sounds good.

I don't believe the loops can be combined? The loop depends on the outcome of the previous loop.

On Sun, Dec 31, 2023, at 00:26, riperiperi wrote:

@.**** approved this pull request.

All around great work. I can merge without combining the loops if you don't have the time, just let me know.

In TSOClient/tso.common/Utils/TextureUtils.cs https://github.com/riperiperi/FreeSO/pull/276#discussion_r1438643889:

  • if (col.R > maxCol.R) maxCol.R = col.R;
  • if (col.G > maxCol.G) maxCol.G = col.G;
  • if (col.B > maxCol.B) maxCol.B = col.B;
  • // Find color furthest from average
  • int leftDist = 0;
  • int leftIdx = 0;
  • for (int i = 0; i < 16; i++)

This loop can be combined with the next one. That would skip duplicating the loop overhead, and let you do the fetch from block[i] into local variable once instead of (at least) twice.

— Reply to this email directly, view it on GitHub https://github.com/riperiperi/FreeSO/pull/276#pullrequestreview-1799569710, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMB77KSTTR42V47C6BSTJDYMA6D7AVCNFSM6AAAAABA4PS5J2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMYTOOJZGU3DSNZRGA. You are receiving this because you authored the thread.Message ID: @.***>

riperiperi commented 11 months ago

Ah, I misread it - thought left col wasn't used. Looks good to me then.