Skip to content

Commit 2f630c9

Browse files
authored
Merge pull request #707 from zeux/gltf-rdo
gltfpack: Rebalance texture quality table
2 parents 5158851 + 79a9be9 commit 2f630c9

File tree

3 files changed

+86
-9
lines changed

3 files changed

+86
-9
lines changed

gltf/basisenc.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ struct BasisSettings
2626
};
2727

2828
static const BasisSettings kBasisSettings[10] = {
29-
{1, 1, 0, 1.5f},
30-
{1, 6, 0, 1.f},
31-
{1, 20, 1, 1.0f},
32-
{1, 50, 1, 0.75f},
33-
{1, 90, 1, 0.5f},
34-
{1, 128, 1, 0.4f},
35-
{1, 160, 1, 0.34f},
36-
{1, 192, 1, 0.29f}, // default
37-
{1, 224, 2, 0.26f},
29+
{1, 1, 0, 4.f},
30+
{1, 32, 0, 3.f},
31+
{1, 64, 1, 2.f},
32+
{1, 96, 1, 1.5f},
33+
{1, 128, 1, 1.f}, // quality arguments aligned with basisu defaults
34+
{1, 150, 1, 0.8f},
35+
{1, 170, 1, 0.6f},
36+
{1, 192, 1, 0.4f}, // gltfpack defaults
37+
{1, 224, 2, 0.2f},
3838
{1, 255, 2, 0.f},
3939
};
4040

tools/bitmask.py

100755100644
File mode changed.

tools/gltfbasis.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/python3
2+
3+
import argparse
4+
import concurrent.futures
5+
import matplotlib.pyplot as plt
6+
import os
7+
import os.path
8+
import re
9+
import subprocess
10+
11+
argp = argparse.ArgumentParser()
12+
argp.add_argument('--basisu', type=str, required=True)
13+
argp.add_argument('--graph', type=str, default="basisu.png")
14+
argp.add_argument('--etcbase', action='store_true')
15+
argp.add_argument('files', type=str, nargs='+')
16+
args = argp.parse_args()
17+
18+
def compress(path, flags):
19+
temp_path = "/dev/null" if os.name == "posix" else "NUL"
20+
output = subprocess.check_output([args.basisu, "-file", path, "-output_file", temp_path, "-stats", "-ktx2"] + flags)
21+
for line in output.splitlines():
22+
if m := re.match(r".*source image.*?(\d+)x(\d+)", line.decode()):
23+
pixels = int(m.group(1)) * int(m.group(2))
24+
elif m := re.match(r".*Compression succeeded.*size (\d+) bytes", line.decode()):
25+
bytes = int(m.group(1))
26+
elif m := re.match(r"\.basis RGB Avg:.*RMS: (\d+\.\d+) PSNR: (\d+\.\d+)", line.decode()):
27+
rms = float(m.group(1))
28+
psnr = float(m.group(2))
29+
30+
return {'path': path, 'bpp': bytes * 8 / pixels, 'rms': rms, 'psnr': psnr}
31+
32+
def stats(path):
33+
with concurrent.futures.ThreadPoolExecutor(16) as executor:
34+
futures = []
35+
for i in range(0, 26):
36+
rdo_l = i / 5
37+
flags = ["-uastc", "-uastc_level", "1", "-uastc_rdo_l", str(rdo_l), "-uastc_rdo_d", "1024"]
38+
futures.append((executor.submit(compress, path, flags), rdo_l))
39+
concurrent.futures.wait([f for (f, r) in futures])
40+
results = []
41+
bppbase = 0
42+
for future, rdo_l in futures:
43+
res = future.result()
44+
if rdo_l == 0:
45+
bppbase = res['bpp']
46+
res['rdo_l'] = rdo_l
47+
res['ratio'] = res['bpp'] / bppbase
48+
results.append(res)
49+
return results
50+
51+
fields = ['bpp', 'rms', 'psnr', 'ratio']
52+
fig, axs = plt.subplots(1, len(fields) + 1, layout='constrained')
53+
fig.set_figwidth(5 * (len(fields) + 1))
54+
lines = []
55+
56+
for path in args.files:
57+
print('Processing', path)
58+
results = stats(path)
59+
etcbase = compress(path, ["-q", "192"]) if args.etcbase else None
60+
61+
for idx, field in enumerate(fields):
62+
line, = axs[idx].plot([r['rdo_l'] for r in results], [r[field] for r in results])
63+
if etcbase and field in etcbase:
64+
axs[idx].axhline(etcbase[field], color=line.get_color(), linestyle='dotted')
65+
if idx == 0:
66+
lines.append(line)
67+
68+
axs[len(fields)].scatter([r['ratio'] for r in results], [r['psnr'] for r in results], color=line.get_color())
69+
70+
for idx, field in enumerate(fields):
71+
axs[idx].set_title(field)
72+
73+
axs[len(fields)].set_title('psnr vs ratio')
74+
75+
fig.legend(lines, [os.path.basename(path) for path in args.files], loc='outside right upper')
76+
77+
plt.savefig(args.graph)

0 commit comments

Comments
 (0)