Compare commits
1348 Commits
scripting
...
downsampli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
113614c2f5 | ||
|
|
ac41ace972 | ||
|
|
ebe782e4f4 | ||
|
|
e7439c1503 | ||
|
|
fda87de7e7 | ||
|
|
116bc83d09 | ||
|
|
ddffc055b9 | ||
|
|
1063c3da7f | ||
|
|
0a124ee839 | ||
|
|
2b7b3d8729 | ||
|
|
dacbb7c718 | ||
|
|
6318223f58 | ||
|
|
092e819a07 | ||
|
|
cae1ddc971 | ||
|
|
dc9cdddd4c | ||
|
|
0960160589 | ||
|
|
1765590a6f | ||
|
|
9f41ef9eac | ||
|
|
5ee069fc63 | ||
|
|
4d6124d41b | ||
|
|
a5d90c0b22 | ||
|
|
6043b2331f | ||
|
|
886040b257 | ||
|
|
8353a33e89 | ||
|
|
076f4a6293 | ||
|
|
920f25427e | ||
|
|
78ccbc710c | ||
|
|
548f1da5af | ||
|
|
9054801341 | ||
|
|
80855090d5 | ||
|
|
db14824d61 | ||
|
|
547601559c | ||
|
|
52e6e8ff1e | ||
|
|
f9bb413a40 | ||
|
|
dda10d3576 | ||
|
|
b2c8d25638 | ||
|
|
88cd086633 | ||
|
|
e096827df8 | ||
|
|
e08dda0a0a | ||
|
|
87e367076d | ||
|
|
ba15a76d7b | ||
|
|
d3fe1dfc2c | ||
|
|
fc5553a8c7 | ||
|
|
90cb266886 | ||
|
|
83b4757788 | ||
|
|
08cd649187 | ||
|
|
cd873eb6c1 | ||
|
|
3a64c5e4b3 | ||
|
|
b21312867b | ||
|
|
179e2f1999 | ||
|
|
0fdf984b71 | ||
|
|
e036318559 | ||
|
|
c11468b9f1 | ||
|
|
37e5e64ddc | ||
|
|
f3b7686457 | ||
|
|
5ac5a1d246 | ||
|
|
1d63648d68 | ||
|
|
dcd439e7d8 | ||
|
|
22202f1607 | ||
|
|
d0e1efb1fd | ||
|
|
f51dda3e66 | ||
|
|
a08acdb93a | ||
|
|
8605722cdf | ||
|
|
57be62ffd1 | ||
|
|
884459d1cf | ||
|
|
ffef0c2e38 | ||
|
|
d69d25431e | ||
|
|
f25302c847 | ||
|
|
34f2600f99 | ||
|
|
4c08c716c4 | ||
|
|
a4b359672c | ||
|
|
79b0533df2 | ||
|
|
b76618fdf4 | ||
|
|
1bf076c74f | ||
|
|
e0877c1922 | ||
|
|
69826f2101 | ||
|
|
a3645f3173 | ||
|
|
7228f6f1cf | ||
|
|
3c5db39ee4 | ||
|
|
4d4523dc04 | ||
|
|
c5bd4101b3 | ||
|
|
9cd9042563 | ||
|
|
4e928d7ce1 | ||
|
|
d65ae6ce00 | ||
|
|
401582bb2b | ||
|
|
a08bd43000 | ||
|
|
156b3f989b | ||
|
|
9cba1decad | ||
|
|
468c907fd6 | ||
|
|
d4e393f1a8 | ||
|
|
ab107722f7 | ||
|
|
242561debf | ||
|
|
82a843c121 | ||
|
|
1ed9e609a5 | ||
|
|
b7832e609f | ||
|
|
1a211e0a21 | ||
|
|
0e6ade067c | ||
|
|
5c3abb490d | ||
|
|
799f5bdf97 | ||
|
|
8c807118c0 | ||
|
|
7bb0c7d1fb | ||
|
|
c2589461e9 | ||
|
|
74fd217afb | ||
|
|
25b0bb752a | ||
|
|
c99625e4c3 | ||
|
|
58b0ccf3fc | ||
|
|
69ed6e5e58 | ||
|
|
2da692b341 | ||
|
|
2a8cfc7922 | ||
|
|
4e5b4ba071 | ||
|
|
4b34825afd | ||
|
|
ce71b168c3 | ||
|
|
a44dd1882f | ||
|
|
7b9664d6f2 | ||
|
|
9921d2074c | ||
|
|
5c83bbe5c5 | ||
|
|
272aa4f933 | ||
|
|
55c5e17fdc | ||
|
|
750dd1cb87 | ||
|
|
fa993849f7 | ||
|
|
6903abba55 | ||
|
|
0528ce567c | ||
|
|
00eb54cd15 | ||
|
|
d360564cef | ||
|
|
8c2fe430d8 | ||
|
|
b03127b206 | ||
|
|
6f3e9913f5 | ||
|
|
dd180f2fd6 | ||
|
|
b33aa31db8 | ||
|
|
8f6db2c8fa | ||
|
|
b81c87958f | ||
|
|
d010f768c4 | ||
|
|
ad7318f5f9 | ||
|
|
e7ff547f1b | ||
|
|
0565320036 | ||
|
|
c4e0e7fade | ||
|
|
dc18ce2c2a | ||
|
|
f4265edb2d | ||
|
|
86d78e5eca | ||
|
|
33083cfae1 | ||
|
|
00278fa905 | ||
|
|
b8fa97e1a7 | ||
|
|
89f11095bc | ||
|
|
9f73e690ad | ||
|
|
ac05c35292 | ||
|
|
18c509a679 | ||
|
|
307bd86b72 | ||
|
|
2aa466d1c6 | ||
|
|
9a22ac3c70 | ||
|
|
8e254c4baf | ||
|
|
f3f99f7eac | ||
|
|
406cd1b6a1 | ||
|
|
9e04b0bf55 | ||
|
|
a8361f985e | ||
|
|
7f1ebd3767 | ||
|
|
448009f4ef | ||
|
|
515a4d07fb | ||
|
|
0b4e302c22 | ||
|
|
b81287efd2 | ||
|
|
9b62632951 | ||
|
|
556a53e564 | ||
|
|
a919fa71aa | ||
|
|
080d30bf0c | ||
|
|
ad980a7004 | ||
|
|
0aa89ec7b0 | ||
|
|
9b97bd5924 | ||
|
|
e1bd5690ac | ||
|
|
01dfc9ae51 | ||
|
|
62285dcf33 | ||
|
|
6b754e6759 | ||
|
|
26db661a05 | ||
|
|
c4b0430d5e | ||
|
|
7826c258b0 | ||
|
|
2d659fc3eb | ||
|
|
831c982f3b | ||
|
|
6993e6c31f | ||
|
|
10e2079ee4 | ||
|
|
fe1fa765f7 | ||
|
|
568667753d | ||
|
|
7116a80435 | ||
|
|
31c1cfa650 | ||
|
|
2f5bdc9651 | ||
|
|
7442ec2f19 | ||
|
|
fa2442deaf | ||
|
|
8df2a2c446 | ||
|
|
f010d81652 | ||
|
|
b68370dff7 | ||
|
|
cc52320dfe | ||
|
|
4216eef420 | ||
|
|
585b13fbd9 | ||
|
|
b634eecd21 | ||
|
|
23c221be01 | ||
|
|
edfeffd820 | ||
|
|
fda10a6978 | ||
|
|
43af57d735 | ||
|
|
1f1a664908 | ||
|
|
6e2223b517 | ||
|
|
fbb411a946 | ||
|
|
4e1e07a93c | ||
|
|
9d52e27e16 | ||
|
|
666fee2df7 | ||
|
|
2603ce5976 | ||
|
|
03e24637af | ||
|
|
d00627b44b | ||
|
|
5e21234966 | ||
|
|
90e9634c19 | ||
|
|
c0c2e69b59 | ||
|
|
5cbb6b6163 | ||
|
|
e91ae5f1b9 | ||
|
|
dcaee9b87e | ||
|
|
726aa67d1b | ||
|
|
b99fb22522 | ||
|
|
b832dfbb3a | ||
|
|
c25c0067af | ||
|
|
e683c89770 | ||
|
|
5687dd22bd | ||
|
|
2f6eaa1d43 | ||
|
|
0dbab167a8 | ||
|
|
ceef778891 | ||
|
|
25ffc5a248 | ||
|
|
50fbaf90e6 | ||
|
|
8f19912c64 | ||
|
|
db848d1381 | ||
|
|
5577328f35 | ||
|
|
99f133223c | ||
|
|
2e805d56dd | ||
|
|
c3a2156c79 | ||
|
|
cdcf05a878 | ||
|
|
e507fdcb1f | ||
|
|
d8af8e4a60 | ||
|
|
9743ce01a0 | ||
|
|
69947fb907 | ||
|
|
d871c17f3f | ||
|
|
5eac1e4800 | ||
|
|
1edcc8c0ac | ||
|
|
cc567d9498 | ||
|
|
e137d3b5c7 | ||
|
|
5767397231 | ||
|
|
0bb83f6fd7 | ||
|
|
1e839224e8 | ||
|
|
2e6deca76f | ||
|
|
b814666134 | ||
|
|
1bea8817f1 | ||
|
|
42535591bc | ||
|
|
a1928de4d0 | ||
|
|
8bb013540d | ||
|
|
09ba2ed181 | ||
|
|
765a46fc88 | ||
|
|
53c08c52ed | ||
|
|
5d7cb6c5dc | ||
|
|
a4af88bc52 | ||
|
|
31d953dac2 | ||
|
|
9b0a906297 | ||
|
|
5bf7227790 | ||
|
|
1adf36ccb2 | ||
|
|
b6eb41e2cf | ||
|
|
2999f15d7a | ||
|
|
7f3687de81 | ||
|
|
3a661a1c3d | ||
|
|
d5432da082 | ||
|
|
f9155e5ce7 | ||
|
|
5725a0360b | ||
|
|
8c5fadafba | ||
|
|
dbba8deb4b | ||
|
|
c3a9ab3cc8 | ||
|
|
f0c456893c | ||
|
|
acf04ed67a | ||
|
|
e22d67f4aa | ||
|
|
9c327af280 | ||
|
|
52feb1a37d | ||
|
|
c9c4307871 | ||
|
|
042a2d72f7 | ||
|
|
5c4d95fd51 | ||
|
|
6d080c1a3f | ||
|
|
3670c131e3 | ||
|
|
ea632665c1 | ||
|
|
0c7636b3c3 | ||
|
|
541985fb70 | ||
|
|
58f5d7e1ba | ||
|
|
e9644c7eeb | ||
|
|
20df4ec14e | ||
|
|
fe3b4154b7 | ||
|
|
3ca2579882 | ||
|
|
84a1e209ea | ||
|
|
04e472d088 | ||
|
|
d93c713fb7 | ||
|
|
5b6e3a952c | ||
|
|
0a2facfaeb | ||
|
|
d3ceda0c5b | ||
|
|
9a5ee3aae6 | ||
|
|
03eb4a6bf9 | ||
|
|
25063d4018 | ||
|
|
14ff89d0c0 | ||
|
|
297165d1ee | ||
|
|
cbc22a89f7 | ||
|
|
ac79e43cc0 | ||
|
|
3959c83bd4 | ||
|
|
22edf23269 | ||
|
|
6756c96fa2 | ||
|
|
71e1032605 | ||
|
|
2f70d1bd9c | ||
|
|
e9848a6182 | ||
|
|
9df59713da | ||
|
|
0faa9cf650 | ||
|
|
2a7625e67c | ||
|
|
4aa9857c53 | ||
|
|
aff623b772 | ||
|
|
7c627a8c83 | ||
|
|
f9c125c1a1 | ||
|
|
d7d028ac5c | ||
|
|
b87c6dde6c | ||
|
|
4fe3e1147d | ||
|
|
9fc9f4b9e9 | ||
|
|
00132c6070 | ||
|
|
9c2244f40e | ||
|
|
42c5f9169f | ||
|
|
c6746e76f1 | ||
|
|
62414b0c4c | ||
|
|
67041d217b | ||
|
|
145ad2db27 | ||
|
|
9dec34c8c0 | ||
|
|
f1435dcf67 | ||
|
|
53008eb34a | ||
|
|
c6e2235ee2 | ||
|
|
fa4dc381ed | ||
|
|
dfacf9e8db | ||
|
|
ee750b44e3 | ||
|
|
0f51472d64 | ||
|
|
b7fff840c8 | ||
|
|
cbc16bee9e | ||
|
|
b059cda8d5 | ||
|
|
aafc029682 | ||
|
|
ae18db9271 | ||
|
|
682ba71319 | ||
|
|
d5b9b54a69 | ||
|
|
19eee76aec | ||
|
|
6cbfab6eca | ||
|
|
9970944da2 | ||
|
|
5401dc8d52 | ||
|
|
ff3214b8f7 | ||
|
|
d3246deb77 | ||
|
|
83274c7e3b | ||
|
|
b39f1558ec | ||
|
|
c0b4627c11 | ||
|
|
bbe6612b25 | ||
|
|
da501b9294 | ||
|
|
2e31a40dda | ||
|
|
dac5dd562b | ||
|
|
6d72a48708 | ||
|
|
3ed6cc2ba8 | ||
|
|
6be242449b | ||
|
|
eeee1e691a | ||
|
|
208e6c4b35 | ||
|
|
c4d4a7a774 | ||
|
|
73dc52ac98 | ||
|
|
cd216d91db | ||
|
|
2e0825a363 | ||
|
|
b81d6718f4 | ||
|
|
4e43b1ec8c | ||
|
|
a879c11c34 | ||
|
|
97700b85de | ||
|
|
eb390a9b5d | ||
|
|
b28ca2b78a | ||
|
|
57d3aa4850 | ||
|
|
1434507b41 | ||
|
|
b97788a35a | ||
|
|
4edae3cdd0 | ||
|
|
d1b904a1da | ||
|
|
0befbf8021 | ||
|
|
be7a20fef2 | ||
|
|
5fd79254bd | ||
|
|
57595c47af | ||
|
|
4a650fcce2 | ||
|
|
982dccb990 | ||
|
|
b180b26728 | ||
|
|
dec468966c | ||
|
|
a804801a1b | ||
|
|
0ae8fcced3 | ||
|
|
0076af6974 | ||
|
|
40a1bee9ea | ||
|
|
9fa8fee193 | ||
|
|
852239ec8a | ||
|
|
70a4b5c9f2 | ||
|
|
7b230dc4c1 | ||
|
|
ae14c8715d | ||
|
|
8567293103 | ||
|
|
7eb1d4e092 | ||
|
|
24dfd30839 | ||
|
|
3ff1b04576 | ||
|
|
e647192437 | ||
|
|
affbdfc350 | ||
|
|
ff010686f8 | ||
|
|
c970740d12 | ||
|
|
e987b56aae | ||
|
|
88836c431e | ||
|
|
5bcf99fc11 | ||
|
|
5261cfe8e4 | ||
|
|
f67eacc071 | ||
|
|
d2d06adeeb | ||
|
|
5c03e1d940 | ||
|
|
bb24d406f2 | ||
|
|
d26fc89aac | ||
|
|
5d8519897d | ||
|
|
b984f343ae | ||
|
|
0079f7a285 | ||
|
|
e6892e0a54 | ||
|
|
378fd80e3d | ||
|
|
ca9af62f92 | ||
|
|
2da7859143 | ||
|
|
b59f9a1270 | ||
|
|
b726fa8918 | ||
|
|
2791a9a890 | ||
|
|
81e2619e91 | ||
|
|
5a948800b7 | ||
|
|
4b71428846 | ||
|
|
cf0c2ea1e6 | ||
|
|
869b159601 | ||
|
|
988a7c8c6d | ||
|
|
1451e968d5 | ||
|
|
9838dd9df2 | ||
|
|
6c1b98e46a | ||
|
|
122fe3d52f | ||
|
|
ed78a20ea7 | ||
|
|
574f12759c | ||
|
|
97d8a35108 | ||
|
|
7a11b95490 | ||
|
|
725530984c | ||
|
|
8747101648 | ||
|
|
49a6ef7aca | ||
|
|
bb450d5e5f | ||
|
|
d56bcfa4c8 | ||
|
|
854319441c | ||
|
|
5cfb76e3f5 | ||
|
|
9fbb760b18 | ||
|
|
d5e2db0dee | ||
|
|
854a8eb1bb | ||
|
|
61dae0ed6f | ||
|
|
49b669c8be | ||
|
|
194e9bbbe5 | ||
|
|
41a89123c9 | ||
|
|
3cf7a94d1e | ||
|
|
8ec9c90c82 | ||
|
|
2da32d8e57 | ||
|
|
c2316dfdc8 | ||
|
|
350429466a | ||
|
|
babaffcce9 | ||
|
|
b8f397c353 | ||
|
|
801ddf7b36 | ||
|
|
5219e4f987 | ||
|
|
a2af51b856 | ||
|
|
5f607d8c7a | ||
|
|
97938a8b8c | ||
|
|
5cf2c86874 | ||
|
|
4763b6754c | ||
|
|
482f99c323 | ||
|
|
5bc38ffd63 | ||
|
|
e69f0d3cce | ||
|
|
816ef45199 | ||
|
|
365e129792 | ||
|
|
6ffa5bffab | ||
|
|
3f41dcc97d | ||
|
|
596cca9be2 | ||
|
|
5caadec34d | ||
|
|
439e05bbf2 | ||
|
|
92bcf64fe8 | ||
|
|
0234137be4 | ||
|
|
b70a8482bd | ||
|
|
8611f4f438 | ||
|
|
5b600789d6 | ||
|
|
2bf0838634 | ||
|
|
e3e0fe6445 | ||
|
|
3874df6888 | ||
|
|
3a271ffe9b | ||
|
|
160c27e106 | ||
|
|
e8bb6bab10 | ||
|
|
7ac7175da5 | ||
|
|
dec40e234f | ||
|
|
5f6daf8a2a | ||
|
|
a6c19cc90b | ||
|
|
2d22409d2e | ||
|
|
c461ad7b44 | ||
|
|
886ef4cc59 | ||
|
|
ead9e56c4d | ||
|
|
65f3dcbe9b | ||
|
|
2044e35377 | ||
|
|
3952661978 | ||
|
|
7b7dd2bef1 | ||
|
|
57ca5dd2c2 | ||
|
|
88e14dd3ff | ||
|
|
a854ed2da1 | ||
|
|
f889136227 | ||
|
|
2cd3f209e2 | ||
|
|
bcd5cd0027 | ||
|
|
8bd0e6c3f7 | ||
|
|
d0ad4e7264 | ||
|
|
b5c83e671f | ||
|
|
ca2ed61dba | ||
|
|
4c1377774d | ||
|
|
bb740499a5 | ||
|
|
be271e3bfb | ||
|
|
dae5973121 | ||
|
|
88147d8f69 | ||
|
|
ac19768247 | ||
|
|
98cce645a9 | ||
|
|
8c4d595a89 | ||
|
|
a8b588371a | ||
|
|
8f087ab594 | ||
|
|
d416ecb324 | ||
|
|
0fc719c4cf | ||
|
|
a8bc364a2b | ||
|
|
95be381a9f | ||
|
|
2c3d1d9e60 | ||
|
|
12acecbf36 | ||
|
|
775496af8a | ||
|
|
09a825720d | ||
|
|
b4e509d090 | ||
|
|
9733d8a0d1 | ||
|
|
b646f1453d | ||
|
|
145fbff79b | ||
|
|
6551358212 | ||
|
|
afb9ab7d11 | ||
|
|
ad73093ab2 | ||
|
|
9cb2cabd8b | ||
|
|
dfc4e0833e | ||
|
|
65d7f3bf2d | ||
|
|
5518199206 | ||
|
|
5bca12a840 | ||
|
|
814f22f58b | ||
|
|
2043128f98 | ||
|
|
d24e8fda83 | ||
|
|
dadc994ba8 | ||
|
|
a3d55c6e30 | ||
|
|
bfadd608fb | ||
|
|
0dc78e4c23 | ||
|
|
b86fdc1cc1 | ||
|
|
53fb5cd9e1 | ||
|
|
d34707a377 | ||
|
|
166c930738 | ||
|
|
21d19a6297 | ||
|
|
875ccecb90 | ||
|
|
99e65282f6 | ||
|
|
2c57817803 | ||
|
|
c6b74684de | ||
|
|
6cf8ac340b | ||
|
|
aa0c0068ce | ||
|
|
1d21ca61e7 | ||
|
|
218df625df | ||
|
|
24f15acf6c | ||
|
|
8def5b5d0a | ||
|
|
82e9bcc55f | ||
|
|
62de181e97 | ||
|
|
7782bb9845 | ||
|
|
7f5a4a065b | ||
|
|
1ae2dcf192 | ||
|
|
6af71beed5 | ||
|
|
d8cd32d964 | ||
|
|
b92eeec962 | ||
|
|
9e5deb8e35 | ||
|
|
19ae3be0b0 | ||
|
|
080807e557 | ||
|
|
cdd230c040 | ||
|
|
903213c818 | ||
|
|
7d2216c289 | ||
|
|
2d04f2eff9 | ||
|
|
a8d846ac8f | ||
|
|
761c8bdf7f | ||
|
|
631f32a4c9 | ||
|
|
4963dc1759 | ||
|
|
485f81a02f | ||
|
|
3a76485e4b | ||
|
|
19a0854528 | ||
|
|
164c043e1b | ||
|
|
396e7d994a | ||
|
|
bd5a97feca | ||
|
|
c11b250efe | ||
|
|
63685ce5f8 | ||
|
|
32e62725dd | ||
|
|
6e1d8c5213 | ||
|
|
a9bfe2642f | ||
|
|
b62e58776e | ||
|
|
be268d8bf1 | ||
|
|
05c285f760 | ||
|
|
c250209336 | ||
|
|
0d3501d435 | ||
|
|
60f6ee3055 | ||
|
|
825dd13c6b | ||
|
|
4ab22921c4 | ||
|
|
428c3e3426 | ||
|
|
4666057158 | ||
|
|
b277035734 | ||
|
|
45f782962e | ||
|
|
056b629837 | ||
|
|
dbb2274d2d | ||
|
|
e0bc03b525 | ||
|
|
6cc350a459 | ||
|
|
5c4a9f9f1c | ||
|
|
ecc0356fb9 | ||
|
|
aacd62b29b | ||
|
|
8cd4982c62 | ||
|
|
864d6928d3 | ||
|
|
163cb2f653 | ||
|
|
c279376cff | ||
|
|
43ed92415d | ||
|
|
9050098e3e | ||
|
|
e4a358cacb | ||
|
|
41c709ef6f | ||
|
|
d3234a29c8 | ||
|
|
cc275b6ff8 | ||
|
|
49134efe4e | ||
|
|
f83cbbda12 | ||
|
|
76208f5f2d | ||
|
|
57cf0f2643 | ||
|
|
baa9065d2e | ||
|
|
2aea06526c | ||
|
|
f0be61b819 | ||
|
|
b99ee59224 | ||
|
|
50d8bb091f | ||
|
|
854a109a0f | ||
|
|
86a28d5dc0 | ||
|
|
6dc2f0a60b | ||
|
|
eb46142ee7 | ||
|
|
c6055affbf | ||
|
|
005d48a387 | ||
|
|
e2cb54d233 | ||
|
|
d4f3e004cf | ||
|
|
972a0693b2 | ||
|
|
7ad48c9309 | ||
|
|
219e890da5 | ||
|
|
afd36560c1 | ||
|
|
2604df5917 | ||
|
|
11c212260c | ||
|
|
4a57ccc3e8 | ||
|
|
a11ed649bf | ||
|
|
b3ae9cbe4a | ||
|
|
469485974c | ||
|
|
e0b6f6f1b2 | ||
|
|
2079bac40b | ||
|
|
0d05548459 | ||
|
|
d8fef6f22e | ||
|
|
86d66ddf82 | ||
|
|
21ec3c1152 | ||
|
|
1e119c8e2d | ||
|
|
07cb8d9c86 | ||
|
|
412c8f0187 | ||
|
|
5ab65ff484 | ||
|
|
6e26ba3e9e | ||
|
|
ba0708a4ff | ||
|
|
2fc5856c44 | ||
|
|
dedc177300 | ||
|
|
38a331fde4 | ||
|
|
3e26b7ab73 | ||
|
|
3d5503612b | ||
|
|
8680900788 | ||
|
|
83a1386d0b | ||
|
|
407dccb1db | ||
|
|
7ce4c34936 | ||
|
|
dde7ebbb67 | ||
|
|
26b6c704f0 | ||
|
|
0c2ab82252 | ||
|
|
449cd7cbc8 | ||
|
|
1778507995 | ||
|
|
bfbea97776 | ||
|
|
f4b88edc49 | ||
|
|
ff194844de | ||
|
|
f1dd161504 | ||
|
|
32e96b02ca | ||
|
|
9ff4fbd21c | ||
|
|
3fb5fb4c72 | ||
|
|
c9f7ef5f9a | ||
|
|
80971dac5a | ||
|
|
08bdffac64 | ||
|
|
71bb953253 | ||
|
|
52389f48a6 | ||
|
|
0ae4461fc3 | ||
|
|
2f331540b1 | ||
|
|
a83b642a2d | ||
|
|
c740fd9e11 | ||
|
|
887d588029 | ||
|
|
4d5e0b6c54 | ||
|
|
785692dbe1 | ||
|
|
7e72b9fb7b | ||
|
|
51fefb36a0 | ||
|
|
bd050ebb63 | ||
|
|
0730a361a3 | ||
|
|
45c8f6ea56 | ||
|
|
08fe20ad76 | ||
|
|
ccc3b114d4 | ||
|
|
75babc74cb | ||
|
|
07f410bc6a | ||
|
|
6dc4fa5c75 | ||
|
|
9de5794afe | ||
|
|
060146a37a | ||
|
|
3081c4f5cd | ||
|
|
73fd97e770 | ||
|
|
d32143b319 | ||
|
|
e06f1f1002 | ||
|
|
4132b5ef3d | ||
|
|
fee5f760ad | ||
|
|
b51def8a99 | ||
|
|
7d8ae9aa11 | ||
|
|
ca6b99401b | ||
|
|
036e11f7a8 | ||
|
|
615781be39 | ||
|
|
4e880280bd | ||
|
|
a76b48bc7b | ||
|
|
82ed6bb1f3 | ||
|
|
5995471de6 | ||
|
|
df8e950e6e | ||
|
|
29da7f7211 | ||
|
|
b36e2ce6be | ||
|
|
2e4eaeafdc | ||
|
|
e3a84af1aa | ||
|
|
c46ec398dc | ||
|
|
495a0da8d4 | ||
|
|
58dc24cb0d | ||
|
|
a26c3e5620 | ||
|
|
d1eed89292 | ||
|
|
0e4ca9cd93 | ||
|
|
4d74b203af | ||
|
|
991927151c | ||
|
|
fd8f97f4d3 | ||
|
|
5ed96fcfe4 | ||
|
|
50cfbf1629 | ||
|
|
114effd9a1 | ||
|
|
3808217298 | ||
|
|
2cfad2126d | ||
|
|
c0ada65336 | ||
|
|
9a1d92a9c5 | ||
|
|
71cf206dc8 | ||
|
|
b971125469 | ||
|
|
ed7a9e2f8c | ||
|
|
bfc914aaa9 | ||
|
|
d67b826033 | ||
|
|
dae38cb309 | ||
|
|
bb3d27f153 | ||
|
|
2768d27c05 | ||
|
|
23ec40d032 | ||
|
|
cf32774b24 | ||
|
|
206f32e511 | ||
|
|
c439de6364 | ||
|
|
e1c876671a | ||
|
|
986e207cff | ||
|
|
f9941c3f68 | ||
|
|
f169b892c1 | ||
|
|
88bc3a2278 | ||
|
|
3dca598063 | ||
|
|
88381209b3 | ||
|
|
1754ecf4f9 | ||
|
|
df17528b18 | ||
|
|
54e5d93165 | ||
|
|
19698559c3 | ||
|
|
ac8461a28b | ||
|
|
e617f17294 | ||
|
|
e7aa0495ab | ||
|
|
40670726b4 | ||
|
|
a7747c5be3 | ||
|
|
d07c7e4b68 | ||
|
|
5f80cb1188 | ||
|
|
b5df06a54a | ||
|
|
e056bcb5ff | ||
|
|
96ece5de1c | ||
|
|
0538b95d9b | ||
|
|
a5cd3ee7a8 | ||
|
|
64655818ed | ||
|
|
292c1e0f06 | ||
|
|
369599202c | ||
|
|
401295ebdb | ||
|
|
8ba85d62dc | ||
|
|
8b67ed8536 | ||
|
|
b96e6d1425 | ||
|
|
8fa406061a | ||
|
|
a259178d1b | ||
|
|
b5768266bb | ||
|
|
1ffd2f4149 | ||
|
|
fbb92e9225 | ||
|
|
6d637127f2 | ||
|
|
350cf7ee32 | ||
|
|
d28f0fa4e6 | ||
|
|
e17eaf77dd | ||
|
|
e03deb4928 | ||
|
|
d330dca38a | ||
|
|
d981dc7471 | ||
|
|
ad67ab7ec3 | ||
|
|
6f31e562a0 | ||
|
|
f2720b98dd | ||
|
|
ddcb0cb541 | ||
|
|
d7ce028a42 | ||
|
|
66b4391ab9 | ||
|
|
b6414756e5 | ||
|
|
065beff2da | ||
|
|
0abd7c0524 | ||
|
|
20b4581bbe | ||
|
|
2813b4bece | ||
|
|
6c3f33804f | ||
|
|
891d5cefbe | ||
|
|
e93dea5ad8 | ||
|
|
d1770b616f | ||
|
|
fe9d06a194 | ||
|
|
936c945e73 | ||
|
|
c633a6bacc | ||
|
|
128d5254ca | ||
|
|
e2a3fe14f0 | ||
|
|
7bcdf11240 | ||
|
|
de551c1836 | ||
|
|
559aff0ad5 | ||
|
|
a22acfc8a7 | ||
|
|
4c31218d2b | ||
|
|
c42fb7c16e | ||
|
|
6a5f16d89a | ||
|
|
432fd80f3d | ||
|
|
86bff869bc | ||
|
|
3078339f64 | ||
|
|
b10f043350 | ||
|
|
1d83e72887 | ||
|
|
b6c4d6dda9 | ||
|
|
d29444e948 | ||
|
|
1956575710 | ||
|
|
32a3311208 | ||
|
|
9d6ec23dc4 | ||
|
|
940cc636d6 | ||
|
|
af777c16ff | ||
|
|
47a3cd44f3 | ||
|
|
1b2ff7e0e8 | ||
|
|
6ea2bb1810 | ||
|
|
71ec59be06 | ||
|
|
ac5a2a153a | ||
|
|
4b0c1fdbf2 | ||
|
|
1c1b82ed66 | ||
|
|
c5dd48474f | ||
|
|
95185b7308 | ||
|
|
2e080d4998 | ||
|
|
153d95982b | ||
|
|
929b049bd8 | ||
|
|
ab1c85790c | ||
|
|
4c59513c79 | ||
|
|
a074699dab | ||
|
|
2d3c6ace31 | ||
|
|
5b4d625d23 | ||
|
|
4a2714150e | ||
|
|
129df8410e | ||
|
|
a53dc85035 | ||
|
|
0458dfe8be | ||
|
|
a7d8e6d018 | ||
|
|
060c5553c0 | ||
|
|
87eded4bce | ||
|
|
1eb1b03141 | ||
|
|
1446e3035f | ||
|
|
94911abdca | ||
|
|
503004f17c | ||
|
|
f9a594058f | ||
|
|
8274042bb1 | ||
|
|
6d0f92d4fb | ||
|
|
56dac5f52a | ||
|
|
6a3b1a2725 | ||
|
|
63abdb7afd | ||
|
|
4c51337edd | ||
|
|
164a353352 | ||
|
|
b564f928bd | ||
|
|
51cfea49fe | ||
|
|
0ba068e843 | ||
|
|
5ed8af4236 | ||
|
|
4322799201 | ||
|
|
0945a9a27f | ||
|
|
7b178594a0 | ||
|
|
7f9a69b977 | ||
|
|
bee80b0fea | ||
|
|
88ee70ef8a | ||
|
|
7f4e5d55db | ||
|
|
aa955b8ae2 | ||
|
|
3fbdcdb4ff | ||
|
|
14ab642ff3 | ||
|
|
81c9bdeeef | ||
|
|
b84d3f14fc | ||
|
|
cdba1fe25a | ||
|
|
ac139d96f1 | ||
|
|
fe8dada392 | ||
|
|
7df5764835 | ||
|
|
486f410f43 | ||
|
|
63c7f4a893 | ||
|
|
d651c9f477 | ||
|
|
542ef3a6c0 | ||
|
|
667d1bf7c8 | ||
|
|
f243dc075d | ||
|
|
c7a6e7e483 | ||
|
|
ae2e79f401 | ||
|
|
2c27b20090 | ||
|
|
63bf64b05d | ||
|
|
05c7e6009c | ||
|
|
940200f7f3 | ||
|
|
46a6681159 | ||
|
|
344a4a6215 | ||
|
|
e54c4c8101 | ||
|
|
7a05d5aca5 | ||
|
|
b04f721d55 | ||
|
|
c9f5cfc1bc | ||
|
|
88e4bf6aad | ||
|
|
a49be5db7c | ||
|
|
48c2760daa | ||
|
|
0f29cd8d63 | ||
|
|
44471a66f6 | ||
|
|
6deb2eb390 | ||
|
|
5c2fc68755 | ||
|
|
b8026a038c | ||
|
|
a7f3d7b02d | ||
|
|
e8b787fb57 | ||
|
|
f30844cc40 | ||
|
|
f37a97bf18 | ||
|
|
707453b596 | ||
|
|
a2aa040987 | ||
|
|
b378ffb975 | ||
|
|
25d8f1be67 | ||
|
|
f2c0303875 | ||
|
|
599800dfa1 | ||
|
|
c8e61307b2 | ||
|
|
096a0811bf | ||
|
|
a8cac70ee6 | ||
|
|
41fb5d3d9a | ||
|
|
72fc81a705 | ||
|
|
7745c9ef43 | ||
|
|
873b540b82 | ||
|
|
96b8e53fbf | ||
|
|
1425b2fb40 | ||
|
|
9dd83c4f9f | ||
|
|
f0deab2131 | ||
|
|
bda6869084 | ||
|
|
9e3507e0f4 | ||
|
|
8b3fd538ea | ||
|
|
5433b30fec | ||
|
|
417c1e43dd | ||
|
|
9a0d5db74f | ||
|
|
1aa9c2d564 | ||
|
|
3578572aa1 | ||
|
|
ccd7ba9acf | ||
|
|
5c14ac2fd1 | ||
|
|
2971b2f34c | ||
|
|
d4d813f043 | ||
|
|
dadf388657 | ||
|
|
491179a447 | ||
|
|
a764954977 | ||
|
|
8629efc39c | ||
|
|
514116e6c3 | ||
|
|
bcd2424db3 | ||
|
|
3548bbcf90 | ||
|
|
2662694c04 | ||
|
|
fc375d76b5 | ||
|
|
302652df22 | ||
|
|
9a6de196a3 | ||
|
|
7dc78dbcd5 | ||
|
|
64a28aac53 | ||
|
|
b656e1d4ca | ||
|
|
b9679dfb0b | ||
|
|
6dd29eb88f | ||
|
|
b089eaf084 | ||
|
|
3455a0d151 | ||
|
|
ef59a0da12 | ||
|
|
41c8607782 | ||
|
|
86d4d92753 | ||
|
|
1e8ca51f44 | ||
|
|
a0fcbba45c | ||
|
|
aa1596fdab | ||
|
|
fda6140088 | ||
|
|
aa9a5e383d | ||
|
|
b2577ef8bd | ||
|
|
304f69e350 | ||
|
|
ee98912a42 | ||
|
|
3175214c92 | ||
|
|
3772706603 | ||
|
|
e2ea0bfec2 | ||
|
|
6f9e8efee5 | ||
|
|
9d7a3b10c2 | ||
|
|
7ac3e2fe50 | ||
|
|
c6d14febd2 | ||
|
|
b274bf4d57 | ||
|
|
44a12db931 | ||
|
|
ce7bbb47d5 | ||
|
|
052930a8d8 | ||
|
|
681fab5da3 | ||
|
|
823ce581d9 | ||
|
|
7810c95962 | ||
|
|
add46248a3 | ||
|
|
2f5aa45e1f | ||
|
|
2e2451998c | ||
|
|
460acce561 | ||
|
|
f2896d55b8 | ||
|
|
159254c37a | ||
|
|
0f03aa3e30 | ||
|
|
f5815f3183 | ||
|
|
05f9f33ec6 | ||
|
|
7756c5a5e9 | ||
|
|
13a37418e6 | ||
|
|
f99d5ff39d | ||
|
|
0af2c01a18 | ||
|
|
09cdd986b9 | ||
|
|
a6ba2b5e20 | ||
|
|
34e0752b65 | ||
|
|
421bd23dc8 | ||
|
|
e96320daf0 | ||
|
|
cbbfc2f11a | ||
|
|
9e09f53566 | ||
|
|
71738d12e0 | ||
|
|
f48d3b4636 | ||
|
|
5786f3a8c9 | ||
|
|
3e708d066c | ||
|
|
e8693ed10f | ||
|
|
da1fb4c09e | ||
|
|
da4b5df656 | ||
|
|
d5b6d35d3e | ||
|
|
ee07e9e0f1 | ||
|
|
8ad912c340 | ||
|
|
422a0a0ead | ||
|
|
c30c4a5d0a | ||
|
|
9a58327cf2 | ||
|
|
5d84185240 | ||
|
|
78398f82fd | ||
|
|
abbb21ffec | ||
|
|
db4e28f44c | ||
|
|
00a58eb4e5 | ||
|
|
62eb557832 | ||
|
|
af47eb6956 | ||
|
|
5f8082734e | ||
|
|
290c44f4c0 | ||
|
|
8295fd9c3a | ||
|
|
b72e622ae0 | ||
|
|
34df233a95 | ||
|
|
010c7dea33 | ||
|
|
98b1a703f3 | ||
|
|
76f6eafdbc | ||
|
|
55d095174f | ||
|
|
5368a1dcba | ||
|
|
624ab4d377 | ||
|
|
d1f0669374 | ||
|
|
c97516b01d | ||
|
|
8ad133dbc0 | ||
|
|
b2ca23e9da | ||
|
|
4f16cb61b4 | ||
|
|
aeb9d383ce | ||
|
|
70411783cd | ||
|
|
e6a682f8d5 | ||
|
|
81295c8a7d | ||
|
|
3a08ad1840 | ||
|
|
efc821bc84 | ||
|
|
cabba81a76 | ||
|
|
0517aef5bd | ||
|
|
e499f9052a | ||
|
|
2fb5e4495d | ||
|
|
6c5ffba18e | ||
|
|
79bb5f079c | ||
|
|
d862043f1d | ||
|
|
6e795c8977 | ||
|
|
c23ea4b2ad | ||
|
|
35dd4fde36 | ||
|
|
0c15c9eaa8 | ||
|
|
c3bf267936 | ||
|
|
02fbfae6a0 | ||
|
|
c538df317a | ||
|
|
6c0a0e6203 | ||
|
|
59a1cca858 | ||
|
|
ec5d8cb1d6 | ||
|
|
f9079b0151 | ||
|
|
ee538ae0ea | ||
|
|
a2f98541b3 | ||
|
|
143acca03b | ||
|
|
5b590d434b | ||
|
|
30c5ebae72 | ||
|
|
1b9b4699d9 | ||
|
|
7cbd67ecf1 | ||
|
|
a793741747 | ||
|
|
9a626caad9 | ||
|
|
3a83c4265c | ||
|
|
4eb3b2a9a7 | ||
|
|
0518bfb60f | ||
|
|
75cf877b0d | ||
|
|
6d70d24bc4 | ||
|
|
aa400f12ae | ||
|
|
0afcbd3acc | ||
|
|
24abd108f6 | ||
|
|
f1f57d88ce | ||
|
|
2f90651c3f | ||
|
|
33f6cc246e | ||
|
|
534a82d091 | ||
|
|
8c9a885032 | ||
|
|
410cea0f12 | ||
|
|
2d2bc93ada | ||
|
|
e0911d7f54 | ||
|
|
998f77c590 | ||
|
|
0321a2cdc4 | ||
|
|
6ce9e571ed | ||
|
|
a6518ff9dc | ||
|
|
dd8bf2c9d9 | ||
|
|
b5009da2bc | ||
|
|
7aaaf7c575 | ||
|
|
c83b5fdd05 | ||
|
|
ab7a3e1934 | ||
|
|
a3f8162488 | ||
|
|
6da84bf5d0 | ||
|
|
11c6f89162 | ||
|
|
b6b0997e70 | ||
|
|
876f212685 | ||
|
|
40356fc381 | ||
|
|
6fe0c986fa | ||
|
|
7b99fcbbf3 | ||
|
|
a3acb0c5db | ||
|
|
5026e1b276 | ||
|
|
fcd4e60af1 | ||
|
|
c2d24f436c | ||
|
|
f051aa54d9 | ||
|
|
440e08cf3e | ||
|
|
d3dc3ec6d3 | ||
|
|
7a3a72ec3d | ||
|
|
5656f91bd2 | ||
|
|
3282366ea7 | ||
|
|
bf1b023f12 | ||
|
|
e455a5e371 | ||
|
|
1771bfad58 | ||
|
|
0f4af03730 | ||
|
|
0b5287f199 | ||
|
|
dce1221021 | ||
|
|
68575d15a4 | ||
|
|
5ec9c8a397 | ||
|
|
861d4a5aa2 | ||
|
|
5e8870ec69 | ||
|
|
0407f939fc | ||
|
|
b7bfbc0cf6 | ||
|
|
7bbc1745e4 | ||
|
|
49772f0479 | ||
|
|
2a617c505a | ||
|
|
1006fa00da | ||
|
|
e743c5d1b1 | ||
|
|
298f39a0c8 | ||
|
|
ba6b65401d | ||
|
|
deed0c9713 | ||
|
|
fe55446c25 | ||
|
|
28c74f1325 | ||
|
|
533022bb7d | ||
|
|
2938602d75 | ||
|
|
b4136d2834 | ||
|
|
022b2fc013 | ||
|
|
ad374ef5e2 | ||
|
|
78800870bc | ||
|
|
6b78364eab | ||
|
|
14d87602d3 | ||
|
|
a6e34fa632 | ||
|
|
d9ada75d4f | ||
|
|
3172eac8df | ||
|
|
cc667cd88c | ||
|
|
f2e88ce0e5 | ||
|
|
79644bfb2a | ||
|
|
f1f89d3f0f | ||
|
|
52f9e8556a | ||
|
|
efd8aab437 | ||
|
|
495b2ff29e | ||
|
|
9b77a9aff7 | ||
|
|
4f7ddfaae6 | ||
|
|
56dd9878e1 | ||
|
|
0815aedca2 | ||
|
|
2e96931c32 | ||
|
|
5f36c2948f | ||
|
|
d9a224ef6c | ||
|
|
6a920b268e | ||
|
|
f0945ca3ca | ||
|
|
19063d4288 | ||
|
|
7217536fdd | ||
|
|
41e15539f9 | ||
|
|
a6cf320776 | ||
|
|
6176a21ff1 | ||
|
|
24ef76bfee | ||
|
|
567b86ce79 | ||
|
|
aa94b07f30 | ||
|
|
ca2a8f1e1f | ||
|
|
00ccea84b8 | ||
|
|
c286112966 | ||
|
|
92038da3d5 | ||
|
|
0a86aba1cb | ||
|
|
5d5c04c9b4 | ||
|
|
8d94fd54f2 | ||
|
|
c925becd57 | ||
|
|
9a89ab3bab | ||
|
|
f1ca914512 | ||
|
|
9392c19a70 | ||
|
|
44b9d16d9f | ||
|
|
fb747d6ded | ||
|
|
bc30569a6d | ||
|
|
889427e7f6 | ||
|
|
00cc3b65fc | ||
|
|
5381ad9cd1 | ||
|
|
66f31d42b6 | ||
|
|
cf15591704 | ||
|
|
fae6b7ae86 | ||
|
|
fee888758f | ||
|
|
154a5b35b8 | ||
|
|
640ed4a2d3 | ||
|
|
59a2309a83 | ||
|
|
d70f5ddb32 | ||
|
|
d8413719c1 | ||
|
|
df979d4648 | ||
|
|
500fbe5ef1 | ||
|
|
8698298499 | ||
|
|
a5a320720a | ||
|
|
5d4f6e44d2 | ||
|
|
594962d247 | ||
|
|
fd0626aa6d | ||
|
|
ff77bd029f | ||
|
|
afea18f65e | ||
|
|
b7da118f96 | ||
|
|
5da6c926d9 | ||
|
|
2cfa535784 | ||
|
|
97e555a47d | ||
|
|
0f0cc4ea17 | ||
|
|
7c45ad3fed | ||
|
|
2ac2ad605e | ||
|
|
3b9c489787 | ||
|
|
58470cea09 | ||
|
|
226a8eac81 | ||
|
|
11f7bfc461 | ||
|
|
e5c62b8baf | ||
|
|
5881133cf5 | ||
|
|
9be7a37416 | ||
|
|
18b0b11094 | ||
|
|
7c818c0c53 | ||
|
|
c1976f4b53 | ||
|
|
989a19d144 | ||
|
|
4bd7256a37 | ||
|
|
a56ebf24b2 | ||
|
|
93836636a1 | ||
|
|
addadbabc6 | ||
|
|
9143116616 | ||
|
|
8659c8cca6 | ||
|
|
ec851c9d6d | ||
|
|
36abbd97e8 | ||
|
|
de27e5de92 | ||
|
|
f0e2d1a9fa | ||
|
|
d922a43127 | ||
|
|
3b7844be5a | ||
|
|
d831cb69a9 | ||
|
|
5410a42fd7 | ||
|
|
22b273800e | ||
|
|
985b9f8a38 | ||
|
|
b6f7420018 | ||
|
|
f5cc70923b | ||
|
|
7373342ea9 | ||
|
|
7f21226a99 | ||
|
|
fe055280e1 | ||
|
|
aac7a9992c | ||
|
|
e1a9c69a4a | ||
|
|
d63ae8718f | ||
|
|
ff7bfaaadb | ||
|
|
6f50e12ea2 | ||
|
|
a3d600d5c3 | ||
|
|
5cdcdb565f | ||
|
|
40048cbbc8 | ||
|
|
e4470a9929 | ||
|
|
d372609bdc | ||
|
|
ed5a99066f | ||
|
|
bc73dacea4 | ||
|
|
1fd8d2701d | ||
|
|
b06fceffa4 | ||
|
|
9a70003b70 | ||
|
|
eba0794b4f | ||
|
|
29b3fa2b95 | ||
|
|
91962508fe | ||
|
|
b9155ec5ac | ||
|
|
c51db5c6a7 | ||
|
|
23962fd07e | ||
|
|
b6a264b8b4 | ||
|
|
a57101c1f0 | ||
|
|
f5cae1957b | ||
|
|
e1a4c7dfdd | ||
|
|
536b48d706 | ||
|
|
77488db3dc | ||
|
|
d021a61eb5 | ||
|
|
4c0250716d | ||
|
|
3749b812a3 | ||
|
|
9fcc98a60a | ||
|
|
c02bf0f662 | ||
|
|
487eb102b7 | ||
|
|
87f2995f3d | ||
|
|
82b5772d27 | ||
|
|
69c35c9fcd | ||
|
|
4bc9fd7574 | ||
|
|
e59e93696b | ||
|
|
f6d3a7987d | ||
|
|
00d2d862c2 | ||
|
|
f35397cf8d | ||
|
|
eb8df23366 | ||
|
|
4b61a3cbf3 | ||
|
|
7927ec647f | ||
|
|
63b30e2925 | ||
|
|
d178853392 | ||
|
|
3c230ba1bf | ||
|
|
e0509ebd9f | ||
|
|
29533650a8 | ||
|
|
2bcb85d431 | ||
|
|
9ef7e8c5d0 | ||
|
|
ef152c47a6 | ||
|
|
2a7de25505 | ||
|
|
e16f2c4dab | ||
|
|
044d7a4797 | ||
|
|
f9bf2e8239 | ||
|
|
0968610ba7 | ||
|
|
69471950f0 | ||
|
|
faa151d5ad | ||
|
|
0654b2dc43 | ||
|
|
b094c9cd87 | ||
|
|
0ae6ddcf7f | ||
|
|
baab966b4e | ||
|
|
173a61039c | ||
|
|
a255b5bc75 | ||
|
|
31aa040758 | ||
|
|
31c3af4866 | ||
|
|
aabe39d0f8 | ||
|
|
fbdeea7889 | ||
|
|
e1f90e6baf | ||
|
|
6d6659c85e | ||
|
|
da2dc5fa1e | ||
|
|
1963d80d2c | ||
|
|
e169189441 | ||
|
|
037519936a | ||
|
|
422102989c | ||
|
|
44142ab4f9 | ||
|
|
f3671d21f3 | ||
|
|
9b42ad3859 | ||
|
|
be8fbafd71 | ||
|
|
0d3e674500 | ||
|
|
8c0af03448 | ||
|
|
5bf9e1d655 | ||
|
|
890f3fcf5d | ||
|
|
89eea91ed5 | ||
|
|
66ba600a36 | ||
|
|
07e9a01e87 | ||
|
|
34d5cdec96 | ||
|
|
e39a2d00bf | ||
|
|
d8bd35e8d6 | ||
|
|
3f25db79b8 | ||
|
|
1cb3e6bd49 | ||
|
|
80d1056ddf | ||
|
|
0c3cf1f5f8 | ||
|
|
810ce1ce57 | ||
|
|
e4cb359625 | ||
|
|
3877486712 | ||
|
|
41f40248d2 | ||
|
|
8c72fd57f1 | ||
|
|
dd420cbfcf | ||
|
|
a89ec0eaf9 | ||
|
|
5c94ab9f22 | ||
|
|
71c319ccf0 | ||
|
|
12f2ff931b | ||
|
|
ad27f8bac3 | ||
|
|
ebf50edb79 |
94
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,94 +0,0 @@
|
||||
name: Bug report
|
||||
description: Report a bug in DuckStation
|
||||
body:
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Please read before creating a new bug report:**
|
||||
1. Make sure there is not already an issue for this bug by [searching in **both** open and closed issues](https://github.com/stenzek/duckstation/issues?q=is%3Aissue+sort%3Aupdated-desc+).
|
||||
2. All enhancements **must** be off. To quickly disable all enhancements with affecting your normal configuration, you can check **Disable All Enhancements** in Advanced Options.
|
||||
3. All advanced options **must** be at their default values.
|
||||
4. No cheats may be active. If you were using cheats, they should be disabled, and the game must be rebooted before reporting the bug.
|
||||
5. Do not share save state files. (Sharing memory card files is OK.)
|
||||
6. Verify your BIOS and game dumps, as we can not assist with issues resulting from bad dumps.
|
||||
7. If playing PAL region software, please check whether or not the game has LibCrypt protection. If it does, make sure you have a [correct SBI file](https://github.com/stenzek/duckstation#libcrypt-protection-and-sbi-files).
|
||||
8. Please post your bug report in English, as this is the only language spoken by the developers. The [Discord server](https://discord.gg/Buktv3t) has many helpful people if you need help translating.
|
||||
9. Issues about the libretro core will be deleted (you will be blocked from the repository if you create such an issue). That core is not DuckStation, it is a broken fork, and has nothing to do with us.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Game details
|
||||
description: |
|
||||
Specify the game's serial code, full name and region (USA, Europe, Japan).
|
||||
placeholder: SLUS-00404 Ace Combat 2 (USA)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description of the issue/bug
|
||||
description: |
|
||||
Describe what you are seeing and/or hearing during gameplay. What doesn't work, and how do you expect it to work instead?
|
||||
You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
Try to provide as much detail as possible to reproduce the issue.
|
||||
Having reproducible issues is a *prerequisite* for contributors to be able to solve them.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Software and hardware information
|
||||
description: |
|
||||
For desktops and laptops, specify your OS version, CPU and graphics card information (model and driver version).
|
||||
For mobile devices, specify your OS version and device model name.
|
||||
placeholder: Windows 10, Intel Core i7-7500U, Intel HD Graphics 620 (27.20.100.9616)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: DuckStation version
|
||||
description: |
|
||||
Specify your DuckStation version and how you installed it (GitHub Releases, GitHub Actions, compiled from source, …).
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: DuckStation rendering backend
|
||||
description: |
|
||||
Specify the DuckStation rendering backend you were using when reporting this issue.
|
||||
If you can reproduce this issue using more than one rendering backend, mention it in the **Description of the issue/bug** section above.
|
||||
When reporting a graphics-related issue, please test all the rendering backends you can before submitting the issue.
|
||||
options:
|
||||
- Software
|
||||
- Direct3D 11
|
||||
- Direct3D 12
|
||||
- OpenGL
|
||||
- Vulkan
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: DuckStation controller backend, drivers and wrappers
|
||||
description: |
|
||||
Which controller backend are you using in DuckStation's General Settings?
|
||||
Have you installed any drivers or wrappers on your system, or do you have any programs like Steam open?
|
||||
If so, specify which drivers/wrappers you are using.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Add any other context about the problem here.
|
||||
10
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,10 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
|
||||
contact_links:
|
||||
- name: Game compatibility list
|
||||
url: https://docs.google.com/spreadsheets/d/1H66MxViRjjE5f8hOl5RQmF5woS1murio2dsLn14kEqo/edit
|
||||
about: Please refer to the game compatibility list before opening an issue.
|
||||
|
||||
- name: Discord server
|
||||
- url: https://discord.gg/Buktv3t
|
||||
- about: Please ask support questions on the Discord server, not here.
|
||||
43
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,43 +0,0 @@
|
||||
name: Feature request
|
||||
description: Request a feature to be added or improved in DuckStation
|
||||
body:
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Please read before creating a new feature request:**
|
||||
1. Make sure there is not already an issue for this feature request by [searching in **both** open and closed issues](https://github.com/stenzek/duckstation/issues?q=is%3Aissue+sort%3Aupdated-desc+).
|
||||
2. Please open **one issue per requested feature**. Do not cram several unrelated feature requests in a single issue, as this makes it harder for contributors to track what's being worked on.
|
||||
3. Please post your feature request in English, as this is the only language spoken by the developers. The [Discord server](https://discord.gg/Buktv3t) has many helpful people if you need help translating.
|
||||
4. Issues about the libretro core will be deleted (you will be blocked from the repository if you create such an issue). That core is not DuckStation, it is a broken fork, and has nothing to do with us.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Problem statement
|
||||
description: |
|
||||
Is your feature request related to a problem? Please describe.
|
||||
placeholder: Example - "I'm always frustrated when […]"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Proposed solution
|
||||
description: |
|
||||
A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: |
|
||||
Describe alternatives you've considered.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Add any other context about the problem or proposed feature here.
|
||||
22
.github/workflows/flathub-publish.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Flathub Publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
flathub_branch:
|
||||
description: "Flathub branch to push to"
|
||||
required: true
|
||||
default: "stable"
|
||||
type: "choice"
|
||||
options:
|
||||
- "stable"
|
||||
- "beta"
|
||||
|
||||
jobs:
|
||||
linux-flatpak:
|
||||
name: Build Flatpak
|
||||
uses: "./.github/workflows/linux-flatpak-build.yml"
|
||||
with:
|
||||
flathub_publish: true
|
||||
flathub_branch: ${{ inputs.flathub_branch }}
|
||||
secrets: inherit
|
||||
147
.github/workflows/linux-appimage-build.yml
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
name: 🐧 Linux AppImage
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux-x64-appimage-build:
|
||||
name: "x64"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Packages
|
||||
run: scripts/packaging/appimage/install-packages.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: ~/deps
|
||||
key: deps ${{ hashFiles('scripts/deps/build-dependencies-linux.sh', 'scripts/deps/build-ffmpeg-linux.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: scripts/deps/build-dependencies-linux.sh "$HOME/deps"
|
||||
|
||||
- name: Build FFmpeg
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: scripts/deps/build-ffmpeg-linux.sh "$HOME/deps"
|
||||
|
||||
- name: Initialize Build Tag
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tag Asset
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_ASSET "DuckStation-x64.AppImage"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: bash
|
||||
run: |
|
||||
cd data/resources
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Compile Build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "linux-x64-appimage"
|
||||
path: "DuckStation-x64.AppImage"
|
||||
|
||||
|
||||
linux-x64-sse2-appimage-build:
|
||||
name: "x64 SSE2"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Packages
|
||||
run: scripts/packaging/appimage/install-packages.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: ~/deps
|
||||
key: deps ${{ hashFiles('scripts/deps/build-dependencies-linux.sh', 'scripts/deps/build-ffmpeg-linux.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: scripts/deps/build-dependencies-linux.sh "$HOME/deps"
|
||||
|
||||
- name: Build FFmpeg
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: scripts/deps/build-ffmpeg-linux.sh "$HOME/deps"
|
||||
|
||||
- name: Initialize Build Tag
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tag Asset
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_ASSET "DuckStation-x64-SSE2.AppImage"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: bash
|
||||
run: |
|
||||
cd data/resources
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Compile Build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDISABLE_SSE4=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64-SSE2
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "linux-x64-sse2-appimage"
|
||||
path: "DuckStation-x64-SSE2.AppImage"
|
||||
113
.github/workflows/linux-flatpak-build.yml
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
name: 📦 Linux Flatpak
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
flathub_publish:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
flathub_branch:
|
||||
required: false
|
||||
type: string
|
||||
default: "stable"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux-flatpak-build:
|
||||
name: "x64"
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
|
||||
options: --privileged
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
|
||||
# Work around container ownership issue
|
||||
- name: Set Safe Directory
|
||||
shell: bash
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
- name: Initialize Build Tag
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tags
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: bash
|
||||
run: |
|
||||
cd data/resources
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
scripts/packaging/generate-metainfo.sh scripts/packaging/flatpak
|
||||
cat scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate AppStream XML
|
||||
run: flatpak-builder-lint appstream scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate Manifest
|
||||
run: flatpak-builder-lint manifest scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: duckstation-x64.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/media
|
||||
branch: stable
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/packaging/flatpak/**/*.yaml') }}
|
||||
|
||||
- name: Validate Build
|
||||
run: |
|
||||
flatpak-builder-lint repo repo
|
||||
|
||||
- name: Push To Flathub Beta
|
||||
if: inputs.flathub_publish && inputs.flathub_branch == 'beta'
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@b6c92176b7f578aedd80cac74cd8f0336f618e89
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
token: ${{ secrets.FLATHUB_BETA_TOKEN }}
|
||||
build-log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Push To Flathub Stable
|
||||
if: inputs.flathub_publish && inputs.flathub_branch == 'stable'
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@b6c92176b7f578aedd80cac74cd8f0336f618e89
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
token: ${{ secrets.FLATHUB_STABLE_TOKEN }}
|
||||
build-log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Upload Flatpak
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "linux-flatpak"
|
||||
path: "duckstation-x64.flatpak"
|
||||
79
.github/workflows/macos-build.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
name: 🍎 MacOS
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
macos-build:
|
||||
name: "Universal"
|
||||
runs-on: macos-14
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Xcode 16.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.1.app
|
||||
|
||||
- name: Install packages
|
||||
shell: bash
|
||||
run: |
|
||||
brew install ninja
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps-mac
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: ~/deps
|
||||
key: deps-mac ${{ hashFiles('scripts/deps/build-dependencies-mac.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps-mac.outputs.cache-hit != 'true'
|
||||
run: scripts/deps/build-dependencies-mac.sh "$HOME/deps"
|
||||
|
||||
- name: Initialize Build Tag
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tags
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_ASSET "duckstation-mac-release.zip"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: bash
|
||||
run: |
|
||||
cd data/resources
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Compile and Zip .app
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
export MACOSX_DEPLOYMENT_TARGET=11.0
|
||||
cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_BUILD_TYPE=Release -DENABLE_OPENGL=OFF -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -G Ninja ..
|
||||
cmake --build . --parallel
|
||||
mv bin/DuckStation.app .
|
||||
codesign -s - --deep -f -v DuckStation.app
|
||||
zip -r duckstation-mac-release.zip DuckStation.app/
|
||||
|
||||
- name: Upload MacOS .app
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "macos"
|
||||
path: "build/duckstation-mac-release.zip"
|
||||
88
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Automated Builds
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'appveyor.yml'
|
||||
- 'scripts/*'
|
||||
- '.github/ISSUE_TEMPLATE/*'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'appveyor.yml'
|
||||
- 'scripts/*'
|
||||
- '.github/ISSUE_TEMPLATE/*'
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: 💻 Windows
|
||||
uses: "./.github/workflows/windows-build.yml"
|
||||
linux-appimage:
|
||||
name: 🐧 Linux AppImage
|
||||
uses: "./.github/workflows/linux-appimage-build.yml"
|
||||
linux-flatpak:
|
||||
name: 📦 Linux Flatpak
|
||||
uses: "./.github/workflows/linux-flatpak-build.yml"
|
||||
macos:
|
||||
name: 🍎 MacOS
|
||||
uses: "./.github/workflows/macos-build.yml"
|
||||
|
||||
create-release:
|
||||
name: 📤 Create Release
|
||||
needs: [windows, linux-appimage, linux-flatpak, macos]
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
path: ./artifacts/
|
||||
|
||||
- name: Display Downloaded Artifacts
|
||||
run: find ./artifacts/
|
||||
|
||||
- name: Create Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "preview"
|
||||
prerelease: true
|
||||
title: "Latest Preview Build"
|
||||
files: |
|
||||
./artifacts/windows-x64/duckstation-windows-x64-release.zip
|
||||
./artifacts/windows-x64/duckstation-windows-x64-release-symbols.zip
|
||||
./artifacts/windows-x64-sse2/duckstation-windows-x64-sse2-release.zip
|
||||
./artifacts/windows-x64-sse2/duckstation-windows-x64-sse2-release-symbols.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release-symbols.zip
|
||||
./artifacts/linux-x64-appimage/DuckStation-x64.AppImage
|
||||
./artifacts/linux-x64-sse2-appimage/DuckStation-x64-SSE2.AppImage
|
||||
./artifacts/linux-flatpak/duckstation-x64.flatpak
|
||||
./artifacts/macos/duckstation-mac-release.zip
|
||||
|
||||
- name: Create Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "latest"
|
||||
prerelease: false
|
||||
title: "Latest Rolling Release"
|
||||
files: |
|
||||
./artifacts/windows-x64/duckstation-windows-x64-release.zip
|
||||
./artifacts/windows-x64/duckstation-windows-x64-release-symbols.zip
|
||||
./artifacts/windows-x64-sse2/duckstation-windows-x64-sse2-release.zip
|
||||
./artifacts/windows-x64-sse2/duckstation-windows-x64-sse2-release-symbols.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release-symbols.zip
|
||||
./artifacts/linux-x64-appimage/DuckStation-x64.AppImage
|
||||
./artifacts/linux-x64-sse2-appimage/DuckStation-x64-SSE2.AppImage
|
||||
./artifacts/linux-flatpak/duckstation-x64.flatpak
|
||||
./artifacts/macos/duckstation-mac-release.zip
|
||||
|
||||
440
.github/workflows/rolling-release.yml
vendored
@@ -1,440 +0,0 @@
|
||||
name: Create rolling release
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'appveyor.yml'
|
||||
- 'scripts/*'
|
||||
- '.github/ISSUE_TEMPLATE/*'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'appveyor.yml'
|
||||
- 'scripts/*'
|
||||
- '.github/ISSUE_TEMPLATE/*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
windows-build:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: |
|
||||
dep/msvc/deps-arm64
|
||||
dep/msvc/deps-x64
|
||||
key: deps ${{ hashFiles('scripts/build-dependencies-windows-arm64.bat', 'scripts/build-dependencies-windows-x64.bat') }}
|
||||
|
||||
- name: Build X64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/build-dependencies-windows-x64.bat
|
||||
|
||||
- name: Build ARM64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/build-dependencies-windows-arm64.bat
|
||||
|
||||
- name: Tag as preview build
|
||||
if: github.ref == 'refs/heads/master'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-x64-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAG "preview" >> src/scmversion/tag.h
|
||||
|
||||
|
||||
- name: Tag as dev build
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-x64-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAG "latest" >> src/scmversion/tag.h
|
||||
|
||||
- name: Update RC version fields
|
||||
shell: cmd
|
||||
run: |
|
||||
cd src\scmversion
|
||||
call update_rc_version.bat
|
||||
cd ..\..
|
||||
git update-index --assume-unchanged src/duckstation-qt/duckstation-qt.rc
|
||||
|
||||
- name: Compile x64 release build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
msbuild duckstation.sln -t:Build -p:Platform=x64;Configuration=ReleaseLTCG-Clang
|
||||
|
||||
- name: Create x64 symbols archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-x64-release-symbols.zip ./bin/x64/*.pdb
|
||||
|
||||
- name: Remove extra bloat before archiving
|
||||
shell: cmd
|
||||
run: |
|
||||
del /Q bin\x64\*.pdb bin\x64\*.exp bin\x64\*.lib bin\x64\*.iobj bin\x64\*.ipdb bin\x64\common-tests*
|
||||
rename bin\x64\updater-x64-ReleaseLTCG.exe updater.exe
|
||||
|
||||
- name: Create x64 release archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-x64-release.zip ./bin/x64/*
|
||||
|
||||
- name: Upload x64 release artifact
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "windows"
|
||||
path: "duckstation-windows-x64-release*.zip"
|
||||
|
||||
|
||||
windows-arm64-build:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: |
|
||||
dep/msvc/deps-arm64
|
||||
dep/msvc/deps-x64
|
||||
key: deps ${{ hashFiles('scripts/build-dependencies-windows-arm64.bat', 'scripts/build-dependencies-windows-x64.bat') }}
|
||||
|
||||
- name: Build X64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/build-dependencies-windows-x64.bat
|
||||
|
||||
- name: Build ARM64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/build-dependencies-windows-arm64.bat
|
||||
|
||||
- name: Tag as preview build
|
||||
if: github.ref == 'refs/heads/master'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-arm64-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAG "preview" >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as dev build
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-arm64-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAG "latest" >> src/scmversion/tag.h
|
||||
|
||||
- name: Update RC version fields
|
||||
shell: cmd
|
||||
run: |
|
||||
cd src\scmversion
|
||||
call update_rc_version.bat
|
||||
cd ..\..
|
||||
git update-index --assume-unchanged src/duckstation-qt/duckstation-qt.rc
|
||||
|
||||
- name: Compile arm64 release build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
|
||||
msbuild duckstation.sln -t:Build -p:Platform=ARM64;Configuration=ReleaseLTCG-Clang
|
||||
|
||||
- name: Create arm64 symbols archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-arm64-release-symbols.zip ./bin/ARM64/*.pdb
|
||||
|
||||
- name: Remove extra bloat before archiving
|
||||
shell: cmd
|
||||
run: |
|
||||
del /Q bin\ARM64\*.pdb bin\ARM64\*.exp bin\ARM64\*.lib bin\ARM64\*.iobj bin\ARM64\*.ipdb bin\ARM64\common-tests*
|
||||
rename bin\ARM64\updater-ARM64-ReleaseLTCG.exe updater.exe
|
||||
|
||||
- name: Create arm64 release archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-arm64-release.zip ./bin/ARM64/*
|
||||
|
||||
- name: Upload arm64 release artifact
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "windows-arm64"
|
||||
path: "duckstation-windows-arm64-release*.zip"
|
||||
|
||||
|
||||
linux-build:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
# Work around https://github.com/actions/runner-images/issues/8659
|
||||
- name: Remove GCC 13 from runner image
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-downgrades 'libc6=2.35-0ubuntu*' 'libc6-dev=2.35-0ubuntu*' libstdc++6=12.3.0-1ubuntu1~22.04 libgcc-s1=12.3.0-1ubuntu1~22.04
|
||||
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install packages
|
||||
shell: bash
|
||||
run: |
|
||||
# Workaround for https://github.com/actions/runner-images/issues/675
|
||||
scripts/retry.sh wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo scripts/retry.sh apt-add-repository -n 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main'
|
||||
|
||||
sudo scripts/retry.sh apt-get update &&
|
||||
sudo scripts/retry.sh apt-get -y install \
|
||||
build-essential clang-17 cmake curl extra-cmake-modules git libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdecor-0-dev libegl-dev libevdev-dev \
|
||||
libfontconfig-dev libfreetype-dev libfuse2 libgtk-3-dev libgudev-1.0-dev libharfbuzz-dev libinput-dev libopengl-dev libpipewire-0.3-dev libpulse-dev \
|
||||
libssl-dev libudev-dev libwayland-dev libx11-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev libxcb-glx0-dev \
|
||||
libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-shape0-dev \
|
||||
libxcb-shm0-dev libxcb-sync-dev libxcb-util-dev libxcb-xfixes0-dev libxcb-xinput-dev libxcb-xkb-dev libxext-dev libxkbcommon-x11-dev libxrandr-dev lld-17 \
|
||||
llvm-17 ninja-build patchelf pkg-config zlib1g-dev
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: ~/deps
|
||||
key: deps ${{ hashFiles('scripts/build-dependencies-linux.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: scripts/build-dependencies-linux.sh "$HOME/deps"
|
||||
|
||||
- name: Tag as preview build
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_ASSET "DuckStation-x64.AppImage"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as dev build
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_ASSET "DuckStation-x64.AppImage"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
|
||||
- name: Compile build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "linux-x64-appimage-qt"
|
||||
path: "DuckStation-x64.AppImage"
|
||||
|
||||
|
||||
linux-flatpak-build:
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.7
|
||||
options: --privileged
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
|
||||
# Work around container ownership issue
|
||||
- name: Set Safe Directory
|
||||
shell: bash
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
scripts/generate-metainfo.sh scripts/flatpak
|
||||
cat scripts/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate AppStream XML
|
||||
run: flatpak-builder-lint appstream scripts/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate manifest
|
||||
run: flatpak-builder-lint manifest scripts/flatpak/org.duckstation.DuckStation.json
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: duckstation-x64.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: scripts/flatpak/org.duckstation.DuckStation.json
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/media
|
||||
branch: stable
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/flatpak/**/*.json') }}
|
||||
|
||||
- name: Push to Flathub stable
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
token: ${{ secrets.FLATHUB_STABLE_TOKEN }}
|
||||
build-log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Validate build
|
||||
run: |
|
||||
flatpak-builder-lint repo repo
|
||||
|
||||
- name: Upload Flatpak
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "linux-flatpak"
|
||||
path: "duckstation-x64.flatpak"
|
||||
|
||||
|
||||
macos-build:
|
||||
runs-on: macos-14
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Xcode 15.4
|
||||
run: sudo xcode-select -s /Applications/Xcode_15.4.app
|
||||
|
||||
- name: Install packages
|
||||
shell: bash
|
||||
run: |
|
||||
brew install curl ninja
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps-mac
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: ~/deps
|
||||
key: deps-mac ${{ hashFiles('scripts/build-dependencies-mac.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps-mac.outputs.cache-hit != 'true'
|
||||
run: scripts/build-dependencies-mac.sh "$HOME/deps"
|
||||
|
||||
- name: Tag as preview build
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_ASSET "duckstation-mac-release.zip"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as dev build
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_ASSET "duckstation-mac-release.zip"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Compile and zip .app
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
export MACOSX_DEPLOYMENT_TARGET=11.0
|
||||
cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_BUILD_TYPE=Release -DENABLE_OPENGL=OFF -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -G Ninja ..
|
||||
cmake --build . --parallel
|
||||
mv bin/DuckStation.app .
|
||||
codesign -s - --deep -f -v DuckStation.app
|
||||
zip -r duckstation-mac-release.zip DuckStation.app/
|
||||
|
||||
- name: Upload macOS .app
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "macos"
|
||||
path: "build/duckstation-mac-release.zip"
|
||||
|
||||
|
||||
create-release:
|
||||
needs: [windows-build, windows-arm64-build, linux-build, linux-flatpak-build, macos-build]
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
path: ./artifacts/
|
||||
|
||||
- name: Display Downloaded Artifacts
|
||||
run: find ./artifacts/
|
||||
|
||||
- name: Create preview release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "preview"
|
||||
prerelease: true
|
||||
title: "Latest Preview Build"
|
||||
files: |
|
||||
./artifacts/windows/duckstation-windows-x64-release.zip
|
||||
./artifacts/windows/duckstation-windows-x64-release-symbols.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release-symbols.zip
|
||||
./artifacts/linux-x64-appimage-qt/DuckStation-x64.AppImage
|
||||
./artifacts/linux-flatpak/duckstation-x64.flatpak
|
||||
./artifacts/macos/duckstation-mac-release.zip
|
||||
|
||||
- name: Create dev release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "latest"
|
||||
prerelease: false
|
||||
title: "Latest Rolling Release"
|
||||
files: |
|
||||
./artifacts/windows/duckstation-windows-x64-release.zip
|
||||
./artifacts/windows/duckstation-windows-x64-release-symbols.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release.zip
|
||||
./artifacts/windows-arm64/duckstation-windows-arm64-release-symbols.zip
|
||||
./artifacts/linux-x64-appimage-qt/DuckStation-x64.AppImage
|
||||
./artifacts/linux-flatpak/duckstation-x64.flatpak
|
||||
./artifacts/macos/duckstation-mac-release.zip
|
||||
|
||||
36
.github/workflows/upload-caches.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Upload Caches
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
upload-windows-cache:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: |
|
||||
dep/msvc/deps-arm64
|
||||
dep/msvc/deps-x64
|
||||
key: deps ${{ hashFiles('scripts/deps/build-dependencies-windows-arm64.bat', 'scripts/deps/build-dependencies-windows-x64.bat') }}
|
||||
|
||||
- name: Zip Cache Files
|
||||
if: steps.cache-deps.outputs.cache-hit == 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r deps-x64.zip ./dep/msvc/deps-x64
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r deps-arm64.zip ./dep/msvc/deps-arm64
|
||||
|
||||
- name: Upload Cache Files
|
||||
if: steps.cache-deps.outputs.cache-hit == 'true'
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "windows"
|
||||
path: "deps-*.zip"
|
||||
300
.github/workflows/windows-build.yml
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
name: 💻 Windows
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
windows-x64-build:
|
||||
name: "x64"
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: |
|
||||
dep/msvc/deps-arm64
|
||||
dep/msvc/deps-x64
|
||||
key: deps ${{ hashFiles('scripts/deps/build-dependencies-windows-arm64.bat', 'scripts/deps/build-dependencies-windows-x64.bat') }}
|
||||
|
||||
- name: Build x64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/deps/build-dependencies-windows-x64.bat
|
||||
|
||||
- name: Build ARM64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/deps/build-dependencies-windows-arm64.bat
|
||||
|
||||
- name: Initialize Build Tag
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tag Asset
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-x64-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_TAG "preview" >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release Build
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_TAG "latest" >> src/scmversion/tag.h
|
||||
|
||||
- name: Update RC Version Fields
|
||||
shell: cmd
|
||||
run: |
|
||||
cd src\scmversion
|
||||
call update_rc_version.bat
|
||||
cd ..\..
|
||||
git update-index --assume-unchanged src/duckstation-qt/duckstation-qt.rc
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: cmd
|
||||
run: |
|
||||
cd data/resources
|
||||
aria2c -Z "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
aria2c -Z "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Compile x64 Release Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
msbuild duckstation.sln -t:Build -p:Platform=x64;Configuration=ReleaseLTCG-Clang
|
||||
|
||||
- name: Create x64 Symbols Archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-x64-release-symbols.zip ./bin/x64/*.pdb
|
||||
|
||||
- name: Remove Extra Bloat Before Archiving
|
||||
shell: cmd
|
||||
run: |
|
||||
del /Q bin\x64\*.pdb bin\x64\*.exp bin\x64\*.lib bin\x64\*.iobj bin\x64\*.ipdb bin\x64\common-tests*
|
||||
rename bin\x64\updater-x64-ReleaseLTCG.exe updater.exe
|
||||
|
||||
- name: Create x64 Release Archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-x64-release.zip ./bin/x64/*
|
||||
|
||||
- name: Upload x64 Release Artifact
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "windows-x64"
|
||||
path: "duckstation-windows-x64-release*.zip"
|
||||
|
||||
|
||||
windows-x64-sse2-build:
|
||||
name: "x64 SSE2"
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: |
|
||||
dep/msvc/deps-arm64
|
||||
dep/msvc/deps-x64
|
||||
key: deps ${{ hashFiles('scripts/deps/build-dependencies-windows-arm64.bat', 'scripts/deps/build-dependencies-windows-x64.bat') }}
|
||||
|
||||
- name: Build x64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/deps/build-dependencies-windows-x64.bat
|
||||
|
||||
- name: Build ARM64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/deps/build-dependencies-windows-arm64.bat
|
||||
|
||||
- name: Initialize Build Tag
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tag Asset
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-x64-sse2-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_TAG "preview" >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release Build
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_TAG "latest" >> src/scmversion/tag.h
|
||||
|
||||
- name: Update RC Version Fields
|
||||
shell: cmd
|
||||
run: |
|
||||
cd src\scmversion
|
||||
call update_rc_version.bat
|
||||
cd ..\..
|
||||
git update-index --assume-unchanged src/duckstation-qt/duckstation-qt.rc
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: cmd
|
||||
run: |
|
||||
cd data/resources
|
||||
aria2c -Z "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
aria2c -Z "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Compile x64 Release Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
msbuild duckstation.sln -t:Build -p:Platform=x64;Configuration=ReleaseLTCG-Clang-SSE2
|
||||
|
||||
- name: Create x64 Symbols Archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-x64-sse2-release-symbols.zip ./bin/x64/*.pdb
|
||||
|
||||
- name: Remove Extra Bloat Before Archiving
|
||||
shell: cmd
|
||||
run: |
|
||||
del /Q bin\x64\*.pdb bin\x64\*.exp bin\x64\*.lib bin\x64\*.iobj bin\x64\*.ipdb bin\x64\common-tests*
|
||||
rename bin\x64\updater-x64-ReleaseLTCG-SSE2.exe updater.exe
|
||||
|
||||
- name: Create x64 Release Archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-x64-sse2-release.zip ./bin/x64/*
|
||||
|
||||
- name: Upload x64 Release Artifact
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "windows-x64-sse2"
|
||||
path: "duckstation-windows-x64-sse2-release*.zip"
|
||||
|
||||
|
||||
windows-arm64-build:
|
||||
name: "ARM64"
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: |
|
||||
dep/msvc/deps-arm64
|
||||
dep/msvc/deps-x64
|
||||
key: deps ${{ hashFiles('scripts/deps/build-dependencies-windows-arm64.bat', 'scripts/deps/build-dependencies-windows-x64.bat') }}
|
||||
|
||||
- name: Build x64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/deps/build-dependencies-windows-x64.bat
|
||||
|
||||
- name: Build ARM64 Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
DEBUG: 0
|
||||
run: scripts/deps/build-dependencies-windows-arm64.bat
|
||||
|
||||
- name: Initialize Build Tag
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #pragma once > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tag Asset
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_ASSET "duckstation-windows-arm64-release.zip" >> src/scmversion/tag.h
|
||||
echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_TAG "preview" >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
shell: cmd
|
||||
run: |
|
||||
echo #define SCM_RELEASE_TAG "latest" >> src/scmversion/tag.h
|
||||
|
||||
- name: Update RC Version Fields
|
||||
shell: cmd
|
||||
run: |
|
||||
cd src\scmversion
|
||||
call update_rc_version.bat
|
||||
cd ..\..
|
||||
git update-index --assume-unchanged src/duckstation-qt/duckstation-qt.rc
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: cmd
|
||||
run: |
|
||||
cd data/resources
|
||||
aria2c -Z "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
aria2c -Z "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Compile ARM64 Release Build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
|
||||
msbuild duckstation.sln -t:Build -p:Platform=ARM64;Configuration=ReleaseLTCG-Clang
|
||||
|
||||
- name: Create ARM64 symbols archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-arm64-release-symbols.zip ./bin/ARM64/*.pdb
|
||||
|
||||
- name: Remove Extra Bloat Before Archiving
|
||||
shell: cmd
|
||||
run: |
|
||||
del /Q bin\ARM64\*.pdb bin\ARM64\*.exp bin\ARM64\*.lib bin\ARM64\*.iobj bin\ARM64\*.ipdb bin\ARM64\common-tests*
|
||||
rename bin\ARM64\updater-ARM64-ReleaseLTCG.exe updater.exe
|
||||
|
||||
- name: Create ARM64 Release Archive
|
||||
shell: cmd
|
||||
run: |
|
||||
"C:\Program Files\7-Zip\7z.exe" a -r duckstation-windows-arm64-release.zip ./bin/ARM64/*
|
||||
|
||||
- name: Upload ARM64 Release Artifact
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: "windows-arm64"
|
||||
path: "duckstation-windows-arm64-release*.zip"
|
||||
2
.gitignore
vendored
@@ -8,6 +8,7 @@
|
||||
|
||||
# dependency build temp files
|
||||
deps-build/
|
||||
/deps/
|
||||
|
||||
# vs stuff
|
||||
.vs
|
||||
@@ -27,6 +28,7 @@ CMakeFiles
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
/.cache/
|
||||
|
||||
# unix intermediate files
|
||||
config.h
|
||||
|
||||
@@ -33,10 +33,14 @@ detect_cache_line_size()
|
||||
|
||||
# Build options. Depends on system attributes.
|
||||
include(DuckStationBuildOptions)
|
||||
include(DuckStationDependencies)
|
||||
|
||||
# Set _DEBUG macro for Debug builds.
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
# Enable PIC on Linux, otherwise the builds do not support ASLR.
|
||||
if(LINUX OR BSD)
|
||||
include(CheckPIESupported)
|
||||
check_pie_supported()
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
# Release build optimizations for MSVC.
|
||||
if(MSVC)
|
||||
@@ -51,14 +55,18 @@ if(MSVC)
|
||||
|
||||
# RelWithDebInfo is set to Ob1 instead of Ob2.
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_C_FLAGS_DEVEL "${CMAKE_C_FLAGS_DEVEL}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_CXX_FLAGS_DEVEL "${CMAKE_CXX_FLAGS_DEVEL}")
|
||||
|
||||
# Disable incremental linking in RelWithDebInfo.
|
||||
string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_DEVEL}")
|
||||
|
||||
# COMDAT folding/remove unused functions.
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_DEVEL} /OPT:REF /OPT:ICF")
|
||||
endif()
|
||||
|
||||
# Warning disables.
|
||||
@@ -77,6 +85,9 @@ if(MSVC)
|
||||
string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_HAS_EXCEPTIONS=0 /permissive-")
|
||||
if(COMPILER_CLANG_CL)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /clang:-fno-rtti")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
|
||||
endif()
|
||||
@@ -84,6 +95,18 @@ endif()
|
||||
# Write binaries to a seperate directory.
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
|
||||
|
||||
# Installation directories. If INSTALL_SELF_CONTAINED is set, everything goes
|
||||
# into one directory, otherwise CMAKE_INSTALL_PREFIX/bin is used (for Flatpak).
|
||||
if(ALLOW_INSTALL)
|
||||
if(INSTALL_SELF_CONTAINED)
|
||||
set(CMAKE_INSTALL_BINDIR "${CMAKE_INSTALL_PREFIX}")
|
||||
set(CMAKE_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}")
|
||||
else()
|
||||
# Let GNUInstallDirs set the destinations.
|
||||
include(GNUInstallDirs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Enable large file support on Linux 32-bit platforms.
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
add_definitions("-D_FILE_OFFSET_BITS=64")
|
||||
@@ -102,7 +125,6 @@ set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Recursively include the source tree.
|
||||
include(DuckStationDependencies)
|
||||
add_subdirectory(dep)
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ function(copy_base_translations target)
|
||||
target_sources(${target} PRIVATE ${path})
|
||||
if(APPLE)
|
||||
set_source_files_properties(${path} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/translations)
|
||||
elseif(ALLOW_INSTALL)
|
||||
install(FILES "${path}" DESTINATION "${CMAKE_INSTALL_BINDIR}/translations")
|
||||
else()
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${path}" "$<TARGET_FILE_DIR:${target}>/translations")
|
||||
|
||||
@@ -5,11 +5,28 @@ option(BUILD_NOGUI_FRONTEND "Build the NoGUI frontend" OFF)
|
||||
option(BUILD_QT_FRONTEND "Build the Qt frontend" ON)
|
||||
option(BUILD_REGTEST "Build regression test runner" OFF)
|
||||
option(BUILD_TESTS "Build unit tests" OFF)
|
||||
option(DISABLE_SSE4 "Build with SSE4 instructions disabled, reduces performance" OFF)
|
||||
|
||||
if(LINUX OR BSD)
|
||||
option(ENABLE_X11 "Support X11 window system" ON)
|
||||
option(ENABLE_WAYLAND "Support Wayland window system" ON)
|
||||
option(ALLOW_INSTALL "Allow installation to CMAKE_INSTALL_PREFIX" OFF)
|
||||
option(INSTALL_SELF_CONTAINED "Make self-contained install, i.e. everything in one directory" ON)
|
||||
endif()
|
||||
if(APPLE)
|
||||
option(SKIP_POSTPROCESS_BUNDLE "Disable bundle post-processing, including Qt additions" OFF)
|
||||
endif()
|
||||
|
||||
# Set _DEBUG macro for Debug builds.
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
|
||||
# Create the Devel build type based on RelWithDebInfo.
|
||||
set(CMAKE_C_FLAGS_DEVEL "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEVEL" CACHE STRING "Flags used by the C compiler during DEVEL builds." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_DEVEL "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_DEVEL" CACHE STRING "Flags used by the CXX compiler during DEVEL builds." FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used for the linker during DEVEL builds." FORCE)
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEVEL "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of modules during DEVEL builds." FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of shared libraries during DEVEL builds." FORCE)
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_DEVEL "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of static libraries during DEVEL builds." FORCE)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES "Devel")
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL CMAKE_MODULE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_STATIC_LINKER_FLAGS_DEVEL)
|
||||
|
||||
@@ -24,9 +24,30 @@ if(BUILD_TESTS)
|
||||
message(STATUS "Building unit tests.")
|
||||
endif()
|
||||
|
||||
if(ALLOW_INSTALL)
|
||||
message(WARNING "Install target is enabled. This will install all DuckStation files into:
|
||||
${CMAKE_INSTALL_PREFIX}
|
||||
It does **not** use the LSB subdirectories of bin, share, etc, so you should disable this option if it is set to /usr or /usr/local.")
|
||||
|
||||
if(INSTALL_SELF_CONTAINED)
|
||||
message(STATUS "Creating self-contained install at ${CMAKE_INSTALL_PREFIX}")
|
||||
else()
|
||||
message(STATUS "Creating relative install at ${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS " CMAKE_INSTALL_BINDIR: ${CMAKE_INSTALL_BINDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED HOST_MIN_PAGE_SIZE AND DEFINED HOST_MAX_PAGE_SIZE)
|
||||
message(STATUS "Building with a dynamic page size of ${HOST_MIN_PAGE_SIZE} - ${HOST_MAX_PAGE_SIZE} bytes.")
|
||||
elseif(DEFINED HOST_PAGE_SIZE)
|
||||
message(STATUS "Building with detected page size of ${HOST_PAGE_SIZE}")
|
||||
endif()
|
||||
if(DEFINED HOST_CACHE_LINE_SIZE)
|
||||
message(STATUS "Building with detected cache line size of ${HOST_CACHE_LINE_SIZE}")
|
||||
endif()
|
||||
|
||||
if(NOT IS_SUPPORTED_COMPILER)
|
||||
message(WARNING "
|
||||
*************** UNSUPPORTED CONFIGURATION ***************
|
||||
message(WARNING "*************** UNSUPPORTED CONFIGURATION ***************
|
||||
You are not compiling DuckStation with a supported compiler.
|
||||
It may not even build successfully.
|
||||
DuckStation only supports the Clang and MSVC compilers.
|
||||
@@ -35,11 +56,18 @@ No support will be provided, continue at your own risk.
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
message(WARNING "
|
||||
*************** UNSUPPORTED CONFIGURATION ***************
|
||||
message(WARNING "*************** UNSUPPORTED CONFIGURATION ***************
|
||||
You are compiling DuckStation with CMake on Windows.
|
||||
It may not even build successfully.
|
||||
DuckStation only supports MSBuild on Windows.
|
||||
No support will be provided, continue at your own risk.
|
||||
*********************************************************")
|
||||
endif()
|
||||
|
||||
if(CPU_ARCH_X64 AND DISABLE_SSE4)
|
||||
message(WARNING "*********************** WARNING ***********************
|
||||
SSE4 instructions are disabled. This will result in
|
||||
reduced performance. You should not enable this option
|
||||
unless you have a pre-2008 CPU.
|
||||
*******************************************************")
|
||||
endif()
|
||||
|
||||
@@ -9,13 +9,18 @@ endif()
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(SDL2 2.30.4 REQUIRED)
|
||||
find_package(SDL2 2.30.8 REQUIRED)
|
||||
find_package(Zstd 1.5.6 REQUIRED)
|
||||
find_package(WebP REQUIRED) # v1.4.0, spews an error on Linux because no pkg-config.
|
||||
find_package(ZLIB REQUIRED) # 1.3, but Mac currently doesn't use it.
|
||||
find_package(PNG 1.6.40 REQUIRED)
|
||||
find_package(JPEG REQUIRED) # No version because flatpak uses libjpeg-turbo.
|
||||
find_package(Freetype 2.11.1 REQUIRED)
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(Freetype 2.13.2 REQUIRED) # 2.13.3, but flatpak is still on 2.13.2.
|
||||
find_package(lunasvg 2.4.1 REQUIRED)
|
||||
find_package(cpuinfo REQUIRED)
|
||||
find_package(DiscordRPC 3.4.0 REQUIRED)
|
||||
find_package(SoundTouch 2.3.3 REQUIRED)
|
||||
find_package(libzip 1.11.1 REQUIRED)
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package(CURL REQUIRED)
|
||||
@@ -23,8 +28,8 @@ endif()
|
||||
|
||||
if(ENABLE_X11)
|
||||
find_package(X11 REQUIRED)
|
||||
if (NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "XRandR extension is required")
|
||||
if (NOT X11_xcb_FOUND OR NOT X11_xcb_randr_FOUND OR NOT X11_X11_xcb_FOUND)
|
||||
message(FATAL_ERROR "XCB, XCB-randr and X11-xcb are required")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -34,18 +39,21 @@ if(ENABLE_WAYLAND)
|
||||
find_package(Wayland REQUIRED Egl)
|
||||
endif()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
find_package(Shaderc REQUIRED)
|
||||
find_package(spirv_cross_c_shared REQUIRED)
|
||||
if(BUILD_QT_FRONTEND)
|
||||
find_package(Qt6 6.8.0 COMPONENTS Core Gui Widgets LinguistTools REQUIRED)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
# We need to add the rpath for shaderc to the executable.
|
||||
get_filename_component(SHADERC_LIBRARY_DIRECTORY ${SHADERC_LIBRARY} DIRECTORY)
|
||||
list(APPEND CMAKE_BUILD_RPATH ${SHADERC_LIBRARY_DIRECTORY})
|
||||
get_target_property(SPIRV_CROSS_LIBRARY spirv-cross-c-shared IMPORTED_LOCATION)
|
||||
get_filename_component(SPIRV_CROSS_LIBRARY_DIRECTORY ${SPIRV_CROSS_LIBRARY} DIRECTORY)
|
||||
list(APPEND CMAKE_BUILD_RPATH ${SPIRV_CROSS_LIBRARY_DIRECTORY})
|
||||
endif()
|
||||
find_package(Shaderc REQUIRED)
|
||||
find_package(spirv_cross_c_shared REQUIRED)
|
||||
|
||||
if(LINUX AND NOT (ALLOW_INSTALL AND INSTALL_SELF_CONTAINED))
|
||||
# We need to add the rpath for shaderc to the executable.
|
||||
get_target_property(SHADERC_LIBRARY Shaderc::shaderc_shared IMPORTED_LOCATION)
|
||||
get_filename_component(SHADERC_LIBRARY_DIRECTORY ${SHADERC_LIBRARY} DIRECTORY)
|
||||
list(APPEND CMAKE_BUILD_RPATH ${SHADERC_LIBRARY_DIRECTORY})
|
||||
get_target_property(SPIRV_CROSS_LIBRARY spirv-cross-c-shared IMPORTED_LOCATION)
|
||||
get_filename_component(SPIRV_CROSS_LIBRARY_DIRECTORY ${SPIRV_CROSS_LIBRARY} DIRECTORY)
|
||||
list(APPEND CMAKE_BUILD_RPATH ${SPIRV_CROSS_LIBRARY_DIRECTORY})
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
@@ -56,6 +64,16 @@ if(NOT WIN32 AND NOT APPLE)
|
||||
find_package(Libbacktrace REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID AND NOT WIN32)
|
||||
find_package(FFMPEG COMPONENTS avcodec avformat avutil swresample swscale)
|
||||
if(NOT FFMPEG_FOUND)
|
||||
message(WARNING "FFmpeg not found, using bundled headers.")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT ANDROID AND NOT FFMPEG_FOUND)
|
||||
set(FFMPEG_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/dep/ffmpeg/include")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_FIND_FRAMEWORK ${FIND_FRAMEWORK_BACKUP})
|
||||
endif()
|
||||
|
||||
@@ -57,6 +57,8 @@ function(detect_architecture)
|
||||
if("x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES)
|
||||
message(STATUS "Building x86_64 MacOS binaries.")
|
||||
set(CPU_ARCH_X64 TRUE PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Xarch_x86_64 -msse4.1" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xarch_x86_64 -msse4.1" PARENT_SCOPE)
|
||||
endif()
|
||||
if("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)
|
||||
message(STATUS "Building ARM64 MacOS binaries.")
|
||||
@@ -67,6 +69,14 @@ function(detect_architecture)
|
||||
CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(STATUS "Building x86_64 binaries.")
|
||||
set(CPU_ARCH_X64 TRUE PARENT_SCOPE)
|
||||
if(NOT MSVC OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT DISABLE_SSE4)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse4.1" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1" PARENT_SCOPE)
|
||||
elseif(MSVC AND NOT DISABLE_SSE4)
|
||||
# Clang defines these macros, MSVC does not.
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D__SSE3__ /D__SSE4_1__")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D__SSE3__ /D__SSE4_1__")
|
||||
endif()
|
||||
elseif(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64") AND
|
||||
CMAKE_SIZEOF_VOID_P EQUAL 8) # Might have an A64 kernel, e.g. Raspbian.
|
||||
message(STATUS "Building ARM64 binaries.")
|
||||
@@ -77,22 +87,27 @@ function(detect_architecture)
|
||||
AND CMAKE_SIZEOF_VOID_P EQUAL 4))
|
||||
message(STATUS "Building ARM32 binaries.")
|
||||
set(CPU_ARCH_ARM32 TRUE PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm -march=armv7-a" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -marm -march=armv7-a" PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm -march=armv7-a -mfpu=neon-vfpv4" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -marm -march=armv7-a -mfpu=neon-vfpv4" PARENT_SCOPE)
|
||||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "riscv64")
|
||||
message(STATUS "Building RISC-V 64 binaries.")
|
||||
set(CPU_ARCH_RISCV64 TRUE PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finline-atomics" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finline-atomics" PARENT_SCOPE)
|
||||
|
||||
# Still need this, apparently.
|
||||
link_libraries("-latomic")
|
||||
# Don't want function calls for atomics.
|
||||
if(COMPILER_GCC)
|
||||
set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -finline-atomics")
|
||||
|
||||
# Still need this, apparently.
|
||||
link_libraries("-latomic")
|
||||
endif()
|
||||
|
||||
if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
# Frame pointers generate an annoying amount of code on leaf functions.
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer" PARENT_SCOPE)
|
||||
set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fomit-frame-pointer")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}" PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown system processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
@@ -100,13 +115,21 @@ endfunction()
|
||||
|
||||
function(detect_page_size)
|
||||
# This is only needed for ARM64, or if the user hasn't overridden it explicitly.
|
||||
if(NOT CPU_ARCH_ARM64 OR HOST_PAGE_SIZE)
|
||||
# For universal Apple builds, we use preprocessor macros to determine page size.
|
||||
# Similar for Windows, except it's always 4KB.
|
||||
if(NOT CPU_ARCH_ARM64 OR NOT LINUX)
|
||||
unset(HOST_PAGE_SIZE PARENT_SCOPE)
|
||||
unset(HOST_MIN_PAGE_SIZE PARENT_SCOPE)
|
||||
unset(HOST_MAX_PAGE_SIZE PARENT_SCOPE)
|
||||
return()
|
||||
elseif(DEFINED HOST_PAGE_SIZE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT LINUX)
|
||||
# For universal Apple builds, we use preprocessor macros to determine page size.
|
||||
# Similar for Windows, except it's always 4KB.
|
||||
if(DEFINED HOST_MIN_PAGE_SIZE OR DEFINED HOST_MAX_PAGE_SIZE)
|
||||
if(NOT DEFINED HOST_MIN_PAGE_SIZE OR NOT DEFINED HOST_MAX_PAGE_SIZE)
|
||||
message(FATAL_ERROR "Both HOST_MIN_PAGE_SIZE and HOST_MAX_PAGE_SIZE must be defined.")
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -143,6 +166,7 @@ endfunction()
|
||||
function(detect_cache_line_size)
|
||||
# This is only needed for ARM64, or if the user hasn't overridden it explicitly.
|
||||
if(NOT CPU_ARCH_ARM64 OR HOST_CACHE_LINE_SIZE)
|
||||
unset(HOST_CACHE_LINE_SIZE PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -153,7 +177,7 @@ function(detect_cache_line_size)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
message(WARNING "Cross-compiling and can't determine page size, assuming default.")
|
||||
message(WARNING "Cross-compiling and can't determine cache line size, assuming default.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -194,3 +218,30 @@ int main() {
|
||||
set(HOST_CACHE_LINE_SIZE ${detect_cache_line_size_output} CACHE STRING "Reported host cache line size")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(get_scm_version)
|
||||
if(SCM_VERSION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Git)
|
||||
if(EXISTS "${PROJECT_SOURCE_DIR}/.git" AND GIT_FOUND)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --dirty
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE LOCAL_SCM_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
if(NOT LOCAL_SCM_VERSION)
|
||||
set(SCM_VERSION "unknown" PARENT_SCOPE)
|
||||
else()
|
||||
set(SCM_VERSION ${LOCAL_SCM_VERSION} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(install_imported_dep_library name)
|
||||
get_target_property(SONAME "${name}" IMPORTED_SONAME_RELEASE)
|
||||
get_target_property(LOCATION "${name}" IMPORTED_LOCATION_RELEASE)
|
||||
install(FILES "${LOCATION}" RENAME "${SONAME}" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
endfunction()
|
||||
|
||||
215
CMakeModules/FindFFMPEG.cmake
Normal file
@@ -0,0 +1,215 @@
|
||||
#[==[
|
||||
Provides the following variables:
|
||||
|
||||
* `FFMPEG_INCLUDE_DIRS`: Include directories necessary to use FFMPEG.
|
||||
* `FFMPEG_LIBRARIES`: Libraries necessary to use FFMPEG. Note that this only
|
||||
includes libraries for the components requested.
|
||||
* `FFMPEG_VERSION`: The version of FFMPEG found.
|
||||
|
||||
The following components are supported:
|
||||
|
||||
* `avcodec`
|
||||
* `avdevice`
|
||||
* `avfilter`
|
||||
* `avformat`
|
||||
* `avresample`
|
||||
* `avutil`
|
||||
* `swresample`
|
||||
* `swscale`
|
||||
|
||||
For each component, the following are provided:
|
||||
|
||||
* `FFMPEG_<component>_FOUND`: Libraries for the component.
|
||||
* `FFMPEG_<component>_INCLUDE_DIRS`: Include directories for
|
||||
the component.
|
||||
* `FFMPEG_<component>_LIBRARIES`: Libraries for the component.
|
||||
* `FFMPEG::<component>`: A target to use with `target_link_libraries`.
|
||||
|
||||
Note that only components requested with `COMPONENTS` or `OPTIONAL_COMPONENTS`
|
||||
are guaranteed to set these variables or provide targets.
|
||||
#]==]
|
||||
|
||||
function (_ffmpeg_find component headername)
|
||||
find_path("FFMPEG_${component}_INCLUDE_DIR"
|
||||
NAMES
|
||||
"lib${component}/${headername}"
|
||||
PATHS
|
||||
"${FFMPEG_ROOT}/include"
|
||||
"${CMAKE_PREFIX_PATH}/include"
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/sw/include # Fink
|
||||
/opt/local/include # DarwinPorts
|
||||
/opt/csw/include # Blastwave
|
||||
/opt/include
|
||||
/usr/freeware/include
|
||||
PATH_SUFFIXES
|
||||
ffmpeg
|
||||
DOC "FFMPEG's ${component} include directory")
|
||||
mark_as_advanced("FFMPEG_${component}_INCLUDE_DIR")
|
||||
|
||||
# On Windows, static FFMPEG is sometimes built as `lib<name>.a`.
|
||||
if (WIN32)
|
||||
list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib")
|
||||
list(APPEND CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
|
||||
endif ()
|
||||
|
||||
find_library("FFMPEG_${component}_LIBRARY"
|
||||
NAMES
|
||||
"${component}"
|
||||
PATHS
|
||||
"${FFMPEG_ROOT}/lib"
|
||||
"${CMAKE_PREFIX_PATH}/lib"
|
||||
"${CMAKE_PREFIX_PATH}/lib64"
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
/sw/lib
|
||||
/opt/local/lib
|
||||
/opt/csw/lib
|
||||
/opt/lib
|
||||
/usr/freeware/lib64
|
||||
"${FFMPEG_ROOT}/bin"
|
||||
DOC "FFMPEG's ${component} library")
|
||||
mark_as_advanced("FFMPEG_${component}_LIBRARY")
|
||||
|
||||
if (FFMPEG_${component}_LIBRARY AND FFMPEG_${component}_INCLUDE_DIR)
|
||||
set(_deps_found TRUE)
|
||||
set(_deps_link)
|
||||
foreach (_ffmpeg_dep IN LISTS ARGN)
|
||||
if (TARGET "FFMPEG::${_ffmpeg_dep}")
|
||||
list(APPEND _deps_link "FFMPEG::${_ffmpeg_dep}")
|
||||
else ()
|
||||
set(_deps_found FALSE)
|
||||
endif ()
|
||||
endforeach ()
|
||||
if (_deps_found)
|
||||
if (NOT TARGET "FFMPEG::${component}")
|
||||
add_library("FFMPEG::${component}" UNKNOWN IMPORTED)
|
||||
set_target_properties("FFMPEG::${component}" PROPERTIES
|
||||
IMPORTED_LOCATION "${FFMPEG_${component}_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_${component}_INCLUDE_DIR}"
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES "${_deps_link}")
|
||||
endif ()
|
||||
set("FFMPEG_${component}_FOUND" 1
|
||||
PARENT_SCOPE)
|
||||
|
||||
set(version_header_path "${FFMPEG_${component}_INCLUDE_DIR}/lib${component}/version.h")
|
||||
set(major_version_header_path "${FFMPEG_${component}_INCLUDE_DIR}/lib${component}/version_major.h")
|
||||
if (EXISTS "${major_version_header_path}")
|
||||
string(TOUPPER "${component}" component_upper)
|
||||
file(STRINGS "${major_version_header_path}" major_version
|
||||
REGEX "#define *LIB${component_upper}_VERSION_MAJOR ")
|
||||
file(STRINGS "${version_header_path}" version
|
||||
REGEX "#define *LIB${component_upper}_VERSION_(MINOR|MICRO) ")
|
||||
string(REGEX REPLACE ".*_MAJOR *\([0-9]*\).*" "\\1" major "${major_version}")
|
||||
string(REGEX REPLACE ".*_MINOR *\([0-9]*\).*" "\\1" minor "${version}")
|
||||
string(REGEX REPLACE ".*_MICRO *\([0-9]*\).*" "\\1" micro "${version}")
|
||||
if (NOT major STREQUAL "" AND
|
||||
NOT minor STREQUAL "" AND
|
||||
NOT micro STREQUAL "")
|
||||
set("FFMPEG_${component}_VERSION" "${major}.${minor}.${micro}"
|
||||
PARENT_SCOPE)
|
||||
endif ()
|
||||
elseif (EXISTS "${version_header_path}")
|
||||
string(TOUPPER "${component}" component_upper)
|
||||
file(STRINGS "${version_header_path}" version
|
||||
REGEX "#define *LIB${component_upper}_VERSION_(MAJOR|MINOR|MICRO) ")
|
||||
string(REGEX REPLACE ".*_MAJOR *\([0-9]*\).*" "\\1" major "${version}")
|
||||
string(REGEX REPLACE ".*_MINOR *\([0-9]*\).*" "\\1" minor "${version}")
|
||||
string(REGEX REPLACE ".*_MICRO *\([0-9]*\).*" "\\1" micro "${version}")
|
||||
if (NOT major STREQUAL "" AND
|
||||
NOT minor STREQUAL "" AND
|
||||
NOT micro STREQUAL "")
|
||||
set("FFMPEG_${component}_VERSION" "${major}.${minor}.${micro}"
|
||||
PARENT_SCOPE)
|
||||
endif ()
|
||||
endif ()
|
||||
else ()
|
||||
set("FFMPEG_${component}_FOUND" 0
|
||||
PARENT_SCOPE)
|
||||
set(what)
|
||||
if (NOT FFMPEG_${component}_LIBRARY)
|
||||
set(what "library")
|
||||
endif ()
|
||||
if (NOT FFMPEG_${component}_INCLUDE_DIR)
|
||||
if (what)
|
||||
string(APPEND what " or headers")
|
||||
else ()
|
||||
set(what "headers")
|
||||
endif ()
|
||||
endif ()
|
||||
set("FFMPEG_${component}_NOT_FOUND_MESSAGE"
|
||||
"Could not find the ${what} for ${component}."
|
||||
PARENT_SCOPE)
|
||||
endif ()
|
||||
endif ()
|
||||
endfunction ()
|
||||
|
||||
_ffmpeg_find(avutil avutil.h)
|
||||
_ffmpeg_find(avresample avresample.h
|
||||
avutil)
|
||||
_ffmpeg_find(swresample swresample.h
|
||||
avutil)
|
||||
_ffmpeg_find(swscale swscale.h
|
||||
avutil)
|
||||
_ffmpeg_find(avcodec avcodec.h
|
||||
avutil)
|
||||
_ffmpeg_find(avformat avformat.h
|
||||
avcodec avutil)
|
||||
_ffmpeg_find(avfilter avfilter.h
|
||||
avutil)
|
||||
_ffmpeg_find(avdevice avdevice.h
|
||||
avformat avutil)
|
||||
|
||||
if (TARGET FFMPEG::avutil)
|
||||
set(_ffmpeg_version_header_path "${FFMPEG_avutil_INCLUDE_DIR}/libavutil/ffversion.h")
|
||||
if (EXISTS "${_ffmpeg_version_header_path}")
|
||||
file(STRINGS "${_ffmpeg_version_header_path}" _ffmpeg_version
|
||||
REGEX "FFMPEG_VERSION")
|
||||
string(REGEX REPLACE ".*\"n?\(.*\)\"" "\\1" FFMPEG_VERSION "${_ffmpeg_version}")
|
||||
unset(_ffmpeg_version)
|
||||
else ()
|
||||
set(FFMPEG_VERSION FFMPEG_VERSION-NOTFOUND)
|
||||
endif ()
|
||||
unset(_ffmpeg_version_header_path)
|
||||
endif ()
|
||||
|
||||
set(FFMPEG_INCLUDE_DIRS)
|
||||
set(FFMPEG_LIBRARIES)
|
||||
set(_ffmpeg_required_vars)
|
||||
foreach (_ffmpeg_component IN LISTS FFMPEG_FIND_COMPONENTS)
|
||||
if (TARGET "FFMPEG::${_ffmpeg_component}")
|
||||
set(FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS
|
||||
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIR}")
|
||||
set(FFMPEG_${_ffmpeg_component}_LIBRARIES
|
||||
"${FFMPEG_${_ffmpeg_component}_LIBRARY}")
|
||||
list(APPEND FFMPEG_INCLUDE_DIRS
|
||||
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS}")
|
||||
list(APPEND FFMPEG_LIBRARIES
|
||||
"${FFMPEG_${_ffmpeg_component}_LIBRARIES}")
|
||||
if (FFMEG_FIND_REQUIRED_${_ffmpeg_component})
|
||||
list(APPEND _ffmpeg_required_vars
|
||||
"FFMPEG_${_ffmpeg_required_vars}_INCLUDE_DIRS"
|
||||
"FFMPEG_${_ffmpeg_required_vars}_LIBRARIES")
|
||||
endif ()
|
||||
endif ()
|
||||
endforeach ()
|
||||
unset(_ffmpeg_component)
|
||||
|
||||
if (FFMPEG_INCLUDE_DIRS)
|
||||
list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
|
||||
endif ()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(FFMPEG
|
||||
REQUIRED_VARS FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES ${_ffmpeg_required_vars}
|
||||
VERSION_VAR FFMPEG_VERSION
|
||||
HANDLE_COMPONENTS)
|
||||
unset(_ffmpeg_required_vars)
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
FIND_PATH(
|
||||
LIBBACKTRACE_INCLUDE_DIR backtrace.h
|
||||
HINTS /usr/include /usr/local/include
|
||||
HINTS "${CMAKE_PREFIX_PATH}/include" /usr/include /usr/local/include
|
||||
${LIBBACKTRACE_PATH_INCLUDES}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(
|
||||
LIBBACKTRACE_LIBRARY
|
||||
NAMES backtrace
|
||||
PATHS ${ADDITIONAL_LIBRARY_PATHS} ${LIBBACKTRACE_PATH_LIB}
|
||||
PATHS "${CMAKE_PREFIX_PATH}/lib" "${CMAKE_PREFIX_PATH}/lib64" ${ADDITIONAL_LIBRARY_PATHS} ${LIBBACKTRACE_PATH_LIB}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# - Try to find OpenSLES
|
||||
# Once done this will define
|
||||
# OPENSLES_FOUND - System has OpenSLES
|
||||
# OPENSLES_INCLUDE_DIR - The OpenSLES include directory
|
||||
# OPENSLES_LIBRARY - The library needed to use OpenSLES
|
||||
# An imported target OpenSLES::OpenSLES is also created, prefer this
|
||||
|
||||
find_path(OPENSLES_INCLUDE_DIR
|
||||
NAMES SLES/OpenSLES.h
|
||||
)
|
||||
|
||||
find_library(OPENSLES_LIBRARY
|
||||
NAMES OpenSLES
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OpenSLES DEFAULT_MSG
|
||||
OPENSLES_LIBRARY OPENSLES_INCLUDE_DIR)
|
||||
|
||||
if(OpenSLES_FOUND)
|
||||
if(NOT TARGET OpenSLES::OpenSLES)
|
||||
add_library(OpenSLES::OpenSLES UNKNOWN IMPORTED)
|
||||
set_target_properties(OpenSLES::OpenSLES PROPERTIES
|
||||
IMPORTED_LOCATION ${OPENSLES_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${OPENSLES_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(OPENSLES_INCLUDE_DIR OPENSLES_LIBRARY )
|
||||
@@ -1,31 +0,0 @@
|
||||
# - Try to find SHADERC
|
||||
# Once done this will define
|
||||
# SHADERC_FOUND - System has SHADERC
|
||||
# SHADERC_INCLUDE_DIRS - The SHADERC include directories
|
||||
# SHADERC_LIBRARIES - The libraries needed to use SHADERC
|
||||
|
||||
find_path(
|
||||
SHADERC_INCLUDE_DIR shaderc/shaderc.h
|
||||
${SHADERC_PATH_INCLUDES}
|
||||
)
|
||||
|
||||
find_library(
|
||||
SHADERC_LIBRARY
|
||||
NAMES shaderc_shared.1 shaderc_shared
|
||||
PATHS ${ADDITIONAL_LIBRARY_PATHS} ${SHADERC_PATH_LIB}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Shaderc DEFAULT_MSG
|
||||
SHADERC_LIBRARY SHADERC_INCLUDE_DIR)
|
||||
|
||||
if(SHADERC_FOUND)
|
||||
add_library(Shaderc::shaderc_shared UNKNOWN IMPORTED)
|
||||
set_target_properties(Shaderc::shaderc_shared PROPERTIES
|
||||
IMPORTED_LOCATION ${SHADERC_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${SHADERC_INCLUDE_DIR}
|
||||
INTERFACE_COMPILE_DEFINITIONS "SHADERC_SHAREDLIB"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(SHADERC_INCLUDE_DIR SHADERC_LIBRARY)
|
||||
@@ -16,7 +16,8 @@ The following people have contributed to the project in some way, and are credit
|
||||
- posix - @Richard-L, blexx - German
|
||||
- @phoe-nix, @zkdpower - Chinese (Simplified)
|
||||
- Sorer - @MojoJojoDojo - Hebrew
|
||||
- Hipnosis - @Hipnosis183, MrHomunculus, @falsepopsky - Spanish
|
||||
- @Hipnosis183, @falsepopsky - Spanish (Latin America)
|
||||
- @IlDucci - Spanish (Spain)
|
||||
- @RaydenX93 - Italian
|
||||
- @r57zone - Russian
|
||||
- @6lackmag3 - Russian (Android)
|
||||
|
||||
70
README.md
@@ -9,7 +9,7 @@
|
||||
|
||||
DuckStation is an simulator/emulator of the Sony PlayStation(TM) console, focusing on playability, speed, and long-term maintainability. The goal is to be as accurate as possible while maintaining performance suitable for low-end devices. "Hack" options are discouraged, the default configuration should support all playable games with only some of the enhancements having compatibility issues.
|
||||
|
||||
A "BIOS" ROM image is required to to start the emulator and to play games. You can use an image from any hardware version or region, although mismatching game regions and BIOS regions may have compatibility issues. A ROM image is not provided with the emulator for legal reasons, you should dump this from your own console using Caetla or other means.
|
||||
A PS1 or PS2 "BIOS" ROM image is required to to start the emulator and to play games. You can use an image from any hardware version or region, although mismatching game regions and BIOS regions may have compatibility issues. A ROM image is not provided with the emulator for legal reasons, you should dump this from your own console using Caetla or other means.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -25,17 +25,24 @@ Other features include:
|
||||
- CPU Recompiler/JIT (x86-64, armv7/AArch32, AArch64, RISC-V/RV64).
|
||||
- Hardware (D3D11, D3D12, OpenGL, Vulkan, Metal) and software rendering.
|
||||
- Upscaling, texture filtering, and true colour (24-bit) in hardware renderers.
|
||||
- Accurate blending via Rasterizer Order Views/Fragment Shader Interlock.
|
||||
- PGXP for geometry precision, texture correction, and depth buffer emulation.
|
||||
- Texture replacement system in hardware renderers.
|
||||
- Motion adaptive deinterlacing.
|
||||
- Adaptive downsampling filter.
|
||||
- Post processing shader chains (GLSL and experimental Reshade FX).
|
||||
- Screen rotation for vertical or "TATE" shmup games.
|
||||
- Post processing shader chains (GLSL and Reshade FX).
|
||||
- "Fast boot" for skipping BIOS splash/intro.
|
||||
- Save state support.
|
||||
- Save state support, with runahead and rewind.
|
||||
- Windows, Linux, macOS support.
|
||||
- Supports bin/cue images, raw bin/img files, MAME CHD, single-track ECM, MDS/MDF, and unencrypted PBP formats.
|
||||
- Supports reading directly from CD, bin/cue images, raw bin/img files, MAME CHD, single-track ECM, MDS/MDF, and unencrypted PBP formats.
|
||||
- Preloading of disc images to RAM to avoid disk sleeping hitches.
|
||||
- Automatic loading/applying of PPF patches.
|
||||
- Direct booting of homebrew executables.
|
||||
- Direct loading of Portable Sound Format (psf) files.
|
||||
- Time stretched audio when running outside of 100% speed.
|
||||
- Digital and analog controllers for input (rumble is forwarded to host).
|
||||
- Namco GunCon lightgun support (simulated with mouse).
|
||||
- GunCon and Justifier lightgun support (simulated with mouse).
|
||||
- NeGcon support.
|
||||
- Qt and "Big Picture" UI.
|
||||
- Automatic updates with preview and latest channels.
|
||||
@@ -47,7 +54,8 @@ Other features include:
|
||||
- Integrated and remote debugging.
|
||||
- Multitap controllers (up to 8 devices).
|
||||
- RetroAchievements.
|
||||
- Automatic loading/applying of PPF patches.
|
||||
- Discord Rich Presence.
|
||||
- Video capture with Media Foundation (Windows) and [FFmpeg](https://www.ffmpeg.org/) (All Platforms) backends.
|
||||
|
||||
## System Requirements
|
||||
- A CPU faster than a potato. But it needs to be x86_64, AArch32/armv7, AArch64/ARMv8, or RISC-V/RV64.
|
||||
@@ -55,7 +63,11 @@ Other features include:
|
||||
- SDL, XInput or DInput compatible game controller (e.g. XB360/XBOne/XBSeries). DualShock 3 users on Windows will need to install the official DualShock 3 drivers included as part of PlayStation Now.
|
||||
|
||||
## Downloading and running
|
||||
Binaries of DuckStation for Windows x64/ARM64, Linux x86_64 (in AppImage/Flatpak formats), and macOS Universal Binaries are available via GitHub Releases and are automatically built with every commit/push. Binaries or packages distributed through other sources may be out of date and are not supported by the developer, please speak to them for support, not us.
|
||||
Binaries of DuckStation for Windows x64/ARM64, Linux x86_64 (in AppImage/Flatpak formats), and macOS Universal Binaries are available via GitHub Releases and are automatically built with every commit/push.
|
||||
|
||||
As per the terms of CC-BY-NC-ND, redistribution of **unmodified releases and code** is permitted. However, we would prefer if you linked to https://www.duckstation.org/ instead. Please note that pre-configured settings and packages are considered modifications.
|
||||
|
||||
For x86 machines (most systems), you will need a CPU that supports the SSE4.1 instruction set for the "normal" build. This includes all Intel CPUs manufactured after 2007, and AMD CPUs manufactured after 2011. If you have a CPU that is older, you will need to download the "SSE2" build from the releases page, which has lower performance but still supports these CPUs.
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -73,11 +85,7 @@ Once downloaded and extracted, you can launch the emulator with `duckstation-qt-
|
||||
|
||||
### Linux
|
||||
|
||||
The only supported version of DuckStation for Linux are the AppImage and Flatpak in the releases page. If you installed DuckStation from another source or distribution (e.g. EmuDeck), you should contact the packager for support, we have no control over it.
|
||||
|
||||
The release on [Flathub](https://flathub.org/apps/org.duckstation.DuckStation) is official, and synchronized with the latest rolling/stable release on GitHub.
|
||||
|
||||
You **should not** install DuckStation from unofficial repositories such as the AUR, they are **known to be broken**.
|
||||
DuckStation is provided for x86_64 Linux in AppImage and Flatpak formats. The release on [Flathub](https://flathub.org/apps/org.duckstation.DuckStation) is official, and synchronized with the latest rolling/stable release on GitHub.
|
||||
|
||||
#### AppImage
|
||||
|
||||
@@ -113,6 +121,7 @@ To download:
|
||||
You will need a device with armv7 (32-bit ARM), AArch64 (64-bit ARM), or x86_64 (64-bit x86). 64-bit is preferred, the requirements are higher for 32-bit, you'll probably want at least a 1.5GHz CPU.
|
||||
|
||||
Download from Google Play: https://play.google.com/store/apps/details?id=com.github.stenzek.duckstation
|
||||
|
||||
APK and Beta Downloads: https://www.duckstation.org/android/
|
||||
|
||||
**No support is provided for the Android app**, it is free and your expectations should be in line with that. Please **do not** email me about issues about it, or ask for help, you will be ignored.
|
||||
@@ -133,6 +142,14 @@ For example, if your disc image was named `Spyro3.cue`, you would place the SBI
|
||||
|
||||
CHD images with built-in subchannel information are also supported.
|
||||
|
||||
If you are playing directly from a disc and your CD/DVD drive does not support subchannel reading, or has a skew with the returned SubQ, you can place the SBI file in the `subchannel` directory under the user directory, with the serial or title of the game.
|
||||
|
||||
### Cheats and patch database
|
||||
|
||||
DuckStation ships with a built-in cheat and patch database, both provided by the community. Contributions to these are welcome at https://github.com/duckstation/chtdb.
|
||||
|
||||
Each release includes the latest version of the database, however you are free to manually update to the latest version as well.
|
||||
|
||||
## Building
|
||||
|
||||
### Windows
|
||||
@@ -153,18 +170,23 @@ Requirements:
|
||||
|
||||
Ubuntu/Debian package names:
|
||||
```
|
||||
build-essential clang cmake curl extra-cmake-modules git libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdecor-0-dev libegl-dev libevdev-dev libfontconfig-dev libfreetype-dev libgtk-3-dev libgudev-1.0-dev libharfbuzz-dev libinput-dev libopengl-dev libpipewire-0.3-dev libpulse-dev libssl-dev libudev-dev libwayland-dev libx11-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev libxcb-glx0-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-shape0-dev libxcb-shm0-dev libxcb-sync-dev libxcb-util-dev libxcb-xfixes0-dev libxcb-xinput-dev libxcb-xkb-dev libxext-dev libxkbcommon-x11-dev libxrandr-dev lld llvm ninja-build pkg-config zlib1g-dev
|
||||
autoconf automake build-essential clang cmake curl extra-cmake-modules git libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdecor-0-dev libegl-dev libevdev-dev libfontconfig-dev libfreetype-dev libgtk-3-dev libgudev-1.0-dev libharfbuzz-dev libinput-dev libopengl-dev libpipewire-0.3-dev libpulse-dev libssl-dev libudev-dev libwayland-dev libx11-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev libxcb-glx0-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-shape0-dev libxcb-shm0-dev libxcb-sync-dev libxcb-util-dev libxcb-xfixes0-dev libxcb-xinput-dev libxcb-xkb-dev libxext-dev libxkbcommon-x11-dev libxrandr-dev libtool lld llvm nasm ninja-build pkg-config zlib1g-dev
|
||||
```
|
||||
|
||||
Fedora package names:
|
||||
```
|
||||
alsa-lib-devel brotli-devel clang cmake dbus-devel egl-wayland-devel extra-cmake-modules fontconfig-devel gcc-c++ gtk3-devel libcurl-devel libdecor-devel libevdev-devel libICE-devel libinput-devel libSM-devel libX11-devel libXau-devel libxcb-devel libXcomposite-devel libXcursor-devel libXext-devel libXfixes-devel libXft-devel libXi-devel libxkbcommon-devel libxkbcommon-x11-devel libXpresent-devel libXrandr-devel libXrender-devel lld llvm make mesa-libEGL-devel mesa-libGL-devel ninja-build openssl-devel patch pcre2-devel perl-Digest-SHA pipewire-devel pulseaudio-libs-devel systemd-devel wayland-devel xcb-util-cursor-devel xcb-util-devel xcb-util-errors-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-renderutil-devel xcb-util-wm-devel xcb-util-xrm-devel zlib-devel
|
||||
alsa-lib-devel autoconf automake brotli-devel clang cmake dbus-devel egl-wayland-devel extra-cmake-modules fontconfig-devel gcc-c++ gtk3-devel libavcodec-free-devel libavformat-free-devel libavutil-free-devel libcurl-devel libdecor-devel libevdev-devel libICE-devel libinput-devel libSM-devel libswresample-free-devel libswscale-free-devel libX11-devel libXau-devel libxcb-devel libXcomposite-devel libXcursor-devel libXext-devel libXfixes-devel libXft-devel libXi-devel libxkbcommon-devel libxkbcommon-x11-devel libXpresent-devel libXrandr-devel libXrender-devel libtool lld llvm make mesa-libEGL-devel mesa-libGL-devel nasm ninja-build openssl-devel patch pcre2-devel perl-Digest-SHA pipewire-devel pulseaudio-libs-devel systemd-devel wayland-devel xcb-util-cursor-devel xcb-util-devel xcb-util-errors-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-renderutil-devel xcb-util-wm-devel xcb-util-xrm-devel zlib-devel
|
||||
```
|
||||
|
||||
Arch package names:
|
||||
```
|
||||
base-devel clang cmake curl dbus extra-cmake-modules freetype git libjpeg-turbo libpng libwebp libx11 libxrandr lld llvm ninja qt6-base qt6-imageformats qt6-svg qt6-tools wayland zstd
|
||||
```
|
||||
|
||||
#### Building
|
||||
|
||||
1. Clone the repository: `git clone https://github.com/stenzek/duckstation.git`, `cd duckstation`.
|
||||
2. Build dependencies. You can save these outside of the tree if you like. This will take a while. `scripts/build-dependencies-linux.sh deps`.
|
||||
2. Build dependencies. You can save these outside of the tree if you like. This will take a while. `scripts/deps/build-dependencies-linux.sh deps`.
|
||||
3. Run CMake to configure the build system. Assuming a build subdirectory of `build-release`, run `cmake -B build-release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_PREFIX_PATH="$PWD/deps" -G Ninja`. If you want a release (optimized) build, include `-DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON`.
|
||||
4. Compile the source code. For the example above, run `ninja -C build-release`
|
||||
5. Run the binary, located in the build directory under `./build-release/bin/duckstation-qt`.
|
||||
@@ -177,7 +199,7 @@ Requirements:
|
||||
|
||||
|
||||
1. Clone the repository: `git clone https://github.com/stenzek/duckstation.git`.
|
||||
2. Build the dependencies. This will take a while. `scripts/build-dependencies-mac.sh deps`.
|
||||
2. Build the dependencies. This will take a while. `scripts/deps/build-dependencies-mac.sh deps`.
|
||||
2. Run CMake to configure the build system: `cmake -Bbuild-release -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$PWD/deps"`.
|
||||
4. Compile the source code: `cmake --build build-release --parallel`.
|
||||
5. Run the binary, located in the build directory under `bin/DuckStation.app`.
|
||||
@@ -199,16 +221,19 @@ If you wish to use a "portable" build, where the user directory is the same as w
|
||||
in the same directory as the DuckStation executable.
|
||||
|
||||
## Bindings for Qt frontend
|
||||
Your keyboard or game controller can be used to simulate a variety of PlayStation controllers. Controller input is supported through DInput, XInput, and SDL backends and can be changed through `Settings -> General Settings`.
|
||||
Your keyboard or game controller can be used to simulate a variety of PlayStation controllers. Controller input is supported through DInput, XInput, and SDL backends and can be changed through `Settings -> Controllers`.
|
||||
|
||||
To bind your input device, go to `Settings -> Controllers`. Each of the buttons/axes for the simulated controller will be listed, alongside the corresponding key/button on your device that it is currently bound to. To rebind, click the box next to the button/axis name, and press the key or button on your input device that you wish to bind to. When binding rumble, simply press any button on the controller you wish to send rumble to.
|
||||
To bind your input device, go to `Settings -> Controllers`, and select the virtual controller you want to map. Automatic mapping handles the majority of ocntrollers. However, if you need to manually bind a controller, click the box below the button/axis name, and press the key or button on your input device that you wish to bind to.
|
||||
|
||||
## SDL Game Controller Database
|
||||
DuckStation releases ship with a database of game controller mappings for the SDL controller backend, courtesy of https://github.com/gabomdq/SDL_GameControllerDB. The included `gamecontrollerdb.txt` file can be found in the `database` subdirectory of the DuckStation program directory.
|
||||
DuckStation releases ship with a database of game controller mappings for the SDL controller backend, courtesy of https://github.com/mdqinc/SDL_GameControllerDB. The included `gamecontrollerdb.txt` file can be found in the `resources` subdirectory of the DuckStation program directory.
|
||||
|
||||
If you are experiencing issues binding your controller with the SDL controller backend, you may need to add a custom mapping to the database file. Make a copy of `gamecontrollerdb.txt` and place it in your [user directory](#user-directories) (or directly in the program directory, if running in portable mode) and then follow the instructions in the [SDL_GameControllerDB repository](https://github.com/gabomdq/SDL_GameControllerDB) for creating a new mapping. Add this mapping to the new copy of `gamecontrollerdb.txt` and your controller should then be recognized properly.
|
||||
If you are experiencing issues binding your controller with the SDL controller backend, you may need to add a custom mapping to the database file. Make a copy of `gamecontrollerdb.txt` and place it in your [user directory](#user-directories) (or directly in the program directory, if running in portable mode) and then follow the instructions in the [SDL_GameControllerDB repository](https://github.com/mdqinc/SDL_GameControllerDB) for creating a new mapping. Add this mapping to the new copy of `gamecontrollerdb.txt` and your controller should then be recognized properly.
|
||||
|
||||
## Default bindings
|
||||
|
||||
Bindings for controllers and hotkeys can be changed in `Settings -> Controllers`.
|
||||
|
||||
Controller 1:
|
||||
- **Left Stick:** W/A/S/D
|
||||
- **Right Stick:** T/F/G/H
|
||||
@@ -222,6 +247,11 @@ Controller 1:
|
||||
|
||||
Hotkeys:
|
||||
- **Escape:** Open Pause Menu
|
||||
- **F1:** Load State
|
||||
- **F2:** Save State
|
||||
- **F3:** Select Previous Save State
|
||||
- **F4:** Select Next Save State
|
||||
- **F10:** Save Screenshot
|
||||
- **F11:** Toggle Fullscreen
|
||||
- **Tab:** Temporarily Disable Speed Limiter
|
||||
- **Space:** Pause/Resume Emulation
|
||||
|
||||
1077
data/LICENSE.txt
167501
data/resources/chtdb.txt
@@ -4750,13 +4750,13 @@ SLUS-00784:
|
||||
- size: 204887424
|
||||
md5: "0ce86b034427b7c79a85bec2f88c6e0e"
|
||||
SLPS-01830:
|
||||
name: "Animetic Story Game 1 - Card Captor Sakura (Japan) (Disc 1)"
|
||||
name: "Animetic Story Game 1 - Cardcaptor Sakura (Japan) (Disc 1)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 477145536
|
||||
md5: "93653eb589658a67899394ad52acc3cb"
|
||||
SLPS-01831:
|
||||
name: "Animetic Story Game 1 - Card Captor Sakura (Japan) (Disc 2)"
|
||||
name: "Animetic Story Game 1 - Cardcaptor Sakura (Japan) (Disc 2)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 455318976
|
||||
@@ -14685,13 +14685,13 @@ SLUS-00494:
|
||||
- size: 32332944
|
||||
md5: "cda4ae739eeceb0541886c6ebaa7b57a"
|
||||
SLPS-02561:
|
||||
name: "Card Captor Sakura - Clowcard Magic (Japan)"
|
||||
name: "Cardcaptor Sakura - Clow Card Magic (Japan)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 617938608
|
||||
md5: "259802e85fb1fe3b5f39c78033c7efd0"
|
||||
SLPS-02560:
|
||||
name: "Card Captor Sakura - Clowcard Magic (Japan) (Genteiban)"
|
||||
name: "Cardcaptor Sakura - Clow Card Magic (Japan) (Genteiban)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 617940960
|
||||
@@ -67487,13 +67487,13 @@ PAPX-90044:
|
||||
- size: 331662576
|
||||
md5: "de973cbfc9516106adac69984041f7be"
|
||||
SCPS-45317:
|
||||
name: "Metal Gear Solid (Asia) (Disc 1)"
|
||||
name: "Metal Gear Solid (Japan, Asia) (Disc 1) (Ichi) (Premium Package)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 710005296
|
||||
md5: "d3b48095ed5d2a81a51d2b8ccd2ef766"
|
||||
SCPS-45318:
|
||||
name: "Metal Gear Solid (Asia) (Disc 2)"
|
||||
name: "Metal Gear Solid (Japan, Asia) (Disc 2) (Ni) (Premium Package)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 735526848
|
||||
@@ -67658,18 +67658,6 @@ SLUS-90062:
|
||||
- tracks:
|
||||
- size: 123924528
|
||||
md5: "794c18d04a31d1e7c5b39bbe4d088afa"
|
||||
SLPM-86111:
|
||||
name: "Metal Gear Solid [Premium Package Sai Hakkou Kinen]"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 710005296
|
||||
md5: "d3b48095ed5d2a81a51d2b8ccd2ef766"
|
||||
- tracks:
|
||||
- size: 735526848
|
||||
md5: "7c43ca912cdbde3f0e23d90f2a799ffa"
|
||||
- tracks:
|
||||
- size: 225474480
|
||||
md5: "c55b7888dee7b6c471d25a0000c4dc32"
|
||||
SLPS-00008:
|
||||
name: "Metal Jacket (Japan)"
|
||||
trackData:
|
||||
@@ -117489,7 +117477,7 @@ SLPS-00321:
|
||||
- size: 4377072
|
||||
md5: "00d4f2b9eba8200785726e7b4d427348"
|
||||
SLPS-02886:
|
||||
name: "Tetris with Card Captor Sakura - Eternal Heart (Japan)"
|
||||
name: "Tetris with Cardcaptor Sakura - Eternal Heart (Japan)"
|
||||
trackData:
|
||||
- tracks:
|
||||
- size: 382611600
|
||||
|
||||
BIN
data/resources/fonts/TwitterColorEmoji-SVGinOT.ttf.zst
Normal file
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
@@ -3,6 +3,7 @@
|
||||
|
||||
# Windows
|
||||
03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000fa190000918d000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
|
||||
03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
|
||||
03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
|
||||
@@ -19,6 +20,7 @@
|
||||
03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
|
||||
05000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows,
|
||||
03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
|
||||
@@ -72,6 +74,8 @@
|
||||
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
@@ -115,6 +119,7 @@
|
||||
03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows,
|
||||
03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
|
||||
030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
|
||||
030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
|
||||
@@ -323,6 +328,7 @@
|
||||
03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
|
||||
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
|
||||
03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows,
|
||||
03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
|
||||
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
|
||||
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -405,6 +411,7 @@
|
||||
03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
|
||||
0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000242e0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
|
||||
03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
|
||||
03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows,
|
||||
030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
|
||||
@@ -476,6 +483,7 @@
|
||||
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006f0e00008901000000000000,PDP Realmz Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
|
||||
03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
@@ -484,7 +492,7 @@
|
||||
03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -771,7 +779,6 @@
|
||||
03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows,
|
||||
03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
@@ -780,7 +787,6 @@
|
||||
030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -806,6 +812,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000882800000305000000000000,V5 GAME PAD,a:b0,b:b1,x:b2,y:b3,guide:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows
|
||||
|
||||
# Mac OS X
|
||||
030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
@@ -814,6 +821,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
|
||||
03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
@@ -855,6 +863,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001d30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -873,7 +883,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:MacOSX
|
||||
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1081,7 +1091,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -1091,8 +1101,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000022050000,Xbox Wireless Controller,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Mac OS X,
|
||||
03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
@@ -1103,6 +1115,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux,
|
||||
03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
@@ -1116,6 +1129,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
|
||||
03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00006928000011010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
|
||||
05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
|
||||
05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1137,6 +1151,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000060000011010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
|
||||
@@ -1155,6 +1170,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1169,7 +1187,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
|
||||
050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1389,7 +1406,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b000001050000,Microsoft Xbox Series X Controller,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux,
|
||||
060000005e040000120b000001050000,Microsoft Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
@@ -1467,7 +1484,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
@@ -1484,6 +1501,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d62000000b20000001010000,PowerA Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
|
||||
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
|
||||
@@ -1523,6 +1541,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
|
||||
03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick (PS5),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1590,6 +1610,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
|
||||
@@ -1672,6 +1693,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000a102000030060000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e00001503000000020000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000000010000,Xbox 360 EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
@@ -1734,6 +1756,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
|
||||
34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android,
|
||||
38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android,
|
||||
38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
|
||||
30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
|
||||
38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
|
||||
@@ -1901,7 +1924,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android,
|
||||
050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
|
||||
|
||||
5
data/resources/images/flags/Catalan.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="810" height="540">
|
||||
<rect width="810" height="540" fill="#FCDD09"/>
|
||||
<path stroke="#DA121A" stroke-width="60" d="M0,90H810m0,120H0m0,120H810m0,120H0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 242 B |
1
data/resources/images/flags/Chinese.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600"><path fill="#EE1C25" d="M0 0h900v600H0"/><g transform="translate(150,150) scale(3)"><path id="s" d="M0,-30 17.63355,24.27051 -28.53171,-9.27051H28.53171L-17.63355,24.27051" fill="#FF0"/></g><use xlink:href="#s" transform="translate(300,60) rotate(23.036243)"/><use xlink:href="#s" transform="translate(360,120) rotate(45.869898)"/><use xlink:href="#s" transform="translate(360,210) rotate(69.945396)"/><use xlink:href="#s" transform="translate(300,270) rotate(20.659808)"/></svg>
|
||||
|
After Width: | Height: | Size: 587 B |
6
data/resources/images/flags/Czech.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="900" height="600">
|
||||
<rect width="900" height="600" fill="#d7141a"/>
|
||||
<rect width="900" height="300" fill="#fff"/>
|
||||
<path d="M 450,300 0,0 V 600 z" fill="#11457e"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 275 B |
1
data/resources/images/flags/Danish.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 28"><path fill="#c8102e" d="M0,0H37V28H0Z"/><path stroke="#fff" stroke-width="4" d="M0,14h37M14,0v28"/></svg>
|
||||
|
After Width: | Height: | Size: 186 B |
5
data/resources/images/flags/Dutch.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="900" height="600" viewBox="0 0 9 6">
|
||||
<rect fill="#21468B" width="9" height="6"/>
|
||||
<rect fill="#FFF" width="9" height="4"/>
|
||||
<rect fill="#AE1C28" width="9" height="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 223 B |
16
data/resources/images/flags/English.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="1200" height="600">
|
||||
<clipPath id="s">
|
||||
<path d="M0,0 v30 h60 v-30 z"/>
|
||||
</clipPath>
|
||||
<clipPath id="t">
|
||||
<path d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#s)">
|
||||
<path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
|
||||
<path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
|
||||
<path d="M0,0 L60,30 M60,0 L0,30" clip-path="url(#t)" stroke="#C8102E" stroke-width="4"/>
|
||||
<path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
|
||||
<path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 641 B |
5
data/resources/images/flags/Finnish.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1100" viewBox="0 0 18 11">
|
||||
<rect width="18" height="11" fill="#fff"/>
|
||||
<path d="M0,5.5h18M6.5,0v11" stroke="#002F6C" stroke-width="3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 241 B |
2
data/resources/images/flags/French.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="900" height="600"><rect width="900" height="600" fill="#ED2939"/><rect width="600" height="600" fill="#fff"/><rect width="300" height="600" fill="#002395"/></svg>
|
||||
|
After Width: | Height: | Size: 249 B |
8
data/resources/images/flags/German.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="600" viewBox="0 0 5 3">
|
||||
<desc>Flag of Germany</desc>
|
||||
<rect id="black_stripe" width="5" height="3" y="0" x="0" fill="#000"/>
|
||||
<rect id="red_stripe" width="5" height="2" y="1" x="0" fill="#D00"/>
|
||||
<rect id="gold_stripe" width="5" height="1" y="2" x="0" fill="#FFCE00"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 491 B |
5
data/resources/images/flags/Greek.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="400" viewBox="0 0 27 18">
|
||||
<rect fill="#0D5EAF" width="27" height="18"/>
|
||||
<path fill="none" stroke-width="2" stroke="#FFF" d="M5,0V11 M0,5H10 M10,3H27 M10,7H27 M0,11H27 M0,15H27"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 284 B |
1
data/resources/images/flags/Hebrew.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="800"><path d="M 0,0 H 1100 V 800 H 0 Z" fill="#fff"/><path d="M 0,75 H 1100 V 200 H 0 Z" fill="#0038b8"/><path d="M 0,600 H 1100 V 725 H 0 Z" fill="#0038b8"/><path d="M 423.81566,472.85253 H 676.18435 L 550.00001,254.29492 Z m 126.18435,72.85255 126.1843,-218.55765 H 423.81566 Z" fill="none" stroke="#0038b8" stroke-width="27.5"/></svg>
|
||||
|
After Width: | Height: | Size: 398 B |
32
data/resources/images/flags/Iranian.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="630" height="360">
|
||||
<rect width="630" height="360" fill="#da0000"/>
|
||||
<rect width="630" height="240" fill="#fff"/>
|
||||
<rect width="630" height="120" fill="#239f40"/>
|
||||
<g transform="translate(8.4,100.4)">
|
||||
<g id="tb4">
|
||||
<g id="tb1" fill="none" stroke="#fff" stroke-width="2">
|
||||
<path id="tbp1" d="M0,1H26M1,10V5H9V9H17V5H12M4,9H6M26,9H21V5H29M29,0V9H37V0M33,0V9" transform="scale(1.4)"/>
|
||||
<path id="tbp2" d="M0,7H9M10,7H19" transform="scale(2.8)"/>
|
||||
<use xlink:href="#tbp2" y="120"/>
|
||||
<use xlink:href="#tbp1" y="145.2"/>
|
||||
</g>
|
||||
<g id="tb3">
|
||||
<use xlink:href="#tb1" x="56"/>
|
||||
<use xlink:href="#tb1" x="112"/>
|
||||
<use xlink:href="#tb1" x="168"/>
|
||||
</g>
|
||||
</g>
|
||||
<use xlink:href="#tb3" x="168"/>
|
||||
<use xlink:href="#tb4" x="392"/>
|
||||
</g>
|
||||
<g fill="#da0000" transform="matrix(45,0,0,45,315,180)">
|
||||
<g id="emblem_half">
|
||||
<path d="M-0.54815,0.83638A0.912046,0.912046 0 0,0 0.328544,-0.722384A1,1 0 0,1 -0.54815,0.83638"/>
|
||||
<path d="M0.618339,0.661409A0.763932,0.763932 0 0,0 0.421644,-0.741049A1,1 0 0,1 0.618339,0.661409"/>
|
||||
<path d="M0,1 -0.05,0 0,-0.787278A0.309995,0.309995 0 0,0 0.118034,-0.688191V-0.100406L0.077809,0.892905z"/>
|
||||
<path d="M-0.02,-0.85 0,-0.831217A0.14431,0.14431 0 0,0 0.252075,-0.967708A0.136408,0.136408 0 0,1 0,-0.924634"/>
|
||||
</g>
|
||||
<use xlink:href="#emblem_half" transform="scale(-1,1)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
6
data/resources/images/flags/Italian.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="1000" viewBox="0 0 3 2">
|
||||
<rect width="3" height="2" fill="#009246"/>
|
||||
<rect width="2" height="2" x="1" fill="#fff"/>
|
||||
<rect width="1" height="2" x="2" fill="#ce2b37"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 234 B |
1
data/resources/images/flags/Korean.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="900" height="600" viewBox="-72 -48 144 96"><path fill="#fff" d="M-72-48v96H72v-96z"/><g stroke="#000" stroke-width="4"><path transform="rotate(33.69006752598)" d="M-50-12v24m6 0v-24m6 0v24m76 0V1m0-2v-11m6 0v11m0 2v11m6 0V1m0-2v-11"/><path transform="rotate(-33.69006752598)" d="M-50-12v24m6 0V1m0-2v-11m6 0v24m76 0V1m0-2v-11m6 0v24m6 0V1m0-2v-11"/></g><g transform="rotate(33.69006752598)"><path fill="#cd2e3a" d="M12 0a18 18 0 11-36 0 24 24 0 1148 0"/><path fill="#0047a0" d="M0 0a12 12 0 1124 0 24 24 0 11-48 0 12 12 0 1024 0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 588 B |
6
data/resources/images/flags/NTSC-J.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="900" height="600">
|
||||
<desc>Japanese flag</desc>
|
||||
<rect fill="#fff" height="600" width="900"/>
|
||||
<circle fill="#bc002d" cx="450" cy="300" r="180"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 234 B |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
7
data/resources/images/flags/Non-PS1.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="400">
|
||||
<rect fill="#969594" width="600" height="400"/>
|
||||
<rect fill="#c2c1c1" width="400" height="400"/>
|
||||
<rect fill="#72706f" width="200" height="400"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 286 B |
7
data/resources/images/flags/Norwegian.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 22 16">
|
||||
<title>Flag of Norway</title>
|
||||
<rect width="22" height="16" fill="#ba0c2f"/>
|
||||
<path d="M0,8h22M8,0v16" stroke="#fff" stroke-width="4"/>
|
||||
<path d="M0,8h22M8,0v16" stroke="#00205b" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 319 B |
8
data/resources/images/flags/Other.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="400">
|
||||
<rect fill="#969594" width="600" height="400"/>
|
||||
<rect fill="#c2c1c1" width="400" height="400"/>
|
||||
<rect fill="#72706f" width="200" height="400"/>
|
||||
<path fill="#fff" stroke="#000" stroke-width="0.1524" d="M348.367 270.386h-93.7054v-9.3454c0-15.9122 1.768-28.8778 5.3882-38.8124 3.6202-10.0188 9.0086-19.0274 16.1648-27.2782 7.1564-8.2508 23.237-22.7318 48.242-43.443 13.3024-10.8608 19.9534-20.7954 19.9534-29.8038 0-9.0928-2.694-16.0808-7.9982-21.1322-5.3882-4.9674-13.4706-7.4932-24.3314-7.4932-11.7026 0-21.3006 3.873-28.962 11.6186-7.6614 7.6614-12.5446 21.2164-14.6494 40.412l-95.7262-11.871c3.2836-35.1922 16.0808-63.4806 38.3074-84.9496 22.3108-21.469 56.4928-32.1612 102.546-32.1612 35.8658 0 64.7436 7.493 86.8018 22.395 29.8882 20.2902 44.8744 47.2316 44.8744 80.9084 0 13.9758-3.8728 27.5306-11.6186 40.4962-7.6614 12.9656-23.4894 28.8778-47.3158 47.5684-16.5858 13.2182-27.1098 23.7422-31.4878 31.7404-4.2938 7.914-6.4828 18.3538-6.4828 31.151zm-96.989 24.9208h100.441v88.5698H251.378v-88.5698z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
5
data/resources/images/flags/Polish.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="640" height="400" viewBox="0 0 8 5">
|
||||
<rect width="8" height="5" fill="#dc143c"/>
|
||||
<rect width="8" height="2.5" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 199 B |
62
data/resources/images/flags/Portuguese.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="400">
|
||||
<rect width="600" height="400" fill="#f00"/>
|
||||
<rect width="240" height="400" fill="#060"/>
|
||||
<g fill="#ff0" fill-rule="evenodd" stroke="#000" stroke-width="0.573" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m318.24,262.04c-30.21-0.91-168.74-87.38-169.69-101.15l7.6496-12.757c13.741,19.966,155.36,104.06,169.27,101.08l-7.2299,12.823"/>
|
||||
<path d="m154.59,146.4c-2.7101,7.2937,36.149,31.318,82.903,59.754,46.752,28.434,87.065,46.006,90.053,43.486,0.18256-0.32544,1.4701-2.5409,1.352-2.5232-0.56001,0.84402-1.9234,1.1104-4.0506,0.49741-12.631-3.6433-45.575-18.765-86.374-43.506-40.798-24.743-76.294-47.544-81.811-57.232-0.38363-0.67116-0.65702-1.8962-0.60146-2.8487l-0.13405-0.002-1.1747,2.0532-0.16139,0.32191h-0.00088zm164.36,116.04c-0.51238,0.92957-1.4675,0.96044-3.2816,0.76112-11.3-1.2506-45.589-17.925-86.162-42.213-47.21-28.26-86.2-54.01-81.97-60.74l1.1509-2.0346,0.22665,0.0706c-3.8037,11.405,76.948,57.578,81.702,60.522,46.724,28.947,86.115,45.851,89.601,41.458l-1.2682,2.181v-0.002z"/>
|
||||
<path d="m240.17,169.23c30.237-0.23901,67.55-4.1319,89.023-12.69l-4.6265-7.5168c-12.692,7.0247-50.21,11.644-84.652,12.335-40.736-0.37483-69.49-4.1681-83.897-13.835l-4.3672,8.0045c26.484,11.207,53.623,13.587,88.52,13.703"/>
|
||||
<path d="m330.44,156.71c-0.73904,1.1818-14.743,6.0113-35.373,9.5753-13.988,2.1325-32.234,3.9555-55.004,3.9776-21.633,0.0203-39.305-1.5196-52.684-3.3329-21.656-3.3955-32.833-8.1201-36.965-9.7896,0.39509-0.78581,0.64908-1.337,1.0301-2.0708,11.895,4.736,23.124,7.5918,36.279,9.6158,13.291,1.8,30.75,3.362,52.276,3.3417,22.664-0.0229,40.709-1.9844,54.616-4.0534,21.155-3.4122,32.711-7.8034,34.334-9.8425l1.494,2.5788h-0.002zm-4.0603-7.6226c-2.293,1.8415-13.718,5.8932-33.819,9.1034-13.415,1.9226-30.472,3.6433-52.265,3.6645-20.704,0.0203-37.619-1.375-50.485-3.2491-20.414-2.6661-31.279-7.4754-35.196-8.8776,0.3898-0.67381,0.78666-1.3423,1.1941-2.0135,3.0479,1.5346,13.533,5.7909,34.226,8.7224,12.72,1.8036,29.661,3.1477,50.262,3.1265,21.69-0.0221,38.553-1.7762,51.883-3.6883,20.205-2.7799,31.077-7.9472,32.728-9.241l1.4728,2.4509v0.002z"/>
|
||||
<path d="m140.88,205.66c18.598,10.003,59.905,15.044,98.994,15.391,35.591,0.0564,81.958-5.5016,99.297-14.69l-0.47712-10.012c-5.4246,8.4773-55.113,16.609-99.206,16.276-44.093-0.3325-85.038-7.1429-98.687-15.959l0.0794,8.9914"/>
|
||||
<path d="m340.12,204.22,0.00088,2.3874c-2.606,3.1159-18.946,7.8255-39.437,11.142-15.595,2.391-35.927,4.1945-61.262,4.1945-24.069,0-43.263-1.7163-58.148-4.0014-23.529-3.4264-38.579-9.4262-41.6-11.217l0.0132-2.7852c9.0748,6.0334,33.661,10.447,41.917,11.798,14.788,2.2701,33.868,3.9732,57.817,3.9732,25.216,0,45.434-1.7912,60.931-4.1663,14.701-2.1237,35.644-7.6465,39.767-11.324h0.00088zm0.01-8.4922,0.00088,2.3874c-2.606,3.1142-18.946,7.8237-39.437,11.14-15.595,2.391-35.927,4.1945-61.262,4.1945-24.069,0-43.263-1.7145-58.148-4.0014-23.529-3.4246-38.579-9.4245-41.6-11.216l0.0132-2.7852c9.0748,6.0325,33.661,10.447,41.917,11.796,14.788,2.2719,33.868,3.9758,57.817,3.9758,25.216,0,45.434-1.7921,60.931-4.169,14.701-2.1237,35.644-7.6465,39.767-11.324l0.00088,0.002z"/>
|
||||
<path d="m239.79,260.32c-42.772-0.25489-79.421-11.659-87.16-13.544l5.6433,8.8344c13.67,5.7503,49.424,14.32,81.927,13.371,32.504-0.94809,60.91-3.466,80.928-13.211l5.7862-9.1555c-13.642,6.425-60.068,13.639-87.125,13.705"/>
|
||||
<path stroke-width="0.55" d="m323.3,253.72c-0.85016,1.2991-1.7171,2.5823-2.5963,3.8294-9.4417,3.3293-24.319,6.8245-30.597,7.844-12.824,2.6423-32.665,4.594-50.274,4.6029-37.89-0.55474-68.905-7.9719-83.496-14.299l-1.1773-2.0241,0.19225-0.30427,1.9966,0.77435c25.948,9.2834,55.091,12.987,82.698,13.652,17.538,0.0617,35.095-2.01,49.292-4.5491,21.771-4.3621,30.574-7.65,33.275-9.1405l0.68701-0.38541h-0.00088zm5.0172-8.2753c0.022,0.0256,0.0441,0.0503,0.0653,0.0776-0.63585,1.0733-1.2911,2.1652-1.9622,3.2623-5.0357,1.8-18.702,5.7988-38.659,8.5893-13.149,1.7912-21.322,3.526-47.479,4.034-49.015-1.2471-80.75-10.831-88.289-13.195l-1.1174-2.1431c28.406,7.4154,57.422,12.592,89.408,13.121,23.931-0.50976,34.112-2.2719,47.152-4.0499,23.271-3.6186,34.996-7.4498,38.515-8.5558-0.0441-0.0635-0.0961-0.13053-0.15433-0.19932l2.5231-0.9428-0.002,0.002z"/>
|
||||
<path d="m328.83,197.76c0.13873,28.137-14.26,53.386-25.858,64.525-16.408,15.759-38.163,25.896-63.569,26.363-28.37,0.52117-55.12-17.974-62.295-26.099-14.028-15.885-25.449-36.057-25.815-63.243,1.7376-30.709,13.793-52.1,31.268-66.769s40.743-21.813,60.121-21.302c22.358,0.59003,48.475,11.558,66.521,33.332,11.823,14.266,16.943,29.748,19.627,53.193zm-89.186-96.342c54.485,0,99.296,44.338,99.296,98.703,0,54.364-44.811,98.704-99.296,98.704s-98.924-44.339-98.924-98.704,44.439-98.703,98.924-98.703"/>
|
||||
<path d="m239.91,101.08c54.534,0,99.011,44.483,99.011,99.022,0,54.538-44.478,99.02-99.011,99.02-54.534,0-99.011-44.481-99.011-99.02s44.478-99.022,99.011-99.022zm-96.832,99.0224c0,53.26,43.736,96.842,96.832,96.842,53.097,0,96.833-43.582,96.833-96.842,0-53.262-43.737-96.844-96.833-96.844s-96.832,43.584-96.832,96.844z"/>
|
||||
<path d="m239.99,109.31c49.731,0,90.693,40.821,90.693,90.704,0,49.884-40.963,90.703-90.693,90.703s-90.693-40.819-90.693-90.703c0-49.883,40.964-90.704,90.693-90.704zm-88.515,90.7034c0,48.685,39.979,88.524,88.515,88.524s88.515-39.839,88.515-88.524c0-48.686-39.978-88.525-88.515-88.525-48.536,0-88.515,39.839-88.515,88.525z"/>
|
||||
<path d="m243.98,100.68-8.48545,0,0.01,198.96,8.51455,0z"/>
|
||||
<path d="m243.13,99.546h2.1598l0.0185,201.25h-2.1616l-0.0159-201.25zm-8.4213,0.0018h2.1766l0.003,201.25h-2.1783v-201.25z"/>
|
||||
<path d="m338.99,203.935,0-7.3554-5.99-5.58-34-9-49-5-59,3-42,10-8.48,6.28,0,7.3572l21.48-9.637,51-8h49l36,4,25,6z"/>
|
||||
<path d="m239.95,184.77c23.383-0.0432,46.07,2.2154,64.065,5.7194,18.569,3.7121,31.637,8.3556,36.105,13.571l-0.005,2.5823c-5.3884-6.4902-22.973-11.248-36.518-13.968-17.858-3.474-40.393-5.7168-63.647-5.6736-24.538,0.0459-47.387,2.3698-64.984,5.8032-14.12,2.8019-32.951,8.3679-35.302,13.858v-2.689c1.2911-3.8003,15.313-9.4792,34.984-13.417,17.729-3.4572,40.62-5.7415,65.302-5.7864zm0.01-8.4922c23.383-0.0423,46.07,2.2172,64.065,5.7194,18.569,3.7139,31.637,8.3556,36.105,13.571l-0.005,2.5823c-5.3884-6.4885-22.973-11.247-36.518-13.966-17.858-3.4757-40.393-5.7185-63.647-5.6736-24.538,0.0441-47.276,2.3698-64.875,5.8014-13.626,2.5832-33.226,8.3696-35.412,13.86v-2.6908c1.2911-3.7588,15.597-9.6414,34.985-13.417,17.729-3.4572,40.62-5.7397,65.302-5.7864z"/>
|
||||
<path d="m239.48,132.96c36.849-0.18433,68.99,5.1523,83.695,12.685l5.3638,9.279c-12.781-6.888-47.456-14.05-89.005-12.979-33.854,0.20814-70.027,3.7271-88.176,13.41l6.4035-10.709c14.895-7.7241,50.022-11.643,81.72-11.684"/>
|
||||
<path d="m239.97,140.62c21.017-0.0556,41.325,1.1298,57.476,4.0437,15.041,2.7993,29.385,7.0009,31.436,9.2604l1.5901,2.8099c-4.9881-3.257-17.401-6.8836-33.339-9.906-16.006-3.0083-36.3-4.0049-57.2-3.9502-23.722-0.0811-42.152,1.1712-57.969,3.9291-16.728,3.13-28.334,7.6015-31.197,9.7261l1.5583-2.9704c5.5631-2.8381,14.39-6.2592,29.223-8.9297,16.357-2.988,34.983-3.8841,58.423-4.0128h-0.00088zm-0.009-8.4843c20.113-0.0529,39.972,1.068,55.452,3.8506,12.209,2.3768,24.283,6.0872,28.704,9.3892l2.3256,3.6954c-3.9536-4.3947-18.836-8.5593-31.974-10.892-15.361-2.6494-34.395-3.698-54.508-3.8656-21.108,0.0591-40.615,1.352-55.752,4.1081-14.441,2.7481-23.76,6.0016-27.703,8.5425l2.0451-3.0868c5.4414-2.8646,14.232-5.4954,25.303-7.6465,15.249-2.7764,34.876-4.0358,56.108-4.0949z"/>
|
||||
<path d="m289.15,241.26c-18.218-3.4008-36.469-3.8947-49.217-3.7447-61.407,0.71967-81.244,12.609-83.665,16.209l-4.5894-7.4815c15.634-11.332,49.073-17.687,88.587-17.037,20.518,0.33602,38.224,1.6986,53.119,4.5835l-4.2358,7.4727"/>
|
||||
<path stroke-width="0.55" d="m239.58,236.46c17.082,0.25488,33.849,0.96044,50.033,3.9784l-1.172,2.069c-15.031-2.7746-31.055-3.8365-48.803-3.75-22.663-0.17727-45.585,1.9394-65.541,7.6668-6.2968,1.7524-16.721,5.8006-17.784,9.1458l-1.1659-1.9226c0.33601-1.9773,6.6363-6.081,18.414-9.3901,22.858-6.5458,44.239-7.6491,66.019-7.799v0.002zm0.77519-8.5963c17.698,0.33073,35.975,1.1492,53.74,4.6681l-1.2206,2.1537c-16.042-3.1847-31.369-4.2466-52.415-4.5702-22.735,0.0414-46.851,1.6625-68.778,8.0372-7.0791,2.062-19.297,6.5202-19.704,10.05l-1.1659-2.0655c0.26545-3.2059,10.842-7.388,20.358-10.156,22.096-6.4241,46.275-8.076,69.186-8.1174z"/>
|
||||
<path d="M327.58,247.38,320.201,258.829,299,240,244,203,182,169,149.81,157.99,156.67,145.27,159,144l20,5,66,34,38,24,32,23,13,15z"/>
|
||||
<path d="m148.65,158.29c5.646-3.8294,47.139,14.655,90.555,40.834,43.301,26.254,84.677,55.921,80.942,61.473l-1.2285,1.9323-0.56354,0.4445c0.12083-0.0864,0.74345-0.84755-0.0609-2.906-1.8449-6.0704-31.195-29.491-79.894-58.895-47.475-28.309-87.041-45.371-90.997-40.494l1.247-2.3892h-0.00089zm180.44,88.927c3.57-7.052-34.916-36.044-82.632-64.272-48.813-27.666-83.994-43.951-90.42-39.095l-1.4278,2.5991c-0.0124,0.14287,0.052-0.17727,0.35364-0.4101,1.1685-1.0195,3.1052-0.95074,3.9792-0.96662,11.065,0.16581,42.667,14.709,87.006,40.128,19.428,11.315,82.071,51.491,81.832,62.789,0.0168,0.97102,0.0803,1.1712-0.28485,1.6519l1.5936-2.4236v-0.002z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#fff" stroke="#000" stroke-width="0.67037" stroke-linejoin="bevel" d="m180.6,211.01c0,16.271,6.6628,30.987,17.457,41.742,10.815,10.778,25.512,17.579,41.809,17.579,16.381,0,31.247-6.6525,42.016-17.389,10.769-10.735,17.443-25.552,17.446-41.88h-0.002v-79.189l-118.74-0.14111,0.0123,79.278h0.002z"/>
|
||||
<path fill="#f00" stroke="#000" stroke-width="0.50734" d="m182.82,211.12v0.045c0,15.557,6.4414,29.724,16.775,40.009,10.354,10.305,24.614,16.712,40.214,16.712,15.681,0,29.912-6.3606,40.222-16.626,10.308-10.265,16.697-24.433,16.699-40.044h-0.002v-76.826l-113.84-0.0185-0.0697,76.748m91.022-53.747,0.004,48.891-0.0414,5.1717h0.00088c0,1.3608-0.082,2.9122-0.24076,4.2333-0.92512,7.7294-4.4801,14.467-9.7451,19.708-6.1636,6.1357-14.671,9.9413-24.047,9.9413-9.327,0-17.639-3.9379-23.829-10.1-6.3497-6.32-10.03-14.986-10.03-23.947l-0.0132-54.023,67.94,0.12259,0.002,0.002z"/>
|
||||
<g id="castle3">
|
||||
<g id="castle" fill="#ff0" stroke="#000" stroke-width="0.5">
|
||||
<path stroke="none" d="m190.19,154.43c0.13493-5.521,4.0524-6.828,4.0806-6.8474,0.0282-0.0185,4.2314,1.4076,4.2173,6.8986l-8.2978-0.0512"/>
|
||||
<path d="m186.81,147.69-0.68172,6.3447,4.1406,0.009c0.0397-5.2493,3.9739-6.1225,4.0691-6.1031,0.0891-0.005,3.9889,1.1606,4.0929,6.1031h4.1511l-0.74962-6.3932-15.022,0.0379v0.002z"/>
|
||||
<path d="m185.85,154.06h16.946c0.35717,0,0.64908,0.35277,0.64908,0.78404,0,0.43039-0.29191,0.78141-0.64908,0.78141h-16.946c-0.35717,0-0.64908-0.35102-0.64908-0.78141,0-0.43127,0.29191-0.78404,0.64908-0.78404z"/>
|
||||
<path d="m192.01,154.03c0.0185-3.3126,2.2621-4.2501,2.2736-4.2483,0.00088,0,2.3423,0.96661,2.3609,4.2483h-4.6344"/>
|
||||
<path d="m186.21,145.05h16.245c0.34218,0,0.62263,0.31839,0.62263,0.70468,0,0.38717-0.28045,0.70467-0.62263,0.70467h-16.245c-0.34218,0-0.62263-0.31573-0.62263-0.70467,0-0.38629,0.28045-0.70468,0.62263-0.70468z"/>
|
||||
<path d="m186.55,146.47h15.538c0.32719,0,0.59529,0.31662,0.59529,0.70379,0,0.38805-0.2681,0.70467-0.59529,0.70467h-15.538c-0.32719,0-0.59529-0.31662-0.59529-0.70467,0-0.38717,0.2681-0.70379,0.59529-0.70379z"/>
|
||||
<path d="m191.57,135.88,1.2267,0.002v0.87136h0.89513v-0.89076l1.2567,0.004v0.88723h0.89778v-0.89076h1.2576l-0.002,2.0117c0,0.31574-0.25398,0.52035-0.54854,0.52035h-4.4113c-0.29633,0-0.56972-0.23724-0.5706-0.52652l-0.003-1.9879h0.00088z"/>
|
||||
<path d="m196.19,138.57,0.27691,6.4514-4.3028-0.0159,0.28486-6.4523,3.741,0.0168"/>
|
||||
<path id="cp1" d="m190.94,141.56,0.13141,3.4775-4.1256,0.002,0.11641-3.4793h3.8786-0.00089z"/>
|
||||
<use xlink:href="#cp1" x="10.609"/>
|
||||
<path id="cp2" d="m186.3,139.04,1.1994,0.003v0.87224h0.8775v-0.89253l1.2294,0.004v0.889h0.87926v-0.89253l1.2302,0.002-0.002,2.0117c0,0.31398-0.2487,0.51859-0.5362,0.51859h-4.3169c-0.28926,0-0.55824-0.23548-0.55913-0.52564l-0.003-1.9888h0.00088z"/>
|
||||
<use xlink:href="#cp2" x="10.609"/>
|
||||
<path fill="#000" stroke="none" d="m193.9,140.61c-0.0265-0.62706,0.87661-0.63411,0.86603,0v1.5364h-0.866v-1.536"/>
|
||||
<path id="cp3" fill="#000" stroke="none" d="m188.57,142.84c-0.003-0.6059,0.83693-0.61824,0.82635,0v1.1871h-0.826v-1.187"/>
|
||||
<use xlink:href="#cp3" x="10.641"/>
|
||||
</g>
|
||||
<use xlink:href="#castle" y="46.3198"/>
|
||||
<use xlink:href="#castle" transform="matrix(0.70460892,-0.70959585,0.70959585,0.70460892,-35.341459,275.10898)"/>
|
||||
</g>
|
||||
<use xlink:href="#castle" x="45.7138"/>
|
||||
<use xlink:href="#castle3" transform="matrix(-1,0,0,1,479.79195,0)"/>
|
||||
<g id="quina">
|
||||
<path fill="#039" d="m232.636,202.406v0.005c0,2.2119,0.84927,4.2272,2.2118,5.6894,1.3652,1.4667,3.2454,2.3777,5.302,2.3777,2.0672,0,3.9439-0.90487,5.3029-2.3654,1.3581-1.4587,2.2021-3.47219,2.2021-5.693v-10.768l-14.992-0.0123-0.0273,10.766"/>
|
||||
<path stroke="#fff" stroke-width="2.972" stroke-linecap="round" d="M236.074,195.742v0M244.392,195.742v0M240.225,199.735v0M236.074,203.916v0M244.383,203.905v0"/>
|
||||
</g>
|
||||
<use xlink:href="#quina" y="-26.016"/>
|
||||
<use xlink:href="#quina" x="-20.799"/>
|
||||
<use xlink:href="#quina" x="20.745"/>
|
||||
<use xlink:href="#quina" y="25.784"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
2
data/resources/images/flags/Russian.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 6" width="900" height="600"><rect fill="#fff" width="9" height="3"/><rect fill="#d52b1e" y="3" width="9" height="3"/><rect fill="#0039a6" y="2" width="9" height="2"/></svg>
|
||||
|
After Width: | Height: | Size: 266 B |
705
data/resources/images/flags/Spanish.svg
Normal file
|
After Width: | Height: | Size: 152 KiB |
1
data/resources/images/flags/Swedish.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 5" width="1600" height="1000"><path fill="#005293" d="M0,0H8V5H0Z"/><path stroke="#fecb00" d="M0,2.5h8M3,0v5"/></svg>
|
||||
|
After Width: | Height: | Size: 193 B |
5
data/resources/images/flags/Turkish.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 -30000 90000 60000">
|
||||
<title>Flag of Turkey</title>
|
||||
<path fill="#e30a17" d="m0-30000h90000v60000H0z"/>
|
||||
<path fill="#fff" d="m41750 0 13568-4408-8386 11541V-7133l8386 11541zm925 8021a15000 15000 0 1 1 0-16042 12000 12000 0 1 0 0 16042z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 323 B |
21
data/resources/images/flags/sources.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
Catalan.svg: https://commons.wikimedia.org/wiki/Flag_of_Catalonia.svg
|
||||
Chinese.svg: https://commons.wikimedia.org/wiki/Flag_of_the_People's_Republic_of_China.svg
|
||||
Czech.svg: https://commons.wikimedia.org/wiki/Flag_of_the_Czech_Republic.svg
|
||||
Danish.svg: https://commons.wikimedia.org/wiki/Flag_of_Denmark.svg
|
||||
Dutch.svg: https://commons.wikimedia.org/wiki/Flag_of_the_Netherlands.svg
|
||||
English.svg: https://commons.wikimedia.org/wiki/Flag_of_the_United_Kingdom_(1-2).svg
|
||||
Finnish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Finland.svg
|
||||
French.svg: https://commons.wikimedia.org/wiki/File:Flag_of_France.svg
|
||||
German.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Germany.svg
|
||||
Greek.svg: https://commons.wikimedia.org/wiki/Flag_of_Greece.svg
|
||||
Hebrew.svg: https://commons.wikimedia.org/wiki/Flag_of_Israel.svg
|
||||
Iranian.svg: https://commons.wikimedia.org/wiki/Flag_of_Iran.svg
|
||||
Italian.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Italy.svg
|
||||
Korean.svg: https://commons.wikimedia.org/wiki/Flag_of_South_Korea.svg
|
||||
Norwegian.svg https://commons.wikimedia.org/wiki/File:Flag_of_Norway.svg
|
||||
Polish.svg: https://commons.wikimedia.org/wiki/Flag_of_Poland.svg
|
||||
Portuguese.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Portugal.svg
|
||||
Spanish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Spain.svg
|
||||
Swedish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Sweden.svg
|
||||
Russian.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Russia.svg
|
||||
Other.svg: https://en.wikipedia.org/wiki/File:Flag_with_question_mark.svg
|
||||
128
data/resources/images/star-0.svg
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="88"
|
||||
height="16"
|
||||
viewBox="0 0 87.999995 16"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="star-0.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="37.536584"
|
||||
inkscape:cy="1.9655172"
|
||||
inkscape:window-width="1678"
|
||||
inkscape:window-height="962"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(-4.5440002,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-6"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(13.508654,-3.287675)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-7"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(31.485839,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-5"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(49.500759,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-3"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(66.81011,-3.3684146)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
128
data/resources/images/star-1.svg
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="88"
|
||||
height="16"
|
||||
viewBox="0 0 87.999995 16"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="star-1.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="37.536584"
|
||||
inkscape:cy="1.9655172"
|
||||
inkscape:window-width="1678"
|
||||
inkscape:window-height="962"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(-4.5440002,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-6"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(13.508654,-3.287675)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-7"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(31.485839,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-5"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(49.500759,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-3"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(66.81011,-3.3684146)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
128
data/resources/images/star-2.svg
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="88"
|
||||
height="16"
|
||||
viewBox="0 0 87.999995 16"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="star-2.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="37.536584"
|
||||
inkscape:cy="1.9655172"
|
||||
inkscape:window-width="1678"
|
||||
inkscape:window-height="962"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(-4.5440002,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-6"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(13.508654,-3.287675)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-7"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(31.485839,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-5"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(49.500759,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-3"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(66.81011,-3.3684146)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
128
data/resources/images/star-3.svg
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="88"
|
||||
height="16"
|
||||
viewBox="0 0 87.999995 16"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="star-3.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="37.536584"
|
||||
inkscape:cy="1.9655172"
|
||||
inkscape:window-width="1678"
|
||||
inkscape:window-height="962"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(-4.5440002,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-6"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(13.508654,-3.287675)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-7"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(31.485839,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-5"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(49.500759,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-3"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(66.81011,-3.3684146)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
128
data/resources/images/star-4.svg
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="88"
|
||||
height="16"
|
||||
viewBox="0 0 87.999995 16"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="star-4.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="37.536584"
|
||||
inkscape:cy="1.9655172"
|
||||
inkscape:window-width="1678"
|
||||
inkscape:window-height="962"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(-4.5440002,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-6"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(13.508654,-3.287675)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-7"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(31.485839,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-5"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(49.500759,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;fill-opacity:1"
|
||||
id="path238-3"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(66.81011,-3.3684146)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
128
data/resources/images/star-5.svg
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="88"
|
||||
height="16"
|
||||
viewBox="0 0 87.999995 16"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="star-5.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.429825"
|
||||
inkscape:cx="37.536584"
|
||||
inkscape:cy="1.9655172"
|
||||
inkscape:window-width="1678"
|
||||
inkscape:window-height="962"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(-4.5440002,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-6"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(13.508654,-3.287675)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-7"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(31.485839,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-5"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(49.500759,-3.3684146)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ffff33;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path238-3"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="12.866945"
|
||||
sodipodi:cy="12"
|
||||
sodipodi:r1="8.2255917"
|
||||
sodipodi:r2="4.1127963"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 12.866945,3.7744083 2.417441,4.8982696 5.405562,0.7854747 -3.911501,3.8127714 0.92338,5.38372 L 12.866945,16.112796 8.0320636,18.654643 8.9554435,13.270924 5.0439428,9.4581522 10.449504,8.6726779 Z"
|
||||
inkscape:transform-center-y="-0.78547412"
|
||||
transform="translate(66.81011,-3.3684146)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -1,238 +0,0 @@
|
||||
/*===============================================================================*\
|
||||
|######################## [Dolphin FX Suite 2.20] #######################|
|
||||
|########################## By Asmodean ##########################|
|
||||
|| ||
|
||||
|| This program is free software; you can redistribute it and/or ||
|
||||
|| modify it under the terms of the GNU General Public License ||
|
||||
|| as published by the Free Software Foundation; either version 2 ||
|
||||
|| of the License, or (at your option) any later version. ||
|
||||
|| ||
|
||||
|| This program is distributed in the hope that it will be useful, ||
|
||||
|| but WITHOUT ANY WARRANTY; without even the implied warranty of ||
|
||||
|| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ||
|
||||
|| GNU General Public License for more details. (C)2015 ||
|
||||
|| ||
|
||||
|#################################################################################|
|
||||
\*===============================================================================*/
|
||||
|
||||
// Sourced from https://raw.githubusercontent.com/Asmodean-/dolphin/89d640cd557189bb5f921fc219150c74c39bdc55/Data/Sys/Shaders/DolphinFX.glsl with modifications.
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionRangeInteger]
|
||||
GUIName = BloomType
|
||||
OptionName = A_BLOOM_TYPE
|
||||
MinValue = 0
|
||||
MaxValue = 5
|
||||
StepAmount = 1
|
||||
DefaultValue = 0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BloomStrength
|
||||
OptionName = B_BLOOM_STRENGTH
|
||||
MinValue = 0.000
|
||||
MaxValue = 1.000
|
||||
StepAmount = 0.001
|
||||
DefaultValue = 0.220
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BlendStrength
|
||||
OptionName = C_BLEND_STRENGTH
|
||||
MinValue = 0.000
|
||||
MaxValue = 1.200
|
||||
StepAmount = 0.010
|
||||
DefaultValue = 1.000
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BloomDefocus
|
||||
OptionName = D_B_DEFOCUS
|
||||
MinValue = 1.000
|
||||
MaxValue = 4.000
|
||||
StepAmount = 0.100
|
||||
DefaultValue = 2.000
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BloomWidth
|
||||
OptionName = D_BLOOM_WIDTH
|
||||
MinValue = 1.000
|
||||
MaxValue = 8.000
|
||||
StepAmount = 0.100
|
||||
DefaultValue = 3.200
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BloomReds
|
||||
OptionName = E_BLOOM_REDS
|
||||
MinValue = 0.000
|
||||
MaxValue = 0.500
|
||||
StepAmount = 0.001
|
||||
DefaultValue = 0.020
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BloomGreens
|
||||
OptionName = F_BLOOM_GREENS
|
||||
MinValue = 0.000
|
||||
MaxValue = 0.500
|
||||
StepAmount = 0.001
|
||||
DefaultValue = 0.010
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = BloomBlues
|
||||
OptionName = G_BLOOM_BLUES
|
||||
MinValue = 0.000
|
||||
MaxValue = 0.500
|
||||
StepAmount = 0.001
|
||||
DefaultValue = 0.010
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
//Average relative luminance
|
||||
CONSTANT float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750);
|
||||
float AvgLuminance(float3 color)
|
||||
{
|
||||
return sqrt(
|
||||
(color.x * color.x * lumCoeff.x) +
|
||||
(color.y * color.y * lumCoeff.y) +
|
||||
(color.z * color.z * lumCoeff.z));
|
||||
}
|
||||
|
||||
float smootherstep(float a, float b, float x)
|
||||
{
|
||||
x = saturate((x - a) / (b - a));
|
||||
return x*x*x*(x*(x * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
float3 BlendAddLight(float3 bloom, float3 blend)
|
||||
{
|
||||
return saturate(bloom + blend);
|
||||
}
|
||||
|
||||
float3 BlendScreen(float3 bloom, float3 blend)
|
||||
{
|
||||
return (bloom + blend) - (bloom * blend);
|
||||
}
|
||||
|
||||
float3 BlendAddGlow(float3 bloom, float3 blend)
|
||||
{
|
||||
float glow = smootherstep(0.0, 1.0, AvgLuminance(bloom));
|
||||
return lerp(saturate(bloom + blend),
|
||||
(blend + blend) - (blend * blend), glow);
|
||||
}
|
||||
|
||||
float3 BlendGlow(float3 bloom, float3 blend)
|
||||
{
|
||||
float glow = smootherstep(0.0, 1.0, AvgLuminance(bloom));
|
||||
return lerp((bloom + blend) - (bloom * blend),
|
||||
(blend + blend) - (blend * blend), glow);
|
||||
}
|
||||
|
||||
float3 BlendLuma(float3 bloom, float3 blend)
|
||||
{
|
||||
float lumavg = smootherstep(0.0, 1.0, AvgLuminance(bloom + blend));
|
||||
return lerp((bloom * blend), (1.0 -
|
||||
((1.0 - bloom) * (1.0 - blend))), lumavg);
|
||||
}
|
||||
|
||||
float3 BlendOverlay(float3 bloom, float3 blend)
|
||||
{
|
||||
float3 overlay = step(0.5, bloom);
|
||||
return lerp((bloom * blend * 2.0), (1.0 - (2.0 *
|
||||
(1.0 - bloom) * (1.0 - blend))), overlay);
|
||||
}
|
||||
|
||||
float3 BloomCorrection(float3 color)
|
||||
{
|
||||
float3 bloom = color;
|
||||
|
||||
bloom.r = 2.0 / 3.0 * (1.0 - (bloom.r * bloom.r));
|
||||
bloom.g = 2.0 / 3.0 * (1.0 - (bloom.g * bloom.g));
|
||||
bloom.b = 2.0 / 3.0 * (1.0 - (bloom.b * bloom.b));
|
||||
|
||||
bloom.r = saturate(color.r + GetOption(E_BLOOM_REDS) * bloom.r);
|
||||
bloom.g = saturate(color.g + GetOption(F_BLOOM_GREENS) * bloom.g);
|
||||
bloom.b = saturate(color.b + GetOption(G_BLOOM_BLUES) * bloom.b);
|
||||
|
||||
color = saturate(bloom);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 PyramidFilter(float2 texcoord, float2 width)
|
||||
{
|
||||
float4 X = SampleLocation(texcoord + float2(0.5, 0.5) * width);
|
||||
float4 Y = SampleLocation(texcoord + float2(-0.5, 0.5) * width);
|
||||
float4 Z = SampleLocation(texcoord + float2(0.5, -0.5) * width);
|
||||
float4 W = SampleLocation(texcoord + float2(-0.5, -0.5) * width);
|
||||
|
||||
return (X + Y + Z + W) / 4.0;
|
||||
}
|
||||
|
||||
float3 Blend(float3 bloom, float3 blend)
|
||||
{
|
||||
if (GetOption(A_BLOOM_TYPE) == 0) { return BlendGlow(bloom, blend); }
|
||||
else if (GetOption(A_BLOOM_TYPE) == 1) { return BlendAddGlow(bloom, blend); }
|
||||
else if (GetOption(A_BLOOM_TYPE) == 2) { return BlendAddLight(bloom, blend); }
|
||||
else if (GetOption(A_BLOOM_TYPE) == 3) { return BlendScreen(bloom, blend); }
|
||||
else if (GetOption(A_BLOOM_TYPE) == 4) { return BlendLuma(bloom, blend); }
|
||||
else /*if (GetOption(A_BLOOM_TYPE) == 5) */ { return BlendOverlay(bloom, blend); }
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float4 color = Sample();
|
||||
float2 texcoord = GetCoordinates();
|
||||
float2 pixelSize = GetInvResolution();
|
||||
|
||||
float anflare = 4.0;
|
||||
|
||||
float2 defocus = float2(GetOption(D_B_DEFOCUS), GetOption(D_B_DEFOCUS));
|
||||
float4 bloom = PyramidFilter(texcoord, pixelSize * defocus);
|
||||
|
||||
float2 dx = float2(pixelSize.x * GetOption(D_BLOOM_WIDTH), 0.0);
|
||||
float2 dy = float2(0.0, pixelSize.y * GetOption(D_BLOOM_WIDTH));
|
||||
|
||||
float2 mdx = mul(dx, 2.0);
|
||||
float2 mdy = mul(dy, 2.0);
|
||||
|
||||
float4 blend = bloom * 0.22520613262190495;
|
||||
|
||||
blend += 0.002589001911021066 * SampleLocation(texcoord - mdx + mdy);
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord - dx + mdy);
|
||||
blend += 0.024146616900339800 * SampleLocation(texcoord + mdy);
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord + dx + mdy);
|
||||
blend += 0.002589001911021066 * SampleLocation(texcoord + mdx + mdy);
|
||||
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord - mdx + dy);
|
||||
blend += 0.044875475183061630 * SampleLocation(texcoord - dx + dy);
|
||||
blend += 0.100529757860782610 * SampleLocation(texcoord + dy);
|
||||
blend += 0.044875475183061630 * SampleLocation(texcoord + dx + dy);
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord + mdx + dy);
|
||||
|
||||
blend += 0.024146616900339800 * SampleLocation(texcoord - mdx);
|
||||
blend += 0.100529757860782610 * SampleLocation(texcoord - dx);
|
||||
blend += 0.100529757860782610 * SampleLocation(texcoord + dx);
|
||||
blend += 0.024146616900339800 * SampleLocation(texcoord + mdx);
|
||||
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord - mdx - dy);
|
||||
blend += 0.044875475183061630 * SampleLocation(texcoord - dx - dy);
|
||||
blend += 0.100529757860782610 * SampleLocation(texcoord - dy);
|
||||
blend += 0.044875475183061630 * SampleLocation(texcoord + dx - dy);
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord + mdx - dy);
|
||||
|
||||
blend += 0.002589001911021066 * SampleLocation(texcoord - mdx - mdy);
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord - dx - mdy);
|
||||
blend += 0.024146616900339800 * SampleLocation(texcoord - mdy);
|
||||
blend += 0.010778807494659370 * SampleLocation(texcoord + dx - mdy);
|
||||
blend += 0.002589001911021066 * SampleLocation(texcoord + mdx - mdy);
|
||||
blend = lerp(color, blend, GetOption(C_BLEND_STRENGTH));
|
||||
|
||||
bloom.xyz = Blend(bloom.xyz, blend.xyz);
|
||||
bloom.xyz = BloomCorrection(bloom.xyz);
|
||||
|
||||
color.a = AvgLuminance(color.xyz);
|
||||
bloom.a = AvgLuminance(bloom.xyz);
|
||||
bloom.a *= anflare;
|
||||
|
||||
SetOutput(lerp(color, bloom, GetOption(B_BLOOM_STRENGTH)));
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*===============================================================================*\
|
||||
|######################## [Dolphin FX Suite 2.20] #######################|
|
||||
|########################## By Asmodean ##########################|
|
||||
|| ||
|
||||
|| This program is free software; you can redistribute it and/or ||
|
||||
|| modify it under the terms of the GNU General Public License ||
|
||||
|| as published by the Free Software Foundation; either version 2 ||
|
||||
|| of the License, or (at your option) any later version. ||
|
||||
|| ||
|
||||
|| This program is distributed in the hope that it will be useful, ||
|
||||
|| but WITHOUT ANY WARRANTY; without even the implied warranty of ||
|
||||
|| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ||
|
||||
|| GNU General Public License for more details. (C)2015 ||
|
||||
|| ||
|
||||
|#################################################################################|
|
||||
\*===============================================================================*/
|
||||
|
||||
// Sourced from https://raw.githubusercontent.com/Asmodean-/dolphin/89d640cd557189bb5f921fc219150c74c39bdc55/Data/Sys/Shaders/DolphinFX.glsl with modifications.
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = EdgeStrength
|
||||
OptionName = A_EDGE_STRENGTH
|
||||
MinValue = 0.00
|
||||
MaxValue = 4.00
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 1.00
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = EdgeFilter
|
||||
OptionName = B_EDGE_FILTER
|
||||
MinValue = 0.25
|
||||
MaxValue = 1.00
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.60
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = EdgeThickness
|
||||
OptionName = C_EDGE_THICKNESS
|
||||
MinValue = 0.25
|
||||
MaxValue = 2.00
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 1.00
|
||||
|
||||
[OptionRangeInteger]
|
||||
GUIName = PaletteType
|
||||
OptionName = D_PALETTE_TYPE
|
||||
MinValue = 0
|
||||
MaxValue = 2
|
||||
StepAmount = 1
|
||||
DefaultValue = 1
|
||||
|
||||
[OptionRangeInteger]
|
||||
GUIName = UseYuvLuma
|
||||
OptionName = E_YUV_LUMA
|
||||
MinValue = 0
|
||||
MaxValue = 1
|
||||
StepAmount = 1
|
||||
DefaultValue = 0
|
||||
|
||||
[OptionRangeInteger]
|
||||
GUIName = ColourRounding
|
||||
OptionName = G_COLOR_ROUNDING
|
||||
MinValue = 0
|
||||
MaxValue = 1
|
||||
StepAmount = 1
|
||||
DefaultValue = 1
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
//Average relative luminance
|
||||
CONSTANT float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750);
|
||||
float AvgLuminance(float3 color)
|
||||
{
|
||||
return sqrt(
|
||||
(color.x * color.x * lumCoeff.x) +
|
||||
(color.y * color.y * lumCoeff.y) +
|
||||
(color.z * color.z * lumCoeff.z));
|
||||
}
|
||||
|
||||
float3 YUVtoRGB(float3 YUV)
|
||||
{
|
||||
const float3x3 m = float3x3(
|
||||
1.000, 0.000, 1.28033,
|
||||
1.000,-0.21482,-0.38059,
|
||||
1.000, 2.12798, 0.000 );
|
||||
|
||||
return mul(m, YUV);
|
||||
}
|
||||
|
||||
float3 RGBtoYUV(float3 RGB)
|
||||
{
|
||||
const float3x3 m = float3x3(
|
||||
0.2126, 0.7152, 0.0722,
|
||||
-0.09991,-0.33609, 0.436,
|
||||
0.615, -0.55861, -0.05639 );
|
||||
|
||||
return mul(m, RGB);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float4 color = Sample();
|
||||
float2 texcoord = GetCoordinates();
|
||||
float2 pixelSize = GetInvResolution();
|
||||
float2 texSize = GetResolution();
|
||||
|
||||
float3 yuv;
|
||||
float3 sum = color.rgb;
|
||||
|
||||
const int NUM = 9;
|
||||
const float2 RoundingOffset = float2(0.25, 0.25);
|
||||
const float3 thresholds = float3(9.0, 8.0, 6.0);
|
||||
|
||||
float lum[NUM];
|
||||
float3 col[NUM];
|
||||
float2 set[NUM] = BEGIN_ARRAY(float2, NUM)
|
||||
float2(-0.0078125, -0.0078125),
|
||||
float2(0.00, -0.0078125),
|
||||
float2(0.0078125, -0.0078125),
|
||||
float2(-0.0078125, 0.00),
|
||||
float2(0.00, 0.00),
|
||||
float2(0.0078125, 0.00),
|
||||
float2(-0.0078125, 0.0078125),
|
||||
float2(0.00, 0.0078125),
|
||||
float2(0.0078125, 0.0078125) END_ARRAY;
|
||||
|
||||
for (int i = 0; i < NUM; i++)
|
||||
{
|
||||
col[i] = SampleLocation(texcoord + set[i] * RoundingOffset).rgb;
|
||||
|
||||
if (GetOption(G_COLOR_ROUNDING) == 1) {
|
||||
col[i].r = round(col[i].r * thresholds.r) / thresholds.r;
|
||||
col[i].g = round(col[i].g * thresholds.g) / thresholds.g;
|
||||
col[i].b = round(col[i].b * thresholds.b) / thresholds.b; }
|
||||
|
||||
lum[i] = AvgLuminance(col[i].xyz);
|
||||
yuv = RGBtoYUV(col[i]);
|
||||
|
||||
if (GetOption(E_YUV_LUMA) == 0)
|
||||
{ yuv.r = round(yuv.r * thresholds.r) / thresholds.r; }
|
||||
else
|
||||
{ yuv.r = saturate(round(yuv.r * lum[i]) / thresholds.r + lum[i]); }
|
||||
|
||||
yuv = YUVtoRGB(yuv);
|
||||
sum += yuv;
|
||||
}
|
||||
|
||||
float3 shadedColor = (sum / NUM);
|
||||
float2 pixel = float2((1.0/texSize.x) * GetOption(C_EDGE_THICKNESS),
|
||||
(1.0/texSize.y) * GetOption(C_EDGE_THICKNESS));
|
||||
|
||||
float edgeX = dot(SampleLocation(texcoord + pixel).rgb, lumCoeff);
|
||||
edgeX = dot(float4(SampleLocation(texcoord - pixel).rgb, edgeX), float4(lumCoeff, -1.0));
|
||||
|
||||
float edgeY = dot(SampleLocation(texcoord + float2(pixel.x, -pixel.y)).rgb, lumCoeff);
|
||||
edgeY = dot(float4(SampleLocation(texcoord + float2(-pixel.x, pixel.y)).rgb, edgeY), float4(lumCoeff, -1.0));
|
||||
|
||||
float edge = dot(float2(edgeX, edgeY), float2(edgeX, edgeY));
|
||||
|
||||
if (GetOption(D_PALETTE_TYPE) == 0)
|
||||
{ color.rgb = lerp(color.rgb, color.rgb + pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH), GetOption(A_EDGE_STRENGTH)); }
|
||||
else if (GetOption(D_PALETTE_TYPE) == 1)
|
||||
{ color.rgb = lerp(color.rgb + pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH), shadedColor, 0.25); }
|
||||
else if (GetOption(D_PALETTE_TYPE) == 2)
|
||||
{ color.rgb = lerp(shadedColor + edge * -GetOption(A_EDGE_STRENGTH), pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH) + color.rgb, 0.50); }
|
||||
|
||||
color.a = AvgLuminance(color.rgb);
|
||||
|
||||
SetOutput(saturate(color));
|
||||
}
|
||||
@@ -1,780 +0,0 @@
|
||||
// Crt-Consumer
|
||||
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Pre-Scale Sharpening
|
||||
OptionName = PRE_SCALE
|
||||
MinValue = 1.0
|
||||
MaxValue = 4.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 1.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Convergence X
|
||||
OptionName = blurx
|
||||
MinValue = -4.0
|
||||
MaxValue = 4.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.25
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Convergence Y
|
||||
OptionName = blury
|
||||
MinValue = -4.0
|
||||
MaxValue = 4.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = -0.1
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Curvature X
|
||||
OptionName = warpx
|
||||
MinValue = 0.0
|
||||
MaxValue = 0.12
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.03
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Curvature Y
|
||||
OptionName = warpy
|
||||
MinValue = 0.0
|
||||
MaxValue = 0.12
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.04
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Corner size
|
||||
OptionName = corner
|
||||
MinValue = 0.0
|
||||
MaxValue = 0.10
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.03
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Border Smoothness
|
||||
OptionName = smoothness
|
||||
MinValue = 100.0
|
||||
MaxValue = 600.0
|
||||
StepAmount = 5.0
|
||||
DefaultValue = 400.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Interlacing Toggle
|
||||
OptionName = inter
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Interlacing Downscale Scanlines
|
||||
OptionName = Downscale
|
||||
MinValue = 1.0
|
||||
MaxValue = 8.0
|
||||
StepAmount = 1.
|
||||
DefaultValue = 2.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Beam low
|
||||
OptionName = scanlow
|
||||
MinValue = 1.0
|
||||
MaxValue = 15.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 6.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Beam high
|
||||
OptionName = scanhigh
|
||||
MinValue = 1.0
|
||||
MaxValue = 15.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 8.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanlines dark
|
||||
OptionName = beamlow
|
||||
MinValue = 0.5
|
||||
MaxValue = 2.5
|
||||
StepAmount = 0.0
|
||||
DefaultValue = 1.45
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanlines bright
|
||||
OptionName = beamhigh
|
||||
MinValue = 0.5
|
||||
MaxValue = 2.5
|
||||
StepAmount = 0.0
|
||||
DefaultValue = 1.05
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Protect White On Masks
|
||||
OptionName = preserve
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.98
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Bright boost dark pixels
|
||||
OptionName = brightboost1
|
||||
MinValue = 0.0
|
||||
MaxValue = 3.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.25
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Bright boost bright pixels
|
||||
OptionName = brightboost2
|
||||
MinValue = 0.0
|
||||
MaxValue = 3.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Glow pixels per axis
|
||||
OptionName = glow
|
||||
MinValue = 1.0
|
||||
MaxValue = 6.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 3.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Glow quality
|
||||
OptionName = quality
|
||||
MinValue = 0.25
|
||||
MaxValue = 4.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Glow intensity
|
||||
OptionName = glow_str
|
||||
MinValue = 0.0001
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.3
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Add Noise
|
||||
OptionName = nois
|
||||
MinValue = 0.0
|
||||
MaxValue = 32.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Post Brightness
|
||||
OptionName = postbr
|
||||
MinValue = 0.0
|
||||
MaxValue = 2.5
|
||||
StepAmount = 0.02
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Palette Fixes. Sega, PUAE Atari ST dark colors
|
||||
OptionName = palette_fix
|
||||
MinValue = 0.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Type
|
||||
OptionName = Shadowmask
|
||||
MinValue = -1.0
|
||||
MaxValue = 8.0
|
||||
StepAmount = 1.
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Size
|
||||
OptionName = masksize
|
||||
MinValue = 1.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask dark
|
||||
OptionName = MaskDark
|
||||
MinValue = 0.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 0.2
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask light
|
||||
OptionName = MaskLight
|
||||
MinValue = 0.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 1.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Slot Mask Strength
|
||||
OptionName = slotmask
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Slot Mask Width
|
||||
OptionName = slotwidth
|
||||
MinValue = 1.0
|
||||
MaxValue = 6.0
|
||||
StepAmount = 0.5
|
||||
DefaultValue = 2.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Slot Mask Height: 2x1 or 4x1
|
||||
OptionName = double_slot
|
||||
MinValue = 1.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Slot Mask Size
|
||||
OptionName = slotms
|
||||
MinValue = 1.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Gamma Out
|
||||
OptionName = GAMMA_OUT
|
||||
MinValue = 0.0
|
||||
MaxValue = 4.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 2.25
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Saturation
|
||||
OptionName = sat
|
||||
MinValue = 0.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Contrast, 1.0:Off
|
||||
OptionName = contrast
|
||||
MinValue = 0.00
|
||||
MaxValue = 2.00
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Color Temperature %
|
||||
OptionName = WP
|
||||
MinValue = -100.0
|
||||
MaxValue = 100.0
|
||||
StepAmount = 5.
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Red-Green Tint
|
||||
OptionName = rg
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.005
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Red-Blue Tint
|
||||
OptionName = rb
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.005
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Green-Red Tint
|
||||
OptionName = gr
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.005
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Green-Blue Tint
|
||||
OptionName = gb
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.005
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Blue-Red Tint
|
||||
OptionName = br
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.005
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Blue-Green Tint
|
||||
OptionName = bg
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.005
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Vignette On/Off
|
||||
OptionName = vignette
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Vignette Power
|
||||
OptionName = vpower
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.15
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Vignette strength
|
||||
OptionName = vstr
|
||||
MinValue = 0.0
|
||||
MaxValue = 50.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 40.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Switch off shader
|
||||
OptionName = alloff
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 0.0
|
||||
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
#define iTime (float(GetTime())/2.0)
|
||||
#define iTimer (float(GetTime())/60.0)
|
||||
|
||||
#define SourceSize (vec4(1.0/GetInvNativePixelSize(),GetInvNativePixelSize()))
|
||||
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos * 2.0 - 1.0;
|
||||
pos *= vec2(1.0 + (pos.y * pos.y) * warpx, 1.0 + (pos.x * pos.x) * warpy);
|
||||
return pos * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
float sw(float y, float l)
|
||||
{
|
||||
float beam = mix(scanlow, scanhigh, y);
|
||||
float scan = mix(beamlow, beamhigh, l);
|
||||
float ex = y * scan;
|
||||
return exp2(-beam * ex * ex);
|
||||
}
|
||||
|
||||
vec3 mask(vec2 x, vec3 col, float l)
|
||||
{
|
||||
x = floor(x / masksize);
|
||||
|
||||
if (Shadowmask == 0.0)
|
||||
{
|
||||
float m = fract(x.x * 0.4999);
|
||||
if (m < 0.4999) return vec3(1.0, MaskDark, 1.0);
|
||||
else return vec3(MaskDark, 1.0, MaskDark);
|
||||
}
|
||||
|
||||
else if (Shadowmask == 1.0)
|
||||
{
|
||||
vec3 Mask = vec3(MaskDark, MaskDark, MaskDark);
|
||||
float line = MaskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(x.x / 6.0) < 0.5) odd = 1.0;
|
||||
if (fract((x.y + odd) / 2.0) < 0.5) line = MaskDark;
|
||||
|
||||
float m = fract(x.x / 3.0);
|
||||
if (m < 0.333) Mask.b = MaskLight;
|
||||
else if (m < 0.666) Mask.g = MaskLight;
|
||||
else Mask.r = MaskLight;
|
||||
|
||||
Mask *= line;
|
||||
return Mask;
|
||||
}
|
||||
|
||||
else if (Shadowmask == 2.0)
|
||||
{
|
||||
float m = fract(x.x*0.3333);
|
||||
if (m < 0.3333) return vec3(MaskDark, MaskDark, MaskLight);
|
||||
if (m < 0.6666) return vec3(MaskDark, MaskLight, MaskDark);
|
||||
else return vec3(MaskLight, MaskDark, MaskDark);
|
||||
}
|
||||
|
||||
if (Shadowmask == 3.0)
|
||||
{
|
||||
float m = fract(x.x * 0.5);
|
||||
if (m < 0.5) return vec3(1.0, 1.0, 1.0);
|
||||
else return vec3(MaskDark, MaskDark, MaskDark);
|
||||
}
|
||||
|
||||
else if (Shadowmask == 4.0)
|
||||
{
|
||||
vec3 Mask = vec3(col.rgb);
|
||||
float line = MaskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(x.x / 4.0) < 0.5) odd = 1.0;
|
||||
if (fract((x.y + odd) / 2.0) < 0.5) line = MaskDark;
|
||||
|
||||
float m = fract(x.x / 2.0);
|
||||
if (m < 0.5) { Mask.r = 1.0; Mask.b = 1.0; }
|
||||
else Mask.g = 1.0;
|
||||
|
||||
Mask *= line;
|
||||
return Mask;
|
||||
}
|
||||
|
||||
else if (Shadowmask == 5.0)
|
||||
{
|
||||
vec3 Mask = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
if (fract(x.x / 4.0) < 0.5)
|
||||
{
|
||||
if (fract(x.y / 3.0) < 0.666)
|
||||
{
|
||||
if (fract(x.x / 2.0) < 0.5) Mask = vec3(1.0, MaskDark, 1.0);
|
||||
else Mask = vec3(MaskDark, 1.0, MaskDark);
|
||||
}
|
||||
else Mask *= l;
|
||||
}
|
||||
else if (fract(x.x / 4.0) >= 0.5)
|
||||
{
|
||||
if (fract(x.y / 3.0) > 0.333)
|
||||
{
|
||||
if (fract(x.x / 2.0) < 0.5) Mask = vec3(1.0, MaskDark, 1.0);
|
||||
else Mask = vec3(MaskDark, 1.0, MaskDark);
|
||||
}
|
||||
else Mask *= l;
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}
|
||||
|
||||
else if (Shadowmask == 6.0)
|
||||
{
|
||||
vec3 Mask = vec3(MaskDark, MaskDark, MaskDark);
|
||||
if (fract(x.x / 6.0) < 0.5)
|
||||
{
|
||||
if (fract(x.y / 4.0) < 0.75)
|
||||
{
|
||||
if (fract(x.x / 3.0) < 0.3333) Mask.r = MaskLight;
|
||||
else if (fract(x.x / 3.0) < 0.6666) Mask.g = MaskLight;
|
||||
else Mask.b = MaskLight;
|
||||
}
|
||||
else Mask * l * 0.9;
|
||||
}
|
||||
else if (fract(x.x / 6.0) >= 0.5)
|
||||
{
|
||||
if (fract(x.y / 4.0) >= 0.5 || fract(x.y / 4.0) < 0.25)
|
||||
{
|
||||
if (fract(x.x / 3.0) < 0.3333) Mask.r = MaskLight;
|
||||
else if (fract(x.x / 3.0) < 0.6666) Mask.g = MaskLight;
|
||||
else Mask.b = MaskLight;
|
||||
}
|
||||
else Mask * l * 0.9;
|
||||
}
|
||||
return Mask;
|
||||
}
|
||||
|
||||
else if (Shadowmask == 7.0)
|
||||
{
|
||||
float m = fract(x.x * 0.3333);
|
||||
|
||||
if (m < 0.3333) return vec3(MaskDark, MaskLight, MaskLight * col.b); //Cyan
|
||||
if (m < 0.6666) return vec3(MaskLight * col.r, MaskDark, MaskLight); //Magenta
|
||||
else return vec3(MaskLight, MaskLight * col.g, MaskDark); //Yellow
|
||||
}
|
||||
|
||||
else if (Shadowmask == 8.0)
|
||||
{
|
||||
vec3 Mask = vec3(MaskDark, MaskDark, MaskDark);
|
||||
|
||||
float bright = MaskLight;
|
||||
float left = 0.0;
|
||||
if (fract(x.x / 6.0) < 0.5) left = 1.0;
|
||||
|
||||
float m = fract(x.x / 3.0);
|
||||
if (m < 0.333) Mask.b = 0.9;
|
||||
else if (m < 0.666) Mask.g = 0.9;
|
||||
else Mask.r = 0.9;
|
||||
|
||||
if (mod(x.y, 2.0) == 1.0 && left == 1.0 || mod(x.y, 2.0) == 0.0 && left == 0.0)
|
||||
Mask *= bright;
|
||||
|
||||
return Mask;
|
||||
}
|
||||
|
||||
else return vec3(1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
float SlotMask(vec2 pos, vec3 c)
|
||||
{
|
||||
if (slotmask == 0.0) return 1.0;
|
||||
|
||||
pos = floor(pos / slotms);
|
||||
float mx = pow(max(max(c.r, c.g), c.b), 1.33);
|
||||
float mlen = slotwidth * 2.0;
|
||||
float px = fract(pos.x / mlen);
|
||||
float py = floor(fract(pos.y / (2.0 * double_slot)) * 2.0 * double_slot);
|
||||
float slot_dark = mix(1.0 - slotmask, 1.0 - 0.80 * slotmask, mx);
|
||||
float slot = 1.0 + 0.7 * slotmask * (1.0 - mx);
|
||||
|
||||
if (py == 0.0 && px < 0.5) slot = slot_dark;
|
||||
else if (py == double_slot && px >= 0.5) slot = slot_dark;
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
mat4 contrastMatrix(float contrast)
|
||||
{
|
||||
float t = (1.0 - contrast) / 2.0;
|
||||
|
||||
return mat4(contrast, 0, 0, 0,
|
||||
0, contrast, 0, 0,
|
||||
0, 0, contrast, 0,
|
||||
t, t, t, 1);
|
||||
}
|
||||
|
||||
mat3 vign(float l)
|
||||
{
|
||||
// vec2 vpos = vTexCoord;
|
||||
vec2 vpos = GetCoordinates();
|
||||
vpos *= 1.0 - vpos.xy;
|
||||
|
||||
float vig = vpos.x * vpos.y * vstr;
|
||||
vig = min(pow(vig, vpower), 1.0);
|
||||
if (vignette == 0.0) vig = 1.0;
|
||||
|
||||
return mat3(vig, 0, 0,
|
||||
0, vig, 0,
|
||||
0, 0, vig);
|
||||
}
|
||||
|
||||
vec3 saturation(vec3 textureColor)
|
||||
{
|
||||
float luminance = length(textureColor.rgb) * 0.5775;
|
||||
|
||||
vec3 luminanceWeighting = vec3(0.4, 0.5, 0.1);
|
||||
if (luminance < 0.5) luminanceWeighting.rgb = (luminanceWeighting.rgb * luminanceWeighting.rgb)
|
||||
+ (luminanceWeighting.rgb * luminanceWeighting.rgb);
|
||||
|
||||
luminance = dot(textureColor.rgb, luminanceWeighting);
|
||||
vec3 greyScaleColor = vec3(luminance, luminance, luminance);
|
||||
|
||||
vec3 res = vec3(mix(greyScaleColor, textureColor.rgb, sat));
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vec3 glow0 (vec2 texcoord, vec3 col)
|
||||
{
|
||||
|
||||
// the more quality, the smaller the offset and better quality, less visible glow too
|
||||
vec2 size = SourceSize.zw/quality;
|
||||
|
||||
vec3 c01;
|
||||
vec3 sum = vec3(0.0);
|
||||
|
||||
// glow = pixels per axis, the more the slower!
|
||||
|
||||
for (float x = -glow; x <= glow; x = x+1.0)
|
||||
{
|
||||
|
||||
// multiply texture, the more far away the less pronounced
|
||||
float factor = 1.0/glow;
|
||||
for (float y = -glow; y <= glow; y = y+1.0)
|
||||
{
|
||||
|
||||
vec2 offset = vec2(x, y) * size;
|
||||
|
||||
c01 = SampleLocation(texcoord + offset).rgb*factor; c01 = c01*c01;
|
||||
|
||||
sum += c01;
|
||||
}
|
||||
}
|
||||
|
||||
return (glow_str * sum / (glow * glow )) ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float noise(vec2 co)
|
||||
{
|
||||
return fract(sin(iTimer * dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
float corner0(vec2 coord)
|
||||
{
|
||||
coord = (coord - vec2(0.5, 0.5)) * 1.0 + vec2(0.5, 0.5);
|
||||
coord = min(coord, vec2(1.0, 1.0) - coord) * vec2(1.0, SourceSize.y / SourceSize.x);
|
||||
|
||||
vec2 cdist = vec2(corner, corner);
|
||||
coord = (cdist - min(coord, cdist));
|
||||
float dist = sqrt(dot(coord, coord));
|
||||
|
||||
return clamp((cdist.x - dist) * smoothness, 0.0, 1.0);
|
||||
}
|
||||
|
||||
const mat3 D65_to_XYZ = mat3(
|
||||
0.4306190, 0.2220379, 0.0201853,
|
||||
0.3415419, 0.7066384, 0.1295504,
|
||||
0.1783091, 0.0713236, 0.9390944);
|
||||
|
||||
const mat3 XYZ_to_D65 = mat3(
|
||||
3.0628971, -0.9692660, 0.0678775,
|
||||
-1.3931791, 1.8760108, -0.2288548,
|
||||
-0.4757517, 0.0415560, 1.0693490);
|
||||
|
||||
const mat3 D50_to_XYZ = mat3(
|
||||
0.4552773, 0.2323025, 0.0145457,
|
||||
0.3675500, 0.7077956, 0.1049154,
|
||||
0.1413926, 0.0599019, 0.7057489);
|
||||
|
||||
const mat3 XYZ_to_D50 = mat3(
|
||||
2.9603944, -0.9787684, 0.0844874,
|
||||
-1.4678519, 1.9161415, -0.2545973,
|
||||
-0.4685105, 0.0334540, 1.4216174);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 vTexCoord = GetCoordinates();
|
||||
vec2 pos = Warp(vTexCoord.xy);
|
||||
vec2 tex_size = 1.0 / GetInvNativePixelSize();
|
||||
vec2 OutputSize = GetWindowSize();
|
||||
|
||||
|
||||
vec2 pC4 = (pos + 0.5/tex_size);
|
||||
vec2 fp = fract(pos * tex_size);
|
||||
if (inter < 0.5 && tex_size.y > 400.0){ fp.y = fract(pos.y * tex_size.y*1.0/Downscale);}
|
||||
|
||||
vec4 res = vec4(1.0);
|
||||
|
||||
if (alloff == 1.0)
|
||||
res = SampleLocation(pC4);
|
||||
else
|
||||
{
|
||||
|
||||
vec2 texel = pos * tex_size;
|
||||
vec2 texel_floored = floor(texel);
|
||||
|
||||
float scale = PRE_SCALE;
|
||||
float region_range = 0.5 - 0.5 / scale;
|
||||
|
||||
// Figure out where in the texel to sample to get correct pre-scaled bilinear.
|
||||
// Uses the hardware bilinear interpolator to avoid having to sample 4 times manually.
|
||||
|
||||
vec2 center_dist = fp - 0.5;
|
||||
|
||||
vec2 fpp = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5;
|
||||
|
||||
vec2 mod_texel = texel_floored + fpp;
|
||||
vec2 coords = mod_texel / SourceSize.xy;
|
||||
|
||||
vec3 sample1 = SampleLocation(vec2(coords.x + blurx*SourceSize.z, coords.y - blury*SourceSize.w)).rgb;
|
||||
vec3 sample2 = SampleLocation(coords).rgb;
|
||||
vec3 sample3 = SampleLocation(vec2(coords.x - blurx*SourceSize.z, coords.y + blury*SourceSize.w )).rgb;
|
||||
|
||||
vec3 color = vec3(sample1.r * 0.5 + sample2.r * 0.5,
|
||||
sample1.g * 0.25 + sample2.g * 0.5 + sample3.g * 0.25,
|
||||
sample2.b * 0.5 + sample3.b * 0.5);
|
||||
if (palette_fix != 0.0)
|
||||
{
|
||||
if (palette_fix == 1.0) color = color* 1.0667;
|
||||
else if (palette_fix == 2.0) color = color * 2.0;
|
||||
}
|
||||
|
||||
//COLOR TEMPERATURE FROM GUEST.R-DR.VENOM
|
||||
if (WP != 0.0)
|
||||
{
|
||||
vec3 warmer = D50_to_XYZ * color;
|
||||
warmer = XYZ_to_D65 * warmer;
|
||||
|
||||
vec3 cooler = D65_to_XYZ * color;
|
||||
cooler = XYZ_to_D50 * cooler;
|
||||
|
||||
float m = abs(WP) / 100.0;
|
||||
vec3 comp = (WP < 0.0) ? cooler : warmer;
|
||||
comp = clamp(comp, 0.0, 1.0);
|
||||
|
||||
color = vec3(mix(color, comp, m));
|
||||
}
|
||||
|
||||
mat3 hue = mat3 (1., rg, rb, //red tint
|
||||
gr, 1., gb, //green tint
|
||||
br, bg, 1.); //blue tint
|
||||
|
||||
color = hue * color;
|
||||
|
||||
color = (2.0*pow(color,vec3(2.8))) - pow(color,vec3(3.6));
|
||||
|
||||
float lum = color.r * 0.3 + color.g * 0.6 + color.b * 0.1;
|
||||
|
||||
float f = fract(fp.y -0.5);
|
||||
|
||||
if (inter > 0.5 && tex_size.y > 400.0) color = color;
|
||||
else
|
||||
{color = color * sw(f,lum) + color * sw (1.0-f,lum);}
|
||||
|
||||
float lum1 = color.r * 0.3 + color.g * 0.6 + color.b * 0.1;
|
||||
|
||||
|
||||
color *= mix(mask((vTexCoord * OutputSize.xy), color,lum1), vec3(1.0), lum1*preserve);
|
||||
|
||||
|
||||
if (slotmask != 0.0) color *= SlotMask((vTexCoord * OutputSize.xy) * 1.0001, color);
|
||||
|
||||
color *= mix(brightboost1, brightboost2, max(max(color.r, color.g), color.b));
|
||||
|
||||
|
||||
|
||||
color = pow(color,vec3(1.0 / GAMMA_OUT));
|
||||
if (glow_str != 0.0) color += glow0(coords,color);
|
||||
|
||||
if (sat != 1.0) color = saturation(color);
|
||||
if (corner != 0.0) color *= corner0(pC4);
|
||||
if (nois != 0.0) color *= 1.0 + noise(coords * 2.0) / nois;
|
||||
|
||||
color *= mix(1.0, postbr, lum);
|
||||
res = vec4(color, 1.0);
|
||||
if (contrast != 1.0) res = contrastMatrix(contrast) * res;
|
||||
if (inter > 0.5 && SourceSize.y > 400.0 && fract(iTime) < 0.5) res = res * 0.95;
|
||||
res.rgb *= vign(lum);
|
||||
|
||||
}
|
||||
|
||||
SetOutput(res);
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
// CRT Shader by EasyMode
|
||||
// License: GPL
|
||||
|
||||
// A flat CRT shader ideally for 1080p or higher displays.
|
||||
|
||||
// Recommended Settings:
|
||||
|
||||
// Video
|
||||
// - Aspect Ratio: 4:3
|
||||
// - Integer Scale: Off
|
||||
|
||||
// Shader
|
||||
// - Filter: Nearest
|
||||
// - Scale: Don't Care
|
||||
|
||||
// Example RGB Mask Parameter Settings:
|
||||
|
||||
// Aperture Grille (Default)
|
||||
// - Dot Width: 1
|
||||
// - Dot Height: 1
|
||||
// - Stagger: 0
|
||||
|
||||
// Lottes' Shadow Mask
|
||||
// - Dot Width: 2
|
||||
// - Dot Height: 1
|
||||
// - Stagger: 3
|
||||
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Sharpness Horizontal
|
||||
OptionName = SHARPNESS_H
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Sharpness Vertical
|
||||
OptionName = SHARPNESS_V
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Strength
|
||||
OptionName = MASK_STRENGTH
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.3
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Dot Width
|
||||
OptionName = MASK_DOT_WIDTH
|
||||
MinValue = 1.0
|
||||
MaxValue = 100.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Dot Height
|
||||
OptionName = MASK_DOT_HEIGHT
|
||||
MinValue = 1.0
|
||||
MaxValue = 100.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Stagger
|
||||
OptionName = MASK_STAGGER
|
||||
MinValue = 0.0
|
||||
MaxValue = 100.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Size
|
||||
OptionName = MASK_SIZE
|
||||
MinValue = 1.0
|
||||
MaxValue = 100.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Strength
|
||||
OptionName = SCANLINE_STRENGTH
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Beam Width Min.
|
||||
OptionName = SCANLINE_BEAM_WIDTH_MIN
|
||||
MinValue = 0.5
|
||||
MaxValue = 5.0
|
||||
StepAmount = 0.5
|
||||
DefaultValue = 1.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Beam Width Max.
|
||||
OptionName = SCANLINE_BEAM_WIDTH_MAX
|
||||
MinValue = 0.5
|
||||
MaxValue = 5.0
|
||||
StepAmount = 0.5
|
||||
DefaultValue = 1.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Brightness Min.
|
||||
OptionName = SCANLINE_BRIGHT_MIN
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.35
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Brightness Max.
|
||||
OptionName = SCANLINE_BRIGHT_MAX
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.65
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Cutoff
|
||||
OptionName = SCANLINE_CUTOFF
|
||||
MinValue = 1.0
|
||||
MaxValue = 1000.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 400.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Gamma Input
|
||||
OptionName = GAMMA_INPUT
|
||||
MinValue = 0.1
|
||||
MaxValue = 5.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 2.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Gamma Output
|
||||
OptionName = GAMMA_OUTPUT
|
||||
MinValue = 0.1
|
||||
MaxValue = 5.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 1.8
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Brightness Boost
|
||||
OptionName = BRIGHT_BOOST
|
||||
MinValue = 1.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 1.2
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Dilation
|
||||
OptionName = DILATION
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
#define FIX(c) max(abs(c), 1e-5)
|
||||
#define PI 3.141592653589
|
||||
|
||||
#define TEX2D(c) dilate(SampleLocation(c))
|
||||
|
||||
// Set to 0 to use linear filter and gain speed
|
||||
#define ENABLE_LANCZOS 1
|
||||
|
||||
vec4 dilate(vec4 col)
|
||||
{
|
||||
vec4 x = mix(vec4(1.0), col, GetOption(DILATION));
|
||||
|
||||
return col * x;
|
||||
}
|
||||
|
||||
float curve_distance(float x, float sharp)
|
||||
{
|
||||
|
||||
/*
|
||||
apply half-circle s-curve to distance for sharper (more pixelated) interpolation
|
||||
single line formula for Graph Toy:
|
||||
0.5 - sqrt(0.25 - (x - step(0.5, x)) * (x - step(0.5, x))) * sign(0.5 - x)
|
||||
*/
|
||||
|
||||
float x_step = step(0.5, x);
|
||||
float curve = 0.5 - sqrt(0.25 - (x - x_step) * (x - x_step)) * sign(0.5 - x);
|
||||
|
||||
return mix(x, curve, sharp);
|
||||
}
|
||||
|
||||
mat4x4 get_color_matrix(vec2 co, vec2 dx)
|
||||
{
|
||||
return mat4x4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
|
||||
}
|
||||
|
||||
vec3 filter_lanczos(vec4 coeffs, mat4x4 color_matrix)
|
||||
{
|
||||
vec4 col = color_matrix * coeffs;
|
||||
vec4 sample_min = min(color_matrix[1], color_matrix[2]);
|
||||
vec4 sample_max = max(color_matrix[1], color_matrix[2]);
|
||||
|
||||
col = clamp(col, sample_min, sample_max);
|
||||
|
||||
return col.rgb;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 vTexCoord = GetCoordinates();
|
||||
vec2 nativeSize = 1.0 / GetInvNativePixelSize();
|
||||
vec4 SourceSize = vec4(nativeSize, 1.0/nativeSize);
|
||||
|
||||
vec2 dx = vec2(SourceSize.z, 0.0);
|
||||
vec2 dy = vec2(0.0, SourceSize.w);
|
||||
vec2 pix_co = vTexCoord * SourceSize.xy - vec2(0.5, 0.5);
|
||||
vec2 tex_co = (floor(pix_co) + vec2(0.5, 0.5)) * SourceSize.zw;
|
||||
vec2 dist = fract(pix_co);
|
||||
float curve_x;
|
||||
vec3 col, col2;
|
||||
|
||||
#if ENABLE_LANCZOS
|
||||
curve_x = curve_distance(dist.x, GetOption(SHARPNESS_H) * GetOption(SHARPNESS_H));
|
||||
|
||||
vec4 coeffs = PI * vec4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
|
||||
|
||||
coeffs = FIX(coeffs);
|
||||
coeffs = 2.0 * sin(coeffs) * sin(coeffs * 0.5) / (coeffs * coeffs);
|
||||
coeffs /= dot(coeffs, vec4(1.0));
|
||||
|
||||
col = filter_lanczos(coeffs, get_color_matrix(tex_co, dx));
|
||||
col2 = filter_lanczos(coeffs, get_color_matrix(tex_co + dy, dx));
|
||||
#else
|
||||
curve_x = curve_distance(dist.x, GetOption(SHARPNESS_H));
|
||||
|
||||
col = mix(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x);
|
||||
col2 = mix(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x);
|
||||
#endif
|
||||
|
||||
col = mix(col, col2, curve_distance(dist.y, GetOption(SHARPNESS_V)));
|
||||
col = pow(col, vec3(GetOption(GAMMA_INPUT) / (GetOption(DILATION) + 1.0)));
|
||||
|
||||
float luma = dot(vec3(0.2126, 0.7152, 0.0722), col);
|
||||
float bright = (max(col.r, max(col.g, col.b)) + luma) * 0.5;
|
||||
float scan_bright = clamp(bright, GetOption(SCANLINE_BRIGHT_MIN), GetOption(SCANLINE_BRIGHT_MAX));
|
||||
float scan_beam = clamp(bright * GetOption(SCANLINE_BEAM_WIDTH_MAX), GetOption(SCANLINE_BEAM_WIDTH_MIN), GetOption(SCANLINE_BEAM_WIDTH_MAX));
|
||||
float scan_weight = 1.0 - pow(cos(vTexCoord.y * 2.0 * PI * SourceSize.y) * 0.5 + 0.5, scan_beam) * GetOption(SCANLINE_STRENGTH);
|
||||
|
||||
float mask = 1.0 - GetOption(MASK_STRENGTH);
|
||||
vec2 mod_fac = floor(vTexCoord * GetWindowSize().xy * SourceSize.xy / (SourceSize.xy * vec2(GetOption(MASK_SIZE), GetOption(MASK_DOT_HEIGHT) * GetOption(MASK_SIZE))));
|
||||
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * GetOption(MASK_STAGGER)) / GetOption(MASK_DOT_WIDTH), 3.0));
|
||||
vec3 mask_weight;
|
||||
|
||||
if (dot_no == 0) mask_weight = vec3(1.0, mask, mask);
|
||||
else if (dot_no == 1) mask_weight = vec3(mask, 1.0, mask);
|
||||
else mask_weight = vec3(mask, mask, 1.0);
|
||||
|
||||
if (SourceSize.y >= GetOption(SCANLINE_CUTOFF))
|
||||
scan_weight = 1.0;
|
||||
|
||||
col2 = col.rgb;
|
||||
col *= vec3(scan_weight);
|
||||
col = mix(col, col2, scan_bright);
|
||||
col *= mask_weight;
|
||||
col = pow(col, vec3(1.0 / GetOption(GAMMA_OUTPUT)));
|
||||
|
||||
SetOutput(vec4(col * GetOption(BRIGHT_BOOST), 1.0));
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
// zfast_crt - A very simple CRT shader.
|
||||
|
||||
// Copyright (C) 2017 Greg Hogan (SoltanGris42)
|
||||
// edited by metallic 77.
|
||||
// ported to slang by gregoricavichioli & hunterk.
|
||||
// ported to dolphinfx by Hyllian.
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or (at your option)
|
||||
// any later version.
|
||||
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Curvature
|
||||
OptionName = Curvature
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Convergence X-Axis
|
||||
OptionName = blurx
|
||||
MinValue = -1.0
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.85
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Convergence Y-Axis
|
||||
OptionName = blury
|
||||
MinValue = -1.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = -0.10
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Amount (Low)
|
||||
OptionName = HIGHSCANAMOUNT1
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.4
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Scanline Amount (High)
|
||||
OptionName = HIGHSCANAMOUNT2
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.3
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Type
|
||||
OptionName = TYPE
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 0.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask Effect Amount
|
||||
OptionName = MASK_DARK
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.3
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Mask/Scanline Fade
|
||||
OptionName = MASK_FADE
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 0.7
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Saturation
|
||||
OptionName = sat
|
||||
MinValue = 0.0
|
||||
MaxValue = 3.0
|
||||
StepAmount = 0.05
|
||||
DefaultValue = 1.0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Flicker
|
||||
OptionName = FLICK
|
||||
MinValue = 0.0
|
||||
MaxValue = 50.0
|
||||
StepAmount = 1.0
|
||||
DefaultValue = 10.0
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
#define pi 3.14159
|
||||
|
||||
#define blur_y GetOption(blury)/(SourceSize.y*2.0)
|
||||
#define blur_x GetOption(blurx)/(SourceSize.x*2.0)
|
||||
#define iTimer (float(GetTime())*2.0)
|
||||
#define flicker GetOption(FLICK)/1000.0
|
||||
|
||||
// Distortion of scanlines, and end of screen alpha.
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos*2.0-1.0;
|
||||
pos *= vec2(1.0 + (pos.y*pos.y)*0.03, 1.0 + (pos.x*pos.x)*0.05);
|
||||
|
||||
return pos*0.5 + 0.5;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 vTexCoord = GetCoordinates();
|
||||
vec2 texSize = 1.0 / GetInvNativePixelSize();
|
||||
vec4 SourceSize = vec4(texSize, 1.0 / texSize);
|
||||
|
||||
float maskFade = 0.3333*GetOption(MASK_FADE);
|
||||
float omega = 2.0*pi*SourceSize.y;
|
||||
|
||||
vec2 pos,corn;
|
||||
if (GetOption(Curvature) == 1.0)
|
||||
{
|
||||
pos = Warp(vTexCoord.xy);
|
||||
corn = min(pos,vec2(1.0)-pos); // This is used to mask the rounded
|
||||
corn.x = 0.00001/corn.x; // corners later on
|
||||
|
||||
}
|
||||
|
||||
else pos = vTexCoord;
|
||||
float OGL2Pos = pos.y*SourceSize.y;
|
||||
float cent = floor(OGL2Pos)+0.5;
|
||||
float ycoord = cent*SourceSize.w;
|
||||
ycoord = mix(pos.y,ycoord,0.6);
|
||||
pos = vec2(pos.x,ycoord);
|
||||
|
||||
|
||||
vec3 sample1 = sin(iTimer)*flicker + SampleLocation(vec2(pos.x + blur_x, pos.y - blur_y)).rgb;
|
||||
vec3 sample2 = 0.5*SampleLocation(pos).rgb;
|
||||
vec3 sample3 = sin(iTimer)*flicker + SampleLocation(vec2(pos.x - blur_x, pos.y + blur_y)).rgb;
|
||||
|
||||
vec3 colour = vec3 (sample1.r*0.5 + sample2.r,
|
||||
sample1.g*0.25 + sample2.g + sample3.g*0.25,
|
||||
sample2.b + sample3.b*0.5);
|
||||
|
||||
vec3 interl = colour;
|
||||
vec3 lumweight=vec3(0.22,0.71,0.07);
|
||||
float lumsat = dot(colour,lumweight);
|
||||
|
||||
vec3 graycolour = vec3(lumsat);
|
||||
colour = vec3(mix(graycolour,colour.rgb,sat));
|
||||
|
||||
float SCANAMOUNT = mix(GetOption(HIGHSCANAMOUNT1),GetOption(HIGHSCANAMOUNT2),max(max(colour.r,colour.g),colour.b));
|
||||
|
||||
|
||||
if (SourceSize.y > 400.0) {
|
||||
colour ;
|
||||
}
|
||||
else {
|
||||
colour *= SCANAMOUNT * sin(fract(OGL2Pos)*3.14159)+1.0-SCANAMOUNT;
|
||||
colour *= SCANAMOUNT * sin(fract(1.0-OGL2Pos)*3.14159)+1.0-SCANAMOUNT;
|
||||
colour *= SCANAMOUNT * sin(fract(1.0+OGL2Pos)*3.14159)+1.0-SCANAMOUNT;
|
||||
}
|
||||
|
||||
float steps; if (GetOption(TYPE) == 0.0) steps = 0.5; else steps = 0.3333;
|
||||
float whichmask = fract(vTexCoord.x*GetWindowSize().x*steps);
|
||||
float mask = 1.0 + float(whichmask < steps) * (-GetOption(MASK_DARK));
|
||||
|
||||
colour.rgb = mix(mask*colour, colour, dot(colour.rgb,vec3(maskFade)));
|
||||
|
||||
if (GetOption(Curvature) == 1.0 && corn.y < corn.x || GetOption(Curvature) == 1.0 && corn.x < 0.00001 )
|
||||
colour = vec3(0.0);
|
||||
|
||||
SetOutput(vec4(colour.rgb, 1.0));
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
|
||||
// Hyllian's jinc windowed-jinc 2-lobe with anti-ringing Shader
|
||||
|
||||
// Copyright (C) 2011-2024 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Window Sinc Param
|
||||
OptionName = JINC2_WINDOW_SINC
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.50
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Sinc Param
|
||||
OptionName = JINC2_SINC
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.88
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = Anti-ringing Strength
|
||||
OptionName = JINC2_AR_STRENGTH
|
||||
MinValue = 0.0
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 0.5
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
#define halfpi 1.5707963267948966192313216916398
|
||||
#define pi 3.1415926535897932384626433832795
|
||||
#define wa (JINC2_WINDOW_SINC*pi)
|
||||
#define wb (JINC2_SINC*pi)
|
||||
|
||||
// Calculates the distance between two points
|
||||
float d(vec2 pt1, vec2 pt2)
|
||||
{
|
||||
vec2 v = pt2 - pt1;
|
||||
return sqrt(dot(v,v));
|
||||
}
|
||||
|
||||
vec3 min4(vec3 a, vec3 b, vec3 c, vec3 d)
|
||||
{
|
||||
return min(a, min(b, min(c, d)));
|
||||
}
|
||||
|
||||
vec3 max4(vec3 a, vec3 b, vec3 c, vec3 d)
|
||||
{
|
||||
return max(a, max(b, max(c, d)));
|
||||
}
|
||||
|
||||
vec4 resampler(vec4 x)
|
||||
{
|
||||
vec4 res;
|
||||
res.x = (x.x==0.0) ? wa*wb : sin(x.x*wa)*sin(x.x*wb)/(x.x*x.x);
|
||||
res.y = (x.y==0.0) ? wa*wb : sin(x.y*wa)*sin(x.y*wb)/(x.y*x.y);
|
||||
res.z = (x.z==0.0) ? wa*wb : sin(x.z*wa)*sin(x.z*wb)/(x.z*x.z);
|
||||
res.w = (x.w==0.0) ? wa*wb : sin(x.w*wa)*sin(x.w*wb)/(x.w*x.w);
|
||||
return res;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 SourceSize = 1.0 / GetInvNativePixelSize();
|
||||
vec2 invSourceSize = 1.0 / SourceSize;
|
||||
vec2 vTexCoord = GetCoordinates();
|
||||
|
||||
vec3 color;
|
||||
mat4x4 weights;
|
||||
|
||||
vec2 dx = vec2(1.0, 0.0);
|
||||
vec2 dy = vec2(0.0, 1.0);
|
||||
|
||||
vec2 pc = vTexCoord*SourceSize;
|
||||
|
||||
vec2 tc = (floor(pc-vec2(0.5,0.5))+vec2(0.5,0.5));
|
||||
|
||||
weights[0] = resampler(vec4(d(pc, tc -dx -dy), d(pc, tc -dy), d(pc, tc +dx -dy), d(pc, tc+2.0*dx -dy)));
|
||||
weights[1] = resampler(vec4(d(pc, tc -dx ), d(pc, tc ), d(pc, tc +dx ), d(pc, tc+2.0*dx )));
|
||||
weights[2] = resampler(vec4(d(pc, tc -dx +dy), d(pc, tc +dy), d(pc, tc +dx +dy), d(pc, tc+2.0*dx +dy)));
|
||||
weights[3] = resampler(vec4(d(pc, tc -dx+2.0*dy), d(pc, tc +2.0*dy), d(pc, tc +dx+2.0*dy), d(pc, tc+2.0*dx+2.0*dy)));
|
||||
|
||||
dx = dx * invSourceSize;
|
||||
dy = dy * invSourceSize;
|
||||
tc = tc * invSourceSize;
|
||||
|
||||
// reading the texels
|
||||
|
||||
vec3 c00 = SampleLocation(tc -dx -dy).xyz;
|
||||
vec3 c10 = SampleLocation(tc -dy).xyz;
|
||||
vec3 c20 = SampleLocation(tc +dx -dy).xyz;
|
||||
vec3 c30 = SampleLocation(tc+2.0*dx -dy).xyz;
|
||||
vec3 c01 = SampleLocation(tc -dx ).xyz;
|
||||
vec3 c11 = SampleLocation(tc ).xyz;
|
||||
vec3 c21 = SampleLocation(tc +dx ).xyz;
|
||||
vec3 c31 = SampleLocation(tc+2.0*dx ).xyz;
|
||||
vec3 c02 = SampleLocation(tc -dx +dy).xyz;
|
||||
vec3 c12 = SampleLocation(tc +dy).xyz;
|
||||
vec3 c22 = SampleLocation(tc +dx +dy).xyz;
|
||||
vec3 c32 = SampleLocation(tc+2.0*dx +dy).xyz;
|
||||
vec3 c03 = SampleLocation(tc -dx+2.0*dy).xyz;
|
||||
vec3 c13 = SampleLocation(tc +2.0*dy).xyz;
|
||||
vec3 c23 = SampleLocation(tc +dx+2.0*dy).xyz;
|
||||
vec3 c33 = SampleLocation(tc+2.0*dx+2.0*dy).xyz;
|
||||
|
||||
// Get min/max samples
|
||||
vec3 min_sample = min4(c11, c21, c12, c22);
|
||||
vec3 max_sample = max4(c11, c21, c12, c22);
|
||||
|
||||
color = mat4x3(c00, c10, c20, c30) * weights[0];
|
||||
color+= mat4x3(c01, c11, c21, c31) * weights[1];
|
||||
color+= mat4x3(c02, c12, c22, c32) * weights[2];
|
||||
color+= mat4x3(c03, c13, c23, c33) * weights[3];
|
||||
color = color/(dot(weights * vec4(1.0), vec4(1.0)));
|
||||
|
||||
// Anti-ringing
|
||||
vec3 aux = color;
|
||||
color = clamp(color, min_sample, max_sample);
|
||||
|
||||
color = mix(aux, color, JINC2_AR_STRENGTH);
|
||||
|
||||
// final sum and weight normalization
|
||||
SetOutput(vec4(color, 1.0));
|
||||
}
|
||||
@@ -1,120 +1,65 @@
|
||||
/*===============================================================================*\
|
||||
|######################## [Dolphin FX Suite 2.20] #######################|
|
||||
|########################## By Asmodean ##########################|
|
||||
|| ||
|
||||
|| This program is free software; you can redistribute it and/or ||
|
||||
|| modify it under the terms of the GNU General Public License ||
|
||||
|| as published by the Free Software Foundation; either version 2 ||
|
||||
|| of the License, or (at your option) any later version. ||
|
||||
|| ||
|
||||
|| This program is distributed in the hope that it will be useful, ||
|
||||
|| but WITHOUT ANY WARRANTY; without even the implied warranty of ||
|
||||
|| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ||
|
||||
|| GNU General Public License for more details. (C)2015 ||
|
||||
|| ||
|
||||
|#################################################################################|
|
||||
\*===============================================================================*/
|
||||
|
||||
// Sourced from https://raw.githubusercontent.com/Asmodean-/dolphin/89d640cd557189bb5f921fc219150c74c39bdc55/Data/Sys/Shaders/DolphinFX.glsl with modifications.
|
||||
|
||||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionRangeInteger]
|
||||
GUIName = ScanlineType
|
||||
OptionName = A_SCANLINE_TYPE
|
||||
MinValue = 0
|
||||
MaxValue = 2
|
||||
StepAmount = 1
|
||||
DefaultValue = 0
|
||||
[OptionRangeFloat]
|
||||
GUIName = Active Line Brightness
|
||||
OptionName = BRIGHTEN
|
||||
MinValue = 0.1
|
||||
MaxValue = 2.0
|
||||
StepAmount = 0.1
|
||||
DefaultValue = 1.1
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = ScanlineIntensity
|
||||
OptionName = B_SCANLINE_INTENSITY
|
||||
MinValue = 0.15
|
||||
MaxValue = 0.30
|
||||
GUIName = Inactive Line Darkness
|
||||
OptionName = DARKEN
|
||||
MinValue = 0.1
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.18
|
||||
DefaultValue = 0.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = ScanlineThickness
|
||||
OptionName = B_SCANLINE_THICKNESS
|
||||
MinValue = 0.20
|
||||
MaxValue = 0.80
|
||||
GUIName = Scanline Thickness
|
||||
OptionName = THICKNESS
|
||||
MinValue = 0.1
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.50
|
||||
DefaultValue = 0.5
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = ScanlineBrightness
|
||||
OptionName = B_SCANLINE_BRIGHTNESS
|
||||
MinValue = 0.50
|
||||
MaxValue = 2.00
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 1.10
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = ScanlineSpacing
|
||||
OptionName = B_SCANLINE_SPACING
|
||||
MinValue = 0.10
|
||||
MaxValue = 0.99
|
||||
GUIName = Scanline Spacing
|
||||
OptionName = SPACING
|
||||
MinValue = 0.1
|
||||
MaxValue = 1.0
|
||||
StepAmount = 0.01
|
||||
DefaultValue = 0.25
|
||||
|
||||
[/configuration]
|
||||
*/
|
||||
|
||||
//Average relative luminance
|
||||
CONSTANT float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750);
|
||||
float AvgLuminance(float3 color)
|
||||
float3 RGBToYUV(float3 rgb)
|
||||
{
|
||||
return sqrt(
|
||||
(color.x * color.x * lumCoeff.x) +
|
||||
(color.y * color.y * lumCoeff.y) +
|
||||
(color.z * color.z * lumCoeff.z));
|
||||
return float3(dot(rgb.rgb, float3(0.299, 0.587, 0.114)),
|
||||
dot(rgb.rgb, float3(-0.14713, -0.28886, 0.436)),
|
||||
dot(rgb.rgb, float3(0.615, -0.51499, -0.10001)));
|
||||
}
|
||||
|
||||
float3 YUVToRGB(float3 yuv)
|
||||
{
|
||||
return float3(dot(yuv, float3(1.0f, 0.0, 1.13983)),
|
||||
dot(yuv, float3(1.0f, -0.39465, -0.58060)),
|
||||
dot(yuv, float3(1.0f, 2.03211, 0.0)));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float4 color = Sample();
|
||||
float4 intensity = float4(0.0, 0.0, 0.0, 0.0);
|
||||
float2 pos = GetFragCoord();
|
||||
float4 color = Sample();
|
||||
float3 yuv = RGBToYUV(color.rgb);
|
||||
|
||||
if (GetOption(A_SCANLINE_TYPE) == 0) { //X coord scanlines
|
||||
if (fract(gl_FragCoord.y * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS))
|
||||
{
|
||||
intensity = float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
intensity = smoothstep(0.2, GetOption(B_SCANLINE_BRIGHTNESS), color) +
|
||||
normalize(float4(color.xyz, AvgLuminance(color.xyz)));
|
||||
} }
|
||||
float thickness = GetOption(THICKNESS);
|
||||
float spacing = GetOption(SPACING);
|
||||
yuv.r *= (frac(pos.y * spacing) > thickness) ? (1.0 - GetOption(DARKEN)) : GetOption(BRIGHTEN);
|
||||
|
||||
else if (GetOption(A_SCANLINE_TYPE) == 1) { //Y coord scanlines
|
||||
if (fract(gl_FragCoord.x * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS))
|
||||
{
|
||||
intensity = float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
intensity = smoothstep(0.2, GetOption(B_SCANLINE_BRIGHTNESS), color) +
|
||||
normalize(float4(color.xyz, AvgLuminance(color.xyz)));
|
||||
} }
|
||||
|
||||
else if (GetOption(A_SCANLINE_TYPE) == 2) { //XY coord scanlines
|
||||
if (fract(gl_FragCoord.x * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS) &&
|
||||
fract(gl_FragCoord.y * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS))
|
||||
{
|
||||
intensity = float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
intensity = smoothstep(0.2, GetOption(B_SCANLINE_BRIGHTNESS), color) +
|
||||
normalize(float4(color.xyz, AvgLuminance(color.xyz)));
|
||||
} }
|
||||
|
||||
float level = (4.0-GetCoordinates().x) * GetOption(B_SCANLINE_INTENSITY);
|
||||
|
||||
color = intensity * (0.5 - level) + color * 1.1;
|
||||
|
||||
SetOutput(saturate(color));
|
||||
}
|
||||
color.rgb = YUVToRGB(yuv);
|
||||
SetOutput(color);
|
||||
}
|
||||
|
||||
427
data/resources/shaders/reshade/Shaders/DisplayDepth.fx
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
DisplayDepth by CeeJay.dk (with many updates and additions by the Reshade community)
|
||||
|
||||
Visualizes the depth buffer. The distance of pixels determine their brightness.
|
||||
Close objects are dark. Far away objects are bright.
|
||||
Use this to configure the depth input preprocessor definitions (RESHADE_DEPTH_INPUT_*).
|
||||
*/
|
||||
|
||||
#include "ReShade.fxh"
|
||||
|
||||
// -- Basic options --
|
||||
#if RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
|
||||
#define TEXT_UPSIDE_DOWN "1"
|
||||
#define TEXT_UPSIDE_DOWN_ALTER "0"
|
||||
#else
|
||||
#define TEXT_UPSIDE_DOWN "0"
|
||||
#define TEXT_UPSIDE_DOWN_ALTER "1"
|
||||
#endif
|
||||
#if RESHADE_DEPTH_INPUT_IS_REVERSED
|
||||
#define TEXT_REVERSED "1"
|
||||
#define TEXT_REVERSED_ALTER "0"
|
||||
#else
|
||||
#define TEXT_REVERSED "0"
|
||||
#define TEXT_REVERSED_ALTER "1"
|
||||
#endif
|
||||
#if RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
|
||||
#define TEXT_LOGARITHMIC "1"
|
||||
#define TEXT_LOGARITHMIC_ALTER "0"
|
||||
#else
|
||||
#define TEXT_LOGARITHMIC "0"
|
||||
#define TEXT_LOGARITHMIC_ALTER "1"
|
||||
#endif
|
||||
|
||||
// "ui_text" was introduced in ReShade 4.5, so cannot show instructions in older versions
|
||||
|
||||
uniform int iUIPresentType <
|
||||
ui_label = "Present type";
|
||||
ui_label_ja_jp = "画面効果";
|
||||
ui_type = "combo";
|
||||
ui_items = "Depth map\0Normal map\0Show both (Vertical 50/50)\0";
|
||||
ui_items_ja_jp = "深度マップ\0法線マップ\0両方を表示 (左右分割)\0";
|
||||
#if __RESHADE__ < 40500
|
||||
ui_tooltip =
|
||||
#else
|
||||
ui_text =
|
||||
#endif
|
||||
"The right settings need to be set in the dialog that opens after clicking the \"Edit global preprocessor definitions\" button above.\n"
|
||||
"\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN is currently set to " TEXT_UPSIDE_DOWN ".\n"
|
||||
"If the Depth map is shown upside down set it to " TEXT_UPSIDE_DOWN_ALTER ".\n"
|
||||
"\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_REVERSED is currently set to " TEXT_REVERSED ".\n"
|
||||
"If close objects in the Depth map are bright and far ones are dark set it to " TEXT_REVERSED_ALTER ".\n"
|
||||
"Also try this if you can see the normals, but the depth view is all black.\n"
|
||||
"\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_LOGARITHMIC is currently set to " TEXT_LOGARITHMIC ".\n"
|
||||
"If the Normal map has banding artifacts (extra stripes) set it to " TEXT_LOGARITHMIC_ALTER ".";
|
||||
ui_text_ja_jp =
|
||||
#if ADDON_ADJUST_DEPTH
|
||||
"Adjust Depthアドオンのインストールを検出しました。\n"
|
||||
"'設定に保存して反映する'ボタンをクリックすると、このエフェクトで調節した全ての変数が共通設定に反映されます。\n"
|
||||
"または、上の'プリプロセッサの定義を編集'ボタンをクリックした後に開くダイアログで直接編集する事もできます。";
|
||||
#else
|
||||
"調節が終わったら、上の'プリプロセッサの定義を編集'ボタンをクリックした後に開くダイアログに入力する必要があります。\n"
|
||||
"\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWNは現在" TEXT_UPSIDE_DOWN "に設定されています。\n"
|
||||
"深度マップが上下逆さまに表示されている場合は" TEXT_UPSIDE_DOWN_ALTER "に変更して下さい。\n"
|
||||
"\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_REVERSEDは現在" TEXT_REVERSED "に設定されています。\n"
|
||||
"画面効果が深度マップのとき、近くの形状がより白く、遠くの形状がより黒い場合は" TEXT_REVERSED_ALTER "に変更して下さい。\n"
|
||||
"また、法線マップで形が判別出来るが、深度マップが真っ暗に見えるという場合も、この設定の変更を試して下さい。\n"
|
||||
"\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_LOGARITHMICは現在" TEXT_LOGARITHMIC "に設定されています。\n"
|
||||
"画面効果に実際のレンダリングと合致しない縞模様がある場合は" TEXT_LOGARITHMIC_ALTER "に変更して下さい。";
|
||||
#endif
|
||||
ui_tooltip_ja_jp =
|
||||
"'深度マップ'は、形状の遠近を白黒で表現します。正しい見え方では、近くの形状ほど黒く、遠くの形状ほど白くなります。\n"
|
||||
"'法線マップ'は、形状を滑らかに表現します。正しい見え方では、全体的に青緑風で、地平線を見たときに地面が緑掛かった色合いになります。\n"
|
||||
"'両方を表示 (左右分割)'が選択された場合は、左に法線マップ、右に深度マップを表示します。";
|
||||
> = 2;
|
||||
|
||||
uniform bool bUIShowOffset <
|
||||
ui_label = "Blend Depth map into the image (to help with finding the right offset)";
|
||||
ui_label_ja_jp = "透かし比較";
|
||||
ui_tooltip_ja_jp = "補正作業を支援するために、画面効果を半透過で適用します。";
|
||||
> = false;
|
||||
|
||||
uniform bool bUIUseLivePreview <
|
||||
ui_category = "Preview settings";
|
||||
ui_category_ja_jp = "基本的な補正";
|
||||
#if __RESHADE__ <= 50902
|
||||
ui_category_closed = true;
|
||||
#elif !ADDON_ADJUST_DEPTH
|
||||
ui_category_toggle = true;
|
||||
#endif
|
||||
ui_label = "Show live preview and ignore preprocessor definitions";
|
||||
ui_label_ja_jp = "プリプロセッサの定義を無視 (補正プレビューをオン)";
|
||||
ui_tooltip = "Enable this to preview with the current preset settings instead of the global preprocessor settings.";
|
||||
ui_tooltip_ja_jp =
|
||||
"共通設定に保存されたプリプロセッサの定義ではなく、これより下のプレビュー設定を使用するには、これを有効にします。\n"
|
||||
#if ADDON_ADJUST_DEPTH
|
||||
"設定の準備が出来たら、'設定に保存して反映する'ボタンをクリックしてから、このチェックボックスをオフにして下さい。"
|
||||
#else
|
||||
"設定の準備が出来たら、上の'プリプロセッサの定義を編集'ボタンをクリックした後に開くダイアログに入力して下さい。"
|
||||
#endif
|
||||
"\n\n"
|
||||
"プレビューをオンにした場合と比較して画面効果がまったく同じになれば、正しく設定が反映されています。";
|
||||
> = false;
|
||||
|
||||
#if __RESHADE__ <= 50902
|
||||
uniform int iUIUpsideDown <
|
||||
#else
|
||||
uniform bool iUIUpsideDown <
|
||||
#endif
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Upside Down";
|
||||
ui_label_ja_jp = "深度バッファの上下反転を修正";
|
||||
#if __RESHADE__ <= 50902
|
||||
ui_type = "combo";
|
||||
ui_items = "Off\0On\0";
|
||||
#endif
|
||||
ui_text_ja_jp =
|
||||
"\n"
|
||||
#if ADDON_ADJUST_DEPTH
|
||||
"項目にカーソルを合わせると、設定が必要な状況の説明が表示されます。"
|
||||
#else
|
||||
"項目にカーソルを合わせると、設定が必要な状況の説明と、プリプロセッサの定義が表示されます。"
|
||||
#endif
|
||||
;
|
||||
ui_tooltip_ja_jp =
|
||||
"深度マップが上下逆さまに表示されている場合は変更して下さい。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN=値\n"
|
||||
"定義値は次の通りです。オンの場合は1、オフの場合は0を指定して下さい。\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN=1\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN=0"
|
||||
#endif
|
||||
;
|
||||
> = RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN;
|
||||
|
||||
#if __RESHADE__ <= 50902
|
||||
uniform int iUIReversed <
|
||||
#else
|
||||
uniform bool iUIReversed <
|
||||
#endif
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Reversed";
|
||||
ui_label_ja_jp = "深度バッファの奥行反転を修正";
|
||||
#if __RESHADE__ <= 50902
|
||||
ui_type = "combo";
|
||||
ui_items = "Off\0On\0";
|
||||
#endif
|
||||
ui_tooltip_ja_jp =
|
||||
"画面効果が深度マップのとき、近くの形状が明るく、遠くの形状が暗い場合は変更して下さい。\n"
|
||||
"また、法線マップで形が判別出来るが、深度マップが真っ暗に見えるという場合も、この設定の変更を試して下さい。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_REVERSED=値\n"
|
||||
"定義値は次の通りです。オンの場合は1、オフの場合は0を指定して下さい。\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_REVERSED=1\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_REVERSED=0"
|
||||
#endif
|
||||
;
|
||||
> = RESHADE_DEPTH_INPUT_IS_REVERSED;
|
||||
|
||||
#if __RESHADE__ <= 50902
|
||||
uniform int iUILogarithmic <
|
||||
#else
|
||||
uniform bool iUILogarithmic <
|
||||
#endif
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Logarithmic";
|
||||
ui_label_ja_jp = "深度バッファを対数分布として扱うように修正";
|
||||
#if __RESHADE__ <= 50902
|
||||
ui_type = "combo";
|
||||
ui_items = "Off\0On\0";
|
||||
#endif
|
||||
ui_tooltip = "Change this setting if the displayed surface normals have stripes in them.";
|
||||
ui_tooltip_ja_jp =
|
||||
"画面効果に実際のゲーム画面と合致しない縞模様がある場合は変更して下さい。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_LOGARITHMIC=値\n"
|
||||
"定義値は次の通りです。オンの場合は1、オフの場合は0を指定して下さい。\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_LOGARITHMIC=1\n"
|
||||
"RESHADE_DEPTH_INPUT_IS_LOGARITHMIC=0"
|
||||
#endif
|
||||
;
|
||||
> = RESHADE_DEPTH_INPUT_IS_LOGARITHMIC;
|
||||
|
||||
// -- Advanced options --
|
||||
|
||||
uniform float2 fUIScale <
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Scale";
|
||||
ui_label_ja_jp = "拡大率";
|
||||
ui_type = "drag";
|
||||
ui_text =
|
||||
"\n"
|
||||
" * Advanced options\n"
|
||||
"\n"
|
||||
"The following settings also need to be set using \"Edit global preprocessor definitions\" above in order to take effect.\n"
|
||||
"You can preview how they will affect the Depth map using the controls below.\n"
|
||||
"\n"
|
||||
"It is rarely necessary to change these though, as their defaults fit almost all games.\n\n";
|
||||
ui_text_ja_jp =
|
||||
"\n"
|
||||
" * その他の補正 (不定形またはその他)\n"
|
||||
"\n"
|
||||
"これより下は、深度バッファが不定形など、特別なケース向けの設定です。\n"
|
||||
"通常はこれより上の'基本的な補正'のみでほとんどのゲームに適合します。\n"
|
||||
"また、これらの設定は画質の向上にはまったく役に立ちません。\n\n";
|
||||
ui_tooltip =
|
||||
"Best use 'Present type'->'Depth map' and enable 'Offset' in the options below to set the scale.\n"
|
||||
"Use these values for:\nRESHADE_DEPTH_INPUT_X_SCALE=<left value>\nRESHADE_DEPTH_INPUT_Y_SCALE=<right value>\n"
|
||||
"\n"
|
||||
"If you know the right resolution of the games depth buffer then this scale value is simply the ratio\n"
|
||||
"between the correct resolution and the resolution Reshade thinks it is.\n"
|
||||
"For example:\n"
|
||||
"If it thinks the resolution is 1920 x 1080, but it's really 1280 x 720 then the right scale is (1.5 , 1.5)\n"
|
||||
"because 1920 / 1280 is 1.5 and 1080 / 720 is also 1.5, so 1.5 is the right scale for both the x and the y";
|
||||
ui_tooltip_ja_jp =
|
||||
"深度バッファの解像度がクライアント解像度と異なる場合に変更して下さい。\n"
|
||||
"このスケール値は、深度バッファの解像度とクライアント解像度との単純な比率になります。\n"
|
||||
"深度バッファの解像度が1280×720でクライアント解像度が1920×1080の場合、横の比率が1920÷1280、縦の比率が1080÷720となります。\n"
|
||||
"計算した結果を設定すると、値はそれぞれX_SCALE=1.5、Y_SCALE=1.5となります。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_INPUT_X_SCALE=横の値\n"
|
||||
"RESHADE_DEPTH_INPUT_Y_SCALE=縦の値\n"
|
||||
"定義値は次の通りです。横の値はX_SCALE、縦の値はY_SCALEに指定して下さい。\n"
|
||||
"RESHADE_DEPTH_INPUT_X_SCALE=1.0\n"
|
||||
"RESHADE_DEPTH_INPUT_Y_SCALE=1.0"
|
||||
#endif
|
||||
;
|
||||
ui_min = 0.0; ui_max = 2.0;
|
||||
ui_step = 0.001;
|
||||
> = float2(RESHADE_DEPTH_INPUT_X_SCALE, RESHADE_DEPTH_INPUT_Y_SCALE);
|
||||
|
||||
uniform int2 iUIOffset <
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Offset";
|
||||
ui_label_ja_jp = "位置オフセット";
|
||||
ui_type = "slider";
|
||||
ui_tooltip =
|
||||
"Best use 'Present type'->'Depth map' and enable 'Offset' in the options below to set the offset in pixels.\n"
|
||||
"Use these values for:\nRESHADE_DEPTH_INPUT_X_PIXEL_OFFSET=<left value>\nRESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET=<right value>";
|
||||
ui_tooltip_ja_jp =
|
||||
"深度バッファにレンダリングされた物体の形状が画面効果と重なり合っていない場合に変更して下さい。\n"
|
||||
"この値は、ピクセル単位で指定します。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET=横の値\n"
|
||||
"RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET=縦の値\n"
|
||||
"定義値は次の通りです。横の値はX_PIXEL_OFFSET、縦の値はY_PIXEL_OFFSETに指定して下さい。\n"
|
||||
"RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET=0.0\n"
|
||||
"RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET=0.0"
|
||||
#endif
|
||||
;
|
||||
ui_min = -BUFFER_SCREEN_SIZE;
|
||||
ui_max = BUFFER_SCREEN_SIZE;
|
||||
ui_step = 1;
|
||||
> = int2(RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET, RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET);
|
||||
|
||||
uniform float fUIFarPlane <
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Far Plane";
|
||||
ui_label_ja_jp = "遠点距離";
|
||||
ui_type = "drag";
|
||||
ui_tooltip =
|
||||
"RESHADE_DEPTH_LINEARIZATION_FAR_PLANE=<value>\n"
|
||||
"Changing this value is not necessary in most cases.";
|
||||
ui_tooltip_ja_jp =
|
||||
"深度マップの色合いが距離感と合致しない、法線マップの表面が平面に見える、などの場合に変更して下さい。\n"
|
||||
"遠点距離を1000に設定すると、ゲームの描画距離が1000メートルであると見なします。\n\n"
|
||||
"このプレビュー画面はあくまでプレビューであり、ほとんどの場合、深度バッファは深度マップの色数より遥かに高い精度で表現されています。\n"
|
||||
"例えば、10m前後の距離の形状が純粋な黒に見えるからという理由で値を変更しないで下さい。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_LINEARIZATION_FAR_PLANE=値\n"
|
||||
"定義値は次の通りです。\n"
|
||||
"RESHADE_DEPTH_LINEARIZATION_FAR_PLANE=1000.0"
|
||||
#endif
|
||||
;
|
||||
ui_min = 0.0; ui_max = 1000.0;
|
||||
ui_step = 0.1;
|
||||
> = RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
|
||||
|
||||
uniform float fUIDepthMultiplier <
|
||||
ui_category = "Preview settings";
|
||||
ui_label = "Multiplier";
|
||||
ui_label_ja_jp = "深度乗数";
|
||||
ui_type = "drag";
|
||||
ui_tooltip = "RESHADE_DEPTH_MULTIPLIER=<value>";
|
||||
ui_tooltip_ja_jp =
|
||||
"特定のエミュレータソフトウェアにおける深度バッファを修正するため、特別に追加された変数です。\n"
|
||||
"この値は僅かな変更でも計算式を破壊するため、設定すべき値を知らない場合は変更しないで下さい。"
|
||||
#if !ADDON_ADJUST_DEPTH
|
||||
"\n\n"
|
||||
"定義名は次の通りです。文字は完全に一致する必要があり、半角大文字の英字とアンダーバーを用いなければなりません。\n"
|
||||
"RESHADE_DEPTH_MULTIPLIER=値\n"
|
||||
"定義値は次の通りです。\n"
|
||||
"RESHADE_DEPTH_MULTIPLIER=1.0"
|
||||
#endif
|
||||
;
|
||||
ui_min = 0.0; ui_max = 1000.0;
|
||||
ui_step = 0.001;
|
||||
> = RESHADE_DEPTH_MULTIPLIER;
|
||||
|
||||
float GetLinearizedDepth(float2 texcoord)
|
||||
{
|
||||
if (!bUIUseLivePreview)
|
||||
{
|
||||
return ReShade::GetLinearizedDepth(texcoord);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iUIUpsideDown) // RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
|
||||
texcoord.y = 1.0 - texcoord.y;
|
||||
|
||||
texcoord.x /= fUIScale.x; // RESHADE_DEPTH_INPUT_X_SCALE
|
||||
texcoord.y /= fUIScale.y; // RESHADE_DEPTH_INPUT_Y_SCALE
|
||||
texcoord.x -= iUIOffset.x * BUFFER_RCP_WIDTH; // RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET
|
||||
texcoord.y += iUIOffset.y * BUFFER_RCP_HEIGHT; // RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET
|
||||
|
||||
float depth = tex2Dlod(ReShade::DepthBuffer, float4(texcoord, 0, 0)).x * fUIDepthMultiplier;
|
||||
|
||||
const float C = 0.01;
|
||||
if (iUILogarithmic) // RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
|
||||
depth = (exp(depth * log(C + 1.0)) - 1.0) / C;
|
||||
|
||||
if (iUIReversed) // RESHADE_DEPTH_INPUT_IS_REVERSED
|
||||
depth = 1.0 - depth;
|
||||
|
||||
const float N = 1.0;
|
||||
depth /= fUIFarPlane - depth * (fUIFarPlane - N);
|
||||
|
||||
return depth;
|
||||
}
|
||||
}
|
||||
|
||||
float3 GetScreenSpaceNormal(float2 texcoord)
|
||||
{
|
||||
float3 offset = float3(BUFFER_PIXEL_SIZE, 0.0);
|
||||
float2 posCenter = texcoord.xy;
|
||||
float2 posNorth = posCenter - offset.zy;
|
||||
float2 posEast = posCenter + offset.xz;
|
||||
|
||||
float3 vertCenter = float3(posCenter - 0.5, 1) * GetLinearizedDepth(posCenter);
|
||||
float3 vertNorth = float3(posNorth - 0.5, 1) * GetLinearizedDepth(posNorth);
|
||||
float3 vertEast = float3(posEast - 0.5, 1) * GetLinearizedDepth(posEast);
|
||||
|
||||
return normalize(cross(vertCenter - vertNorth, vertCenter - vertEast)) * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
void PS_DisplayDepth(in float4 position : SV_Position, in float2 texcoord : TEXCOORD, out float3 color : SV_Target)
|
||||
{
|
||||
float3 depth = GetLinearizedDepth(texcoord).xxx;
|
||||
float3 normal = GetScreenSpaceNormal(texcoord);
|
||||
|
||||
// Ordered dithering
|
||||
#if 1
|
||||
const float dither_bit = 8.0; // Number of bits per channel. Should be 8 for most monitors.
|
||||
// Calculate grid position
|
||||
float grid_position = frac(dot(texcoord, (BUFFER_SCREEN_SIZE * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
|
||||
// Calculate how big the shift should be
|
||||
float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0));
|
||||
// Shift the individual colors differently, thus making it even harder to see the dithering pattern
|
||||
float3 dither_shift_RGB = float3(dither_shift, -dither_shift, dither_shift); // Subpixel dithering
|
||||
// Modify shift acording to grid position.
|
||||
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position);
|
||||
depth += dither_shift_RGB;
|
||||
#endif
|
||||
|
||||
color = depth;
|
||||
if (iUIPresentType == 1)
|
||||
color = normal;
|
||||
if (iUIPresentType == 2)
|
||||
color = lerp(normal, depth, step(BUFFER_WIDTH * 0.5, position.x));
|
||||
|
||||
if (bUIShowOffset)
|
||||
{
|
||||
float3 color_orig = tex2D(ReShade::BackBuffer, texcoord).rgb;
|
||||
|
||||
// Blend depth and back buffer color with 'overlay' so the offset is more noticeable
|
||||
color = lerp(2 * color * color_orig, 1.0 - 2.0 * (1.0 - color) * (1.0 - color_orig), max(color.r, max(color.g, color.b)) < 0.5 ? 0.0 : 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
technique DisplayDepth <
|
||||
ui_tooltip =
|
||||
"This shader helps you set the right preprocessor settings for depth input.\n"
|
||||
"To set the settings click on 'Edit global preprocessor definitions' and set them there - not in this shader.\n"
|
||||
"The settings will then take effect for all shaders, including this one.\n"
|
||||
"\n"
|
||||
"By default calculated normals and depth are shown side by side.\n"
|
||||
"Normals (on the left) should look smooth and the ground should be greenish when looking at the horizon.\n"
|
||||
"Depth (on the right) should show close objects as dark and use gradually brighter shades the further away objects are.\n";
|
||||
ui_tooltip_ja_jp =
|
||||
"これは、深度バッファの入力をReShade側の計算式に合わせる調節をするための、設定作業の支援に特化した特殊な扱いのエフェクトです。\n"
|
||||
"初期状態では「両方を表示」が選択されており、左に法線マップ、右に深度マップが表示されます。\n"
|
||||
"\n"
|
||||
"法線マップ(左側)は、形状を滑らかに表現します。正しい設定では、全体的に青緑風で、地平線を見たときに地面が緑を帯びた色になります。\n"
|
||||
"深度マップ(右側)は、形状の遠近を白黒で表現します。正しい設定では、近くの形状ほど黒く、遠くの形状ほど白くなります。\n"
|
||||
"\n"
|
||||
#if ADDON_ADJUST_DEPTH
|
||||
"設定を完了するには、DisplayDepth.fxエフェクトの変数の一覧にある'設定に保存して反映する'ボタンをクリックして下さい。\n"
|
||||
#else
|
||||
"設定を完了するには、エフェクト変数の編集画面にある'プリプロセッサの定義を編集'ボタンをクリックした後に開くダイアログに入力して下さい。\n"
|
||||
#endif
|
||||
"すると、インストール先のゲームに対して共通の設定として保存され、他のプリセットでも正しく表示されるようになります。";
|
||||
>
|
||||
|
||||
{
|
||||
pass
|
||||
{
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = PS_DisplayDepth;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__RESHADE__) || __RESHADE__ < 30000
|
||||
@@ -105,6 +109,7 @@ namespace ReShade
|
||||
}
|
||||
|
||||
// Vertex shader generating a triangle covering the entire screen
|
||||
// See also https://www.reddit.com/r/gamedev/comments/2j17wk/a_slightly_faster_bufferless_vertex_shader_trick/
|
||||
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
|
||||
{
|
||||
texcoord.x = (id == 2) ? 2.0 : 0.0;
|
||||
|
||||
@@ -7,27 +7,27 @@
|
||||
#define RESHADE_VERSION(major,minor,build) (10000 * (major) + 100 * (minor) + (build))
|
||||
#define SUPPORTED_VERSION(major,minor,build) (__RESHADE__ >= RESHADE_VERSION(major,minor,build))
|
||||
|
||||
// Since 3.0.0
|
||||
// >= 3.0.0
|
||||
// Commit current in-game user interface status
|
||||
// https://github.com/crosire/reshade/commit/302bacc49ae394faedc2e29a296c1cebf6da6bb2#diff-82cf230afdb2a0d5174111e6f17548a5R1183
|
||||
// Added various GUI related uniform variable annotations
|
||||
// https://reshade.me/forum/releases/2341-3-0
|
||||
#define __UNIFORM_INPUT_ANY ui_type = "input";
|
||||
|
||||
#define __UNIFORM_INPUT_BOOL1 __UNIFORM_INPUT_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_INPUT_BOOL2 __UNIFORM_INPUT_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_INPUT_BOOL3 __UNIFORM_INPUT_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_INPUT_BOOL4 __UNIFORM_INPUT_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_INPUT_INT1 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_INT2 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_INT3 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_INT4 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_FLOAT1 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_FLOAT2 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_FLOAT3 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_FLOAT4 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_INPUT_BOOL1 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_BOOL2 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_BOOL3 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_BOOL4 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_INT1 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_INT2 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_INT3 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_INT4 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_FLOAT1 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_FLOAT2 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_FLOAT3 __UNIFORM_INPUT_ANY
|
||||
#define __UNIFORM_INPUT_FLOAT4 __UNIFORM_INPUT_ANY
|
||||
|
||||
// Since 4.0.1
|
||||
// >= 4.0.1
|
||||
// Change slider widget to be used with new "slider" instead of a "drag" type annotation
|
||||
// https://github.com/crosire/reshade/commit/746229f31cd6f311a3e72a543e4f1f23faa23f11#diff-59405a313bd8cbfb0ca6dd633230e504R1701
|
||||
// Changed slider widget to be used with < ui_type = "slider"; > instead of < ui_type = "drag"; >
|
||||
@@ -35,7 +35,7 @@
|
||||
#if SUPPORTED_VERSION(4,0,1)
|
||||
#define __UNIFORM_DRAG_ANY ui_type = "drag";
|
||||
|
||||
// Since 4.0.0
|
||||
// >= 4.0.0
|
||||
// Rework statistics tab and add drag widgets back
|
||||
// https://github.com/crosire/reshade/commit/1b2c38795f00efd66c007da1f483f1441b230309
|
||||
// Changed drag widget to a slider widget (old one is still available via < ui_type = "drag2"; >)
|
||||
@@ -43,7 +43,7 @@
|
||||
#elif SUPPORTED_VERSION(4,0,0)
|
||||
#define __UNIFORM_DRAG_ANY ui_type = "drag2";
|
||||
|
||||
// Since 3.0.0
|
||||
// >= 3.0.0
|
||||
// Commit current in-game user interface status
|
||||
// https://github.com/crosire/reshade/commit/302bacc49ae394faedc2e29a296c1cebf6da6bb2#diff-82cf230afdb2a0d5174111e6f17548a5R1187
|
||||
// Added various GUI related uniform variable annotations
|
||||
@@ -52,20 +52,20 @@
|
||||
#define __UNIFORM_DRAG_ANY ui_type = "drag";
|
||||
#endif
|
||||
|
||||
#define __UNIFORM_DRAG_BOOL1 __UNIFORM_DRAG_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_DRAG_BOOL2 __UNIFORM_DRAG_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_DRAG_BOOL3 __UNIFORM_DRAG_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_DRAG_BOOL4 __UNIFORM_DRAG_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_DRAG_INT1 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_INT2 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_INT3 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_INT4 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_FLOAT1 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_FLOAT2 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_FLOAT3 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_FLOAT4 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_DRAG_BOOL1 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_BOOL2 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_BOOL3 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_BOOL4 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_INT1 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_INT2 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_INT3 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_INT4 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_FLOAT1 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_FLOAT2 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_FLOAT3 __UNIFORM_DRAG_ANY
|
||||
#define __UNIFORM_DRAG_FLOAT4 __UNIFORM_DRAG_ANY
|
||||
|
||||
// Since 4.0.1
|
||||
// >= 4.0.1
|
||||
// Change slider widget to be used with new "slider" instead of a "drag" type annotation
|
||||
// https://github.com/crosire/reshade/commit/746229f31cd6f311a3e72a543e4f1f23faa23f11#diff-59405a313bd8cbfb0ca6dd633230e504R1699
|
||||
// Changed slider widget to be used with < ui_type = "slider"; > instead of < ui_type = "drag"; >
|
||||
@@ -73,7 +73,7 @@
|
||||
#if SUPPORTED_VERSION(4,0,1)
|
||||
#define __UNIFORM_SLIDER_ANY ui_type = "slider";
|
||||
|
||||
// Since 4.0.0
|
||||
// >= 4.0.0
|
||||
// Rework statistics tab and add drag widgets back
|
||||
// https://github.com/crosire/reshade/commit/1b2c38795f00efd66c007da1f483f1441b230309
|
||||
// Changed drag widget to a slider widget (old one is still available via < ui_type = "drag2"; >)
|
||||
@@ -84,20 +84,20 @@
|
||||
#define __UNIFORM_SLIDER_ANY __UNIFORM_DRAG_ANY
|
||||
#endif
|
||||
|
||||
#define __UNIFORM_SLIDER_BOOL1 __UNIFORM_SLIDER_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_SLIDER_BOOL2 __UNIFORM_SLIDER_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_SLIDER_BOOL3 __UNIFORM_SLIDER_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_SLIDER_BOOL4 __UNIFORM_SLIDER_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_SLIDER_INT1 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_INT2 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_INT3 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_INT4 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_FLOAT1 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_FLOAT2 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_FLOAT3 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_FLOAT4 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_SLIDER_BOOL1 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_BOOL2 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_BOOL3 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_BOOL4 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_INT1 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_INT2 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_INT3 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_INT4 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_FLOAT1 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_FLOAT2 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_FLOAT3 __UNIFORM_SLIDER_ANY
|
||||
#define __UNIFORM_SLIDER_FLOAT4 __UNIFORM_SLIDER_ANY
|
||||
|
||||
// Since 3.0.0
|
||||
// >= 3.0.0
|
||||
// Add combo box display type for uniform variables and fix displaying of integer variable under Direct3D 9
|
||||
// https://github.com/crosire/reshade/commit/b025bfae5f7343509ec0cacf6df0cff537c499f2#diff-82cf230afdb2a0d5174111e6f17548a5R1631
|
||||
// Added various GUI related uniform variable annotations
|
||||
@@ -105,19 +105,19 @@
|
||||
#define __UNIFORM_COMBO_ANY ui_type = "combo";
|
||||
|
||||
// __UNIFORM_COMBO_BOOL1
|
||||
#define __UNIFORM_COMBO_BOOL2 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_BOOL3 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_BOOL4 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_INT1 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_COMBO_INT2 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_COMBO_INT3 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_COMBO_INT4 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_COMBO_FLOAT1 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_FLOAT2 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_FLOAT3 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_FLOAT4 __UNIFORM_COMBO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COMBO_BOOL2 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_BOOL3 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_BOOL4 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_INT1 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_INT2 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_INT3 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_INT4 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_FLOAT1 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_FLOAT2 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_FLOAT3 __UNIFORM_COMBO_ANY
|
||||
#define __UNIFORM_COMBO_FLOAT4 __UNIFORM_COMBO_ANY
|
||||
|
||||
// Since 4.0.0 (but the ui_items force set "Off\0On\0"), and if less than it force converted to checkbox
|
||||
// >= 4.0.0
|
||||
// Add option to display boolean values as combo box instead of checkbox
|
||||
// https://github.com/crosire/reshade/commit/aecb757c864c9679e77edd6f85a1521c49e489c1#diff-59405a313bd8cbfb0ca6dd633230e504R1147
|
||||
// https://github.com/crosire/reshade/blob/v4.0.0/source/gui.cpp
|
||||
@@ -125,7 +125,7 @@
|
||||
// https://reshade.me/forum/releases/4772-4-0
|
||||
#define __UNIFORM_COMBO_BOOL1 __UNIFORM_COMBO_ANY
|
||||
|
||||
// Since 4.0.0
|
||||
// >= 4.0.0
|
||||
// Cleanup GUI code and rearrange some widgets
|
||||
// https://github.com/crosire/reshade/commit/6751f7bd50ea7c0556cf0670f10a4b4ba912ee7d#diff-59405a313bd8cbfb0ca6dd633230e504R1711
|
||||
// Added radio button widget (via < ui_type = "radio"; ui_items = "Button 1\0Button 2\0...\0"; >)
|
||||
@@ -136,48 +136,46 @@
|
||||
#define __UNIFORM_RADIO_ANY __UNIFORM_COMBO_ANY
|
||||
#endif
|
||||
|
||||
#define __UNIFORM_RADIO_BOOL1 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_BOOL2 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_BOOL3 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_BOOL4 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_INT1 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_RADIO_INT2 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_RADIO_INT3 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_RADIO_INT4 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_RADIO_FLOAT1 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_FLOAT2 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_FLOAT3 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_FLOAT4 __UNIFORM_RADIO_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_RADIO_BOOL1 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_BOOL2 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_BOOL3 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_BOOL4 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_INT1 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_INT2 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_INT3 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_INT4 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_FLOAT1 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_FLOAT2 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_FLOAT3 __UNIFORM_RADIO_ANY
|
||||
#define __UNIFORM_RADIO_FLOAT4 __UNIFORM_RADIO_ANY
|
||||
|
||||
// Since 4.1.0
|
||||
// >= 4.1.0
|
||||
// Fix floating point uniforms with unknown "ui_type" not showing up in UI
|
||||
// https://github.com/crosire/reshade/commit/50e5bf44dfc84bc4220c2b9f19d5f50c7a0fda66#diff-59405a313bd8cbfb0ca6dd633230e504R1788
|
||||
// Fixed floating point uniforms with unknown "ui_type" not showing up in UI
|
||||
// https://reshade.me/forum/releases/5021-4-1
|
||||
#define __UNIFORM_COLOR_ANY ui_type = "color";
|
||||
|
||||
// Since 3.0.0
|
||||
// >= 3.0.0
|
||||
// Move technique list to preset configuration file
|
||||
// https://github.com/crosire/reshade/blob/84bba3aa934c1ebe4c6419b69dfe1690d9ab9d34/source/runtime.cpp#L1328
|
||||
// Added various GUI related uniform variable annotations
|
||||
// https://reshade.me/forum/releases/2341-3-0
|
||||
|
||||
// If empty, these versions before 4.1.0 are decide that the type is color from the number of components
|
||||
|
||||
#define __UNIFORM_COLOR_BOOL1 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_BOOL2 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_BOOL3 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_BOOL4 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_INT1 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_INT2 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_INT3 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_INT4 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_BOOL1 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_BOOL2 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_BOOL3 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_BOOL4 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_INT1 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_INT2 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_INT3 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_INT4 __UNIFORM_COLOR_ANY
|
||||
// __UNIFORM_COLOR_FLOAT1
|
||||
#define __UNIFORM_COLOR_FLOAT2 __UNIFORM_COLOR_ANY // It is unsupported on all version
|
||||
#define __UNIFORM_COLOR_FLOAT3 __UNIFORM_COLOR_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_COLOR_FLOAT4 __UNIFORM_COLOR_ANY // If it was not supported in someday or now, please add information
|
||||
#define __UNIFORM_COLOR_FLOAT2 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_FLOAT3 __UNIFORM_COLOR_ANY
|
||||
#define __UNIFORM_COLOR_FLOAT4 __UNIFORM_COLOR_ANY
|
||||
|
||||
// Since 4.2.0
|
||||
// >= 4.2.0
|
||||
// Add alpha slider widget for single component uniform variables (#86)
|
||||
// https://github.com/crosire/reshade/commit/87a740a8e3c4dcda1dd4eeec8d5cff7fa35fe829#diff-59405a313bd8cbfb0ca6dd633230e504R1820
|
||||
// Added alpha slider widget for single component uniform variables
|
||||
@@ -188,7 +186,7 @@
|
||||
#define __UNIFORM_COLOR_FLOAT1 __UNIFORM_SLIDER_ANY
|
||||
#endif
|
||||
|
||||
// Since 4.3.0
|
||||
// >= 4.3.0
|
||||
// Add new "list" GUI widget (#103)
|
||||
// https://github.com/crosire/reshade/commit/515287d20ce615c19cf3d4c21b49f83896f04ddc#diff-59405a313bd8cbfb0ca6dd633230e504R1894
|
||||
// Added new "list" GUI widget
|
||||
@@ -200,17 +198,17 @@
|
||||
#endif
|
||||
|
||||
// __UNIFORM_LIST_BOOL1
|
||||
#define __UNIFORM_LIST_BOOL2 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_BOOL3 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_BOOL4 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_INT1 __UNIFORM_LIST_ANY // Supported in 4.3.0
|
||||
#define __UNIFORM_LIST_INT2 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_INT3 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_INT4 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_FLOAT1 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_FLOAT2 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_FLOAT3 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_FLOAT4 __UNIFORM_LIST_ANY // Not supported in all versions
|
||||
#define __UNIFORM_LIST_BOOL2 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_BOOL3 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_BOOL4 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_INT1 __UNIFORM_LIST_ANY // >= 4.3.0
|
||||
#define __UNIFORM_LIST_INT2 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_INT3 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_INT4 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_FLOAT1 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_FLOAT2 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_FLOAT3 __UNIFORM_LIST_ANY
|
||||
#define __UNIFORM_LIST_FLOAT4 __UNIFORM_LIST_ANY
|
||||
|
||||
// For compatible with ComboBox
|
||||
// For compatible with 'combo'
|
||||
#define __UNIFORM_LIST_BOOL1 __UNIFORM_COMBO_ANY
|
||||
|
||||
289
data/resources/shaders/reshade/Shaders/UIMask.fx
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
Simple UIMask shader by luluco250
|
||||
|
||||
I have no idea why this was never ported back to ReShade 3.0 from 2.0,
|
||||
but if you missed it, here it is.
|
||||
|
||||
It doesn't feature the auto mask from the original shader.
|
||||
|
||||
It does feature a new multi-channnel masking feature. UI masks can now contain
|
||||
separate 'modes' within each of the three color channels.
|
||||
|
||||
For example, you can have the regular hud on the red channel (the default one),
|
||||
a mask for an inventory screen on the green channel and a mask for a quest menu
|
||||
on the blue channel. You can then use keyboard keys to toggle each channel on or off.
|
||||
|
||||
Multiple channels can be active at once, they'll just add up to mask the image.
|
||||
|
||||
Simple/legacy masks are not affected by this, they'll work just as you'd expect,
|
||||
so you can still make simple black and white masks that use all color channels, it'll
|
||||
be no different than just having it on a single channel.
|
||||
|
||||
Tips:
|
||||
|
||||
--You can adjust how much it will affect your HUD by changing "Mask Intensity".
|
||||
|
||||
--You don't actually need to place the UIMask_Bottom technique at the bottom of
|
||||
your shader pipeline, if you have any effects that don't necessarily affect
|
||||
the visibility of the HUD you can place it before that.
|
||||
For instance, if you use color correction shaders like LUT, you might want
|
||||
to place UIMask_Bottom just before that.
|
||||
|
||||
--Preprocessor flags:
|
||||
--UIMASK_MULTICHANNEL:
|
||||
Enables having up to three different masks on each color channel.
|
||||
|
||||
--Refer to this page for keycodes:
|
||||
https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
|
||||
|
||||
--To make a custom mask:
|
||||
|
||||
1-Take a screenshot of your game with the HUD enabled,
|
||||
preferrably with any effects disabled for maximum visibility.
|
||||
|
||||
2-Open the screenshot with your preferred image editor program, I use GIMP.
|
||||
|
||||
3-Make a background white layer if there isn't one already.
|
||||
Be sure to leave it behind your actual screenshot for the while.
|
||||
|
||||
4-Make an empty layer for the mask itself, you can call it "mask".
|
||||
|
||||
5-Having selected the mask layer, paint the places where HUD constantly is,
|
||||
such as health bars, important messages, minimaps etc.
|
||||
|
||||
6-Delete or make your screenshot layer invisible.
|
||||
|
||||
7-Before saving your mask, let's do some gaussian blurring to improve it's look and feel:
|
||||
For every step of blurring you want to do, make a new layer, such as:
|
||||
Mask - Blur16x16
|
||||
Mask - Blur8x8
|
||||
Mask - Blur4x4
|
||||
Mask - Blur2x2
|
||||
Mask - NoBlur
|
||||
You should use your image editor's default gaussian blurring filter, if there is one.
|
||||
This avoids possible artifacts and makes the mask blend more easily on the eyes.
|
||||
You may not need this if your mask is accurate enough and/or the HUD is simple enough.
|
||||
|
||||
8-Now save the final image with a unique name such as "MyUIMask.png" in your textures folder.
|
||||
|
||||
9-Set the preprocessor definition UIMASK_TEXTURE to the unique name of your image, with quotes.
|
||||
You're done!
|
||||
|
||||
|
||||
MIT Licensed:
|
||||
|
||||
Copyright (c) 2017 Lucas Melo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
//#region Preprocessor
|
||||
|
||||
#include "ReShade.fxh"
|
||||
#include "ReShadeUI.fxh"
|
||||
|
||||
#ifndef UIMASK_MULTICHANNEL
|
||||
#define UIMASK_MULTICHANNEL 0
|
||||
#endif
|
||||
|
||||
#if !UIMASK_MULTICHANNEL
|
||||
#define TEXFORMAT R8
|
||||
#else
|
||||
#define TEXFORMAT RGBA8
|
||||
#endif
|
||||
|
||||
#ifndef UIMASK_TEXTURE
|
||||
#define UIMASK_TEXTURE "UIMask.png"
|
||||
#endif
|
||||
|
||||
//#endregion
|
||||
|
||||
namespace UIMask
|
||||
{
|
||||
|
||||
//#region Uniforms
|
||||
|
||||
uniform int _Help
|
||||
<
|
||||
ui_label = " ";
|
||||
ui_text =
|
||||
"For more detailed instructions, see the text at the top of this "
|
||||
"effect's shader file (UIMask.fx).\n"
|
||||
"\n"
|
||||
"Available preprocessor definitions:\n"
|
||||
" UIMASK_MULTICHANNEL:\n"
|
||||
" If set to 1, each of the RGB color channels in the texture is "
|
||||
"treated as a separate mask.\n"
|
||||
"\n"
|
||||
"How to create a mask:\n"
|
||||
"\n"
|
||||
"1. Take a screenshot with the game's UI appearing.\n"
|
||||
"2. Open the screenshot in an image editor, GIMP or Photoshop are "
|
||||
"recommended.\n"
|
||||
"3. Create a new layer over the screenshot layer, fill it with black.\n"
|
||||
"4. Reduce the layer opacity so you can see the screenshot layer "
|
||||
"below.\n"
|
||||
"5. Cover the UI with white to mask it from effects. The stronger the "
|
||||
"mask white color, the more opaque the mask will be.\n"
|
||||
"6. Set the mask layer opacity back to 100%.\n"
|
||||
"7. Save the image in one of your texture folders, making sure to "
|
||||
"use a unique name such as: \"MyUIMask.png\"\n"
|
||||
"8. Set the preprocessor definition UIMASK_TEXTURE to the name of "
|
||||
"your image, with quotes: \"MyUIMask.png\"\n"
|
||||
;
|
||||
ui_category = "Help";
|
||||
ui_category_closed = true;
|
||||
ui_type = "radio";
|
||||
>;
|
||||
|
||||
uniform float fMask_Intensity
|
||||
<
|
||||
__UNIFORM_SLIDER_FLOAT1
|
||||
|
||||
ui_label = "Mask Intensity";
|
||||
ui_tooltip =
|
||||
"How much to mask effects from affecting the original image.\n"
|
||||
"\nDefault: 1.0";
|
||||
ui_min = 0.0;
|
||||
ui_max = 1.0;
|
||||
ui_step = 0.001;
|
||||
> = 1.0;
|
||||
|
||||
uniform bool bDisplayMask <
|
||||
ui_label = "Display Mask";
|
||||
ui_tooltip =
|
||||
"Display the mask texture.\n"
|
||||
"Useful for testing multiple channels or simply the mask itself.\n"
|
||||
"\nDefault: Off";
|
||||
> = false;
|
||||
|
||||
#if UIMASK_MULTICHANNEL
|
||||
|
||||
uniform bool bToggleRed <
|
||||
ui_label = "Toggle Red Channel";
|
||||
ui_tooltip = "Toggle UI masking for the red channel.\n"
|
||||
"Right click to assign a hotkey.\n"
|
||||
"\nDefault: On";
|
||||
> = true;
|
||||
|
||||
uniform bool bToggleGreen <
|
||||
ui_label = "Toggle Green Channel";
|
||||
ui_tooltip = "Toggle UI masking for the green channel.\n"
|
||||
"Right click to assign a hotkey."
|
||||
"\nDefault: On";
|
||||
> = true;
|
||||
|
||||
uniform bool bToggleBlue <
|
||||
ui_label = "Toggle Blue Channel";
|
||||
ui_tooltip = "Toggle UI masking for the blue channel.\n"
|
||||
"Right click to assign a hotkey."
|
||||
"\nDefault: On";
|
||||
> = true;
|
||||
|
||||
#endif
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Textures
|
||||
|
||||
texture BackupTex
|
||||
{
|
||||
Width = BUFFER_WIDTH;
|
||||
Height = BUFFER_HEIGHT;
|
||||
};
|
||||
sampler Backup
|
||||
{
|
||||
Texture = BackupTex;
|
||||
};
|
||||
|
||||
texture MaskTex <source=UIMASK_TEXTURE;>
|
||||
{
|
||||
Width = BUFFER_WIDTH;
|
||||
Height = BUFFER_HEIGHT;
|
||||
Format = TEXFORMAT;
|
||||
};
|
||||
sampler Mask
|
||||
{
|
||||
Texture = MaskTex;
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Shaders
|
||||
|
||||
float4 BackupPS(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target {
|
||||
return tex2D(ReShade::BackBuffer, uv);
|
||||
}
|
||||
|
||||
float4 MainPS(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target {
|
||||
float4 color = tex2D(ReShade::BackBuffer, uv);
|
||||
float4 backup = tex2D(Backup, uv);
|
||||
|
||||
#if !UIMASK_MULTICHANNEL
|
||||
float mask = tex2D(Mask, uv).r;
|
||||
#else
|
||||
float3 mask_rgb = tex2D(Mask, uv).rgb;
|
||||
|
||||
// This just works, it basically adds masking with each channel that has
|
||||
// been toggled.
|
||||
float mask = saturate(
|
||||
1.0 - dot(1.0 - mask_rgb,
|
||||
float3(bToggleRed, bToggleGreen, bToggleBlue)));
|
||||
#endif
|
||||
|
||||
color = lerp(color, backup, mask * fMask_Intensity);
|
||||
color = bDisplayMask ? mask : color;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Techniques
|
||||
|
||||
technique UIMask_Top
|
||||
<
|
||||
ui_tooltip = "Place this *above* the effects to be masked.";
|
||||
>
|
||||
{
|
||||
pass
|
||||
{
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = BackupPS;
|
||||
RenderTarget = BackupTex;
|
||||
}
|
||||
}
|
||||
|
||||
technique UIMask_Bottom
|
||||
<
|
||||
ui_tooltip =
|
||||
"Place this *below* the effects to be masked.\n"
|
||||
"If you want to add a toggle key for the effect, set it to this one.";
|
||||
>
|
||||
{
|
||||
pass
|
||||
{
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = MainPS;
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
} // Namespace.
|
||||
271
data/resources/shaders/reshade/Shaders/anti-aliasing/fxaa.fx
Normal file
@@ -0,0 +1,271 @@
|
||||
#include "ReShade.fxh"
|
||||
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
|
||||
* *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
|
||||
* OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT,IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
|
||||
* OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
|
||||
* OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY
|
||||
* OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
/*
|
||||
FXAA_PRESET - Choose compile-in knob preset 0-5.
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_EDGE_THRESHOLD - The minimum amount of local contrast required
|
||||
to apply algorithm.
|
||||
1.0/3.0 - too little
|
||||
1.0/4.0 - good start
|
||||
1.0/8.0 - applies to more edges
|
||||
1.0/16.0 - overkill
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_EDGE_THRESHOLD_MIN - Trims the algorithm from processing darks.
|
||||
Perf optimization.
|
||||
1.0/32.0 - visible limit (smaller isn't visible)
|
||||
1.0/16.0 - good compromise
|
||||
1.0/12.0 - upper limit (seeing artifacts)
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SEARCH_STEPS - Maximum number of search steps for end of span.
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SEARCH_THRESHOLD - Controls when to stop searching.
|
||||
1.0/4.0 - seems to be the best quality wise
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SUBPIX_TRIM - Controls sub-pixel aliasing removal.
|
||||
1.0/2.0 - low removal
|
||||
1.0/3.0 - medium removal
|
||||
1.0/4.0 - default removal
|
||||
1.0/8.0 - high removal
|
||||
0.0 - complete removal
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SUBPIX_CAP - Insures fine detail is not completely removed.
|
||||
This is important for the transition of sub-pixel detail,
|
||||
like fences and wires.
|
||||
3.0/4.0 - default (medium amount of filtering)
|
||||
7.0/8.0 - high amount of filtering
|
||||
1.0 - no capping of sub-pixel aliasing removal
|
||||
*/
|
||||
|
||||
|
||||
uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >;
|
||||
uniform float2 ViewportSize < source = "viewportsize"; >;
|
||||
|
||||
sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=LINEAR;MinFilter=LINEAR;};
|
||||
|
||||
|
||||
#ifndef FXAA_PRESET
|
||||
#define FXAA_PRESET 6
|
||||
#endif
|
||||
#if (FXAA_PRESET == 3)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/16.0)
|
||||
#define FXAA_SEARCH_STEPS 16
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 4)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 24
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 5)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 32
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 6)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 32
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (1.0)
|
||||
#define FXAA_SUBPIX_TRIM (0.0)
|
||||
#endif
|
||||
|
||||
#define FXAA_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_SUBPIX_TRIM))
|
||||
|
||||
// Return the luma, the estimation of luminance from rgb inputs.
|
||||
// This approximates luma using one FMA instruction,
|
||||
// skipping normalization and tossing out blue.
|
||||
// FxaaLuma() will range 0.0 to 2.963210702.
|
||||
float FxaaLuma(float3 rgb) {
|
||||
return rgb.y * (0.587/0.299) + rgb.x;
|
||||
}
|
||||
|
||||
float3 FxaaLerp3(float3 a, float3 b, float amountOfA) {
|
||||
return (-float3(amountOfA, amountOfA, amountOfA) * b) + ((a * float3(amountOfA, amountOfA, amountOfA)) + b);
|
||||
}
|
||||
|
||||
float4 FxaaTexOff(sampler2D tex, float2 pos, int2 off, float2 rcpFrame) {
|
||||
float x = pos.x + float(off.x) * rcpFrame.x;
|
||||
float y = pos.y + float(off.y) * rcpFrame.y;
|
||||
return tex2D(tex, float2(x, y));
|
||||
}
|
||||
|
||||
// pos is the output of FxaaVertexShader interpolated across screen.
|
||||
// xy -> actual texture position {0.0 to 1.0}
|
||||
// rcpFrame should be a uniform equal to {1.0/frameWidth, 1.0/frameHeight}
|
||||
float3 FxaaPixelShader(float2 pos, sampler2D tex, float2 rcpFrame)
|
||||
{
|
||||
float3 rgbN = FxaaTexOff(tex, pos.xy, int2( 0,-1), rcpFrame).xyz;
|
||||
float3 rgbW = FxaaTexOff(tex, pos.xy, int2(-1, 0), rcpFrame).xyz;
|
||||
float3 rgbM = FxaaTexOff(tex, pos.xy, int2( 0, 0), rcpFrame).xyz;
|
||||
float3 rgbE = FxaaTexOff(tex, pos.xy, int2( 1, 0), rcpFrame).xyz;
|
||||
float3 rgbS = FxaaTexOff(tex, pos.xy, int2( 0, 1), rcpFrame).xyz;
|
||||
|
||||
float lumaN = FxaaLuma(rgbN);
|
||||
float lumaW = FxaaLuma(rgbW);
|
||||
float lumaM = FxaaLuma(rgbM);
|
||||
float lumaE = FxaaLuma(rgbE);
|
||||
float lumaS = FxaaLuma(rgbS);
|
||||
float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
|
||||
float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
|
||||
|
||||
float range = rangeMax - rangeMin;
|
||||
if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD))
|
||||
{
|
||||
return rgbM;
|
||||
}
|
||||
|
||||
float3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS;
|
||||
|
||||
float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
|
||||
float rangeL = abs(lumaL - lumaM);
|
||||
float blendL = max(0.0, (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE;
|
||||
blendL = min(FXAA_SUBPIX_CAP, blendL);
|
||||
|
||||
float3 rgbNW = FxaaTexOff(tex, pos.xy, int2(-1,-1), rcpFrame).xyz;
|
||||
float3 rgbNE = FxaaTexOff(tex, pos.xy, int2( 1,-1), rcpFrame).xyz;
|
||||
float3 rgbSW = FxaaTexOff(tex, pos.xy, int2(-1, 1), rcpFrame).xyz;
|
||||
float3 rgbSE = FxaaTexOff(tex, pos.xy, int2( 1, 1), rcpFrame).xyz;
|
||||
rgbL += (rgbNW + rgbNE + rgbSW + rgbSE);
|
||||
rgbL *= (1.0/float3(9.0, 9.0, 9.0));
|
||||
|
||||
float lumaNW = FxaaLuma(rgbNW);
|
||||
float lumaNE = FxaaLuma(rgbNE);
|
||||
float lumaSW = FxaaLuma(rgbSW);
|
||||
float lumaSE = FxaaLuma(rgbSE);
|
||||
|
||||
float edgeVert =
|
||||
abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) +
|
||||
abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) +
|
||||
abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE));
|
||||
float edgeHorz =
|
||||
abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) +
|
||||
abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) +
|
||||
abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE));
|
||||
|
||||
bool horzSpan = edgeHorz >= edgeVert;
|
||||
float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
|
||||
|
||||
if(!horzSpan)
|
||||
{
|
||||
lumaN = lumaW;
|
||||
lumaS = lumaE;
|
||||
}
|
||||
|
||||
float gradientN = abs(lumaN - lumaM);
|
||||
float gradientS = abs(lumaS - lumaM);
|
||||
lumaN = (lumaN + lumaM) * 0.5;
|
||||
lumaS = (lumaS + lumaM) * 0.5;
|
||||
|
||||
if (gradientN < gradientS)
|
||||
{
|
||||
lumaN = lumaS;
|
||||
lumaN = lumaS;
|
||||
gradientN = gradientS;
|
||||
lengthSign *= -1.0;
|
||||
}
|
||||
|
||||
float2 posN;
|
||||
posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
|
||||
posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
|
||||
|
||||
gradientN *= FXAA_SEARCH_THRESHOLD;
|
||||
|
||||
float2 posP = posN;
|
||||
float2 offNP = horzSpan ? float2(rcpFrame.x, 0.0) : float2(0.0, rcpFrame.y);
|
||||
float lumaEndN = lumaN;
|
||||
float lumaEndP = lumaN;
|
||||
bool doneN = false;
|
||||
bool doneP = false;
|
||||
posN += offNP * float2(-1.0, -1.0);
|
||||
posP += offNP * float2( 1.0, 1.0);
|
||||
|
||||
for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
|
||||
if(!doneN)
|
||||
{
|
||||
lumaEndN = FxaaLuma(tex2D(tex, posN.xy).xyz);
|
||||
}
|
||||
if(!doneP)
|
||||
{
|
||||
lumaEndP = FxaaLuma(tex2D(tex, posP.xy).xyz);
|
||||
}
|
||||
|
||||
doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN);
|
||||
doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN);
|
||||
|
||||
if(doneN && doneP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(!doneN)
|
||||
{
|
||||
posN -= offNP;
|
||||
}
|
||||
if(!doneP)
|
||||
{
|
||||
posP += offNP;
|
||||
}
|
||||
}
|
||||
|
||||
float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
|
||||
float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
|
||||
bool directionN = dstN < dstP;
|
||||
lumaEndN = directionN ? lumaEndN : lumaEndP;
|
||||
|
||||
if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
|
||||
{
|
||||
lengthSign = 0.0;
|
||||
}
|
||||
|
||||
|
||||
float spanLength = (dstP + dstN);
|
||||
dstN = directionN ? dstN : dstP;
|
||||
float subPixelOffset = (0.5 + (dstN * (-1.0/spanLength))) * lengthSign;
|
||||
float3 rgbF = tex2D(tex, float2(
|
||||
pos.x + (horzSpan ? 0.0 : subPixelOffset),
|
||||
pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz;
|
||||
return FxaaLerp3(rgbL, rgbF, blendL);
|
||||
}
|
||||
|
||||
float4 PS_FXAA(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target
|
||||
{
|
||||
float3 color = FxaaPixelShader(vTexCoord, sBackBuffer, 1.0 / (ViewportSize*BufferToViewportRatio));
|
||||
|
||||
return float4(color, 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
technique FXAA
|
||||
{
|
||||
pass
|
||||
{
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = PS_FXAA;
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
#include "ReShade.fxh"
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
// Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
// Enable or disable the shader
|
||||
#ifndef CONTENT_BOX_VISIBLE
|
||||
#define CONTENT_BOX_VISIBLE 0
|
||||
#endif
|
||||
|
||||
#include "crt-royale/shaders/content-box.fxh"
|
||||
|
||||
#if !CONTENT_BOX_VISIBLE
|
||||
#include "crt-royale/shaders/input-blurring.fxh"
|
||||
#include "crt-royale/shaders/electron-beams.fxh"
|
||||
#include "crt-royale/shaders/blurring.fxh"
|
||||
#include "crt-royale/shaders/deinterlace.fxh"
|
||||
#include "crt-royale/shaders/phosphor-mask.fxh"
|
||||
#include "crt-royale/shaders/brightpass.fxh"
|
||||
#include "crt-royale/shaders/bloom.fxh"
|
||||
#include "crt-royale/shaders/geometry-aa-last-pass.fxh"
|
||||
#endif
|
||||
|
||||
|
||||
technique CRT_Royale
|
||||
{
|
||||
// Toggle the content box to help users configure it
|
||||
#if CONTENT_BOX_VISIBLE
|
||||
pass contentBoxPass
|
||||
{
|
||||
// content-box.fxh
|
||||
// Draw a box that displays the crop we'll perform.
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = contentBoxPixelShader;
|
||||
}
|
||||
#else
|
||||
#if ENABLE_PREBLUR
|
||||
pass PreblurVert
|
||||
{
|
||||
// input-blurring.fxh
|
||||
// Optionally blur the input buffer a little
|
||||
VertexShader = contentCropVS;
|
||||
PixelShader = preblurVertPS;
|
||||
|
||||
RenderTarget = texPreblurVert;
|
||||
|
||||
PrimitiveTopology = TRIANGLESTRIP;
|
||||
VertexCount = 4;
|
||||
}
|
||||
pass PreblurHoriz
|
||||
{
|
||||
// input-blurring.fxh
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = preblurHorizPS;
|
||||
|
||||
RenderTarget = texPreblurHoriz;
|
||||
}
|
||||
#endif
|
||||
pass beamDistPass
|
||||
{
|
||||
// electron-beams.fxh
|
||||
// Simulate emission of the interlaced video as electron beams.
|
||||
VertexShader = calculateBeamDistsVS;
|
||||
PixelShader = calculateBeamDistsPS;
|
||||
|
||||
RenderTarget = texBeamDist;
|
||||
|
||||
// This lets us improve performance by only computing the mask every k frames
|
||||
ClearRenderTargets = false;
|
||||
}
|
||||
pass electronBeamPass
|
||||
{
|
||||
// electron-beams.fxh
|
||||
// Simulate emission of the interlaced video as electron beams.
|
||||
VertexShader = simulateEletronBeamsVS;
|
||||
PixelShader = simulateEletronBeamsPS;
|
||||
|
||||
RenderTarget = texElectronBeams;
|
||||
|
||||
// If the preblur passes are disabled, we have to crop in this pass
|
||||
#if !ENABLE_PREBLUR
|
||||
PrimitiveTopology = TRIANGLESTRIP;
|
||||
VertexCount = 4;
|
||||
#endif
|
||||
}
|
||||
pass beamConvergencePass
|
||||
{
|
||||
// electron-beams.fxh
|
||||
// Simulate beam convergence miscalibration
|
||||
// Not to be confused with beam purity
|
||||
VertexShader = beamConvergenceVS;
|
||||
PixelShader = beamConvergencePS;
|
||||
|
||||
RenderTarget = texBeamConvergence;
|
||||
}
|
||||
pass bloomApproxPassVert
|
||||
{
|
||||
// bloom.fxh
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = approximateBloomVertPS;
|
||||
|
||||
RenderTarget = texBloomApproxVert;
|
||||
}
|
||||
pass bloomApproxPassHoriz
|
||||
{
|
||||
// bloom.fxh
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = approximateBloomHorizPS;
|
||||
|
||||
RenderTarget = texBloomApproxHoriz;
|
||||
}
|
||||
pass blurVerticalPass
|
||||
{
|
||||
// blurring.fxh
|
||||
// Vertically blur the approx bloom
|
||||
VertexShader = blurVerticalVS;
|
||||
PixelShader = blurVerticalPS;
|
||||
|
||||
RenderTarget = texBlurVertical;
|
||||
}
|
||||
pass blurHorizontalPass
|
||||
{
|
||||
// blurring.fxh
|
||||
// Horizontally blur the approx bloom
|
||||
VertexShader = blurHorizontalVS;
|
||||
PixelShader = blurHorizontalPS;
|
||||
|
||||
RenderTarget = texBlurHorizontal;
|
||||
}
|
||||
pass deinterlacePass
|
||||
{
|
||||
// deinterlace.fxh
|
||||
// Optionally deinterlace the video if interlacing is enabled.
|
||||
// Can help approximate the original crt-royale's appearance
|
||||
// without some issues like image retention.
|
||||
VertexShader = deinterlaceVS;
|
||||
PixelShader = deinterlacePS;
|
||||
|
||||
RenderTarget = texDeinterlace;
|
||||
}
|
||||
pass freezeFramePass
|
||||
{
|
||||
// deinterlace.fxh
|
||||
// Capture the current frame, so we can use it in the next
|
||||
// frame's deinterlacing pass.
|
||||
VertexShader = freezeFrameVS;
|
||||
PixelShader = freezeFramePS;
|
||||
|
||||
RenderTarget = texFreezeFrame;
|
||||
|
||||
// Explicitly disable clearing render targets
|
||||
// scanlineBlendPass will not work properly if this ever defaults to true
|
||||
ClearRenderTargets = false;
|
||||
}
|
||||
pass generatePhosphorMask
|
||||
{
|
||||
// phosphor-mask.fxh
|
||||
VertexShader = generatePhosphorMaskVS;
|
||||
PixelShader = generatePhosphorMaskPS;
|
||||
|
||||
RenderTarget = texPhosphorMask;
|
||||
|
||||
// This lets us improve performance by only computing the mask every k frames
|
||||
ClearRenderTargets = false;
|
||||
|
||||
PrimitiveTopology = TRIANGLESTRIP;
|
||||
VertexCount = 4;
|
||||
}
|
||||
pass applyPhosphormask
|
||||
{
|
||||
// phosphor-mask.fxh
|
||||
// Tile the scaled phosphor mask and apply it to
|
||||
// the deinterlaced image.
|
||||
VertexShader = PostProcessVS;
|
||||
PixelShader = applyComputedPhosphorMaskPS;
|
||||
|
||||
RenderTarget = texMaskedScanlines;
|
||||
// RenderTarget = texGeometry;
|
||||
}
|
||||
pass brightpassPass
|
||||
{
|
||||
// brightpass.fxh
|
||||
// Apply a brightpass filter for the bloom effect
|
||||
VertexShader = brightpassVS;
|
||||
PixelShader = brightpassPS;
|
||||
|
||||
RenderTarget = texBrightpass;
|
||||
}
|
||||
pass bloomVerticalPass
|
||||
{
|
||||
// bloom.fxh
|
||||
// Blur vertically for the bloom effect
|
||||
VertexShader = bloomVerticalVS;
|
||||
PixelShader = bloomVerticalPS;
|
||||
|
||||
RenderTarget = texBloomVertical;
|
||||
}
|
||||
pass bloomHorizontalPass
|
||||
{
|
||||
// bloom.fxh
|
||||
// Blur horizontally for the bloom effect.
|
||||
// Also apply various color changes and effects.
|
||||
VertexShader = bloomHorizontalVS;
|
||||
PixelShader = bloomHorizontalPS;
|
||||
|
||||
RenderTarget = texBloomHorizontal;
|
||||
}
|
||||
pass geometryPass
|
||||
{
|
||||
// geometry-aa-last-pass.fxh
|
||||
// Apply screen geometry and anti-aliasing.
|
||||
VertexShader = geometryVS;
|
||||
PixelShader = geometryPS;
|
||||
|
||||
RenderTarget = texGeometry;
|
||||
}
|
||||
pass uncropPass
|
||||
{
|
||||
// content-box.fxh
|
||||
// Uncrop the video, so we draw the game's content
|
||||
// in the same position it started in.
|
||||
VertexShader = contentUncropVS;
|
||||
PixelShader = uncropContentPixelShader;
|
||||
|
||||
PrimitiveTopology = TRIANGLESTRIP;
|
||||
VertexCount = 4;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,908 +0,0 @@
|
||||
#ifndef _BIND_SHADER_PARAMS_H
|
||||
#define _BIND_SHADER_PARAMS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
// Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
///////////////////////////// SETTINGS MANAGEMENT ////////////////////////////
|
||||
|
||||
/////////////////////////////// BEGIN INCLUDES ///////////////////////////////
|
||||
#include "helper-functions-and-macros.fxh"
|
||||
#include "user-settings.fxh"
|
||||
#include "derived-settings-and-constants.fxh"
|
||||
#include "../version-number.fxh"
|
||||
|
||||
//////////////////////////////// END INCLUDES ////////////////////////////////
|
||||
|
||||
// Override some parameters for gamma-management.h and tex2Dantialias.h:
|
||||
#ifndef _OVERRIDE_DEVICE_GAMMA
|
||||
#define _OVERRIDE_DEVICE_GAMMA 1
|
||||
#endif
|
||||
|
||||
#if __RENDERER__ != 0x9000
|
||||
#define _DX9_ACTIVE 0
|
||||
#else
|
||||
#define _DX9_ACTIVE 1
|
||||
#endif
|
||||
|
||||
// #ifndef ANTIALIAS_OVERRIDE_BASICS
|
||||
// #define ANTIALIAS_OVERRIDE_BASICS 1
|
||||
// #endif
|
||||
|
||||
// #ifndef ANTIALIAS_OVERRIDE_PARAMETERS
|
||||
// #define ANTIALIAS_OVERRIDE_PARAMETERS 1
|
||||
// #endif
|
||||
|
||||
#ifndef ADVANCED_SETTINGS
|
||||
#define ADVANCED_SETTINGS 0
|
||||
#endif
|
||||
|
||||
// The width of the game's content
|
||||
#ifndef CONTENT_WIDTH
|
||||
#define CONTENT_WIDTH BUFFER_WIDTH
|
||||
#endif
|
||||
// The height of the game's content
|
||||
#ifndef CONTENT_HEIGHT
|
||||
#define CONTENT_HEIGHT BUFFER_HEIGHT
|
||||
#endif
|
||||
|
||||
#if ADVANCED_SETTINGS == 1
|
||||
// Using vertex uncropping is marginally faster, but vulnerable to DX9 weirdness.
|
||||
// Most users will likely prefer the slower algorithm.
|
||||
#ifndef USE_VERTEX_UNCROPPING
|
||||
#define USE_VERTEX_UNCROPPING 0
|
||||
#endif
|
||||
|
||||
#ifndef NUM_BEAMDIST_COLOR_SAMPLES
|
||||
#define NUM_BEAMDIST_COLOR_SAMPLES 1024
|
||||
#endif
|
||||
|
||||
#ifndef NUM_BEAMDIST_DIST_SAMPLES
|
||||
#define NUM_BEAMDIST_DIST_SAMPLES 120
|
||||
#endif
|
||||
|
||||
#ifndef BLOOMAPPROX_DOWNSIZING_FACTOR
|
||||
#define BLOOMAPPROX_DOWNSIZING_FACTOR 4.0
|
||||
#endif
|
||||
|
||||
// Define this internal value, so ADVANCED_SETTINGS == 0 doesn't cause a redefinition error when
|
||||
// NUM_BEAMDIST_COLOR_SAMPLES defined in the preset file. Also makes it easy to avoid bugs
|
||||
// related to parentheses and order-of-operations when the user defines this arithmetically.
|
||||
static const uint num_beamdist_color_samples = uint(NUM_BEAMDIST_COLOR_SAMPLES);
|
||||
static const uint num_beamdist_dist_samples = uint(NUM_BEAMDIST_DIST_SAMPLES);
|
||||
static const float bloomapprox_downsizing_factor = float(BLOOMAPPROX_DOWNSIZING_FACTOR);
|
||||
#else
|
||||
static const uint USE_VERTEX_CROPPING = 0;
|
||||
static const uint num_beamdist_color_samples = 1024;
|
||||
static const uint num_beamdist_dist_samples = 120;
|
||||
static const float bloomapprox_downsizing_factor = 4.0;
|
||||
#endif
|
||||
|
||||
#ifndef HIDE_HELP_SECTIONS
|
||||
#define HIDE_HELP_SECTIONS 0
|
||||
#endif
|
||||
|
||||
|
||||
// Offset the center of the game's content (horizontal)
|
||||
#ifndef CONTENT_CENTER_X
|
||||
#define CONTENT_CENTER_X 0
|
||||
#endif
|
||||
// Offset the center of the game's content (vertical)
|
||||
#ifndef CONTENT_CENTER_Y
|
||||
#define CONTENT_CENTER_Y 0
|
||||
#endif
|
||||
|
||||
// Wrap the content size in parenthesis for internal use, so the user doesn't have to
|
||||
static const float2 content_size = float2(int(CONTENT_WIDTH), int(CONTENT_HEIGHT));
|
||||
|
||||
#ifndef ENABLE_PREBLUR
|
||||
#define ENABLE_PREBLUR 1
|
||||
#endif
|
||||
|
||||
|
||||
static const float2 buffer_size = float2(BUFFER_WIDTH, BUFFER_HEIGHT);
|
||||
|
||||
|
||||
// The normalized center is 0.5 plus the normalized offset
|
||||
static const float2 content_center = float2(CONTENT_CENTER_X, CONTENT_CENTER_Y) / buffer_size + 0.5;
|
||||
// The content's normalized diameter d is its size divided by the buffer's size. The radius is d/2.
|
||||
static const float2 content_radius = content_size / (2.0 * buffer_size);
|
||||
static const float2 content_scale = content_size / buffer_size;
|
||||
|
||||
static const float content_left = content_center.x - content_radius.x;
|
||||
static const float content_right = content_center.x + content_radius.x;
|
||||
static const float content_upper = content_center.y - content_radius.y;
|
||||
static const float content_lower = content_center.y + content_radius.y;
|
||||
|
||||
// The xy-offset of the top-left pixel in the content box
|
||||
static const float2 content_offset = float2(content_left, content_upper);
|
||||
static const float2 content_offset_from_right = float2(content_right, content_lower);
|
||||
|
||||
uniform uint frame_count < source = "framecount"; >;
|
||||
uniform int overlay_active < source = "overlay_active"; >;
|
||||
|
||||
static const float gba_gamma = 3.5; // Irrelevant but necessary to define.
|
||||
|
||||
|
||||
// === HELP AND INFO ===
|
||||
|
||||
uniform int APPEND_VERSION_SUFFIX(version) <
|
||||
ui_text = "Version: " DOT_VERSION_STR;
|
||||
ui_label = " ";
|
||||
ui_type = "radio";
|
||||
>;
|
||||
|
||||
uniform int basic_setup_help <
|
||||
ui_text = "1. Configure the Content Box if your game has letter-boxing.\n"
|
||||
"2. Configure the Phosphor Mask.\n"
|
||||
"3. Configure the Scanlines.\n"
|
||||
"4. Configure the Colors and Effects.\n"
|
||||
"5. Configure the Screen Geometry.\n"
|
||||
"6. Configure or disable Preblur\n\n"
|
||||
"- In Preprocessor Definitions, set ADVANCED_SETTINGS to 1 to access more settings.\n";
|
||||
ui_category = "Basic Setup Instructions";
|
||||
ui_category_closed = true;
|
||||
ui_label = " ";
|
||||
ui_type = "radio";
|
||||
hidden = HIDE_HELP_SECTIONS;
|
||||
>;
|
||||
|
||||
uniform int content_box_help <
|
||||
ui_text = "1. Expand the Preprocessor Definitions section.\n"
|
||||
"2. Set CONTENT_BOX_VISIBLE to 1.\n"
|
||||
"3. Use the \"CONTENT_\" parameters to configure the Content Box.\n"
|
||||
"4. Align the content box with the border of your game.\n"
|
||||
"5. Set CONTENT_BOX_VISIBLE to 0 when you're done.\n\n"
|
||||
"Parameters to focus on:\n"
|
||||
"- CONTENT_HEIGHT and CONTENT_WIDTH\n"
|
||||
"- CONTENT_CENTER_X and CONTENT_CENTER_Y\n"
|
||||
"- CONTENT_BOX_INSCRIBED\n\n"
|
||||
"Fancy Trick 1:\n"
|
||||
"\tCONTENT_HEIGHT = BUFFER_HEIGHT\n"
|
||||
"\tCONTENT_WIDTH = CONTENT_HEIGHT * 4.0 / 3.0\n"
|
||||
"- Good if your game fills the screen vertically and has a 4:3 aspect ratio.\n"
|
||||
"- Will also rescale automatically if you resize the window.\n\n"
|
||||
"Fancy Trick 2:\n"
|
||||
"\tCONTENT_HEIGHT = CONTENT_WIDTH * 9.0 / 16.0\n"
|
||||
"\tCONTENT_WIDTH = 1500\n"
|
||||
"- Good if your game is 1500 pixels wide with a 16:9 aspect ratio.\n"
|
||||
"- Won't rescale automatically, but you'd only have to change the width.\n";
|
||||
ui_category = "Content Box Instructions";
|
||||
ui_category_closed = true;
|
||||
ui_label = " ";
|
||||
ui_type = "radio";
|
||||
hidden = HIDE_HELP_SECTIONS;
|
||||
>;
|
||||
|
||||
|
||||
// ==== PHOSPHOR MASK ====
|
||||
uniform int mask_type <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "Choose which kind of CRT you want.\n\n";
|
||||
#endif
|
||||
ui_label = "Mask Type";
|
||||
ui_tooltip = "Selects the phosphor shape";
|
||||
ui_type = "combo";
|
||||
ui_items = "Grille\0"
|
||||
"Slot\0"
|
||||
"Shadow\0"
|
||||
"LowRes Grille\0"
|
||||
"LowRes Slot\0"
|
||||
"LowRes Shadow\0";
|
||||
|
||||
ui_category = "Phosphor Mask";
|
||||
ui_category_closed = true;
|
||||
> = mask_type_static;
|
||||
|
||||
uniform uint mask_size_param <
|
||||
ui_label = "Mask Size Param";
|
||||
ui_tooltip = "Switch between using Mask Triad Size or Mask Num Triads";
|
||||
ui_type = "combo";
|
||||
ui_items = "Triad Width\0"
|
||||
"Num Triads Across\0";
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Phosphor Mask";
|
||||
> = mask_size_param_static;
|
||||
|
||||
uniform float mask_triad_width <
|
||||
ui_label = "Mask Triad Width";
|
||||
ui_tooltip = "The width of a triad in pixels";
|
||||
ui_type = "slider";
|
||||
ui_min = 1.0;
|
||||
ui_max = 60.0;
|
||||
ui_step = 0.1;
|
||||
|
||||
ui_category = "Phosphor Mask";
|
||||
> = mask_triad_width_static;
|
||||
|
||||
uniform float mask_num_triads_across <
|
||||
ui_label = "Mask Num Triads Across";
|
||||
ui_tooltip = "The number of triads in the viewport (horizontally)";
|
||||
ui_type = "drag";
|
||||
ui_min = 1.0;
|
||||
ui_max = 1280.0;
|
||||
ui_step = 1.0;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Phosphor Mask";
|
||||
> = mask_num_triads_across_static;
|
||||
|
||||
uniform float scale_triad_height<
|
||||
ui_label = "Scale Triad Height";
|
||||
ui_tooltip = "Scales the height of a triad";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.01;
|
||||
ui_max = 10.0;
|
||||
ui_step = 0.001;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Phosphor Mask";
|
||||
> = 1.0;
|
||||
|
||||
uniform float2 phosphor_thickness <
|
||||
ui_label = "Phosphor Thickness XY";
|
||||
ui_tooltip = "Makes the phosphors appear thicker in each direction";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.01;
|
||||
ui_max = 0.99;
|
||||
ui_step = 0.01;
|
||||
// hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Phosphor Mask";
|
||||
> = 0.2;
|
||||
|
||||
uniform float2 phosphor_sharpness <
|
||||
ui_label = "Phosphor Sharpness XY";
|
||||
ui_tooltip = "Makes the phosphors appear more crisp in each direction";
|
||||
ui_type = "drag";
|
||||
ui_min = 1;
|
||||
ui_max = 100;
|
||||
ui_step = 1;
|
||||
// hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Phosphor Mask";
|
||||
> = 50;
|
||||
|
||||
uniform float3 phosphor_offset_x <
|
||||
ui_label = "Phosphor Offset RGB X";
|
||||
ui_tooltip = "Very slightly shifts the phosphor mask. Can help with subpixel alignment.";
|
||||
ui_type = "drag";
|
||||
ui_min = -1;
|
||||
ui_max = 1;
|
||||
ui_step = 0.01;
|
||||
// hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Phosphor Mask";
|
||||
> = 0;
|
||||
|
||||
uniform float3 phosphor_offset_y <
|
||||
ui_label = "Phosphor Offset RGB Y";
|
||||
ui_tooltip = "Very slightly shifts the phosphor mask. Can help with subpixel alignment.";
|
||||
ui_type = "drag";
|
||||
ui_min = -1;
|
||||
ui_max = 1;
|
||||
ui_step = 0.01;
|
||||
// hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Phosphor Mask";
|
||||
> = 0;
|
||||
|
||||
// static const uint pixel_grid_mode = 0;
|
||||
// static const float2 pixel_size = 1;
|
||||
/*
|
||||
// ==== PIXELATION ===
|
||||
uniform uint pixel_grid_mode <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "- Fix issues displaying pixel art.\n"
|
||||
"- Force high-res games to look low-res.\n\n";
|
||||
#endif
|
||||
ui_label = "Pixel Grid Param";
|
||||
ui_tooltip = "Switch between using Pixel Size or Num Pixels";
|
||||
ui_type = "combo";
|
||||
ui_items = "Pixel Size\0"
|
||||
"Content Resolution\0";
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Pixelation";
|
||||
ui_category_closed = true;
|
||||
> = 0;
|
||||
|
||||
uniform float2 pixel_size <
|
||||
#if !HIDE_HELP_SECTIONS && !ADVANCED_SETTINGS
|
||||
ui_text = "- Fix issues displaying pixel art.\n"
|
||||
"- Force high-res games to look low-res.\n\n";
|
||||
#endif
|
||||
ui_label = "Pixel Size";
|
||||
ui_tooltip = "The size of an in-game pixel on screen, in real-world pixels";
|
||||
ui_type = "slider";
|
||||
ui_min = 1.0;
|
||||
ui_max = 30.0;
|
||||
ui_step = 1.0;
|
||||
|
||||
ui_category = "Pixelation";
|
||||
ui_category_closed = true;
|
||||
> = float2(1, 1);
|
||||
|
||||
uniform float2 pixel_grid_resolution <
|
||||
ui_label = "Num Pixels";
|
||||
ui_tooltip = "The number of in-game pixels displayed on-screen in each direction";
|
||||
ui_type = "drag";
|
||||
ui_min = 1.0;
|
||||
ui_max = 10000.0;
|
||||
ui_step = 1.0;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Pixelation";
|
||||
> = content_size;
|
||||
uniform float2 pixel_grid_offset <
|
||||
ui_label = "Pixel Grid Offset";
|
||||
ui_tooltip = "Shifts the pixel-grid to help with alignment";
|
||||
ui_type = "slider";
|
||||
ui_min = -15.0;
|
||||
ui_max = 15.0;
|
||||
ui_step = 1.0;
|
||||
|
||||
#if ADVANCED_SETTINGS
|
||||
ui_spacing = 2;
|
||||
#endif
|
||||
ui_category = "Pixelation";
|
||||
> = float2(0, 0);
|
||||
*/
|
||||
|
||||
// ==== SCANLINES ====
|
||||
uniform uint scanline_thickness <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "Configure the electron beams and interlacing.\n\n";
|
||||
#endif
|
||||
ui_label = "Scanline Thickness";
|
||||
ui_tooltip = "Sets the height of each scanline";
|
||||
ui_type = "slider";
|
||||
ui_min = 1;
|
||||
ui_max = 30;
|
||||
ui_step = 1;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
ui_category_closed = true;
|
||||
> = 2;
|
||||
|
||||
uniform float scanline_offset <
|
||||
ui_label = "Scanline Offset";
|
||||
ui_tooltip = "Vertically shifts the scanlines to help with alignment";
|
||||
ui_type = "slider";
|
||||
ui_min = -30;
|
||||
ui_max = 30;
|
||||
ui_step = 1;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = 0;
|
||||
|
||||
uniform uint beam_shape_mode <
|
||||
ui_label = "Beam Shape Mode";
|
||||
ui_tooltip = "Select the kind of beam to use.";
|
||||
ui_type = "combo";
|
||||
ui_items = "Digital (Fast)\0"
|
||||
"Linear (Simple)\0"
|
||||
"Gaussian (Realistic)\0"
|
||||
"Multi-Source Gaussian (Expensive)\0";
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = 1;
|
||||
|
||||
uniform bool enable_interlacing <
|
||||
ui_label = "Enable Interlacing";
|
||||
|
||||
ui_spacing = 5;
|
||||
ui_category = "Scanlines";
|
||||
> = false;
|
||||
|
||||
uniform bool interlace_back_field_first <
|
||||
ui_label = "Draw Back-Field First";
|
||||
ui_tooltip = "Draw odd-numbered scanlines first (often has no effect)";
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = interlace_back_field_first_static;
|
||||
|
||||
uniform uint scanline_deinterlacing_mode <
|
||||
ui_label = "Deinterlacing Mode";
|
||||
ui_tooltip = "Selects the deinterlacing algorithm, if any.";
|
||||
ui_type = "combo";
|
||||
ui_items = "None\0"
|
||||
"Fake-Progressive\0"
|
||||
"Weaving\0"
|
||||
"Blended Weaving\0";
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = 1;
|
||||
|
||||
uniform float deinterlacing_blend_gamma <
|
||||
ui_label = "Deinterlacing Blend Gamma";
|
||||
ui_tooltip = "Nudge this if deinterlacing changes your colors too much";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.01;
|
||||
ui_max = 5.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = 1.0;
|
||||
|
||||
uniform float linear_beam_thickness <
|
||||
ui_label = "Linear Beam Thickness";
|
||||
ui_tooltip = "Linearly widens or narrows the beam";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.01;
|
||||
ui_max = 3.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_spacing = 5;
|
||||
ui_category = "Scanlines";
|
||||
> = 1.0;
|
||||
|
||||
uniform float gaussian_beam_min_sigma <
|
||||
ui_label = "Gaussian Beam Min Sigma";
|
||||
ui_tooltip = "For Gaussian Beam Shape, sets thickness of dim pixels";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_spacing = 5;
|
||||
ui_category = "Scanlines";
|
||||
> = gaussian_beam_min_sigma_static;
|
||||
|
||||
uniform float gaussian_beam_max_sigma <
|
||||
ui_label = "Gaussian Beam Max Sigma";
|
||||
ui_tooltip = "For Gaussian Beam Shape, sets thickness of bright pixels";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = gaussian_beam_max_sigma_static;
|
||||
|
||||
uniform float gaussian_beam_spot_power <
|
||||
ui_label = "Gaussian Beam Spot Power";
|
||||
ui_tooltip = "For Gaussian Beam Shape, balances between Min and Max Sigma";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = gaussian_beam_spot_power_static;
|
||||
|
||||
uniform float gaussian_beam_min_shape <
|
||||
ui_label = "Gaussian Beam Min Shape";
|
||||
ui_tooltip = "For Gaussian Beam Shape, sets sharpness of dim pixels";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Scanlines";
|
||||
> = gaussian_beam_min_shape_static;
|
||||
|
||||
uniform float gaussian_beam_max_shape <
|
||||
ui_label = "Gaussian Beam Max Shape";
|
||||
ui_tooltip = "For Gaussian Beam Shape, sets sharpness of bright pixels";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = gaussian_beam_max_shape_static;
|
||||
|
||||
uniform float gaussian_beam_shape_power <
|
||||
ui_label = "Gaussian Beam Shape Power";
|
||||
ui_tooltip = "For Gaussian Beam Shape, balances between Min and Max Shape";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Scanlines";
|
||||
> = gaussian_beam_shape_power_static;
|
||||
|
||||
uniform float3 convergence_offset_x <
|
||||
ui_label = "Convergence Offset X RGB";
|
||||
ui_tooltip = "Shift the color channels horizontally";
|
||||
ui_type = "drag";
|
||||
ui_min = -10;
|
||||
ui_max = 10;
|
||||
ui_step = 0.05;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_spacing = 5;
|
||||
ui_category = "Scanlines";
|
||||
> = 0;
|
||||
uniform float3 convergence_offset_y <
|
||||
ui_label = "Convergence Offset Y RGB";
|
||||
ui_tooltip = "Shift the color channels vertically";
|
||||
ui_type = "drag";
|
||||
ui_min = -10;
|
||||
ui_max = 10;
|
||||
ui_step = 0.05;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
ui_category = "Scanlines";
|
||||
> = 0;
|
||||
|
||||
static uint beam_horiz_filter = beam_horiz_filter_static;
|
||||
static float beam_horiz_sigma = beam_horiz_sigma_static;
|
||||
static float beam_horiz_linear_rgb_weight = beam_horiz_linear_rgb_weight_static;
|
||||
|
||||
// ==== IMAGE COLORIZATION ====
|
||||
uniform float crt_gamma <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "Apply gamma, contrast, and blurring.\n\n";
|
||||
#endif
|
||||
ui_label = "CRT Gamma";
|
||||
ui_tooltip = "The gamma-level of the original content";
|
||||
ui_type = "slider";
|
||||
ui_min = 1.0;
|
||||
ui_max = 5.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Colors and Effects";
|
||||
ui_category_closed = true;
|
||||
> = crt_gamma_static;
|
||||
|
||||
uniform float lcd_gamma <
|
||||
ui_label = "LCD Gamma";
|
||||
ui_tooltip = "The gamma-level of your display";
|
||||
ui_type = "slider";
|
||||
ui_min = 1.0;
|
||||
ui_max = 5.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Colors and Effects";
|
||||
> = lcd_gamma_static;
|
||||
|
||||
uniform float levels_contrast <
|
||||
ui_label = "Levels Contrast";
|
||||
ui_tooltip = "Sets the contrast of the CRT";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.0;
|
||||
ui_max = 4.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_spacing = 5;
|
||||
ui_category = "Colors and Effects";
|
||||
> = levels_contrast_static;
|
||||
|
||||
uniform float halation_weight <
|
||||
ui_label = "Halation";
|
||||
ui_tooltip = "Desaturation due to eletrons exciting the wrong phosphors";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.0;
|
||||
ui_max = 1.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Colors and Effects";
|
||||
> = halation_weight_static;
|
||||
|
||||
uniform float diffusion_weight <
|
||||
ui_label = "Diffusion";
|
||||
ui_tooltip = "Blurring due to refraction from the screen's glass";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.0;
|
||||
ui_max = 1.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Colors and Effects";
|
||||
> = diffusion_weight_static;
|
||||
|
||||
uniform float blur_radius <
|
||||
ui_label = "Blur Radius";
|
||||
ui_tooltip = "Scales the radius of the halation and diffusion effects";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.01;
|
||||
ui_max = 5.0;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Colors and Effects";
|
||||
> = 1.0;
|
||||
|
||||
uniform float bloom_underestimate_levels <
|
||||
ui_label = "Bloom Underestimation";
|
||||
ui_tooltip = "Scale the bloom effect's intensity";
|
||||
ui_type = "drag";
|
||||
ui_min = FIX_ZERO(0.0);
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Colors and Effects";
|
||||
> = bloom_underestimate_levels_static;
|
||||
|
||||
uniform float bloom_excess <
|
||||
ui_label = "Bloom Excess";
|
||||
ui_tooltip = "Extra bloom applied to all colors";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.0;
|
||||
ui_max = 1.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Colors and Effects";
|
||||
> = bloom_excess_static;
|
||||
|
||||
uniform float2 aa_subpixel_r_offset_runtime <
|
||||
ui_label = "AA Subpixel R Offet XY";
|
||||
ui_type = "drag";
|
||||
ui_min = -0.5;
|
||||
ui_max = 0.5;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS || !_RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS;
|
||||
|
||||
ui_category = "Colors and Effects";
|
||||
> = aa_subpixel_r_offset_static;
|
||||
|
||||
static const float aa_cubic_c = aa_cubic_c_static;
|
||||
static const float aa_gauss_sigma = aa_gauss_sigma_static;
|
||||
|
||||
|
||||
// ==== GEOMETRY ====
|
||||
uniform uint geom_rotation_mode <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "Change the geometry of the screen's glass.\n\n";
|
||||
#endif
|
||||
ui_label = "Rotate Screen";
|
||||
ui_type = "combo";
|
||||
ui_items = "0 degrees\0"
|
||||
"90 degrees\0"
|
||||
"180 degrees\0"
|
||||
"270 degrees\0";
|
||||
|
||||
ui_category = "Screen Geometry";
|
||||
ui_category_closed = true;
|
||||
> = 0;
|
||||
uniform uint geom_mode_runtime <
|
||||
ui_label = "Geometry Mode";
|
||||
ui_tooltip = "Select screen curvature type";
|
||||
ui_type = "combo";
|
||||
ui_items = "Flat\0"
|
||||
"Spherical\0"
|
||||
"Spherical (Alt)\0"
|
||||
"Cylindrical (Trinitron)\0";
|
||||
|
||||
ui_category = "Screen Geometry";
|
||||
> = geom_mode_static;
|
||||
|
||||
uniform float geom_radius <
|
||||
ui_label = "Geometry Radius";
|
||||
ui_tooltip = "Select screen curvature radius";
|
||||
ui_type = "slider";
|
||||
ui_min = 1.0 / (2.0 * pi);
|
||||
ui_max = 1024;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Screen Geometry";
|
||||
> = geom_radius_static;
|
||||
|
||||
uniform float geom_view_dist <
|
||||
ui_label = "View Distance";
|
||||
ui_type = "slider";
|
||||
ui_min = 0.5;
|
||||
ui_max = 1024;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Screen Geometry";
|
||||
> = geom_view_dist_static;
|
||||
|
||||
uniform float2 geom_tilt_angle <
|
||||
ui_label = "Screen Tilt Angles";
|
||||
ui_type = "drag";
|
||||
ui_min = -pi;
|
||||
ui_max = pi;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Screen Geometry";
|
||||
> = geom_tilt_angle_static;
|
||||
|
||||
uniform float2 geom_aspect_ratio <
|
||||
ui_label = "Screen Aspect Ratios";
|
||||
ui_type = "drag";
|
||||
ui_min = 1.0;
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_category = "Screen Geometry";
|
||||
> = float2(geom_aspect_ratio_static, 1);
|
||||
uniform float2 geom_overscan <
|
||||
ui_label = "Geom Overscan";
|
||||
ui_type = "drag";
|
||||
ui_min = FIX_ZERO(0.0);
|
||||
ui_step = 0.01;
|
||||
hidden = !ADVANCED_SETTINGS;
|
||||
|
||||
ui_spacing = 2;
|
||||
ui_category = "Screen Geometry";
|
||||
> = geom_overscan_static;
|
||||
|
||||
// ==== BORDER ====
|
||||
uniform float border_size <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "Apply a thin vignette to the edge of the screen.\n\n";
|
||||
#endif
|
||||
ui_label = "Border Size";
|
||||
ui_category_closed = true;
|
||||
ui_type = "slider";
|
||||
ui_min = 0.0;
|
||||
ui_max = 0.5;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Screen Border";
|
||||
> = border_size_static;
|
||||
|
||||
uniform float border_darkness <
|
||||
ui_label = "Border Darkness";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Screen Border";
|
||||
> = border_darkness_static;
|
||||
|
||||
uniform float border_compress <
|
||||
ui_label = "Border Compress";
|
||||
ui_type = "drag";
|
||||
ui_min = 0.0;
|
||||
ui_step = 0.01;
|
||||
|
||||
ui_category = "Screen Border";
|
||||
> = border_compress_static;
|
||||
|
||||
// ==== PREBLUR ====
|
||||
#if ENABLE_PREBLUR
|
||||
uniform float2 preblur_effect_radius <
|
||||
#if !HIDE_HELP_SECTIONS
|
||||
ui_text = "- Apply a linear blur to the input image. Kind of like an NTSC/Composite shader, but much faster.\n"
|
||||
"- If you want to use an NTSC shader or don't like this effect, disable it by setting ENABLE_PREBLUR to 0\n"
|
||||
"- If you leave all of these set to 0, then they don't do anything. Consider disabling the effect to improve performance.\n\n";
|
||||
#endif
|
||||
ui_type = "drag";
|
||||
ui_min = 0;
|
||||
ui_max = 100;
|
||||
ui_step = 1;
|
||||
ui_label = "Effect Radius XY";
|
||||
ui_tooltip = "The radius of the effect visible on the screen (measured in pixels)";
|
||||
|
||||
ui_category = "Pre-Blur";
|
||||
ui_category_closed = true;
|
||||
> = 0;
|
||||
uniform uint2 preblur_sampling_radius <
|
||||
ui_type = "drag";
|
||||
ui_min = 0;
|
||||
ui_max = 100;
|
||||
ui_step = 1;
|
||||
ui_label = "Sampling Radius XY";
|
||||
ui_tooltip = "The number of samples to take on either side of each pixel";
|
||||
|
||||
ui_category = "Pre-Blur";
|
||||
> = 0;
|
||||
#else
|
||||
static const float2 preblur_effect_radius = 0;
|
||||
static const uint2 preblur_sampling_radius = 0;
|
||||
#endif
|
||||
|
||||
// Provide accessors for vector constants that pack scalar uniforms:
|
||||
float2 get_aspect_vector(const float geom_aspect_ratio)
|
||||
{
|
||||
// Get an aspect ratio vector. Enforce geom_max_aspect_ratio, and prevent
|
||||
// the absolute scale from affecting the uv-mapping for curvature:
|
||||
const float geom_clamped_aspect_ratio =
|
||||
min(geom_aspect_ratio, geom_max_aspect_ratio);
|
||||
const float2 geom_aspect =
|
||||
normalize(float2(geom_clamped_aspect_ratio, 1.0));
|
||||
return geom_aspect;
|
||||
}
|
||||
|
||||
float2 get_geom_overscan_vector()
|
||||
{
|
||||
return geom_overscan;
|
||||
}
|
||||
|
||||
float2 get_geom_tilt_angle_vector()
|
||||
{
|
||||
return geom_tilt_angle;
|
||||
}
|
||||
|
||||
float3 get_convergence_offsets_x_vector()
|
||||
{
|
||||
return convergence_offset_x;
|
||||
}
|
||||
|
||||
float3 get_convergence_offsets_y_vector()
|
||||
{
|
||||
return convergence_offset_y;
|
||||
}
|
||||
|
||||
float2 get_convergence_offsets_r_vector()
|
||||
{
|
||||
return float2(convergence_offset_x.r, convergence_offset_y.r);
|
||||
}
|
||||
|
||||
float2 get_convergence_offsets_g_vector()
|
||||
{
|
||||
return float2(convergence_offset_x.g, convergence_offset_y.g);
|
||||
}
|
||||
|
||||
float2 get_convergence_offsets_b_vector()
|
||||
{
|
||||
return float2(convergence_offset_x.b, convergence_offset_y.b);
|
||||
}
|
||||
|
||||
float2 get_aa_subpixel_r_offset()
|
||||
{
|
||||
#if _RUNTIME_ANTIALIAS_WEIGHTS
|
||||
#if _RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
|
||||
// WARNING: THIS IS EXTREMELY EXPENSIVE.
|
||||
return aa_subpixel_r_offset_runtime;
|
||||
#else
|
||||
return aa_subpixel_r_offset_static;
|
||||
#endif
|
||||
#else
|
||||
return aa_subpixel_r_offset_static;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Provide accessors settings which still need "cooking:"
|
||||
float get_mask_amplify()
|
||||
{
|
||||
static const float mask_grille_amplify = 1.0/mask_grille_avg_color;
|
||||
static const float mask_slot_amplify = 1.0/mask_slot_avg_color;
|
||||
static const float mask_shadow_amplify = 1.0/mask_shadow_avg_color;
|
||||
|
||||
float mask_amplify;
|
||||
[flatten]
|
||||
switch (mask_type) {
|
||||
case 0:
|
||||
mask_amplify = mask_grille_amplify;
|
||||
break;
|
||||
case 1:
|
||||
mask_amplify = mask_slot_amplify;
|
||||
break;
|
||||
case 2:
|
||||
mask_amplify = mask_shadow_amplify;
|
||||
break;
|
||||
case 3:
|
||||
mask_amplify = mask_grille_amplify;
|
||||
break;
|
||||
case 4:
|
||||
mask_amplify = mask_slot_amplify;
|
||||
break;
|
||||
default:
|
||||
mask_amplify = mask_shadow_amplify;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return mask_amplify;
|
||||
}
|
||||
|
||||
#endif // _BIND_SHADER_PARAMS_H
|
||||
@@ -1,320 +0,0 @@
|
||||
#ifndef _BLOOM_FUNCTIONS_H
|
||||
#define _BLOOM_FUNCTIONS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
// Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
///////////////////////////////// DESCRIPTION ////////////////////////////////
|
||||
|
||||
// These utility functions and constants help several passes determine the
|
||||
// size and center texel weight of the phosphor bloom in a uniform manner.
|
||||
|
||||
|
||||
////////////////////////////////// INCLUDES //////////////////////////////////
|
||||
|
||||
// We need to calculate the correct blur sigma using some .cgp constants:
|
||||
//#include "../user-settings.h"
|
||||
|
||||
|
||||
#include "user-settings.fxh"
|
||||
#include "derived-settings-and-constants.fxh"
|
||||
#include "bind-shader-params.fxh"
|
||||
#include "blur-functions.fxh"
|
||||
|
||||
/////////////////////////////// BLOOM CONSTANTS //////////////////////////////
|
||||
|
||||
// Compute constants with manual inlines of the functions below:
|
||||
static const float bloom_diff_thresh = 1.0/256.0;
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////// HELPERS //////////////////////////////////
|
||||
|
||||
float get_min_sigma_to_blur_triad(const float triad_size,
|
||||
const float thresh)
|
||||
{
|
||||
// Requires: 1.) triad_size is the final phosphor triad size in pixels
|
||||
// 2.) thresh is the max desired pixel difference in the
|
||||
// blurred triad (e.g. 1.0/256.0).
|
||||
// Returns: Return the minimum sigma that will fully blur a phosphor
|
||||
// triad on the screen to an even color, within thresh.
|
||||
// This closed-form function was found by curve-fitting data.
|
||||
// Estimate: max error = ~0.086036, mean sq. error = ~0.0013387:
|
||||
return -0.05168 + 0.6113*triad_size -
|
||||
1.122*triad_size*sqrt(0.000416 + thresh);
|
||||
// Estimate: max error = ~0.16486, mean sq. error = ~0.0041041:
|
||||
//return 0.5985*triad_size - triad_size*sqrt(thresh)
|
||||
}
|
||||
|
||||
float get_absolute_scale_blur_sigma(const float thresh)
|
||||
{
|
||||
// Requires: 1.) min_expected_triads must be a global float. The number
|
||||
// of horizontal phosphor triads in the final image must be
|
||||
// >= min_allowed_viewport_triads.x for realistic results.
|
||||
// 2.) bloom_approx_scale_x must be a global float equal to the
|
||||
// absolute horizontal scale of BLOOM_APPROX.
|
||||
// 3.) bloom_approx_scale_x/min_allowed_viewport_triads.x
|
||||
// should be <= 1.1658025090 to keep the final result <
|
||||
// 0.62666015625 (the largest sigma ensuring the largest
|
||||
// unused texel weight stays < 1.0/256.0 for a 3x3 blur).
|
||||
// 4.) thresh is the max desired pixel difference in the
|
||||
// blurred triad (e.g. 1.0/256.0).
|
||||
// Returns: Return the minimum Gaussian sigma that will blur the pass
|
||||
// output as much as it would have taken to blur away
|
||||
// bloom_approx_scale_x horizontal phosphor triads.
|
||||
// Description:
|
||||
// BLOOM_APPROX should look like a downscaled phosphor blur. Ideally, we'd
|
||||
// use the same blur sigma as the actual phosphor bloom and scale it down
|
||||
// to the current resolution with (bloom_approx_scale_x/viewport_size_x), but
|
||||
// we don't know the viewport size in this pass. Instead, we'll blur as
|
||||
// much as it would take to blur away min_allowed_viewport_triads.x. This
|
||||
// will blur "more than necessary" if the user actually uses more triads,
|
||||
// but that's not terrible either, because blurring a constant fraction of
|
||||
// the viewport may better resemble a true optical bloom anyway (since the
|
||||
// viewport will generally be about the same fraction of each player's
|
||||
// field of view, regardless of screen size and resolution).
|
||||
// Assume an extremely large viewport size for asymptotic results.
|
||||
return bloom_approx_scale_x/max_viewport_size_x *
|
||||
get_min_sigma_to_blur_triad(
|
||||
max_viewport_size_x/min_allowed_viewport_triads.x, thresh);
|
||||
}
|
||||
|
||||
float get_center_weight(const float sigma)
|
||||
{
|
||||
// Given a Gaussian blur sigma, get the blur weight for the center texel.
|
||||
#if _RUNTIME_PHOSPHOR_BLOOM_SIGMA
|
||||
return get_fast_gaussian_weight_sum_inv(sigma);
|
||||
#else
|
||||
const float denom_inv = 0.5/(sigma*sigma);
|
||||
const float w0 = 1.0;
|
||||
const float w1 = exp(-1.0 * denom_inv);
|
||||
const float w2 = exp(-4.0 * denom_inv);
|
||||
const float w3 = exp(-9.0 * denom_inv);
|
||||
const float w4 = exp(-16.0 * denom_inv);
|
||||
const float w5 = exp(-25.0 * denom_inv);
|
||||
const float w6 = exp(-36.0 * denom_inv);
|
||||
const float w7 = exp(-49.0 * denom_inv);
|
||||
const float w8 = exp(-64.0 * denom_inv);
|
||||
const float w9 = exp(-81.0 * denom_inv);
|
||||
const float w10 = exp(-100.0 * denom_inv);
|
||||
const float w11 = exp(-121.0 * denom_inv);
|
||||
const float w12 = exp(-144.0 * denom_inv);
|
||||
const float w13 = exp(-169.0 * denom_inv);
|
||||
const float w14 = exp(-196.0 * denom_inv);
|
||||
const float w15 = exp(-225.0 * denom_inv);
|
||||
const float w16 = exp(-256.0 * denom_inv);
|
||||
const float w17 = exp(-289.0 * denom_inv);
|
||||
const float w18 = exp(-324.0 * denom_inv);
|
||||
const float w19 = exp(-361.0 * denom_inv);
|
||||
const float w20 = exp(-400.0 * denom_inv);
|
||||
const float w21 = exp(-441.0 * denom_inv);
|
||||
// Note: If the implementation uses a smaller blur than the max allowed,
|
||||
// the worst case scenario is that the center weight will be overestimated,
|
||||
// so we'll put a bit more energy into the brightpass...no huge deal.
|
||||
// Then again, if the implementation uses a larger blur than the max
|
||||
// "allowed" because of dynamic branching, the center weight could be
|
||||
// underestimated, which is more of a problem...consider always using
|
||||
#if PHOSPHOR_BLOOM_TRIAD_SIZE_MODE >= _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
|
||||
// 43x blur:
|
||||
const float weight_sum_inv = 1.0 /
|
||||
(w0 + 2.0 * (w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + w9 + w10 +
|
||||
w11 + w12 + w13 + w14 + w15 + w16 + w17 + w18 + w19 + w20 + w21));
|
||||
#else
|
||||
#if PHOSPHOR_BLOOM_TRIAD_SIZE_MODE >= _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
|
||||
// 31x blur:
|
||||
const float weight_sum_inv = 1.0 /
|
||||
(w0 + 2.0 * (w1 + w2 + w3 + w4 + w5 + w6 + w7 +
|
||||
w8 + w9 + w10 + w11 + w12 + w13 + w14 + w15));
|
||||
#else
|
||||
#if PHOSPHOR_BLOOM_TRIAD_SIZE_MODE >= _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
|
||||
// 25x blur:
|
||||
const float weight_sum_inv = 1.0 / (w0 + 2.0 * (
|
||||
w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + w9 + w10 + w11 + w12));
|
||||
#else
|
||||
#if PHOSPHOR_BLOOM_TRIAD_SIZE_MODE >= _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
|
||||
// 17x blur:
|
||||
const float weight_sum_inv = 1.0 / (w0 + 2.0 * (
|
||||
w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8));
|
||||
#else
|
||||
// 9x blur:
|
||||
const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2 + w3 + w4));
|
||||
#endif // _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
|
||||
#endif // _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
|
||||
#endif // _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
|
||||
#endif // _PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
|
||||
const float center_weight = weight_sum_inv * weight_sum_inv;
|
||||
return center_weight;
|
||||
#endif
|
||||
}
|
||||
|
||||
float3 tex2DblurNfast(const sampler2D tex, const float2 tex_uv,
|
||||
const float2 dxdy, const float sigma,
|
||||
const float input_gamma)
|
||||
{
|
||||
// If sigma is static, we can safely branch and use the smallest blur
|
||||
// that's big enough. Ignore #define hints, because we'll only use a
|
||||
// large blur if we actually need it, and the branches cost nothing.
|
||||
#if !_RUNTIME_PHOSPHOR_BLOOM_SIGMA
|
||||
#define PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
|
||||
#else
|
||||
// It's still worth branching if the profile supports dynamic branches:
|
||||
// It's much faster than using a hugely excessive blur, but each branch
|
||||
// eats ~1% FPS.
|
||||
#if _DRIVERS_ALLOW_DYNAMIC_BRANCHES
|
||||
#define PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
|
||||
#endif
|
||||
#endif
|
||||
// Failed optimization notes:
|
||||
// I originally created a same-size mipmapped 5-tap separable blur10 that
|
||||
// could handle any sigma by reaching into lower mip levels. It was
|
||||
// as fast as blur25fast for runtime sigmas and a tad faster than
|
||||
// blur31fast for static sigmas, but mipmapping two viewport-size passes
|
||||
// ate 10% of FPS across all codepaths, so it wasn't worth it.
|
||||
#ifdef PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
|
||||
if(sigma <= blur9_std_dev)
|
||||
{
|
||||
return tex2Dblur9fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
}
|
||||
else if(sigma <= blur17_std_dev)
|
||||
{
|
||||
return tex2Dblur17fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
}
|
||||
else if(sigma <= blur25_std_dev)
|
||||
{
|
||||
return tex2Dblur25fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
}
|
||||
else if(sigma <= blur31_std_dev)
|
||||
{
|
||||
return tex2Dblur31fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tex2Dblur43fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
}
|
||||
#else
|
||||
// If we can't afford to branch, we can only guess at what blur
|
||||
// size we need. Therefore, use the largest blur allowed.
|
||||
#ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
|
||||
return tex2Dblur43fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
#else
|
||||
#ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
|
||||
return tex2Dblur31fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
#else
|
||||
#ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
|
||||
return tex2Dblur25fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
#else
|
||||
#if PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
|
||||
return tex2Dblur17fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
#else
|
||||
return tex2Dblur9fast(tex, tex_uv, dxdy, sigma, input_gamma);
|
||||
#endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
|
||||
#endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
|
||||
#endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
|
||||
#endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
|
||||
#endif // PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
|
||||
}
|
||||
|
||||
float get_bloom_approx_sigma(const float output_size_x_runtime,
|
||||
const float estimated_viewport_size_x)
|
||||
{
|
||||
// Requires: 1.) output_size_x_runtime == BLOOM_APPROX.output_size.x.
|
||||
// This is included for dynamic codepaths just in case the
|
||||
// following two globals are incorrect:
|
||||
// 2.) bloom_approx_size_x_for_skip should == the same
|
||||
// if PHOSPHOR_BLOOM_FAKE is #defined
|
||||
// 3.) bloom_approx_size_x should == the same otherwise
|
||||
// Returns: For gaussian4x4, return a dynamic small bloom sigma that's
|
||||
// as close to optimal as possible given available information.
|
||||
// For blur3x3, return the a static small bloom sigma that
|
||||
// works well for typical cases. Otherwise, we're using simple
|
||||
// bilinear filtering, so use static calculations.
|
||||
// Assume the default static value. This is a compromise that ensures
|
||||
// typical triads are blurred, even if unusually large ones aren't.
|
||||
static const float mask_num_triads_static =
|
||||
max(min_allowed_viewport_triads.x, mask_num_triads_across_static);
|
||||
const float mask_num_triads_from_size =
|
||||
estimated_viewport_size_x/mask_triad_width;
|
||||
const float mask_num_triads_runtime = max(min_allowed_viewport_triads.x,
|
||||
lerp(mask_num_triads_from_size, mask_num_triads_across,
|
||||
mask_size_param));
|
||||
// Assume an extremely large viewport size for asymptotic results:
|
||||
static const float max_viewport_size_x = 1080.0*1024.0*(4.0/3.0);
|
||||
if(bloom_approx_filter > 1.5) // 4x4 true Gaussian resize
|
||||
{
|
||||
// Use the runtime num triads and output size:
|
||||
const float asymptotic_triad_size =
|
||||
max_viewport_size_x/mask_num_triads_runtime;
|
||||
const float asymptotic_sigma = get_min_sigma_to_blur_triad(
|
||||
asymptotic_triad_size, bloom_diff_thresh);
|
||||
const float bloom_approx_sigma =
|
||||
asymptotic_sigma * output_size_x_runtime/max_viewport_size_x;
|
||||
// The BLOOM_APPROX input has to be ORIG_LINEARIZED to avoid moire, but
|
||||
// account for the Gaussian scanline sigma from the last pass too.
|
||||
// The bloom will be too wide horizontally but tall enough vertically.
|
||||
return length(float2(bloom_approx_sigma, gaussian_beam_max_sigma));
|
||||
}
|
||||
else // 3x3 blur resize (the bilinear resize doesn't need a sigma)
|
||||
{
|
||||
// We're either using blur3x3 or bilinear filtering. The biggest
|
||||
// reason to choose blur3x3 is to avoid dynamic weights, so use a
|
||||
// static calculation.
|
||||
#ifdef PHOSPHOR_BLOOM_FAKE
|
||||
static const float output_size_x_static =
|
||||
bloom_approx_size_x_for_fake;
|
||||
#else
|
||||
static const float output_size_x_static = bloom_approx_size_x;
|
||||
#endif
|
||||
static const float asymptotic_triad_size =
|
||||
max_viewport_size_x/mask_num_triads_static;
|
||||
const float asymptotic_sigma = get_min_sigma_to_blur_triad(
|
||||
asymptotic_triad_size, bloom_diff_thresh);
|
||||
const float bloom_approx_sigma =
|
||||
asymptotic_sigma * output_size_x_static/max_viewport_size_x;
|
||||
// The BLOOM_APPROX input has to be ORIG_LINEARIZED to avoid moire, but
|
||||
// try accounting for the Gaussian scanline sigma from the last pass
|
||||
// too; use the static default value:
|
||||
return length(float2(bloom_approx_sigma, gaussian_beam_max_sigma_static));
|
||||
}
|
||||
}
|
||||
|
||||
float get_final_bloom_sigma(const float bloom_sigma_runtime)
|
||||
{
|
||||
// Requires: 1.) bloom_sigma_runtime is a precalculated sigma that's
|
||||
// optimal for the [known] triad size.
|
||||
// 2.) Call this from a fragment shader (not a vertex shader),
|
||||
// or blurring with static sigmas won't be constant-folded.
|
||||
// Returns: Return the optimistic static sigma if the triad size is
|
||||
// known at compile time. Otherwise return the optimal runtime
|
||||
// sigma (10% slower) or an implementation-specific compromise
|
||||
// between an optimistic or pessimistic static sigma.
|
||||
// Notes: Call this from the fragment shader, NOT the vertex shader,
|
||||
// so static sigmas can be constant-folded!
|
||||
const float bloom_sigma_optimistic = get_min_sigma_to_blur_triad(
|
||||
mask_triad_width_static, bloom_diff_thresh);
|
||||
#if _RUNTIME_PHOSPHOR_BLOOM_SIGMA
|
||||
return bloom_sigma_runtime;
|
||||
#else
|
||||
// Overblurring looks as bad as underblurring, so assume average-size
|
||||
// triads, not worst-case huge triads:
|
||||
return bloom_sigma_optimistic;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif // _BLOOM_FUNCTIONS_H
|
||||
@@ -1,405 +0,0 @@
|
||||
#ifndef _DERIVED_SETTINGS_AND_CONSTANTS_H
|
||||
#define _DERIVED_SETTINGS_AND_CONSTANTS_H
|
||||
|
||||
#include "helper-functions-and-macros.fxh"
|
||||
#include "user-settings.fxh"
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
// Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
///////////////////////////////// DESCRIPTION ////////////////////////////////
|
||||
|
||||
// These macros and constants can be used across the whole codebase.
|
||||
// Unlike the values in user-settings.cgh, end users shouldn't modify these.
|
||||
|
||||
|
||||
/////////////////////////////// BEGIN INCLUDES ///////////////////////////////
|
||||
|
||||
//#include "../user-settings.h"
|
||||
|
||||
//#include "user-cgp-constants.h"
|
||||
|
||||
///////////////////////// BEGIN USER-CGP-CONSTANTS /////////////////////////
|
||||
|
||||
#ifndef _USER_CGP_CONSTANTS_H
|
||||
#define _USER_CGP_CONSTANTS_H
|
||||
|
||||
// IMPORTANT:
|
||||
// These constants MUST be set appropriately for the settings in crt-royale.cgp
|
||||
// (or whatever related .cgp file you're using). If they aren't, you're likely
|
||||
// to get artifacts, the wrong phosphor mask size, etc. I wish these could be
|
||||
// set directly in the .cgp file to make things easier, but...they can't.
|
||||
|
||||
// PASS SCALES AND RELATED CONSTANTS:
|
||||
// Copy the absolute scale_x for BLOOM_APPROX. There are two major versions of
|
||||
// this shader: One does a viewport-scale bloom, and the other skips it. The
|
||||
// latter benefits from a higher bloom_approx_scale_x, so save both separately:
|
||||
static const float bloom_approx_scale_x = 4.0 / 3.0;
|
||||
static const float max_viewport_size_x = 1080.0*1024.0*(4.0/3.0);
|
||||
static const float bloom_diff_thresh_ = 1.0/256.0;
|
||||
|
||||
static const float bloom_approx_size_x = 320.0;
|
||||
static const float bloom_approx_size_x_for_fake = 400.0;
|
||||
// Copy the viewport-relative scales of the phosphor mask resize passes
|
||||
// (MASK_RESIZE and the pass immediately preceding it):
|
||||
static const float2 mask_resize_viewport_scale = float2(0.0625, 0.0625);
|
||||
// Copy the geom_max_aspect_ratio used to calculate the MASK_RESIZE scales, etc.:
|
||||
static const float geom_max_aspect_ratio = 4.0/3.0;
|
||||
|
||||
// PHOSPHOR MASK TEXTURE CONSTANTS:
|
||||
// Set the following constants to reflect the properties of the phosphor mask
|
||||
// texture named in crt-royale.cgp. The shader optionally resizes a mask tile
|
||||
// based on user settings, then repeats a single tile until filling the screen.
|
||||
// The shader must know the input texture size (default 64x64), and to manually
|
||||
// resize, it must also know the horizontal triads per tile (default 8).
|
||||
static const float2 mask_texture_small_size = float2(64.0, 64.0);
|
||||
static const float2 mask_texture_large_size = float2(512.0, 512.0);
|
||||
static const float mask_triads_per_tile = 8.0;
|
||||
// We need the average brightness of the phosphor mask to compensate for the
|
||||
// dimming it causes. The following four values are roughly correct for the
|
||||
// masks included with the shader. Update the value for any LUT texture you
|
||||
// change. [Un]comment "#define PHOSPHOR_MASK_GRILLE14" depending on whether
|
||||
// the loaded aperture grille uses 14-pixel or 15-pixel stripes (default 15).
|
||||
// #ifndef PHOSPHOR_MASK_GRILLE14
|
||||
// #define PHOSPHOR_MASK_GRILLE14 0
|
||||
// #endif
|
||||
static const float mask_grille14_avg_color = 50.6666666/255.0;
|
||||
// TileableLinearApertureGrille14Wide7d33Spacing*.png
|
||||
// TileableLinearApertureGrille14Wide10And6Spacing*.png
|
||||
static const float mask_grille15_avg_color = 53.0/255.0;
|
||||
// TileableLinearApertureGrille15Wide6d33Spacing*.png
|
||||
// TileableLinearApertureGrille15Wide8And5d5Spacing*.png
|
||||
static const float mask_slot_avg_color = 46.0/255.0;
|
||||
// TileableLinearSlotMask15Wide9And4d5Horizontal8VerticalSpacing*.png
|
||||
// TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing*.png
|
||||
static const float mask_shadow_avg_color = 41.0/255.0;
|
||||
// TileableLinearShadowMask*.png
|
||||
// TileableLinearShadowMaskEDP*.png
|
||||
|
||||
// #if PHOSPHOR_MASK_GRILLE14
|
||||
// static const float mask_grille_avg_color = mask_grille14_avg_color;
|
||||
// #else
|
||||
static const float mask_grille_avg_color = mask_grille15_avg_color;
|
||||
// #endif
|
||||
|
||||
|
||||
#endif // _USER_CGP_CONSTANTS_H
|
||||
|
||||
////////////////////////// END USER-CGP-CONSTANTS //////////////////////////
|
||||
|
||||
//////////////////////////////// END INCLUDES ////////////////////////////////
|
||||
|
||||
/////////////////////////////// FIXED SETTINGS ///////////////////////////////
|
||||
|
||||
|
||||
|
||||
#define _SIMULATE_CRT_ON_LCD 1
|
||||
#define _SIMULATE_GBA_ON_LCD 2
|
||||
#define _SIMULATE_LCD_ON_CRT 3
|
||||
#define _SIMULATE_GBA_ON_CRT 4
|
||||
|
||||
// Ensure the first pass decodes CRT gamma and the last encodes LCD gamma.
|
||||
#define GAMMA_SIMULATION_MODE _SIMULATE_CRT_ON_LCD
|
||||
|
||||
// Manually tiling a manually resized texture creates texture coord derivative
|
||||
// discontinuities and confuses anisotropic filtering, causing discolored tile
|
||||
// seams in the phosphor mask. Workarounds:
|
||||
// a.) Using tex2Dlod disables anisotropic filtering for tiled masks. It's
|
||||
// downgraded to tex2Dbias without _DRIVERS_ALLOW_TEX2DLOD #defined and
|
||||
// disabled without _DRIVERS_ALLOW_TEX2DBIAS #defined either.
|
||||
// b.) "Tile flat twice" requires drawing two full tiles without border padding
|
||||
// to the resized mask FBO, and it's incompatible with same-pass curvature.
|
||||
// (Same-pass curvature isn't used but could be in the future...maybe.)
|
||||
// c.) "Fix discontinuities" requires derivatives and drawing one tile with
|
||||
// border padding to the resized mask FBO, but it works with same-pass
|
||||
// curvature. It's disabled without _DRIVERS_ALLOW_DERIVATIVES #defined.
|
||||
// Precedence: a, then, b, then c (if multiple strategies are #defined).
|
||||
// #ifndef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD 1 // 129.7 FPS, 4x, flat; 101.8 at fullscreen
|
||||
// #endif
|
||||
// #ifndef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE 1 // 128.1 FPS, 4x, flat; 101.5 at fullscreen
|
||||
// #endif
|
||||
// #ifndef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES 1 // 124.4 FPS, 4x, flat; 97.4 at fullscreen
|
||||
// #endif
|
||||
// Also, manually resampling the phosphor mask is slightly blurrier with
|
||||
// anisotropic filtering. (Resampling with mipmapping is even worse: It
|
||||
// creates artifacts, but only with the fully bloomed shader.) The difference
|
||||
// is subtle with small triads, but you can fix it for a small cost.
|
||||
// #ifndef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD 0
|
||||
// #endif
|
||||
|
||||
|
||||
////////////////////////////// DERIVED SETTINGS //////////////////////////////
|
||||
|
||||
// Intel HD 4000 GPU's can't handle manual mask resizing (for now), setting the
|
||||
// geometry mode at runtime, or a 4x4 true Gaussian resize. Disable
|
||||
// incompatible settings ASAP. (_INTEGRATED_GRAPHICS_COMPATIBILITY_MODE may be
|
||||
// #defined by either user-settings.h or a wrapper .cg that #includes the
|
||||
// current .cg pass.)
|
||||
#if _INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
|
||||
#if _PHOSPHOR_MASK_MANUALLY_RESIZE
|
||||
#undef _PHOSPHOR_MASK_MANUALLY_RESIZE
|
||||
#define _PHOSPHOR_MASK_MANUALLY_RESIZE 0
|
||||
#endif
|
||||
#if _RUNTIME_GEOMETRY_MODE
|
||||
#undef _RUNTIME_GEOMETRY_MODE
|
||||
#define _RUNTIME_GEOMETRY_MODE 0
|
||||
#endif
|
||||
// Mode 2 (4x4 Gaussian resize) won't work, and mode 1 (3x3 blur) is
|
||||
// inferior in most cases, so replace 2.0 with 0.0:
|
||||
static const float bloom_approx_filter = macro_cond(
|
||||
bloom_approx_filter_static > 1.5,
|
||||
0.0,
|
||||
bloom_approx_filter_static
|
||||
);
|
||||
#else
|
||||
static const float bloom_approx_filter = bloom_approx_filter_static;
|
||||
#endif
|
||||
|
||||
// Disable slow runtime paths if static parameters are used. Most of these
|
||||
// won't be a problem anyway once the params are disabled, but some will.
|
||||
#if !_RUNTIME_SHADER_PARAMS_ENABLE
|
||||
#if _RUNTIME_PHOSPHOR_BLOOM_SIGMA
|
||||
#undef _RUNTIME_PHOSPHOR_BLOOM_SIGMA
|
||||
#define _RUNTIME_PHOSPHOR_BLOOM_SIGMA 0
|
||||
#endif
|
||||
#if _RUNTIME_ANTIALIAS_WEIGHTS
|
||||
#undef _RUNTIME_ANTIALIAS_WEIGHTS
|
||||
#define _RUNTIME_ANTIALIAS_WEIGHTS 0
|
||||
#endif
|
||||
#if _RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
|
||||
#undef _RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
|
||||
#define _RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS 0
|
||||
#endif
|
||||
#if _RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
|
||||
#undef _RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
|
||||
#define _RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE 0
|
||||
#endif
|
||||
#if _RUNTIME_GEOMETRY_TILT
|
||||
#undef _RUNTIME_GEOMETRY_TILT
|
||||
#define _RUNTIME_GEOMETRY_TILT 0
|
||||
#endif
|
||||
#if _RUNTIME_GEOMETRY_MODE
|
||||
#undef _RUNTIME_GEOMETRY_MODE
|
||||
#define _RUNTIME_GEOMETRY_MODE 0
|
||||
#endif
|
||||
// #if FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
|
||||
// #undef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
|
||||
// #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT 0
|
||||
// #endif
|
||||
#endif
|
||||
|
||||
// Make tex2Dbias a backup for tex2Dlod for wider compatibility.
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #endif
|
||||
// #if ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
|
||||
// #endif
|
||||
// Rule out unavailable anisotropic compatibility strategies:
|
||||
#if !_DRIVERS_ALLOW_DERIVATIVES
|
||||
// #if ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES 0
|
||||
// #endif
|
||||
#endif
|
||||
// #if !_DRIVERS_ALLOW_TEX2DLOD
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TEX2DLOD
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD 0
|
||||
// #endif
|
||||
// #if ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
|
||||
// #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD 0
|
||||
// #endif
|
||||
// #ifdef ANTIALIAS_DISABLE_ANISOTROPIC
|
||||
// #undef ANTIALIAS_DISABLE_ANISOTROPIC
|
||||
// #endif
|
||||
// #endif
|
||||
// #if !_DRIVERS_ALLOW_TEX2DBIAS
|
||||
// #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #endif
|
||||
// #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
|
||||
// #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
|
||||
// #endif
|
||||
// #endif
|
||||
// Prioritize anisotropic tiling compatibility strategies by performance and
|
||||
// disable unused strategies. This concentrates all the nesting in one place.
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TEX2DLOD
|
||||
// #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #endif
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE 0
|
||||
// #endif
|
||||
// #if ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES 0
|
||||
// #endif
|
||||
// #else
|
||||
// #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE 0
|
||||
// #endif
|
||||
// #if ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES 0
|
||||
// #endif
|
||||
// #else
|
||||
// // ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE is only compatible with
|
||||
// // flat texture coords in the same pass, but that's all we use.
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// #if ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES 0
|
||||
// #endif
|
||||
// #endif
|
||||
// #endif
|
||||
// #endif
|
||||
// The tex2Dlod and tex2Dbias strategies share a lot in common, and we can
|
||||
// reduce some #ifdef nesting in the next section by essentially OR'ing them:
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TEX2DLOD
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
|
||||
// #endif
|
||||
// #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
|
||||
// #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
|
||||
// #endif
|
||||
// Prioritize anisotropic resampling compatibility strategies the same way:
|
||||
// #if ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
|
||||
// #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
|
||||
// #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
|
||||
/////////////////////// DERIVED PHOSPHOR MASK CONSTANTS //////////////////////
|
||||
|
||||
// If we can use the large mipmapped LUT without mipmapping artifacts, we
|
||||
// should: It gives us more options for using fewer samples.
|
||||
// #if USE_LARGE_PHOSPHOR_MASK
|
||||
// #if ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
|
||||
// // TODO: Take advantage of this!
|
||||
// #define PHOSPHOR_MASK_RESIZE_MIPMAPPED_LUT
|
||||
// static const float2 mask_resize_src_lut_size = mask_texture_large_size;
|
||||
// #else
|
||||
static const float2 mask_resize_src_lut_size = mask_texture_large_size;
|
||||
// #endif
|
||||
// #else
|
||||
// static const float2 mask_resize_src_lut_size = mask_texture_small_size;
|
||||
// #endif
|
||||
|
||||
static const float tile_aspect_inv = mask_resize_src_lut_size.y/mask_resize_src_lut_size.x;
|
||||
|
||||
|
||||
// tex2D's sampler2D parameter MUST be a uniform global, a uniform input to
|
||||
// main_fragment, or a static alias of one of the above. This makes it hard
|
||||
// to select the phosphor mask at runtime: We can't even assign to a uniform
|
||||
// global in the vertex shader or select a sampler2D in the vertex shader and
|
||||
// pass it to the fragment shader (even with explicit TEXUNIT# bindings),
|
||||
// because it just gives us the input texture or a black screen. However, we
|
||||
// can get around these limitations by calling tex2D three times with different
|
||||
// uniform samplers (or resizing the phosphor mask three times altogether).
|
||||
// With dynamic branches, we can process only one of these branches on top of
|
||||
// quickly discarding fragments we don't need (cgc seems able to overcome
|
||||
// limigations around dependent texture fetches inside of branches). Without
|
||||
// dynamic branches, we have to process every branch for every fragment...which
|
||||
// is slower. Runtime sampling mode selection is slower without dynamic
|
||||
// branches as well. Let the user's static #defines decide if it's worth it.
|
||||
#if _DRIVERS_ALLOW_DYNAMIC_BRANCHES
|
||||
#define _RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
|
||||
// #else
|
||||
// #if FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
|
||||
// #define _RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
|
||||
// #endif
|
||||
#endif
|
||||
|
||||
// We need to render some minimum number of tiles in the resize passes.
|
||||
// We need at least 1.0 just to repeat a single tile, and we need extra
|
||||
// padding beyond that for anisotropic filtering, discontinuitity fixing,
|
||||
// antialiasing, same-pass curvature (not currently used), etc. First
|
||||
// determine how many border texels and tiles we need, based on how the result
|
||||
// will be sampled:
|
||||
#ifdef GEOMETRY_EARLY
|
||||
static const float max_subpixel_offset = aa_subpixel_r_offset_static.x;
|
||||
// Most antialiasing filters have a base radius of 4.0 pixels:
|
||||
static const float max_aa_base_pixel_border = 4.0 +
|
||||
max_subpixel_offset;
|
||||
#else
|
||||
static const float max_aa_base_pixel_border = 0.0;
|
||||
#endif
|
||||
// Anisotropic filtering adds about 0.5 to the pixel border:
|
||||
// #ifndef ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
|
||||
static const float max_aniso_pixel_border = max_aa_base_pixel_border + 0.5;
|
||||
// #else
|
||||
// static const float max_aniso_pixel_border = max_aa_base_pixel_border;
|
||||
// #endif
|
||||
// Fixing discontinuities adds 1.0 more to the pixel border:
|
||||
// #if ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
|
||||
// static const float max_tiled_pixel_border = max_aniso_pixel_border + 1.0;
|
||||
// #else
|
||||
static const float max_tiled_pixel_border = max_aniso_pixel_border;
|
||||
// #endif
|
||||
// Convert the pixel border to an integer texel border. Assume same-pass
|
||||
// curvature about triples the texel frequency:
|
||||
#ifdef GEOMETRY_EARLY
|
||||
#define max_mask_texel_border macro_ceil(max_tiled_pixel_border * 3.0f)
|
||||
#else
|
||||
#define max_mask_texel_border macro_ceil(max_tiled_pixel_border)
|
||||
#endif
|
||||
// Convert the texel border to a tile border using worst-case assumptions:
|
||||
static const float max_mask_tile_border = max_mask_texel_border/
|
||||
(mask_min_allowed_triad_size * mask_triads_per_tile);
|
||||
|
||||
// Finally, set the number of resized tiles to render to MASK_RESIZE, and set
|
||||
// the starting texel (inside borders) for sampling it.
|
||||
#ifndef GEOMETRY_EARLY
|
||||
// #if ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
|
||||
// Special case: Render two tiles without borders. Anisotropic
|
||||
// filtering doesn't seem to be a problem here.
|
||||
// static const float mask_resize_num_tiles = 1.0 + 1.0;
|
||||
// static const float mask_start_texels = 0.0;
|
||||
// #else
|
||||
static const float mask_resize_num_tiles = 1.0 + 2.0 * max_mask_tile_border;
|
||||
static const float mask_start_texels = max_mask_texel_border;
|
||||
// #endif
|
||||
#else
|
||||
static const float mask_resize_num_tiles = 1.0 + 2.0*max_mask_tile_border;
|
||||
static const float mask_start_texels = max_mask_texel_border;
|
||||
#endif
|
||||
|
||||
// We have to fit mask_resize_num_tiles into an FBO with a viewport scale of
|
||||
// mask_resize_viewport_scale. This limits the maximum final triad size.
|
||||
// Estimate the minimum number of triads we can split the screen into in each
|
||||
// dimension (we'll be as correct as mask_resize_viewport_scale is):
|
||||
static const float mask_resize_num_triads = mask_resize_num_tiles * mask_triads_per_tile;
|
||||
static const float2 min_allowed_viewport_triads =
|
||||
float2(mask_resize_num_triads, mask_resize_num_triads) / mask_resize_viewport_scale;
|
||||
|
||||
|
||||
|
||||
#endif // _DERIVED_SETTINGS_AND_CONSTANTS_H
|
||||
@@ -1,84 +0,0 @@
|
||||
#ifndef _DOWNSAMPLING_FUNCTIONS_H
|
||||
#define _DOWNSAMPLING_FUNCTIONS_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
float3 opaque_linear_downsample(
|
||||
const sampler2D tex,
|
||||
const float2 texcoord,
|
||||
const uint num_pairs,
|
||||
const float2 delta_uv
|
||||
) {
|
||||
const uint total_num_samples = num_pairs * 2 + 1;
|
||||
const float2 coord_left = texcoord - delta_uv * num_pairs;
|
||||
|
||||
float3 acc = 0;
|
||||
for(int i = 0; i < total_num_samples; i++) {
|
||||
const float2 coord = coord_left + i * delta_uv;
|
||||
acc += tex2D_nograd(tex, coord).rgb;
|
||||
}
|
||||
|
||||
return acc / total_num_samples;
|
||||
}
|
||||
|
||||
|
||||
float3 opaque_lanczos_downsample(
|
||||
const sampler2D tex,
|
||||
const float2 texcoord,
|
||||
const uint num_pairs,
|
||||
const float2 delta_uv,
|
||||
const float num_sinc_lobes,
|
||||
const float weight_at_center
|
||||
) {
|
||||
const uint total_num_samples = num_pairs * 2 + 1;
|
||||
const float2 coord_left = texcoord - delta_uv * num_pairs;
|
||||
const float sinc_dx = num_sinc_lobes / num_pairs; // 2 * num_sinc_lobes / (total_num_samples - 1)
|
||||
|
||||
float3 acc = 0;
|
||||
float w_sum = 0;
|
||||
for(int i = 0; i < total_num_samples; i++) {
|
||||
const float2 coord = coord_left + i * delta_uv;
|
||||
const float sinc_x = i * sinc_dx;
|
||||
|
||||
const float weight = (i != num_pairs) ?
|
||||
num_sinc_lobes * sin(pi*sinc_x) * sin(pi*sinc_x/num_sinc_lobes) / (pi*pi * sinc_x*sinc_x) :
|
||||
weight_at_center;
|
||||
|
||||
acc += weight * tex2D_nograd(tex, coord).rgb;
|
||||
w_sum += weight;
|
||||
}
|
||||
|
||||
return acc / w_sum;
|
||||
}
|
||||
|
||||
float3 opaque_lanczos_downsample(
|
||||
const sampler2D tex,
|
||||
const float2 texcoord,
|
||||
const uint num_pairs,
|
||||
const float2 delta_uv,
|
||||
const float num_sinc_lobes
|
||||
) {
|
||||
return opaque_lanczos_downsample(tex, texcoord, num_pairs, delta_uv, num_sinc_lobes, 1);
|
||||
}
|
||||
|
||||
#endif // _DOWNSAMPLING_FUNCTIONS_H
|
||||
@@ -1,225 +0,0 @@
|
||||
#ifndef _GAMMA_MANAGEMENT_H
|
||||
#define _GAMMA_MANAGEMENT_H
|
||||
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2014 TroggleMonkey
|
||||
// Copyright (C) 2020 Alex Gunter
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "helper-functions-and-macros.fxh"
|
||||
|
||||
|
||||
/////////////////////////////// BASE CONSTANTS ///////////////////////////////
|
||||
|
||||
// Set standard gamma constants, but allow users to override them:
|
||||
#ifndef OVERRIDE_STANDARD_GAMMA
|
||||
// Standard encoding gammas:
|
||||
static const float ntsc_gamma = 2.2; // Best to use NTSC for PAL too?
|
||||
static const float pal_gamma = 2.8; // Never actually 2.8 in practice
|
||||
// Typical device decoding gammas (only use for emulating devices):
|
||||
// CRT/LCD reference gammas are higher than NTSC and Rec.709 video standard
|
||||
// gammas: The standards purposely undercorrected for an analog CRT's
|
||||
// assumed 2.5 reference display gamma to maintain contrast in assumed
|
||||
// [dark] viewing conditions: http://www.poynton.com/PDFs/GammaFAQ.pdf
|
||||
// These unstated assumptions about display gamma and perceptual rendering
|
||||
// intent caused a lot of confusion, and more modern CRT's seemed to target
|
||||
// NTSC 2.2 gamma with circuitry. LCD displays seem to have followed suit
|
||||
// (they struggle near black with 2.5 gamma anyway), especially PC/laptop
|
||||
// displays designed to view sRGB in bright environments. (Standards are
|
||||
// also in flux again with BT.1886, but it's underspecified for displays.)
|
||||
static const float crt_reference_gamma_high = 2.5; // In (2.35, 2.55)
|
||||
static const float crt_reference_gamma_low = 2.35; // In (2.35, 2.55)
|
||||
static const float lcd_reference_gamma = 2.5; // To match CRT
|
||||
static const float crt_office_gamma = 2.2; // Circuitry-adjusted for NTSC
|
||||
static const float lcd_office_gamma = 2.2; // Approximates sRGB
|
||||
#endif // OVERRIDE_STANDARD_GAMMA
|
||||
|
||||
// Assuming alpha == 1.0 might make it easier for users to avoid some bugs,
|
||||
// but only if they're aware of it.
|
||||
#ifndef OVERRIDE_ALPHA_ASSUMPTIONS
|
||||
static const bool assume_opaque_alpha = false;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////// DERIVED CONSTANTS AS FUNCTIONS ///////////////////////
|
||||
|
||||
// gamma-management.h should be compatible with overriding gamma values with
|
||||
// runtime user parameters, but we can only define other global constants in
|
||||
// terms of static constants, not uniform user parameters. To get around this
|
||||
// limitation, we need to define derived constants using functions.
|
||||
|
||||
// Set device gamma constants, but allow users to override them:
|
||||
#if _OVERRIDE_DEVICE_GAMMA
|
||||
// The user promises to globally define the appropriate constants:
|
||||
float get_crt_gamma() { return crt_gamma; }
|
||||
float get_gba_gamma() { return gba_gamma; }
|
||||
float get_lcd_gamma() { return lcd_gamma; }
|
||||
#else
|
||||
float get_crt_gamma() { return crt_reference_gamma_high; }
|
||||
float get_gba_gamma() { return 3.5; } // Game Boy Advance; in (3.0, 4.0)
|
||||
float get_lcd_gamma() { return lcd_office_gamma; }
|
||||
#endif // _OVERRIDE_DEVICE_GAMMA
|
||||
|
||||
// Set decoding/encoding gammas for the first/lass passes, but allow overrides:
|
||||
#ifdef OVERRIDE_FINAL_GAMMA
|
||||
// The user promises to globally define the appropriate constants:
|
||||
float get_intermediate_gamma() { return intermediate_gamma; }
|
||||
float get_input_gamma() { return input_gamma; }
|
||||
float get_output_gamma() { return output_gamma; }
|
||||
#else
|
||||
// If we gamma-correct every pass, always use ntsc_gamma between passes to
|
||||
// ensure middle passes don't need to care if anything is being simulated:
|
||||
|
||||
// TODO: Figure out the correct way to configure this now that intermediate
|
||||
// FBOs all use get_intermediate_gamma() directly. Also refer to the
|
||||
// original code to confirm when a shader uses ntsc_gamma despite
|
||||
// GAMMA_ENCODE_EVERY_FBO being undefined.
|
||||
// float get_intermediate_gamma() { return ntsc_gamma; }
|
||||
float get_intermediate_gamma() { return 1.0; }
|
||||
|
||||
#if GAMMA_SIMULATION_MODE == _SIMULATE_CRT_ON_LCD
|
||||
float get_input_gamma() { return get_crt_gamma(); }
|
||||
float get_output_gamma() { return get_lcd_gamma(); }
|
||||
#else
|
||||
#if GAMMA_SIMULATION_MODE == _SIMULATE_GBA_ON_LCD
|
||||
float get_input_gamma() { return get_gba_gamma(); }
|
||||
float get_output_gamma() { return get_lcd_gamma(); }
|
||||
#else
|
||||
#if GAMMA_SIMULATION_MODE == _SIMULATE_LCD_ON_CRT
|
||||
float get_input_gamma() { return get_lcd_gamma(); }
|
||||
float get_output_gamma() { return get_crt_gamma(); }
|
||||
#else
|
||||
#if GAMMA_SIMULATION_MODE == _SIMULATE_GBA_ON_CRT
|
||||
float get_input_gamma() { return get_gba_gamma(); }
|
||||
float get_output_gamma() { return get_crt_gamma(); }
|
||||
#else // Don't simulate anything:
|
||||
float get_input_gamma() { return ntsc_gamma; }
|
||||
float get_output_gamma() { return ntsc_gamma; }
|
||||
#endif // _SIMULATE_GBA_ON_CRT
|
||||
#endif // _SIMULATE_LCD_ON_CRT
|
||||
#endif // _SIMULATE_GBA_ON_LCD
|
||||
#endif // _SIMULATE_CRT_ON_LCD
|
||||
#endif // OVERRIDE_FINAL_GAMMA
|
||||
|
||||
|
||||
// Set decoding/encoding gammas for the current pass. Use static constants for
|
||||
// linearize_input and gamma_encode_output, because they aren't derived, and
|
||||
// they let the compiler do dead-code elimination.
|
||||
// #ifndef GAMMA_ENCODE_EVERY_FBO
|
||||
// #ifdef FIRST_PASS
|
||||
// static const bool linearize_input = true;
|
||||
// float get_pass_input_gamma() { return get_input_gamma(); }
|
||||
// #else
|
||||
// static const bool linearize_input = false;
|
||||
// float get_pass_input_gamma() { return 1.0; }
|
||||
// #endif
|
||||
// #ifdef LAST_PASS
|
||||
// static const bool gamma_encode_output = true;
|
||||
// float get_pass_output_gamma() { return get_output_gamma(); }
|
||||
// #else
|
||||
// static const bool gamma_encode_output = false;
|
||||
// float get_pass_output_gamma() { return 1.0; }
|
||||
// #endif
|
||||
// #else
|
||||
// static const bool linearize_input = true;
|
||||
// static const bool gamma_encode_output = true;
|
||||
// #ifdef FIRST_PASS
|
||||
// float get_pass_input_gamma() { return get_input_gamma(); }
|
||||
// #else
|
||||
// float get_pass_input_gamma() { return get_intermediate_gamma(); }
|
||||
// #endif
|
||||
// #ifdef LAST_PASS
|
||||
// float get_pass_output_gamma() { return get_output_gamma(); }
|
||||
// #else
|
||||
// float get_pass_output_gamma() { return get_intermediate_gamma(); }
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// Users might want to know if bilinear filtering will be gamma-correct:
|
||||
// static const bool gamma_aware_bilinear = !linearize_input;
|
||||
|
||||
|
||||
////////////////////// COLOR ENCODING/DECODING FUNCTIONS /////////////////////
|
||||
|
||||
float4 encode_output_opaque(const float4 color, const float gamma)
|
||||
{
|
||||
static const float3 g = 1.0 / float3(gamma, gamma, gamma);
|
||||
return float4(pow(color.rgb, g), 1);
|
||||
}
|
||||
|
||||
float4 decode_input_opaque(const float4 color, const float gamma)
|
||||
{
|
||||
static const float3 g = float3(gamma, gamma, gamma);
|
||||
return float4(pow(color.rgb, g), 1);
|
||||
}
|
||||
|
||||
float4 encode_output(const float4 color, const float gamma)
|
||||
{
|
||||
static const float3 g = 1.0 / float3(gamma, gamma, gamma);
|
||||
return float4(pow(color.rgb, g), color.a);
|
||||
}
|
||||
|
||||
float4 decode_input(const float4 color, const float gamma)
|
||||
{
|
||||
static const float3 g = float3(gamma, gamma, gamma);
|
||||
return float4(pow(color.rgb, g), color.a);
|
||||
}
|
||||
|
||||
/////////////////////////// TEXTURE LOOKUP WRAPPERS //////////////////////////
|
||||
|
||||
// "SMART" LINEARIZING TEXTURE LOOKUP FUNCTIONS:
|
||||
// Provide a wide array of linearizing texture lookup wrapper functions. The
|
||||
// Cg shader spec Retroarch uses only allows for 2D textures, but 1D and 3D
|
||||
// lookups are provided for completeness in case that changes someday. Nobody
|
||||
// is likely to use the *fetch and *proj functions, but they're included just
|
||||
// in case. The only tex*D texture sampling functions omitted are:
|
||||
// - tex*Dcmpbias
|
||||
// - tex*Dcmplod
|
||||
// - tex*DARRAY*
|
||||
// - tex*DMS*
|
||||
// - Variants returning integers
|
||||
// Standard line length restrictions are ignored below for vertical brevity.
|
||||
|
||||
// tex2D:
|
||||
float4 tex2D_linearize(const sampler2D tex, const float2 tex_coords, const float gamma)
|
||||
{ return decode_input(tex2D(tex, tex_coords), gamma); }
|
||||
|
||||
float4 tex2D_linearize(const sampler2D tex, const float3 tex_coords, const float gamma)
|
||||
{ return decode_input(tex2D(tex, tex_coords.xy), gamma); }
|
||||
|
||||
// float4 tex2D_linearize(const sampler2D tex, const float2 tex_coords, const int texel_off, const float gamma)
|
||||
// { return decode_input(tex2Dlod(tex, float4(tex_coords.x, tex_coords.y, 0, 0), texel_off), gamma); }
|
||||
|
||||
// float4 tex2D_linearize(const sampler2D tex, const float3 tex_coords, const int texel_off, const float gamma)
|
||||
// { return decode_input(tex2Dlod(tex, float4(tex_coords.x, tex_coords.y, 0, 0), texel_off), gamma); }
|
||||
|
||||
// tex2Dlod:
|
||||
float4 tex2Dlod_linearize(const sampler2D tex, const float2 tex_coords, const float gamma)
|
||||
{ return decode_input(tex2Dlod(tex, float4(tex_coords, 0, 0), 0.0), gamma); }
|
||||
|
||||
float4 tex2Dlod_linearize(const sampler2D tex, const float4 tex_coords, const float gamma)
|
||||
{ return decode_input(tex2Dlod(tex, float4(tex_coords.xy, 0, 0), 0.0), gamma); }
|
||||
|
||||
// float4 tex2Dlod_linearize(const sampler2D tex, const float4 tex_coords, const int texel_off, const float gamma)
|
||||
// { return decode_input(tex2Dlod(tex, float4(tex_coords.x, tex_coords.y, 0, 0), texel_off), gamma); }
|
||||
|
||||
#endif // _GAMMA_MANAGEMENT_H
|
||||
@@ -1,715 +0,0 @@
|
||||
#ifndef _GEOMETRY_FUNCTIONS_H
|
||||
#define _GEOMETRY_FUNCTIONS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
// Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
////////////////////////////////// INCLUDES //////////////////////////////////
|
||||
|
||||
#include "user-settings.fxh"
|
||||
#include "derived-settings-and-constants.fxh"
|
||||
#include "bind-shader-params.fxh"
|
||||
|
||||
|
||||
//////////////////////////// MACROS AND CONSTANTS ////////////////////////////
|
||||
|
||||
// Curvature-related constants:
|
||||
#define MAX_POINT_CLOUD_SIZE 9
|
||||
|
||||
|
||||
///////////////////////////// CURVATURE FUNCTIONS /////////////////////////////
|
||||
|
||||
float2 quadratic_solve(const float a, const float b_over_2, const float c)
|
||||
{
|
||||
// Requires: 1.) a, b, and c are quadratic formula coefficients
|
||||
// 2.) b_over_2 = b/2.0 (simplifies terms to factor 2 out)
|
||||
// 3.) b_over_2 must be guaranteed < 0.0 (avoids a branch)
|
||||
// Returns: Returns float2(first_solution, discriminant), so the caller
|
||||
// can choose how to handle the "no intersection" case. The
|
||||
// Kahan or Citardauq formula is used for numerical robustness.
|
||||
const float discriminant = b_over_2*b_over_2 - a*c;
|
||||
const float solution0 = c/(-b_over_2 + sqrt(discriminant));
|
||||
return float2(solution0, discriminant);
|
||||
}
|
||||
|
||||
float2 intersect_sphere(const float3 view_vec, const float3 eye_pos_vec)
|
||||
{
|
||||
// Requires: 1.) view_vec and eye_pos_vec are 3D vectors in the sphere's
|
||||
// local coordinate frame (eye_pos_vec is a position, i.e.
|
||||
// a vector from the origin to the eye/camera)
|
||||
// 2.) geom_radius is a global containing the sphere's radius
|
||||
// Returns: Cast a ray of direction view_vec from eye_pos_vec at a
|
||||
// sphere of radius geom_radius, and return the distance to
|
||||
// the first intersection in units of length(view_vec).
|
||||
// http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
|
||||
// Quadratic formula coefficients (b_over_2 is guaranteed negative):
|
||||
const float a = dot(view_vec, view_vec);
|
||||
const float b_over_2 = dot(view_vec, eye_pos_vec); // * 2.0 factored out
|
||||
const float c = dot(eye_pos_vec, eye_pos_vec) - geom_radius*geom_radius;
|
||||
return quadratic_solve(a, b_over_2, c);
|
||||
}
|
||||
|
||||
float2 intersect_cylinder(const float3 view_vec, const float3 eye_pos_vec)
|
||||
{
|
||||
// Requires: 1.) view_vec and eye_pos_vec are 3D vectors in the sphere's
|
||||
// local coordinate frame (eye_pos_vec is a position, i.e.
|
||||
// a vector from the origin to the eye/camera)
|
||||
// 2.) geom_radius is a global containing the cylinder's radius
|
||||
// Returns: Cast a ray of direction view_vec from eye_pos_vec at a
|
||||
// cylinder of radius geom_radius, and return the distance to
|
||||
// the first intersection in units of length(view_vec). The
|
||||
// derivation of the coefficients is in Christer Ericson's
|
||||
// Real-Time Collision Detection, p. 195-196, and this version
|
||||
// uses LaGrange's identity to reduce operations.
|
||||
// Arbitrary "cylinder top" reference point for an infinite cylinder:
|
||||
const float3 cylinder_top_vec = float3(0.0, geom_radius, 0.0);
|
||||
const float3 cylinder_axis_vec = float3(0.0, 1.0, 0.0);//float3(0.0, 2.0*geom_radius, 0.0);
|
||||
const float3 top_to_eye_vec = eye_pos_vec - cylinder_top_vec;
|
||||
const float3 axis_x_view = cross(cylinder_axis_vec, view_vec);
|
||||
const float3 axis_x_top_to_eye = cross(cylinder_axis_vec, top_to_eye_vec);
|
||||
// Quadratic formula coefficients (b_over_2 is guaranteed negative):
|
||||
const float a = dot(axis_x_view, axis_x_view);
|
||||
const float b_over_2 = dot(axis_x_top_to_eye, axis_x_view);
|
||||
const float c = dot(axis_x_top_to_eye, axis_x_top_to_eye) -
|
||||
geom_radius*geom_radius;//*dot(cylinder_axis_vec, cylinder_axis_vec);
|
||||
return quadratic_solve(a, b_over_2, c);
|
||||
}
|
||||
|
||||
float2 cylinder_xyz_to_uv(const float3 intersection_pos_local,
|
||||
const float2 geom_aspect)
|
||||
{
|
||||
// Requires: An xyz intersection position on a cylinder.
|
||||
// Returns: video_uv coords mapped to range [-0.5, 0.5]
|
||||
// Mapping: Define square_uv.x to be the signed arc length in xz-space,
|
||||
// and define square_uv.y = -intersection_pos_local.y (+v = -y).
|
||||
// Start with a numerically robust arc length calculation.
|
||||
const float angle_from_image_center = atan2(intersection_pos_local.x,
|
||||
intersection_pos_local.z);
|
||||
const float signed_arc_len = angle_from_image_center * geom_radius;
|
||||
// Get a uv-mapping where [-0.5, 0.5] maps to a "square" area, then divide
|
||||
// by the aspect ratio to stretch the mapping appropriately:
|
||||
const float2 square_uv = float2(signed_arc_len, -intersection_pos_local.y);
|
||||
const float2 video_uv = square_uv / geom_aspect;
|
||||
return video_uv;
|
||||
}
|
||||
|
||||
float3 cylinder_uv_to_xyz(const float2 video_uv, const float2 geom_aspect)
|
||||
{
|
||||
// Requires: video_uv coords mapped to range [-0.5, 0.5]
|
||||
// Returns: An xyz intersection position on a cylinder. This is the
|
||||
// inverse of cylinder_xyz_to_uv().
|
||||
// Expand video_uv by the aspect ratio to get proportionate x/y lengths,
|
||||
// then calculate an xyz position for the cylindrical mapping above.
|
||||
const float2 square_uv = video_uv * geom_aspect;
|
||||
const float arc_len = square_uv.x;
|
||||
const float angle_from_image_center = arc_len / geom_radius;
|
||||
const float x_pos = sin(angle_from_image_center) * geom_radius;
|
||||
const float z_pos = cos(angle_from_image_center) * geom_radius;
|
||||
// Or: z = sqrt(geom_radius**2 - x**2)
|
||||
// Or: z = geom_radius/sqrt(1.0 + tan(angle)**2), x = z * tan(angle)
|
||||
const float3 intersection_pos_local = float3(x_pos, -square_uv.y, z_pos);
|
||||
return intersection_pos_local;
|
||||
}
|
||||
|
||||
float2 sphere_xyz_to_uv(const float3 intersection_pos_local,
|
||||
const float2 geom_aspect)
|
||||
{
|
||||
// Requires: An xyz intersection position on a sphere.
|
||||
// Returns: video_uv coords mapped to range [-0.5, 0.5]
|
||||
// Mapping: First define square_uv.x/square_uv.y ==
|
||||
// intersection_pos_local.x/intersection_pos_local.y. Then,
|
||||
// length(square_uv) is the arc length from the image center
|
||||
// at (0.0, 0.0, geom_radius) along the tangent great circle.
|
||||
// Credit for this mapping goes to cgwg: I never managed to
|
||||
// understand his code, but he told me his mapping was based on
|
||||
// great circle distances when I asked him about it, which
|
||||
// informed this very similar (almost identical) mapping.
|
||||
// Start with a numerically robust arc length calculation between the ray-
|
||||
// sphere intersection point and the image center using a method posted by
|
||||
// Roger Stafford on comp.soft-sys.matlab:
|
||||
// https://groups.google.com/d/msg/comp.soft-sys.matlab/zNbUui3bjcA/c0HV_bHSx9cJ
|
||||
const float3 image_center_pos_local = float3(0.0, 0.0, geom_radius);
|
||||
const float cp_len =
|
||||
length(cross(intersection_pos_local, image_center_pos_local));
|
||||
const float dp = dot(intersection_pos_local, image_center_pos_local);
|
||||
const float angle_from_image_center = atan2(cp_len, dp);
|
||||
const float arc_len = angle_from_image_center * geom_radius;
|
||||
// Get a uv-mapping where [-0.5, 0.5] maps to a "square" area, then divide
|
||||
// by the aspect ratio to stretch the mapping appropriately:
|
||||
const float2 square_uv_unit = normalize(float2(intersection_pos_local.x,
|
||||
-intersection_pos_local.y));
|
||||
const float2 square_uv = arc_len * square_uv_unit;
|
||||
const float2 video_uv = square_uv / geom_aspect;
|
||||
return video_uv;
|
||||
}
|
||||
|
||||
float3 sphere_uv_to_xyz(const float2 video_uv, const float2 geom_aspect)
|
||||
{
|
||||
// Requires: video_uv coords mapped to range [-0.5, 0.5]
|
||||
// Returns: An xyz intersection position on a sphere. This is the
|
||||
// inverse of sphere_xyz_to_uv().
|
||||
// Expand video_uv by the aspect ratio to get proportionate x/y lengths,
|
||||
// then calculate an xyz position for the spherical mapping above.
|
||||
if (video_uv.x != 0 && video_uv.y != 0) {
|
||||
const float2 square_uv = video_uv * geom_aspect;
|
||||
// Using length or sqrt here butchers the framerate on my 8800GTS if
|
||||
// this function is called too many times, and so does taking the max
|
||||
// component of square_uv/square_uv_unit (program length threshold?).
|
||||
//float arc_len = length(square_uv);
|
||||
const float2 square_uv_unit = normalize(square_uv);
|
||||
const float arc_len = square_uv.y/square_uv_unit.y;
|
||||
const float angle_from_image_center = arc_len / geom_radius;
|
||||
const float xy_dist_from_sphere_center =
|
||||
sin(angle_from_image_center) * geom_radius;
|
||||
//float2 xy_pos = xy_dist_from_sphere_center * (square_uv/FIX_ZERO(arc_len));
|
||||
const float2 xy_pos = xy_dist_from_sphere_center * square_uv_unit;
|
||||
const float z_pos = cos(angle_from_image_center) * geom_radius;
|
||||
const float3 intersection_pos_local = float3(xy_pos.x, -xy_pos.y, z_pos);
|
||||
return intersection_pos_local;
|
||||
}
|
||||
else if (video_uv.x != 0) {
|
||||
const float2 square_uv = video_uv * geom_aspect;
|
||||
// Using length or sqrt here butchers the framerate on my 8800GTS if
|
||||
// this function is called too many times, and so does taking the max
|
||||
// component of square_uv/square_uv_unit (program length threshold?).
|
||||
//float arc_len = length(square_uv);
|
||||
const float2 square_uv_unit = normalize(square_uv);
|
||||
const float angle_from_image_center = 0;
|
||||
const float xy_dist_from_sphere_center = sin(angle_from_image_center) * geom_radius;
|
||||
const float2 xy_pos = xy_dist_from_sphere_center * square_uv_unit;
|
||||
const float z_pos = cos(angle_from_image_center) * geom_radius;
|
||||
const float3 intersection_pos_local = float3(xy_pos.x, -xy_pos.y, z_pos);
|
||||
return intersection_pos_local;
|
||||
}
|
||||
else {
|
||||
const float2 xy_pos = float2(0, 0);
|
||||
const float z_pos = geom_radius;
|
||||
const float3 intersection_pos_local = float3(xy_pos.x, -xy_pos.y, z_pos);
|
||||
return intersection_pos_local;
|
||||
}
|
||||
}
|
||||
|
||||
float2 sphere_alt_xyz_to_uv(const float3 intersection_pos_local,
|
||||
const float2 geom_aspect)
|
||||
{
|
||||
// Requires: An xyz intersection position on a cylinder.
|
||||
// Returns: video_uv coords mapped to range [-0.5, 0.5]
|
||||
// Mapping: Define square_uv.x to be the signed arc length in xz-space,
|
||||
// and define square_uv.y == signed arc length in yz-space.
|
||||
// See cylinder_xyz_to_uv() for implementation details (very similar).
|
||||
const float2 angle_from_image_center = atan2(
|
||||
float2(intersection_pos_local.x, -intersection_pos_local.y),
|
||||
intersection_pos_local.zz);
|
||||
const float2 signed_arc_len = angle_from_image_center * geom_radius;
|
||||
const float2 video_uv = signed_arc_len / geom_aspect;
|
||||
return video_uv;
|
||||
}
|
||||
|
||||
float3 sphere_alt_uv_to_xyz(const float2 video_uv, const float2 geom_aspect)
|
||||
{
|
||||
// Requires: video_uv coords mapped to range [-0.5, 0.5]
|
||||
// Returns: An xyz intersection position on a sphere. This is the
|
||||
// inverse of sphere_alt_xyz_to_uv().
|
||||
// See cylinder_uv_to_xyz() for implementation details (very similar).
|
||||
const float2 square_uv = video_uv * geom_aspect;
|
||||
const float2 arc_len = square_uv;
|
||||
const float2 angle_from_image_center = arc_len / geom_radius;
|
||||
const float2 xy_pos = sin(angle_from_image_center) * geom_radius;
|
||||
const float z_pos = sqrt(geom_radius*geom_radius - dot(xy_pos, xy_pos));
|
||||
return float3(xy_pos.x, -xy_pos.y, z_pos);
|
||||
}
|
||||
|
||||
float2 intersect(const float3 view_vec_local, const float3 eye_pos_local,
|
||||
const float geom_mode)
|
||||
{
|
||||
return geom_mode < 2.5 ? intersect_sphere(view_vec_local, eye_pos_local) :
|
||||
intersect_cylinder(view_vec_local, eye_pos_local);
|
||||
}
|
||||
|
||||
float2 xyz_to_uv(const float3 intersection_pos_local,
|
||||
const float2 geom_aspect, const float geom_mode)
|
||||
{
|
||||
return geom_mode < 1.5 ?
|
||||
sphere_xyz_to_uv(intersection_pos_local, geom_aspect) :
|
||||
geom_mode < 2.5 ?
|
||||
sphere_alt_xyz_to_uv(intersection_pos_local, geom_aspect) :
|
||||
cylinder_xyz_to_uv(intersection_pos_local, geom_aspect);
|
||||
}
|
||||
|
||||
float3 uv_to_xyz(const float2 uv, const float2 geom_aspect,
|
||||
const float geom_mode)
|
||||
{
|
||||
return geom_mode < 1.5 ? sphere_uv_to_xyz(uv, geom_aspect) :
|
||||
geom_mode < 2.5 ? sphere_alt_uv_to_xyz(uv, geom_aspect) :
|
||||
cylinder_uv_to_xyz(uv, geom_aspect);
|
||||
}
|
||||
|
||||
float2 view_vec_to_uv(const float3 view_vec_local, const float3 eye_pos_local,
|
||||
const float2 geom_aspect, const float geom_mode, out float3 intersection_pos)
|
||||
{
|
||||
// Get the intersection point on the primitive, given an eye position
|
||||
// and view vector already in its local coordinate frame:
|
||||
const float2 intersect_dist_and_discriminant = intersect(view_vec_local,
|
||||
eye_pos_local, geom_mode);
|
||||
const float3 intersection_pos_local = eye_pos_local +
|
||||
view_vec_local * intersect_dist_and_discriminant.x;
|
||||
// Save the intersection position to an output parameter:
|
||||
intersection_pos = intersection_pos_local;
|
||||
// Transform into uv coords, but give out-of-range coords if the
|
||||
// view ray doesn't intersect the primitive in the first place:
|
||||
return intersect_dist_and_discriminant.y > 0.005 ?
|
||||
xyz_to_uv(intersection_pos_local, geom_aspect, geom_mode) : float2(1.0, 1.0);
|
||||
}
|
||||
|
||||
float3 get_ideal_global_eye_pos_for_points(float3 eye_pos,
|
||||
const float2 geom_aspect, const float3 global_coords[MAX_POINT_CLOUD_SIZE],
|
||||
const int num_points)
|
||||
{
|
||||
// Requires: Parameters:
|
||||
// 1.) Starting eye_pos is a global 3D position at which the
|
||||
// camera contains all points in global_coords[] in its FOV
|
||||
// 2.) geom_aspect = get_aspect_vector(
|
||||
// IN.output_size.x / IN.output_size.y);
|
||||
// 3.) global_coords is a point cloud containing global xyz
|
||||
// coords of extreme points on the simulated CRT screen.
|
||||
// Globals:
|
||||
// 1.) geom_view_dist must be > 0.0. It controls the "near
|
||||
// plane" used to interpret flat_video_uv as a view
|
||||
// vector, which controls the field of view (FOV).
|
||||
// Eyespace coordinate frame: +x = right, +y = up, +z = back
|
||||
// Returns: Return an eye position at which the point cloud spans as
|
||||
// much of the screen as possible (given the FOV controlled by
|
||||
// geom_view_dist) without being cropped or sheared.
|
||||
// Algorithm:
|
||||
// 1.) Move the eye laterally to a point which attempts to maximize the
|
||||
// the amount we can move forward without clipping the CRT screen.
|
||||
// 2.) Move forward by as much as possible without clipping the CRT.
|
||||
// Get the allowed movement range by solving for the eye_pos offsets
|
||||
// that result in each point being projected to a screen edge/corner in
|
||||
// pseudo-normalized device coords (where xy ranges from [-0.5, 0.5]
|
||||
// and z = eyespace z):
|
||||
// pndc_coord = float3(float2(eyespace_xyz.x, -eyespace_xyz.y)*
|
||||
// geom_view_dist / (geom_aspect * -eyespace_xyz.z), eyespace_xyz.z);
|
||||
// Notes:
|
||||
// The field of view is controlled by geom_view_dist's magnitude relative to
|
||||
// the view vector's x and y components:
|
||||
// view_vec.xy ranges from [-0.5, 0.5] * geom_aspect
|
||||
// view_vec.z = -geom_view_dist
|
||||
// But for the purposes of perspective divide, it should be considered:
|
||||
// view_vec.xy ranges from [-0.5, 0.5] * geom_aspect / geom_view_dist
|
||||
// view_vec.z = -1.0
|
||||
static const int max_centering_iters = 1; // Keep for easy testing.
|
||||
for(int iter = 0; iter < max_centering_iters; iter++)
|
||||
{
|
||||
// 0.) Get the eyespace coordinates of our point cloud:
|
||||
float3 eyespace_coords[MAX_POINT_CLOUD_SIZE];
|
||||
for(int i = 0; i < num_points; i++)
|
||||
{
|
||||
eyespace_coords[i] = global_coords[i] - eye_pos;
|
||||
}
|
||||
// 1a.)For each point, find out how far we can move eye_pos in each
|
||||
// lateral direction without the point clipping the frustum.
|
||||
// Eyespace +y = up, screenspace +y = down, so flip y after
|
||||
// applying the eyespace offset (on the way to "clip space").
|
||||
// Solve for two offsets per point based on:
|
||||
// (eyespace_xyz.xy - offset_dr) * float2(1.0, -1.0) *
|
||||
// geom_view_dist / (geom_aspect * -eyespace_xyz.z) = float2(-0.5)
|
||||
// (eyespace_xyz.xy - offset_dr) * float2(1.0, -1.0) *
|
||||
// geom_view_dist / (geom_aspect * -eyespace_xyz.z) = float2(0.5)
|
||||
// offset_ul and offset_dr represent the farthest we can move the
|
||||
// eye_pos up-left and down-right. Save the min of all offset_dr's
|
||||
// and the max of all offset_ul's (since it's negative).
|
||||
float abs_radius = abs(geom_radius); // In case anyone gets ideas. ;)
|
||||
float2 offset_dr_min = float2(10.0 * abs_radius, 10.0 * abs_radius);
|
||||
float2 offset_ul_max = float2(-10.0 * abs_radius, -10.0 * abs_radius);
|
||||
for(int i = 0; i < num_points; i++)
|
||||
{
|
||||
static const float2 flipy = float2(1.0, -1.0);
|
||||
float3 eyespace_xyz = eyespace_coords[i];
|
||||
float2 offset_dr = eyespace_xyz.xy - float2(-0.5, -0.5) *
|
||||
(geom_aspect * -eyespace_xyz.z) / (geom_view_dist * flipy);
|
||||
float2 offset_ul = eyespace_xyz.xy - float2(0.5, 0.5) *
|
||||
(geom_aspect * -eyespace_xyz.z) / (geom_view_dist * flipy);
|
||||
offset_dr_min = min(offset_dr_min, offset_dr);
|
||||
offset_ul_max = max(offset_ul_max, offset_ul);
|
||||
}
|
||||
// 1b.)Update eye_pos: Adding the average of offset_ul_max and
|
||||
// offset_dr_min gives it equal leeway on the top vs. bottom
|
||||
// and left vs. right. Recalculate eyespace_coords accordingly.
|
||||
float2 center_offset = 0.5 * (offset_ul_max + offset_dr_min);
|
||||
eye_pos.xy += center_offset;
|
||||
for(int i = 0; i < num_points; i++)
|
||||
{
|
||||
eyespace_coords[i] = global_coords[i] - eye_pos;
|
||||
}
|
||||
// 2a.)For each point, find out how far we can move eye_pos forward
|
||||
// without the point clipping the frustum. Flip the y
|
||||
// direction in advance (matters for a later step, not here).
|
||||
// Solve for four offsets per point based on:
|
||||
// eyespace_xyz_flipy.x * geom_view_dist /
|
||||
// (geom_aspect.x * (offset_z - eyespace_xyz_flipy.z)) =-0.5
|
||||
// eyespace_xyz_flipy.y * geom_view_dist /
|
||||
// (geom_aspect.y * (offset_z - eyespace_xyz_flipy.z)) =-0.5
|
||||
// eyespace_xyz_flipy.x * geom_view_dist /
|
||||
// (geom_aspect.x * (offset_z - eyespace_xyz_flipy.z)) = 0.5
|
||||
// eyespace_xyz_flipy.y * geom_view_dist /
|
||||
// (geom_aspect.y * (offset_z - eyespace_xyz_flipy.z)) = 0.5
|
||||
// We'll vectorize the actual computation. Take the maximum of
|
||||
// these four for a single offset, and continue taking the max
|
||||
// for every point (use max because offset.z is negative).
|
||||
float offset_z_max = -10.0 * geom_radius * geom_view_dist;
|
||||
for(int i = 0; i < num_points; i++)
|
||||
{
|
||||
float3 eyespace_xyz_flipy = eyespace_coords[i] *
|
||||
float3(1.0, -1.0, 1.0);
|
||||
float4 offset_zzzz = eyespace_xyz_flipy.zzzz +
|
||||
(eyespace_xyz_flipy.xyxy * geom_view_dist) /
|
||||
(float4(-0.5, -0.5, 0.5, 0.5) * float4(geom_aspect, geom_aspect));
|
||||
// Ignore offsets that push positive x/y values to opposite
|
||||
// boundaries, and vice versa, and don't let the camera move
|
||||
// past a point in the dead center of the screen:
|
||||
offset_z_max = (eyespace_xyz_flipy.x < 0.0) ?
|
||||
max(offset_z_max, offset_zzzz.x) : offset_z_max;
|
||||
offset_z_max = (eyespace_xyz_flipy.y < 0.0) ?
|
||||
max(offset_z_max, offset_zzzz.y) : offset_z_max;
|
||||
offset_z_max = (eyespace_xyz_flipy.x > 0.0) ?
|
||||
max(offset_z_max, offset_zzzz.z) : offset_z_max;
|
||||
offset_z_max = (eyespace_xyz_flipy.y > 0.0) ?
|
||||
max(offset_z_max, offset_zzzz.w) : offset_z_max;
|
||||
offset_z_max = max(offset_z_max, eyespace_xyz_flipy.z);
|
||||
}
|
||||
// 2b.)Update eye_pos: Add the maximum (smallest negative) z offset.
|
||||
eye_pos.z += offset_z_max;
|
||||
}
|
||||
return eye_pos;
|
||||
}
|
||||
|
||||
float3 get_ideal_global_eye_pos(const float3x3 local_to_global,
|
||||
const float2 geom_aspect, const float geom_mode)
|
||||
{
|
||||
// Start with an initial eye_pos that includes the entire primitive
|
||||
// (sphere or cylinder) in its field-of-view:
|
||||
const float3 high_view = float3(0.0, geom_aspect.y, -geom_view_dist);
|
||||
const float3 low_view = high_view * float3(1.0, -1.0, 1.0);
|
||||
const float len_sq = dot(high_view, high_view);
|
||||
const float fov = abs(acos(dot(high_view, low_view)/len_sq));
|
||||
// Trigonometry/similar triangles say distance = geom_radius/sin(fov/2):
|
||||
const float eye_z_spherical = geom_radius/sin(fov*0.5);
|
||||
const float3 eye_pos = geom_mode < 2.5 ?
|
||||
float3(0.0, 0.0, eye_z_spherical) :
|
||||
float3(0.0, 0.0, max(geom_view_dist, eye_z_spherical));
|
||||
|
||||
// Get global xyz coords of extreme sample points on the simulated CRT
|
||||
// screen. Start with the center, edge centers, and corners of the
|
||||
// video image. We can't ignore backfacing points: They're occluded
|
||||
// by closer points on the primitive, but they may NOT be occluded by
|
||||
// the convex hull of the remaining samples (i.e. the remaining convex
|
||||
// hull might not envelope points that do occlude a back-facing point.)
|
||||
static const int num_points = MAX_POINT_CLOUD_SIZE;
|
||||
float3 global_coords[MAX_POINT_CLOUD_SIZE];
|
||||
global_coords[0] = mul(local_to_global, uv_to_xyz(float2(0.0, 0.0), geom_aspect, geom_mode));
|
||||
global_coords[1] = mul(local_to_global, uv_to_xyz(float2(0.0, -0.5), geom_aspect, geom_mode));
|
||||
global_coords[2] = mul(local_to_global, uv_to_xyz(float2(0.0, 0.5), geom_aspect, geom_mode));
|
||||
global_coords[3] = mul(local_to_global, uv_to_xyz(float2(-0.5, 0.0), geom_aspect, geom_mode));
|
||||
global_coords[4] = mul(local_to_global, uv_to_xyz(float2(0.5, 0.0), geom_aspect, geom_mode));
|
||||
global_coords[5] = mul(local_to_global, uv_to_xyz(float2(-0.5, -0.5), geom_aspect, geom_mode));
|
||||
global_coords[6] = mul(local_to_global, uv_to_xyz(float2(0.5, -0.5), geom_aspect, geom_mode));
|
||||
global_coords[7] = mul(local_to_global, uv_to_xyz(float2(-0.5, 0.5), geom_aspect, geom_mode));
|
||||
global_coords[8] = mul(local_to_global, uv_to_xyz(float2(0.5, 0.5), geom_aspect, geom_mode));
|
||||
// Adding more inner image points could help in extreme cases, but too many
|
||||
// points will kille the framerate. For safety, default to the initial
|
||||
// eye_pos if any z coords are negative:
|
||||
float num_negative_z_coords = 0.0;
|
||||
for(int i = 0; i < num_points; i++)
|
||||
{
|
||||
num_negative_z_coords += float(global_coords[0].z < 0.0);
|
||||
}
|
||||
// Outsource the optimized eye_pos calculation:
|
||||
return num_negative_z_coords > 0.5 ? eye_pos :
|
||||
get_ideal_global_eye_pos_for_points(eye_pos, geom_aspect,
|
||||
global_coords, num_points);
|
||||
}
|
||||
|
||||
float3x3 get_pixel_to_object_matrix(const float3x3 global_to_local,
|
||||
const float3 eye_pos_local, const float3 view_vec_global,
|
||||
const float3 intersection_pos_local, const float3 normal,
|
||||
const float2 output_size_inv)
|
||||
{
|
||||
// Requires: See get_curved_video_uv_coords_and_tangent_matrix for
|
||||
// descriptions of each parameter.
|
||||
// Returns: Return a transformation matrix from 2D pixel-space vectors
|
||||
// (where (+1.0, +1.0) is a vector to one pixel down-right,
|
||||
// i.e. same directionality as uv texels) to 3D object-space
|
||||
// vectors in the CRT's local coordinate frame (right-handed)
|
||||
// ***which are tangent to the CRT surface at the intersection
|
||||
// position.*** (Basically, we want to convert pixel-space
|
||||
// vectors to 3D vectors along the CRT's surface, for later
|
||||
// conversion to uv vectors.)
|
||||
// Shorthand inputs:
|
||||
const float3 pos = intersection_pos_local;
|
||||
const float3 eye_pos = eye_pos_local;
|
||||
// Get a piecewise-linear matrix transforming from "pixelspace" offset
|
||||
// vectors (1.0 = one pixel) to object space vectors in the tangent
|
||||
// plane (faster than finding 3 view-object intersections).
|
||||
// 1.) Get the local view vecs for the pixels to the right and down:
|
||||
const float3 view_vec_right_global = view_vec_global +
|
||||
float3(output_size_inv.x, 0.0, 0.0);
|
||||
const float3 view_vec_down_global = view_vec_global +
|
||||
float3(0.0, -output_size_inv.y, 0.0);
|
||||
const float3 view_vec_right_local =
|
||||
mul(global_to_local, view_vec_right_global);
|
||||
const float3 view_vec_down_local =
|
||||
mul(global_to_local, view_vec_down_global);
|
||||
// 2.) Using the true intersection point, intersect the neighboring
|
||||
// view vectors with the tangent plane:
|
||||
const float3 intersection_vec_dot_normal = float3(dot(pos - eye_pos, normal), dot(pos - eye_pos, normal), dot(pos - eye_pos, normal));
|
||||
const float3 right_pos = eye_pos + (intersection_vec_dot_normal /
|
||||
dot(view_vec_right_local, normal))*view_vec_right_local;
|
||||
const float3 down_pos = eye_pos + (intersection_vec_dot_normal /
|
||||
dot(view_vec_down_local, normal))*view_vec_down_local;
|
||||
// 3.) Subtract the original intersection pos from its neighbors; the
|
||||
// resulting vectors are object-space vectors tangent to the plane.
|
||||
// These vectors are the object-space transformations of (1.0, 0.0)
|
||||
// and (0.0, 1.0) pixel offsets, so they form the first two basis
|
||||
// vectors of a pixelspace to object space transformation. This
|
||||
// transformation is 2D to 3D, so use (0, 0, 0) for the third vector.
|
||||
const float3 object_right_vec = right_pos - pos;
|
||||
const float3 object_down_vec = down_pos - pos;
|
||||
const float3x3 pixel_to_object = float3x3(
|
||||
object_right_vec.x, object_down_vec.x, 0.0,
|
||||
object_right_vec.y, object_down_vec.y, 0.0,
|
||||
object_right_vec.z, object_down_vec.z, 0.0);
|
||||
return pixel_to_object;
|
||||
}
|
||||
|
||||
float3x3 get_object_to_tangent_matrix(const float3 intersection_pos_local,
|
||||
const float3 normal, const float2 geom_aspect, const float geom_mode)
|
||||
{
|
||||
// Requires: See get_curved_video_uv_coords_and_tangent_matrix for
|
||||
// descriptions of each parameter.
|
||||
// Returns: Return a transformation matrix from 3D object-space vectors
|
||||
// in the CRT's local coordinate frame (right-handed, +y = up)
|
||||
// to 2D video_uv vectors (+v = down).
|
||||
// Description:
|
||||
// The TBN matrix formed by the [tangent, bitangent, normal] basis
|
||||
// vectors transforms ordinary vectors from tangent->object space.
|
||||
// The cotangent matrix formed by the [cotangent, cobitangent, normal]
|
||||
// basis vectors transforms normal vectors (covectors) from
|
||||
// tangent->object space. It's the inverse-transpose of the TBN matrix.
|
||||
// We want the inverse of the TBN matrix (transpose of the cotangent
|
||||
// matrix), which transforms ordinary vectors from object->tangent space.
|
||||
// Start by calculating the relevant basis vectors in accordance with
|
||||
// Christian Schüler's blog post "Followup: Normal Mapping Without
|
||||
// Precomputed Tangents": http://www.thetenthplanet.de/archives/1180
|
||||
// With our particular uv mapping, the scale of the u and v directions
|
||||
// is determined entirely by the aspect ratio for cylindrical and ordinary
|
||||
// spherical mappings, and so tangent and bitangent lengths are also
|
||||
// determined by it (the alternate mapping is more complex). Therefore, we
|
||||
// must ensure appropriate cotangent and cobitangent lengths as well.
|
||||
// Base these off the uv<=>xyz mappings for each primitive.
|
||||
const float3 pos = intersection_pos_local;
|
||||
static const float3 x_vec = float3(1.0, 0.0, 0.0);
|
||||
static const float3 y_vec = float3(0.0, 1.0, 0.0);
|
||||
// The tangent and bitangent vectors correspond with increasing u and v,
|
||||
// respectively. Mathematically we'd base the cotangent/cobitangent on
|
||||
// those, but we'll compute the cotangent/cobitangent directly when we can.
|
||||
float3 cotangent_unscaled, cobitangent_unscaled;
|
||||
// geom_mode should be constant-folded without _RUNTIME_GEOMETRY_MODE.
|
||||
if(geom_mode < 1.5)
|
||||
{
|
||||
// Sphere:
|
||||
// tangent = normalize(cross(normal, cross(x_vec, pos))) * geom_aspect.x
|
||||
// bitangent = normalize(cross(cross(y_vec, pos), normal)) * geom_aspect.y
|
||||
// inv_determinant = 1.0/length(cross(bitangent, tangent))
|
||||
// cotangent = cross(normal, bitangent) * inv_determinant
|
||||
// == normalize(cross(y_vec, pos)) * geom_aspect.y * inv_determinant
|
||||
// cobitangent = cross(tangent, normal) * inv_determinant
|
||||
// == normalize(cross(x_vec, pos)) * geom_aspect.x * inv_determinant
|
||||
// Simplified (scale by inv_determinant below):
|
||||
cotangent_unscaled = normalize(cross(y_vec, pos)) * geom_aspect.y;
|
||||
cobitangent_unscaled = normalize(cross(x_vec, pos)) * geom_aspect.x;
|
||||
}
|
||||
else if(geom_mode < 2.5)
|
||||
{
|
||||
// Sphere, alternate mapping:
|
||||
// This mapping works a bit like the cylindrical mapping in two
|
||||
// directions, which makes the lengths and directions more complex.
|
||||
// Unfortunately, I can't find much of a shortcut:
|
||||
const float3 tangent = normalize(
|
||||
cross(y_vec, float3(pos.x, 0.0, pos.z))) * geom_aspect.x;
|
||||
const float3 bitangent = normalize(
|
||||
cross(x_vec, float3(0.0, pos.yz))) * geom_aspect.y;
|
||||
cotangent_unscaled = cross(normal, bitangent);
|
||||
cobitangent_unscaled = cross(tangent, normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cylinder:
|
||||
// tangent = normalize(cross(y_vec, normal)) * geom_aspect.x;
|
||||
// bitangent = float3(0.0, -geom_aspect.y, 0.0);
|
||||
// inv_determinant = 1.0/length(cross(bitangent, tangent))
|
||||
// cotangent = cross(normal, bitangent) * inv_determinant
|
||||
// == normalize(cross(y_vec, pos)) * geom_aspect.y * inv_determinant
|
||||
// cobitangent = cross(tangent, normal) * inv_determinant
|
||||
// == float3(0.0, -geom_aspect.x, 0.0) * inv_determinant
|
||||
cotangent_unscaled = cross(y_vec, normal) * geom_aspect.y;
|
||||
cobitangent_unscaled = float3(0.0, -geom_aspect.x, 0.0);
|
||||
}
|
||||
const float3 computed_normal =
|
||||
cross(cobitangent_unscaled, cotangent_unscaled);
|
||||
const float inv_determinant = rsqrt(dot(computed_normal, computed_normal));
|
||||
const float3 cotangent = cotangent_unscaled * inv_determinant;
|
||||
const float3 cobitangent = cobitangent_unscaled * inv_determinant;
|
||||
// The [cotangent, cobitangent, normal] column vecs form the cotangent
|
||||
// frame, i.e. the inverse-transpose TBN matrix. Get its transpose:
|
||||
const float3x3 object_to_tangent = float3x3(cotangent, cobitangent, normal);
|
||||
return object_to_tangent;
|
||||
}
|
||||
|
||||
float2 get_curved_video_uv_coords_and_tangent_matrix(
|
||||
const float2 flat_video_uv, const float3 eye_pos_local,
|
||||
const float2 output_size_inv, const float2 geom_aspect,
|
||||
const float geom_mode, const float3x3 global_to_local,
|
||||
out float2x2 pixel_to_tangent_video_uv)
|
||||
{
|
||||
// Requires: Parameters:
|
||||
// 1.) flat_video_uv coords are in range [0.0, 1.0], where
|
||||
// (0.0, 0.0) is the top-left corner of the screen and
|
||||
// (1.0, 1.0) is the bottom-right corner.
|
||||
// 2.) eye_pos_local is the 3D camera position in the simulated
|
||||
// CRT's local coordinate frame. For best results, it must
|
||||
// be computed based on the same geom_view_dist used here.
|
||||
// 3.) output_size_inv = float2(1.0)/IN.output_size
|
||||
// 4.) geom_aspect = get_aspect_vector(
|
||||
// IN.output_size.x / IN.output_size.y);
|
||||
// 5.) geom_mode is a static or runtime mode setting:
|
||||
// 0 = off, 1 = sphere, 2 = sphere alt., 3 = cylinder
|
||||
// 6.) global_to_local is a 3x3 matrix transforming (ordinary)
|
||||
// worldspace vectors to the CRT's local coordinate frame
|
||||
// Globals:
|
||||
// 1.) geom_view_dist must be > 0.0. It controls the "near
|
||||
// plane" used to interpret flat_video_uv as a view
|
||||
// vector, which controls the field of view (FOV).
|
||||
// Returns: Return final uv coords in [0.0, 1.0], and return a pixel-
|
||||
// space to video_uv tangent-space matrix in the out parameter.
|
||||
// (This matrix assumes pixel-space +y = down, like +v = down.)
|
||||
// We'll transform flat_video_uv into a view vector, project
|
||||
// the view vector from the camera/eye, intersect with a sphere
|
||||
// or cylinder representing the simulated CRT, and convert the
|
||||
// intersection position into final uv coords and a local
|
||||
// transformation matrix.
|
||||
// First get the 3D view vector (geom_aspect and geom_view_dist are globals):
|
||||
// 1.) Center uv around (0.0, 0.0) and make (-0.5, -0.5) and (0.5, 0.5)
|
||||
// correspond to the top-left/bottom-right output screen corners.
|
||||
// 2.) Multiply by geom_aspect to preemptively "undo" Retroarch's screen-
|
||||
// space 2D aspect correction. We'll reapply it in uv-space.
|
||||
// 3.) (x, y) = (u, -v), because +v is down in 2D screenspace, but +y
|
||||
// is up in 3D worldspace (enforce a right-handed system).
|
||||
// 4.) The view vector z controls the "near plane" distance and FOV.
|
||||
// For the effect of "looking through a window" at a CRT, it should be
|
||||
// set equal to the user's distance from their physical screen, in
|
||||
// units of the viewport's physical diagonal size.
|
||||
const float2 view_uv = (flat_video_uv - float2(0.5, 0.5)) * geom_aspect;
|
||||
const float3 view_vec_global =
|
||||
float3(view_uv.x, -view_uv.y, -geom_view_dist);
|
||||
// Transform the view vector into the CRT's local coordinate frame, convert
|
||||
// to video_uv coords, and get the local 3D intersection position:
|
||||
const float3 view_vec_local = mul(global_to_local, view_vec_global);
|
||||
float3 pos;
|
||||
const float2 centered_uv = view_vec_to_uv(
|
||||
view_vec_local, eye_pos_local, geom_aspect, geom_mode, pos);
|
||||
const float2 video_uv = centered_uv + float2(0.5, 0.5);
|
||||
// Get a pixel-to-tangent-video-uv matrix. The caller could deal with
|
||||
// all but one of these cases, but that would be more complicated.
|
||||
#if _DRIVERS_ALLOW_DERIVATIVES
|
||||
// Derivatives obtain a matrix very fast, but the direction of pixel-
|
||||
// space +y seems to depend on the pass. Enforce the correct direction
|
||||
// on a best-effort basis (but it shouldn't matter for antialiasing).
|
||||
const float2 duv_dx = ddx(video_uv);
|
||||
const float2 duv_dy = ddy(video_uv);
|
||||
#ifdef LAST_PASS
|
||||
pixel_to_tangent_video_uv = float2x2(
|
||||
duv_dx.x, duv_dy.x,
|
||||
-duv_dx.y, -duv_dy.y);
|
||||
#else
|
||||
pixel_to_tangent_video_uv = float2x2(
|
||||
duv_dx.x, duv_dy.x,
|
||||
duv_dx.y, duv_dy.y);
|
||||
#endif
|
||||
#else
|
||||
// Manually define a transformation matrix. We'll assume pixel-space
|
||||
// +y = down, just like +v = down.
|
||||
if(geom_force_correct_tangent_matrix)
|
||||
{
|
||||
// Get the surface normal based on the local intersection position:
|
||||
const float3 normal_base = geom_mode < 2.5 ? pos :
|
||||
float3(pos.x, 0.0, pos.z);
|
||||
const float3 normal = normalize(normal_base);
|
||||
// Get pixel-to-object and object-to-tangent matrices and combine
|
||||
// them into a 2x2 pixel-to-tangent matrix for video_uv offsets:
|
||||
const float3x3 pixel_to_object = get_pixel_to_object_matrix(
|
||||
global_to_local, eye_pos_local, view_vec_global, pos, normal,
|
||||
output_size_inv);
|
||||
const float3x3 object_to_tangent = get_object_to_tangent_matrix(
|
||||
pos, normal, geom_aspect, geom_mode);
|
||||
const float3x3 pixel_to_tangent3x3 =
|
||||
mul(object_to_tangent, pixel_to_object);
|
||||
pixel_to_tangent_video_uv = float2x2(
|
||||
pixel_to_tangent3x3[0][0], pixel_to_tangent3x3[0][1], pixel_to_tangent3x3[1][0], pixel_to_tangent3x3[1][1]);//._m00_m01_m10_m11);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore curvature, and just consider flat scaling. The
|
||||
// difference is only apparent with strong curvature:
|
||||
pixel_to_tangent_video_uv = float2x2(
|
||||
output_size_inv.x, 0.0, 0.0, output_size_inv.y);
|
||||
}
|
||||
#endif
|
||||
return video_uv;
|
||||
}
|
||||
|
||||
float get_border_dim_factor(const float2 video_uv, const float2 geom_aspect)
|
||||
{
|
||||
// COPYRIGHT NOTE FOR THIS FUNCTION:
|
||||
// Copyright (C) 2010-2012 cgwg, 2014 TroggleMonkey
|
||||
// This function uses an algorithm first coded in several of cgwg's GPL-
|
||||
// licensed lines in crt-geom-curved.cg and its ancestors. The line
|
||||
// between algorithm and code is nearly indistinguishable here, so it's
|
||||
// unclear whether I could even release this project under a non-GPL
|
||||
// license with this function included.
|
||||
|
||||
// Calculate border_dim_factor from the proximity to uv-space image
|
||||
// borders; geom_aspect/border_size/border/darkness/border_compress are globals:
|
||||
const float2 edge_dists = min(video_uv, float2(1.0, 1.0) - video_uv) *
|
||||
geom_aspect;
|
||||
const float2 border_penetration =
|
||||
max(float2(border_size, border_size) - edge_dists, float2(0.0, 0.0));
|
||||
const float penetration_ratio = border_size > 0 ? length(border_penetration)/border_size : 0;
|
||||
const float border_escape_ratio = max(1.0 - penetration_ratio, 0.0);
|
||||
const float border_dim_factor =
|
||||
pow(border_escape_ratio, border_darkness) * max(1.0, border_compress);
|
||||
return min(border_dim_factor, 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // _GEOMETRY_FUNCTIONS_H
|
||||
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
#ifndef _HELPER_FUNCTIONS_AND_MACROS_H
|
||||
#define _HELPER_FUNCTIONS_AND_MACROS_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2020 Alex Gunter
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
|
||||
float4 tex2D_nograd(sampler2D tex, float2 tex_coords)
|
||||
{
|
||||
return tex2Dlod(tex, float4(tex_coords, 0, 0), 0.0);
|
||||
}
|
||||
|
||||
// ReShade 4 does not permit the use of functions or the ternary operator
|
||||
// outside of a function definition. This is a problem for this port
|
||||
// because the original crt-royale shader makes heavy use of these
|
||||
// constructs at the root level.
|
||||
|
||||
// These preprocessor definitions are a workaround for this limitation.
|
||||
// Note that they are strictly intended for defining complex global
|
||||
// constants. I doubt they're more performant than the built-in
|
||||
// equivalents, so I recommend using the built-ins whenever you can.
|
||||
|
||||
|
||||
#define macro_sign(c) -((int) ((c) != 0)) * -((int) ((c) > 0))
|
||||
#define macro_abs(c) (c) * macro_sign(c)
|
||||
|
||||
#define macro_min(c, d) (c) * ((int) ((c) <= (d))) + (d) * ((int) ((c) > (d)))
|
||||
#define macro_max(c, d) (c) * ((int) ((c) >= (d))) + (d) * ((int) ((c) < (d)))
|
||||
#define macro_clamp(c, l, u) macro_min(macro_max(c, l), u)
|
||||
|
||||
#define macro_ceil(c) (float) ((int) (c) + (int) (((int) (c)) < (c)))
|
||||
|
||||
#define macro_cond(c, a, b) float(c) * (a) + float(!(c)) * (b)
|
||||
|
||||
|
||||
|
||||
//////////////////////// COMMON MATHEMATICAL CONSTANTS ///////////////////////
|
||||
|
||||
static const float pi = 3.141592653589;
|
||||
// We often want to find the location of the previous texel, e.g.:
|
||||
// const float2 curr_texel = uv * texture_size;
|
||||
// const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5);
|
||||
// const float2 prev_texel_uv = prev_texel / texture_size;
|
||||
// However, many GPU drivers round incorrectly around exact texel locations.
|
||||
// We need to subtract a little less than 0.5 before flooring, and some GPU's
|
||||
// require this value to be farther from 0.5 than others; define it here.
|
||||
// const float2 prev_texel =
|
||||
// floor(curr_texel - float2(under_half)) + float2(0.5);
|
||||
static const float under_half = 0.4995;
|
||||
|
||||
// Avoid dividing by zero; using a macro overloads for float, float2, etc.:
|
||||
#define FIX_ZERO(c) (macro_max(macro_abs(c), 0.0000152587890625)) // 2^-16
|
||||
|
||||
// #define fmod(x, y) ((x) - (y) * floor((x)/(y) + FIX_ZERO(0.0)))
|
||||
#define fmod(x, y) (frac((x) / (y)) * (y))
|
||||
|
||||
#endif // _HELPER_FUNCTIONS_AND_MACROS_H
|
||||
@@ -1,624 +0,0 @@
|
||||
#ifndef _PHOSHOR_MASK_CALCULATIONS_H
|
||||
#define _PHOSHOR_MASK_CALCULATIONS_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2020 Alex Gunter
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
|
||||
/*
|
||||
* Our goal is to use arithmetic to generate the phosphor mask.
|
||||
* Phosphor masks are regular patterns, so we want something periodic.
|
||||
* We need to avoid integer arithmetic because it tends to cause rounding errors.
|
||||
*
|
||||
* For all masks, we want to approximate a pulse wave in at least one dimension. This pulse wave
|
||||
* will have narrow peaks, wide troughs, and constant periodicity.
|
||||
* GRILLE will have a pulse wave along the x-axis and will be constant along the y-axis.
|
||||
* SLOT and SHADOW will likely have a superposition of two out-of-phase pulse waves along each axis.
|
||||
* For SHADOW, the width of the peaks will vary such that they generate ellipsoids on the screen.
|
||||
*
|
||||
* We can get a periodic function by starting with a triangle wave: T(t, f) = abs(1 - 2*frac(t * f)).
|
||||
* This function gives us a triangle wave with f cycles in the domain [0, 1].
|
||||
* Note that T(0, f) = 1.
|
||||
*
|
||||
* Then we can compose this with a sigmoid curve to squish the triangle wave into a pulse wave.
|
||||
* P(s, p, q) = exp(q s - q/2) / (exp(q s - q/2) + exp(-p))
|
||||
* s(t, f, o) = T(t*f - o, 1)
|
||||
*
|
||||
* f is the number of pulses to render along the given axis.
|
||||
* o is the channel's horizontal ofset along the given axis, normalized via the quotient raw_offset / raw_triad width.
|
||||
* p and q control how closely P resembles an ideal pulse wave and also how wide the peaks and troughs are.
|
||||
*
|
||||
* The interaction between p and q is rather complicated and difficult to describe, so they're not a good pair
|
||||
* of parameters for users. But we have the info necessary to solve for p in terms of q.
|
||||
* We know the width of a phosphor and the width of a triad, and we know the domain and range of P.
|
||||
* We can choose a coordinate (t0, y0) that will denote the edge of the phosphor.
|
||||
* Note that y0 = P(t0, p, q) for some p and q.
|
||||
* We let t0 = raw_phosphor_width / raw_triad_width, since we need to respect the shape of the phosphor.
|
||||
* We let the user define P(t0).
|
||||
* Technically, this means the user is defining the brightness of the phosphor's furthest edge.
|
||||
* Visually, this looks like the user is defining the width of the phosphor.
|
||||
* We'll call this the Phosphor Thickness.
|
||||
* We let the user define q.
|
||||
* Technically, this means the user is defining the squareness of the pulse wave.
|
||||
* Visually, this looks like the user is defining the sharpness of the phosphor.
|
||||
* We'll call this the Phosphor Sharpness.
|
||||
*
|
||||
* We can solve for p in terms of q very efficiently.
|
||||
* p = (ln(y0 / (1 - y0)) - q) / (0.5 - 2 t0)
|
||||
*
|
||||
* Note that, if you work through the algebra, you get a denominator of (t0 - 0.5).
|
||||
* Using (0.5 - 2 t0) actually works better. It also matches up when you try plotting P and (t0, y0).
|
||||
*
|
||||
* For the GRILLE and SLOT masks, we can compute p once and recycle it.
|
||||
* For the SHADOW mask, we can either compute p on each iteration or find a way to interpolate between min_p and max_p.
|
||||
*
|
||||
* One might expect it'd be way better to use a clamped triangle wave rather than a sigmoid or exponentiated cosine wave.
|
||||
* As far as I can tell, this ends up being incorrect surprisingly enough. Although it's a good bit faster,
|
||||
* it has terrible aliasing artifacts at small scales. The other implementations are slower, but they produce
|
||||
* evenly-sized RGB phosphors for a variety of configurations even when the triad width is 3 pixels. At that
|
||||
* scale, the triangle wave approach produces triads where one of the phosphors is thicker than the others.
|
||||
* Taking into account the compute_mask_factor trick, the triangle wave approach would be a negligible
|
||||
* performance improvement at the cost of a large drop in visual quality and user friendliness.
|
||||
*/
|
||||
|
||||
|
||||
#include "bind-shader-params.fxh"
|
||||
#include "scanline-functions.fxh"
|
||||
|
||||
/*
|
||||
* The GRILLE mask consists of an array of vertical stripes, so each channel will vary along the x-axis and will be constant
|
||||
* along the y-axis.
|
||||
*
|
||||
* It has the following dimensions:
|
||||
* Phosphors are 18 units wide with unbounded height.
|
||||
* Phosphors in a triad are 2 units apart.
|
||||
* Triads are 6 units apart.
|
||||
* Triad centers are 64 units apart.
|
||||
* The phosphors follow an RGB pattern.
|
||||
* The left-most phosphor is red and offset by 3 units to the right.
|
||||
*/
|
||||
static const float grille_raw_phosphor_width = 18;
|
||||
static const float grille_raw_phosphor_gap = 2;
|
||||
static const float grille_raw_triad_horiz_gap = 6;
|
||||
static const float grille_raw_triad_width = 3*grille_raw_phosphor_width + 2*grille_raw_phosphor_gap + grille_raw_triad_horiz_gap;
|
||||
|
||||
static const float grille_raw_r_offset = (grille_raw_triad_horiz_gap + grille_raw_phosphor_width) / 2;
|
||||
static const float grille_raw_g_offset = grille_raw_r_offset + grille_raw_phosphor_width + grille_raw_phosphor_gap;
|
||||
static const float grille_raw_b_offset = grille_raw_g_offset + grille_raw_phosphor_width + grille_raw_phosphor_gap;
|
||||
static const float3 grille_norm_center_offsets = float3(
|
||||
grille_raw_r_offset,
|
||||
grille_raw_g_offset,
|
||||
grille_raw_b_offset
|
||||
) / grille_raw_triad_width;
|
||||
|
||||
static const float grille_edge_t = grille_raw_phosphor_width / 2;
|
||||
static const float grille_edge_norm_t = grille_edge_t / grille_raw_triad_width;
|
||||
|
||||
|
||||
/*
|
||||
* The SLOT mask consists of an array of rectangles, so each channel will vary along both the x- and y-axes.
|
||||
*
|
||||
* It has the following dimensions:
|
||||
* Phosphors are 18 units wide and 66 units tall.
|
||||
* Phosphors in a triad are 2 units apart.
|
||||
* Triads are 6 units apart horizontally and 6 units apart vertically.
|
||||
* Triad centers are 64 units apart horizontally and 73 units apart vertically.
|
||||
* The phosphors follow an RGB pattern.
|
||||
* The upper-left-most phosphor is red and offset by 3 units to the right and 3 units down.
|
||||
*/
|
||||
static const float slot_raw_phosphor_width = 18;
|
||||
static const float slot_raw_phosphor_gap = 2;
|
||||
static const float slot_raw_triad_horiz_gap = 6;
|
||||
static const float slot_raw_triad_width = 3*slot_raw_phosphor_width + 2*slot_raw_phosphor_gap + slot_raw_triad_horiz_gap;
|
||||
|
||||
static const float slot_raw_phosphor_height = 66;
|
||||
static const float slot_raw_triad_vert_gap = 6;
|
||||
static const float slot_raw_triad_height = slot_raw_phosphor_height + slot_raw_triad_vert_gap;
|
||||
|
||||
static const float slot_aspect_ratio = slot_raw_triad_height / slot_raw_triad_width;
|
||||
|
||||
static const float slot_raw_r_offset_x = (slot_raw_triad_horiz_gap + slot_raw_phosphor_width) / 2;
|
||||
static const float slot_raw_g_offset_x = slot_raw_r_offset_x + slot_raw_phosphor_width + slot_raw_phosphor_gap;
|
||||
static const float slot_raw_b_offset_x = slot_raw_g_offset_x + slot_raw_phosphor_width + slot_raw_phosphor_gap;
|
||||
static const float3 slot_norm_center_offsets_x = float3(
|
||||
slot_raw_r_offset_x,
|
||||
slot_raw_g_offset_x,
|
||||
slot_raw_b_offset_x
|
||||
) / slot_raw_triad_width;
|
||||
static const float3 slot_norm_center_offsets_y = float3(0.5, 0.5, 0.5);
|
||||
|
||||
static const float slot_edge_tx = slot_raw_phosphor_width / 2;
|
||||
// We draw the slot mask as two sets of columns. To do that, we have to pretend the horizontal gap is the size of a whole triad.
|
||||
// Then we need to halve the position of the phosphor edge.
|
||||
static const float slot_edge_norm_tx = 0.5 * slot_edge_tx / slot_raw_triad_width;
|
||||
static const float slot_edge_ty = slot_raw_phosphor_height / 2;
|
||||
static const float slot_edge_norm_ty = slot_edge_ty / slot_raw_triad_height;
|
||||
|
||||
/*
|
||||
* The SHADOW mask consists of an array of circles, so each channel will vary along both the x- and y-axes.
|
||||
*
|
||||
* It has the following dimensions:
|
||||
* Phosphors are 21 units in diameter.
|
||||
* All phosphors are 0 units apart.
|
||||
* Triad centers are 63 units apart horizontally and 21 units apart vertically.
|
||||
* The phosphors follow a GBR pattern on odd rows and RBG on even rows.
|
||||
* The upper-left-most phosphor is green and centered on the corner of the screen.
|
||||
*/
|
||||
static const float shadow_raw_phosphor_diam = 21;
|
||||
static const float shadow_raw_phosphor_gap = 0;
|
||||
static const float shadow_raw_triad_horiz_gap = 0;
|
||||
static const float shadow_raw_triad_vert_gap = 0;
|
||||
|
||||
static const float shadow_raw_triad_width = 3*shadow_raw_phosphor_diam + 2*shadow_raw_phosphor_gap + shadow_raw_triad_horiz_gap;
|
||||
static const float shadow_raw_triad_height = shadow_raw_phosphor_diam + shadow_raw_triad_vert_gap;
|
||||
|
||||
static const float shadow_aspect_ratio = shadow_raw_triad_height / shadow_raw_triad_width;
|
||||
|
||||
static const float shadow_raw_g_offset_x = 0;
|
||||
static const float shadow_raw_b_offset_x = shadow_raw_g_offset_x + shadow_raw_phosphor_diam + shadow_raw_phosphor_gap;
|
||||
static const float shadow_raw_r_offset_x = shadow_raw_b_offset_x + shadow_raw_phosphor_diam + shadow_raw_phosphor_gap;
|
||||
static const float3 shadow_norm_center_offsets_x = float3(
|
||||
shadow_raw_r_offset_x,
|
||||
shadow_raw_g_offset_x,
|
||||
shadow_raw_b_offset_x
|
||||
) / shadow_raw_triad_width;
|
||||
|
||||
static const float3 shadow_norm_center_offsets_y = float3(0.0, 0.0, 0.0);
|
||||
|
||||
static const float shadow_edge_tx = shadow_raw_phosphor_diam / 2;
|
||||
static const float shadow_edge_norm_tx = shadow_edge_tx / shadow_raw_triad_width;
|
||||
static const float shadow_edge_ty = shadow_raw_phosphor_diam / 2;
|
||||
// We draw the shadow mask as two sets of rows. To do that, we have to pretend the vertical gap is the size of a whole triad.
|
||||
// Then we need to halve the position of the phosphor edge.
|
||||
static const float shadow_edge_norm_ty = 0.5 * shadow_edge_ty / shadow_raw_triad_height;
|
||||
static const float shadow_norm_phosphor_rad = (shadow_raw_phosphor_diam/2) / shadow_raw_triad_width;
|
||||
|
||||
|
||||
/*
|
||||
* The SMALL GRILLE mask is composed of magenta and green stripes.
|
||||
* Sourced from http://filthypants.blogspot.com/2020/02/crt-shader-masks.html
|
||||
*
|
||||
* It has the following dimensions:
|
||||
* Stripes are 32 units wide.
|
||||
* Stripes in a triad are 0 units apart.
|
||||
* Triads are 0 units apart horizontally.
|
||||
*
|
||||
* Each triad has two quads, side-by-side and aligned.
|
||||
* Neighboring triads are offset vertically.
|
||||
* Below is an array of 2 triads.
|
||||
* x's denote magenta stripes, and o's denote green ones.
|
||||
*
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
*
|
||||
* The phosphors follow a MG pattern.
|
||||
* The left-most phosphor is magenta and offset by 16 units to the right.
|
||||
*/
|
||||
|
||||
static const float smallgrille_raw_stripe_width = 32;
|
||||
static const float smallgrille_raw_triad_width = 2*smallgrille_raw_stripe_width;
|
||||
|
||||
static const float smallgrille_raw_r_offset_x = 0.5 * smallgrille_raw_stripe_width;
|
||||
static const float smallgrille_raw_g_offset_x = smallgrille_raw_r_offset_x + smallgrille_raw_stripe_width;
|
||||
static const float smallgrille_raw_b_offset_x = smallgrille_raw_r_offset_x;
|
||||
static const float3 smallgrille_norm_center_offsets_x = float3(
|
||||
smallgrille_raw_r_offset_x,
|
||||
smallgrille_raw_g_offset_x,
|
||||
smallgrille_raw_b_offset_x
|
||||
) / smallgrille_raw_triad_width;
|
||||
|
||||
static const float smallgrille_edge_t = 0.5 * smallgrille_raw_stripe_width;
|
||||
static const float smallgrille_edge_norm_t = smallgrille_edge_t / smallgrille_raw_triad_width;
|
||||
|
||||
|
||||
/*
|
||||
* The SMALL SLOT mask is composed of magenta and green quads.
|
||||
* Sourced from http://filthypants.blogspot.com/2020/02/crt-shader-masks.html
|
||||
*
|
||||
* It has the following dimensions:
|
||||
* Quads are 32 units wide and 48 units tall.
|
||||
* Quads in a triad are 0 units apart.
|
||||
* Triads are 0 units apart horizontally and 16 units apart vertically.
|
||||
*
|
||||
* Each triad has two quads, side-by-side and aligned.
|
||||
* Neighboring triads are offset vertically.
|
||||
* Below is a 2x2 matrix of 4 triads.
|
||||
* x's denote magenta quads, and o's denote green ones.
|
||||
*
|
||||
* xxoo
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* xxoo
|
||||
* xxoo
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* xxoo
|
||||
*
|
||||
* The phosphors follow a MG pattern.
|
||||
* The upper-left-most phosphor is magenta and offset by 16 units to the right and 16 units down.
|
||||
*/
|
||||
|
||||
static const float smallslot_raw_quad_width = 32;
|
||||
static const float smallslot_raw_triad_width = 2*smallslot_raw_quad_width;
|
||||
|
||||
static const float smallslot_raw_quad_height = 1.5 * smallslot_raw_quad_width;
|
||||
static const float smallslot_raw_triad_vert_gap = 0.5 * smallslot_raw_quad_width;
|
||||
static const float smallslot_raw_triad_height = smallslot_raw_quad_height + smallslot_raw_triad_vert_gap;
|
||||
|
||||
static const float smallslot_aspect_ratio = smallslot_raw_triad_height / smallslot_raw_triad_width;
|
||||
|
||||
static const float smallslot_raw_r_offset_x = 0.5 * smallslot_raw_quad_width;
|
||||
static const float smallslot_raw_g_offset_x = smallslot_raw_r_offset_x + smallslot_raw_quad_width;
|
||||
static const float smallslot_raw_b_offset_x = smallslot_raw_r_offset_x;
|
||||
static const float3 smallslot_norm_center_offsets_x = float3(
|
||||
smallslot_raw_r_offset_x,
|
||||
smallslot_raw_g_offset_x,
|
||||
smallslot_raw_b_offset_x
|
||||
) / smallslot_raw_triad_width;
|
||||
|
||||
static const float3 smallslot_norm_center_offsets_y1 = 0.5 * smallslot_raw_quad_height / smallslot_raw_triad_height;
|
||||
static const float3 smallslot_norm_center_offsets_y2 = smallslot_norm_center_offsets_y1 + smallslot_raw_triad_vert_gap / smallslot_raw_triad_height;
|
||||
|
||||
static const float smallslot_edge_tx = 0.5 * smallslot_raw_quad_width;
|
||||
// We draw the slot mask as two sets of columns. To do that, we have to pretend the horizontal gap is the size of a whole triad.
|
||||
// Then we need to halve the position of the phosphor edge.
|
||||
static const float smallslot_edge_norm_tx = 0.5 * smallslot_edge_tx / smallslot_raw_triad_width;
|
||||
static const float smallslot_edge_ty = smallslot_raw_quad_height / 2;
|
||||
static const float smallslot_edge_norm_ty = smallslot_edge_ty / smallslot_raw_triad_height;
|
||||
|
||||
/*
|
||||
* The SMALL SHADOW mask is composed of magenta and green quads.
|
||||
* Sourced from http://filthypants.blogspot.com/2020/02/crt-shader-masks.html
|
||||
*
|
||||
* It has the following dimensions:
|
||||
* Quads are 17 units wide and 17 units tall.
|
||||
* Quads in a triad are 0 units apart.
|
||||
* Triads are 0 units apart horizontally and 0 units apart vertically.
|
||||
*
|
||||
* Each triad has two quads, side-by-side and aligned.
|
||||
* Neighboring triads are offset vertically.
|
||||
* Below is a 2x2 matrix of 4 triads.
|
||||
* x's denote magenta quads, and o's denote green ones.
|
||||
*
|
||||
* xxooxxoo
|
||||
* xxooxxoo
|
||||
* ooxxooxx
|
||||
* ooxxooxx
|
||||
*
|
||||
* The phosphors follow a MG pattern.
|
||||
* The upper-left-most phosphor is magenta and offset by 16 units to the right and 16 units down.
|
||||
*/
|
||||
|
||||
static const float smallshadow_raw_quad_width = 17;
|
||||
static const float smallshadow_raw_triad_width = 2 * smallshadow_raw_quad_width;
|
||||
|
||||
static const float smallshadow_raw_quad_height = 17;
|
||||
static const float smallshadow_raw_triad_height = smallshadow_raw_quad_height;
|
||||
|
||||
static const float smallshadow_aspect_ratio = smallshadow_raw_triad_height / smallshadow_raw_triad_width;
|
||||
|
||||
static const float smallshadow_raw_r_offset_x = 0.5 * smallshadow_raw_quad_width;
|
||||
static const float smallshadow_raw_g_offset_x = smallshadow_raw_r_offset_x + smallshadow_raw_quad_width;
|
||||
static const float smallshadow_raw_b_offset_x = smallshadow_raw_r_offset_x;
|
||||
static const float3 smallshadow_norm_center_offsets_x = float3(
|
||||
smallshadow_raw_r_offset_x,
|
||||
smallshadow_raw_g_offset_x,
|
||||
smallshadow_raw_b_offset_x
|
||||
) / smallshadow_raw_triad_width;
|
||||
|
||||
static const float3 smallshadow_norm_center_offsets_y = 0.5 * smallshadow_raw_triad_height;
|
||||
|
||||
static const float smallshadow_edge_tx = 0.5 * smallshadow_raw_quad_width;
|
||||
static const float smallshadow_edge_norm_tx = smallshadow_edge_tx / smallshadow_raw_triad_width;
|
||||
static const float smallshadow_edge_ty = 0.5 * smallshadow_raw_quad_height;
|
||||
// We draw the shadow mask as two sets of rows. To do that, we have to pretend the vertical gap is the size of a whole triad.
|
||||
// Then we need to halve the position of the phosphor edge.
|
||||
static const float smallshadow_edge_norm_ty = 0.5 * smallshadow_edge_ty / smallshadow_raw_triad_height;
|
||||
|
||||
|
||||
|
||||
|
||||
float get_selected_aspect_ratio() {
|
||||
float aspect_ratio;
|
||||
[flatten]
|
||||
if (mask_type == 0 || mask_type == 3) {
|
||||
aspect_ratio = scale_triad_height;
|
||||
}
|
||||
else if (mask_type == 1 || mask_type == 4) {
|
||||
aspect_ratio = scale_triad_height * slot_aspect_ratio;
|
||||
}
|
||||
else {
|
||||
aspect_ratio = scale_triad_height * shadow_aspect_ratio;
|
||||
}
|
||||
[flatten]
|
||||
switch (mask_type) {
|
||||
case 0:
|
||||
aspect_ratio = scale_triad_height;
|
||||
break;
|
||||
case 1:
|
||||
aspect_ratio = scale_triad_height * slot_aspect_ratio;
|
||||
break;
|
||||
case 2:
|
||||
aspect_ratio = scale_triad_height * shadow_aspect_ratio;
|
||||
break;
|
||||
case 3:
|
||||
aspect_ratio = scale_triad_height;
|
||||
break;
|
||||
case 4:
|
||||
aspect_ratio = scale_triad_height * smallslot_aspect_ratio;
|
||||
break;
|
||||
default:
|
||||
aspect_ratio = scale_triad_height * smallshadow_aspect_ratio;
|
||||
break;
|
||||
}
|
||||
|
||||
return aspect_ratio;
|
||||
}
|
||||
|
||||
float2 calc_triad_size() {
|
||||
const float aspect_ratio = get_selected_aspect_ratio();
|
||||
|
||||
[branch]
|
||||
if (mask_size_param == 0) {
|
||||
return float2(1, aspect_ratio) * mask_triad_width;
|
||||
}
|
||||
else {
|
||||
float triad_width = content_size.x * rcp(mask_num_triads_across);
|
||||
return float2(1, aspect_ratio) * triad_width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float2 calc_phosphor_viewport_frequency_factor() {
|
||||
const float aspect_ratio = get_selected_aspect_ratio();
|
||||
|
||||
float2 triad_size_factor;
|
||||
float2 num_triads_factor;
|
||||
[branch]
|
||||
if (geom_rotation_mode == 0 || geom_rotation_mode == 2) {
|
||||
triad_size_factor = content_size * rcp(mask_triad_width * float2(1, aspect_ratio));
|
||||
num_triads_factor = mask_num_triads_across * float2(1, content_size.y * rcp(content_size.x) * rcp(aspect_ratio));
|
||||
}
|
||||
else {
|
||||
triad_size_factor = content_size * rcp(mask_triad_width * float2(1, aspect_ratio)).yx;
|
||||
num_triads_factor = mask_num_triads_across * float2(1, content_size.y * rcp(content_size.x) * rcp(aspect_ratio)).yx;
|
||||
}
|
||||
|
||||
return ((mask_size_param == 0) ? triad_size_factor : num_triads_factor);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We have a pulse wave f(t0_norm, p, q) = y0 with unknown p.
|
||||
* This function solves for p.
|
||||
*/
|
||||
#define calculate_phosphor_p_value(t0_norm, y0, q) (log((y0) * rcp(1 - (y0))) - (q) * (0.5 - 2*(t0_norm)))
|
||||
|
||||
/*
|
||||
* If we don't rescale the phosphor_thickness parameter, it has a logarithmic effect on the phosphor shape.
|
||||
* Rescaling it makes it look closer to a linear effect.
|
||||
*/
|
||||
#define linearize_phosphor_thickness_param(p) (1 - exp(-(p)))
|
||||
|
||||
|
||||
/*
|
||||
* Generates a grille mask with the desired resolution and sharpness.
|
||||
*/
|
||||
float3 get_phosphor_intensity_grille(
|
||||
const float2 texcoord,
|
||||
const float2 viewport_frequency_factor,
|
||||
const float2 grille_pq
|
||||
) {
|
||||
float3 center_offsets = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
grille_norm_center_offsets.bgr : grille_norm_center_offsets;
|
||||
|
||||
center_offsets += phosphor_offset_x * 0.5;
|
||||
|
||||
float3 theta = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets, 1);
|
||||
float3 alpha = exp((theta - 0.5) * grille_pq.y);
|
||||
return alpha * rcp(alpha + grille_pq.x);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generates a slot mask with the desired resolution and sharpness.
|
||||
*/
|
||||
float3 get_phosphor_intensity_slot(
|
||||
const float2 texcoord,
|
||||
const float2 viewport_frequency_factor,
|
||||
const float2 slot_pq_x,
|
||||
const float2 slot_pq_y
|
||||
) {
|
||||
float3 center_offsets_x = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
slot_norm_center_offsets_x.bgr : slot_norm_center_offsets_x;
|
||||
float3 center_offsets_y = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
slot_norm_center_offsets_y.bgr : slot_norm_center_offsets_y;
|
||||
|
||||
center_offsets_x += phosphor_offset_x * 0.5;
|
||||
center_offsets_y += phosphor_offset_y * 0.5;
|
||||
|
||||
float3 theta_x1 = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x, 0.5);
|
||||
float3 alpha_x1 = exp((theta_x1 - 0.5) * slot_pq_x.y);
|
||||
alpha_x1 *= rcp(alpha_x1 + slot_pq_x.x);
|
||||
|
||||
float3 theta_x2 = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x + 1, 0.5);
|
||||
float3 alpha_x2 = exp((theta_x2 - 0.5) * slot_pq_x.y);
|
||||
alpha_x2 *= rcp(alpha_x2 + slot_pq_x.x);
|
||||
|
||||
float3 theta_y1 = triangle_wave(texcoord.y * viewport_frequency_factor.y - center_offsets_y, 1);
|
||||
float3 alpha_y1 = exp((theta_y1 - 0.5) * slot_pq_y.y);
|
||||
alpha_y1 *= rcp(alpha_y1 + slot_pq_y.x);
|
||||
|
||||
float3 theta_y2 = triangle_wave(texcoord.y * viewport_frequency_factor.y - center_offsets_y + 0.5, 1);
|
||||
float3 alpha_y2 = exp((theta_y2 - 0.5) * slot_pq_y.y);
|
||||
alpha_y2 *= rcp(alpha_y2 + slot_pq_y.x);
|
||||
|
||||
return alpha_x1 * alpha_y1 + alpha_x2 * alpha_y2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a shadow mask with the desired resolution and sharpness.
|
||||
*/
|
||||
float3 get_phosphor_intensity_shadow(
|
||||
const float2 texcoord,
|
||||
const float2 viewport_frequency_factor,
|
||||
const float2 shadow_q
|
||||
) {
|
||||
float3 center_offsets_x = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
shadow_norm_center_offsets_x.bgr : shadow_norm_center_offsets_x;
|
||||
float3 center_offsets_y = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
shadow_norm_center_offsets_y.bgr : shadow_norm_center_offsets_y;
|
||||
|
||||
center_offsets_x += phosphor_offset_x * 0.5;
|
||||
center_offsets_y += phosphor_offset_y * 0.5;
|
||||
|
||||
const float2 thickness_scaled = linearize_phosphor_thickness_param(phosphor_thickness);
|
||||
|
||||
const float3 x_adj = texcoord.x * viewport_frequency_factor.x - center_offsets_x;
|
||||
const float3 y_adj = texcoord.y * viewport_frequency_factor.y - center_offsets_y;
|
||||
|
||||
const float3 texcoord_x_periodic1 = shadow_norm_phosphor_rad * triangle_wave(x_adj * 3 - 0.5, 1.0);
|
||||
const float3 texcoord_x_periodic2 = shadow_norm_phosphor_rad * triangle_wave(x_adj * 3, 1.0);
|
||||
const float3 ty1 = sqrt(
|
||||
shadow_norm_phosphor_rad*shadow_norm_phosphor_rad - texcoord_x_periodic1*texcoord_x_periodic1
|
||||
);
|
||||
const float3 ty2 = sqrt(
|
||||
shadow_norm_phosphor_rad*shadow_norm_phosphor_rad - texcoord_x_periodic2*texcoord_x_periodic2
|
||||
);
|
||||
|
||||
const float shadow_px = exp(-calculate_phosphor_p_value(shadow_edge_norm_tx, thickness_scaled.x, shadow_q.x));
|
||||
const float3 shadow_py1 = exp(-calculate_phosphor_p_value(ty1 * 0.5 * rcp(shadow_aspect_ratio), thickness_scaled.y, shadow_q.y));
|
||||
const float3 shadow_py2 = exp(-calculate_phosphor_p_value(ty2 * 0.5 * rcp(shadow_aspect_ratio), thickness_scaled.y, shadow_q.y));
|
||||
|
||||
float3 theta_x1 = triangle_wave(x_adj, 1);
|
||||
float3 alpha_x1 = exp((theta_x1 - 0.5) * shadow_q.x);
|
||||
alpha_x1 *= rcp(alpha_x1 + shadow_px);
|
||||
|
||||
float3 theta_x2 = triangle_wave(x_adj + 0.5, 1);
|
||||
float3 alpha_x2 = exp((theta_x2 - 0.5) * shadow_q.x);
|
||||
alpha_x2 *= rcp(alpha_x2 + shadow_px);
|
||||
|
||||
float3 theta_y1 = triangle_wave(y_adj, 0.5);
|
||||
float3 alpha_y1 = exp((theta_y1 - 0.5) * shadow_q.y);
|
||||
alpha_y1 *= rcp(alpha_y1 + shadow_py1);
|
||||
|
||||
float3 theta_y2 = triangle_wave(y_adj + 1, 0.5);
|
||||
float3 alpha_y2 = exp((theta_y2 - 0.5) * shadow_q.y);
|
||||
alpha_y2 *= rcp(alpha_y2 + shadow_py2);
|
||||
|
||||
return alpha_x1 * alpha_y1 + alpha_x2 * alpha_y2;
|
||||
}
|
||||
|
||||
float3 get_phosphor_intensity_grille_small(
|
||||
const float2 texcoord,
|
||||
const float2 viewport_frequency_factor,
|
||||
const float2 grille_pq_x
|
||||
) {
|
||||
float3 center_offsets_x = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
smallgrille_norm_center_offsets_x.grg : smallgrille_norm_center_offsets_x;
|
||||
|
||||
center_offsets_x += phosphor_offset_x * 0.5;
|
||||
|
||||
float3 theta = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x, 1);
|
||||
float3 alpha = exp((theta - 0.5) * grille_pq_x.y);
|
||||
alpha *= rcp(alpha + grille_pq_x.x);
|
||||
|
||||
// Taking a sqrt here helps hide the gaps between the pixels when the triad size is small
|
||||
return sqrt(alpha);
|
||||
}
|
||||
|
||||
float3 get_phosphor_intensity_slot_small(
|
||||
const float2 texcoord,
|
||||
const float2 viewport_frequency_factor,
|
||||
const float2 slot_pq_x,
|
||||
const float2 slot_pq_y
|
||||
) {
|
||||
float3 center_offsets_x = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
smallslot_norm_center_offsets_x.grg : smallslot_norm_center_offsets_x;
|
||||
float3 center_offsets_y1 = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
smallslot_norm_center_offsets_y1.grg : smallslot_norm_center_offsets_y1;
|
||||
float3 center_offsets_y2 = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
smallslot_norm_center_offsets_y2.grg : smallslot_norm_center_offsets_y2;
|
||||
|
||||
center_offsets_x += phosphor_offset_x * 0.5;
|
||||
center_offsets_y1 += phosphor_offset_y * 0.5;
|
||||
center_offsets_y2 += phosphor_offset_y * 0.5;
|
||||
|
||||
float3 theta_x1 = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x, 0.5);
|
||||
float3 alpha_x1 = exp((theta_x1 - 0.5) * slot_pq_x.y);
|
||||
alpha_x1 *= rcp(alpha_x1 + slot_pq_x.x);
|
||||
|
||||
float3 theta_x2 = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x + 1, 0.5);
|
||||
float3 alpha_x2 = exp((theta_x2 - 0.5) * slot_pq_x.y);
|
||||
alpha_x2 *= rcp(alpha_x2 + slot_pq_x.x);
|
||||
|
||||
float3 theta_y1 = triangle_wave(texcoord.y * viewport_frequency_factor.y - center_offsets_y1, 1);
|
||||
float3 alpha_y1 = exp((theta_y1 - 0.5) * slot_pq_y.y);
|
||||
alpha_y1 *= rcp(alpha_y1 + slot_pq_y.x);
|
||||
|
||||
float3 theta_y2 = triangle_wave(texcoord.y * viewport_frequency_factor.y - center_offsets_y2 + 0.5, 1);
|
||||
float3 alpha_y2 = exp((theta_y2 - 0.5) * slot_pq_y.y);
|
||||
alpha_y2 *= rcp(alpha_y2 + slot_pq_y.x);
|
||||
|
||||
// Taking a sqrt here helps hide the gaps between the pixels when the triad size is small
|
||||
return (alpha_x1 * alpha_y1 + alpha_x2 * alpha_y2);
|
||||
}
|
||||
|
||||
float3 get_phosphor_intensity_shadow_small(
|
||||
const float2 texcoord,
|
||||
const float2 viewport_frequency_factor,
|
||||
const float2 shadow_pq_x,
|
||||
const float2 shadow_pq_y
|
||||
) {
|
||||
float3 center_offsets_x = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
smallshadow_norm_center_offsets_x.grg : smallshadow_norm_center_offsets_x;
|
||||
float3 center_offsets_y = (geom_rotation_mode == 2 || geom_rotation_mode == 3) ?
|
||||
smallshadow_norm_center_offsets_y.grg : smallshadow_norm_center_offsets_y;
|
||||
|
||||
center_offsets_x += phosphor_offset_x * 0.5;
|
||||
center_offsets_y += phosphor_offset_y * 0.5;
|
||||
|
||||
float3 theta_x1 = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x, 1);
|
||||
float3 alpha_x1 = exp((theta_x1 - 0.5) * shadow_pq_x.y);
|
||||
alpha_x1 *= rcp(alpha_x1 + shadow_pq_x.x);
|
||||
|
||||
float3 theta_x2 = triangle_wave(texcoord.x * viewport_frequency_factor.x - center_offsets_x + 0.5, 1);
|
||||
float3 alpha_x2 = exp((theta_x2 - 0.5) * shadow_pq_x.y);
|
||||
alpha_x2 *= rcp(alpha_x2 + shadow_pq_x.x);
|
||||
|
||||
float3 theta_y1 = triangle_wave(texcoord.y * viewport_frequency_factor.y - center_offsets_y, 0.5);
|
||||
float3 alpha_y1 = exp((theta_y1 - 0.5) * shadow_pq_y.y);
|
||||
alpha_y1 *= rcp(alpha_y1 + shadow_pq_y.x);
|
||||
|
||||
float3 theta_y2 = triangle_wave(texcoord.y * viewport_frequency_factor.y - center_offsets_y + 1, 0.5);
|
||||
float3 alpha_y2 = exp((theta_y2 - 0.5) * shadow_pq_y.y);
|
||||
alpha_y2 *= rcp(alpha_y2 + shadow_pq_y.x);
|
||||
|
||||
// Taking a sqrt here helps hide the gaps between the pixels when the triad size is small
|
||||
return sqrt(alpha_x1 * alpha_y1 + alpha_x2 * alpha_y2);
|
||||
}
|
||||
|
||||
#endif // _PHOSHOR_MASK_CALCULATIONS_H
|
||||
@@ -1,243 +0,0 @@
|
||||
|
||||
#ifndef _QUAD_PIXEL_COMMUNICATION_H
|
||||
#define _QUAD_PIXEL_COMMUNICATION_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2014 TroggleMonkey*
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
///////////////////////////////// DISCLAIMER /////////////////////////////////
|
||||
|
||||
// *This code was inspired by "Shader Amortization using Pixel Quad Message
|
||||
// Passing" by Eric Penner, published in GPU Pro 2, Chapter VI.2. My intent
|
||||
// is not to plagiarize his fundamentally similar code and assert my own
|
||||
// copyright, but the algorithmic helper functions require so little code that
|
||||
// implementations can't vary by much except bugfixes and conventions. I just
|
||||
// wanted to license my own particular code here to avoid ambiguity and make it
|
||||
// clear that as far as I'm concerned, people can do as they please with it.
|
||||
|
||||
///////////////////////////////// DESCRIPTION ////////////////////////////////
|
||||
|
||||
// Given screen pixel numbers, derive a "quad vector" describing a fragment's
|
||||
// position in its 2x2 pixel quad. Given that vector, obtain the values of any
|
||||
// variable at neighboring fragments.
|
||||
// Requires: Using this file in general requires:
|
||||
// 1.) ddx() and ddy() are present in the current Cg profile.
|
||||
// 2.) The GPU driver is using fine/high-quality derivatives.
|
||||
// Functions will give incorrect results if this is not true,
|
||||
// so a test function is included.
|
||||
|
||||
|
||||
///////////////////// QUAD-PIXEL COMMUNICATION PRIMITIVES ////////////////////
|
||||
|
||||
float4 get_quad_vector_naive(float4 output_pixel_num_wrt_uvxy)
|
||||
{
|
||||
// Requires: Two measures of the current fragment's output pixel number
|
||||
// in the range ([0, output_size.x), [0, output_size.y)):
|
||||
// 1.) output_pixel_num_wrt_uvxy.xy increase with uv coords.
|
||||
// 2.) output_pixel_num_wrt_uvxy.zw increase with screen xy.
|
||||
// Returns: Two measures of the fragment's position in its 2x2 quad:
|
||||
// 1.) The .xy components are its 2x2 placement with respect to
|
||||
// uv direction (the origin (0, 0) is at the top-left):
|
||||
// top-left = (-1.0, -1.0) top-right = ( 1.0, -1.0)
|
||||
// bottom-left = (-1.0, 1.0) bottom-right = ( 1.0, 1.0)
|
||||
// You need this to arrange/weight shared texture samples.
|
||||
// 2.) The .zw components are its 2x2 placement with respect to
|
||||
// screen xy direction (position); the origin varies.
|
||||
// quad_gather needs this measure to work correctly.
|
||||
// Note: quad_vector.zw = quad_vector.xy * float2(
|
||||
// ddx(output_pixel_num_wrt_uvxy.x),
|
||||
// ddy(output_pixel_num_wrt_uvxy.y));
|
||||
// Caveats: This function assumes the GPU driver always starts 2x2 pixel
|
||||
// quads at even pixel numbers. This assumption can be wrong
|
||||
// for odd output resolutions (nondeterministically so).
|
||||
float4 pixel_odd = frac(output_pixel_num_wrt_uvxy * 0.5) * 2.0;
|
||||
float4 quad_vector = pixel_odd * 2.0 - float4(1.0, 1.0, 1.0, 1.0);
|
||||
return quad_vector;
|
||||
}
|
||||
|
||||
float4 get_quad_vector(float4 output_pixel_num_wrt_uvxy)
|
||||
{
|
||||
// Requires: Same as get_quad_vector_naive() (see that first).
|
||||
// Returns: Same as get_quad_vector_naive() (see that first), but it's
|
||||
// correct even if the 2x2 pixel quad starts at an odd pixel,
|
||||
// which can occur at odd resolutions.
|
||||
float4 quad_vector_guess =
|
||||
get_quad_vector_naive(output_pixel_num_wrt_uvxy);
|
||||
// If quad_vector_guess.zw doesn't increase with screen xy, we know
|
||||
// the 2x2 pixel quad starts at an odd pixel:
|
||||
float2 odd_start_mirror = 0.5 * float2(ddx(quad_vector_guess.z),
|
||||
ddy(quad_vector_guess.w));
|
||||
return quad_vector_guess * odd_start_mirror.xyxy;
|
||||
}
|
||||
|
||||
float4 get_quad_vector(float2 output_pixel_num_wrt_uv)
|
||||
{
|
||||
// Requires: 1.) ddx() and ddy() are present in the current Cg profile.
|
||||
// 2.) output_pixel_num_wrt_uv must increase with uv coords and
|
||||
// measure the current fragment's output pixel number in:
|
||||
// ([0, output_size.x), [0, output_size.y))
|
||||
// Returns: Same as get_quad_vector_naive() (see that first), but it's
|
||||
// correct even if the 2x2 pixel quad starts at an odd pixel,
|
||||
// which can occur at odd resolutions.
|
||||
// Caveats: This function requires less information than the version
|
||||
// taking a float4, but it's potentially slower.
|
||||
// Do screen coords increase with or against uv? Get the direction
|
||||
// with respect to (uv.x, uv.y) for (screen.x, screen.y) in {-1, 1}.
|
||||
float2 screen_uv_mirror = float2(ddx(output_pixel_num_wrt_uv.x),
|
||||
ddy(output_pixel_num_wrt_uv.y));
|
||||
float2 pixel_odd_wrt_uv = frac(output_pixel_num_wrt_uv * 0.5) * 2.0;
|
||||
float2 quad_vector_uv_guess = (pixel_odd_wrt_uv - float2(0.5, 0.5)) * 2.0;
|
||||
float2 quad_vector_screen_guess = quad_vector_uv_guess * screen_uv_mirror;
|
||||
// If quad_vector_screen_guess doesn't increase with screen xy, we know
|
||||
// the 2x2 pixel quad starts at an odd pixel:
|
||||
float2 odd_start_mirror = 0.5 * float2(ddx(quad_vector_screen_guess.x),
|
||||
ddy(quad_vector_screen_guess.y));
|
||||
float4 quad_vector_guess = float4(
|
||||
quad_vector_uv_guess, quad_vector_screen_guess);
|
||||
return quad_vector_guess * odd_start_mirror.xyxy;
|
||||
}
|
||||
|
||||
void quad_gather(float4 quad_vector, float4 curr,
|
||||
out float4 adjx, out float4 adjy, out float4 diag)
|
||||
{
|
||||
// Requires: 1.) ddx() and ddy() are present in the current Cg profile.
|
||||
// 2.) The GPU driver is using fine/high-quality derivatives.
|
||||
// 3.) quad_vector describes the current fragment's location in
|
||||
// its 2x2 pixel quad using get_quad_vector()'s conventions.
|
||||
// 4.) curr is any vector you wish to get neighboring values of.
|
||||
// Returns: Values of an input vector (curr) at neighboring fragments
|
||||
// adjacent x, adjacent y, and diagonal (via out parameters).
|
||||
adjx = curr - ddx(curr) * quad_vector.z;
|
||||
adjy = curr - ddy(curr) * quad_vector.w;
|
||||
diag = adjx - ddy(adjx) * quad_vector.w;
|
||||
}
|
||||
|
||||
void quad_gather(float4 quad_vector, float3 curr,
|
||||
out float3 adjx, out float3 adjy, out float3 diag)
|
||||
{
|
||||
// Float3 version
|
||||
adjx = curr - ddx(curr) * quad_vector.z;
|
||||
adjy = curr - ddy(curr) * quad_vector.w;
|
||||
diag = adjx - ddy(adjx) * quad_vector.w;
|
||||
}
|
||||
|
||||
void quad_gather(float4 quad_vector, float2 curr,
|
||||
out float2 adjx, out float2 adjy, out float2 diag)
|
||||
{
|
||||
// Float2 version
|
||||
adjx = curr - ddx(curr) * quad_vector.z;
|
||||
adjy = curr - ddy(curr) * quad_vector.w;
|
||||
diag = adjx - ddy(adjx) * quad_vector.w;
|
||||
}
|
||||
|
||||
float4 quad_gather(float4 quad_vector, float curr)
|
||||
{
|
||||
// Float version:
|
||||
// Returns: return.x == current
|
||||
// return.y == adjacent x
|
||||
// return.z == adjacent y
|
||||
// return.w == diagonal
|
||||
float4 all = float4(curr, curr, curr, curr);
|
||||
all.y = all.x - ddx(all.x) * quad_vector.z;
|
||||
all.zw = all.xy - ddy(all.xy) * quad_vector.w;
|
||||
return all;
|
||||
}
|
||||
|
||||
float4 quad_gather_sum(float4 quad_vector, float4 curr)
|
||||
{
|
||||
// Requires: Same as quad_gather()
|
||||
// Returns: Sum of an input vector (curr) at all fragments in a quad.
|
||||
float4 adjx, adjy, diag;
|
||||
quad_gather(quad_vector, curr, adjx, adjy, diag);
|
||||
return (curr + adjx + adjy + diag);
|
||||
}
|
||||
|
||||
float3 quad_gather_sum(float4 quad_vector, float3 curr)
|
||||
{
|
||||
// Float3 version:
|
||||
float3 adjx, adjy, diag;
|
||||
quad_gather(quad_vector, curr, adjx, adjy, diag);
|
||||
return (curr + adjx + adjy + diag);
|
||||
}
|
||||
|
||||
float2 quad_gather_sum(float4 quad_vector, float2 curr)
|
||||
{
|
||||
// Float2 version:
|
||||
float2 adjx, adjy, diag;
|
||||
quad_gather(quad_vector, curr, adjx, adjy, diag);
|
||||
return (curr + adjx + adjy + diag);
|
||||
}
|
||||
|
||||
float quad_gather_sum(float4 quad_vector, float curr)
|
||||
{
|
||||
// Float version:
|
||||
float4 all_values = quad_gather(quad_vector, curr);
|
||||
return (all_values.x + all_values.y + all_values.z + all_values.w);
|
||||
}
|
||||
|
||||
bool fine_derivatives_working(float4 quad_vector, float4 curr)
|
||||
{
|
||||
// Requires: 1.) ddx() and ddy() are present in the current Cg profile.
|
||||
// 2.) quad_vector describes the current fragment's location in
|
||||
// its 2x2 pixel quad using get_quad_vector()'s conventions.
|
||||
// 3.) curr must be a test vector with non-constant derivatives
|
||||
// (its value should change nonlinearly across fragments).
|
||||
// Returns: true if fine/hybrid/high-quality derivatives are used, or
|
||||
// false if coarse derivatives are used or inconclusive
|
||||
// Usage: Test whether quad-pixel communication is working!
|
||||
// Method: We can confirm fine derivatives are used if the following
|
||||
// holds (ever, for any value at any fragment):
|
||||
// (ddy(curr) != ddy(adjx)) or (ddx(curr) != ddx(adjy))
|
||||
// The more values we test (e.g. test a float4 two ways), the
|
||||
// easier it is to demonstrate fine derivatives are working.
|
||||
// TODO: Check for floating point exact comparison issues!
|
||||
float4 ddx_curr = ddx(curr);
|
||||
float4 ddy_curr = ddy(curr);
|
||||
float4 adjx = curr - ddx_curr * quad_vector.z;
|
||||
float4 adjy = curr - ddy_curr * quad_vector.w;
|
||||
bool ddy_different = any(bool4(ddy_curr.x != ddy(adjx).x, ddy_curr.y != ddy(adjx).y, ddy_curr.z != ddy(adjx).z, ddy_curr.w != ddy(adjx).w));
|
||||
bool ddx_different = any(bool4(ddx_curr.x != ddx(adjy).x, ddx_curr.y != ddx(adjy).y, ddx_curr.z != ddx(adjy).z, ddx_curr.w != ddx(adjy).w));
|
||||
return any(bool2(ddy_different, ddx_different));
|
||||
}
|
||||
|
||||
bool fine_derivatives_working_fast(float4 quad_vector, float curr)
|
||||
{
|
||||
// Requires: Same as fine_derivatives_working()
|
||||
// Returns: Same as fine_derivatives_working()
|
||||
// Usage: This is faster than fine_derivatives_working() but more
|
||||
// likely to return false negatives, so it's less useful for
|
||||
// offline testing/debugging. It's also useless as the basis
|
||||
// for dynamic runtime branching as of May 2014: Derivatives
|
||||
// (and quad-pixel communication) are currently disallowed in
|
||||
// branches. However, future GPU's may allow you to use them
|
||||
// in dynamic branches if you promise the branch condition
|
||||
// evaluates the same for every fragment in the quad (and/or if
|
||||
// the driver enforces that promise by making a single fragment
|
||||
// control branch decisions). If that ever happens, this
|
||||
// version may become a more economical choice.
|
||||
float ddx_curr = ddx(curr);
|
||||
float ddy_curr = ddy(curr);
|
||||
float adjx = curr - ddx_curr * quad_vector.z;
|
||||
return (ddy_curr != ddy(adjx));
|
||||
}
|
||||
|
||||
#endif // _QUAD_PIXEL_COMMUNICATION_H
|
||||
@@ -1,501 +0,0 @@
|
||||
#ifndef _SCANLINE_FUNCTIONS_H
|
||||
#define _SCANLINE_FUNCTIONS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
// Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
/////////////////////////////// BEGIN INCLUDES ///////////////////////////////
|
||||
|
||||
#include "bind-shader-params.fxh"
|
||||
#include "gamma-management.fxh"
|
||||
#include "special-functions.fxh"
|
||||
|
||||
//////////////////////////////// END INCLUDES ////////////////////////////////
|
||||
|
||||
///////////////////////////// SCANLINE FUNCTIONS /////////////////////////////
|
||||
|
||||
float2 round_coord(
|
||||
const float2 c,
|
||||
const float2 starting_position,
|
||||
const float2 bin_size
|
||||
) {
|
||||
const float2 adj_c = c - starting_position;
|
||||
return c - fmod(adj_c, bin_size) + bin_size * 0.5;
|
||||
}
|
||||
|
||||
|
||||
// Use preproc defs for these, so they work for arbitrary choices of float1/2/3/4
|
||||
#define triangle_wave(t, f) abs(1 - 2*frac((t) * (f)))
|
||||
|
||||
#define sawtooth_incr_wave(t, f) frac((t) * (f))
|
||||
|
||||
// using fmod(-t*f, 1.0) outputs 0 at t == 0, but I want it to output 1
|
||||
#define sawtooth_decr_wave(t, f) 1 - frac((t) * (f))
|
||||
|
||||
|
||||
struct InterpolationFieldData {
|
||||
float triangle_wave_freq;
|
||||
bool field_parity;
|
||||
bool scanline_parity;
|
||||
bool wrong_field;
|
||||
};
|
||||
|
||||
InterpolationFieldData precalc_interpolation_field_data(float2 texcoord) {
|
||||
InterpolationFieldData data;
|
||||
|
||||
data.triangle_wave_freq = 2;
|
||||
|
||||
const float field_wave = triangle_wave(texcoord.y + rcp(2*data.triangle_wave_freq), data.triangle_wave_freq * 0.5) * 2 - 1;
|
||||
data.scanline_parity = field_wave >= 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
InterpolationFieldData calc_interpolation_field_data(float2 texcoord, float scale) {
|
||||
InterpolationFieldData data;
|
||||
|
||||
data.triangle_wave_freq = scale * rcp(scanline_thickness);
|
||||
// data.triangle_wave_freq = content_size.y * rcp(scanline_thickness);
|
||||
|
||||
const bool frame_count_parity = (frame_count % 2 == 1) && (scanline_deinterlacing_mode != 1);
|
||||
data.field_parity = (frame_count_parity && !interlace_back_field_first) || (!frame_count_parity && interlace_back_field_first);
|
||||
|
||||
const float field_wave = triangle_wave(texcoord.y + rcp(2*data.triangle_wave_freq), data.triangle_wave_freq * 0.5) * 2 - 1;
|
||||
data.scanline_parity = field_wave >= 0;
|
||||
|
||||
const bool wrong_field_raw = (data.scanline_parity && !data.field_parity) || (!data.scanline_parity && data.field_parity);
|
||||
data.wrong_field = enable_interlacing && wrong_field_raw;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
float get_gaussian_sigma(const float color, const float sigma_range)
|
||||
{
|
||||
// Requires: Globals:
|
||||
// 1.) gaussian_beam_min_sigma and gaussian_beam_max_sigma are global floats
|
||||
// containing the desired minimum and maximum beam standard
|
||||
// deviations, for dim and bright colors respectively.
|
||||
// 2.) gaussian_beam_max_sigma must be > 0.0
|
||||
// 3.) gaussian_beam_min_sigma must be in (0.0, gaussian_beam_max_sigma]
|
||||
// 4.) gaussian_beam_spot_power must be defined as a global float.
|
||||
// Parameters:
|
||||
// 1.) color is the underlying source color along a scanline
|
||||
// 2.) sigma_range = gaussian_beam_max_sigma - gaussian_beam_min_sigma; we take
|
||||
// sigma_range as a parameter to avoid repeated computation
|
||||
// when beam_{min, max}_sigma are runtime shader parameters
|
||||
// Optional: Users may set beam_spot_shape_function to 1 to define the
|
||||
// inner f(color) subfunction (see below) as:
|
||||
// f(color) = sqrt(1.0 - (color - 1.0)*(color - 1.0))
|
||||
// Otherwise (technically, if beam_spot_shape_function < 0.5):
|
||||
// f(color) = pow(color, gaussian_beam_spot_power)
|
||||
// Returns: The standard deviation of the Gaussian beam for "color:"
|
||||
// sigma = gaussian_beam_min_sigma + sigma_range * f(color)
|
||||
// Details/Discussion:
|
||||
// The beam's spot shape vaguely resembles an aspect-corrected f() in the
|
||||
// range [0, 1] (not quite, but it's related). f(color) = color makes
|
||||
// spots look like diamonds, and a spherical function or cube balances
|
||||
// between variable width and a soft/realistic shape. A gaussian_beam_spot_power
|
||||
// > 1.0 can produce an ugly spot shape and more initial clipping, but the
|
||||
// final shape also differs based on the horizontal resampling filter and
|
||||
// the phosphor bloom. For instance, resampling horizontally in nonlinear
|
||||
// light and/or with a sharp (e.g. Lanczos) filter will sharpen the spot
|
||||
// shape, but a sixth root is still quite soft. A power function (default
|
||||
// 1.0/3.0 gaussian_beam_spot_power) is most flexible, but a fixed spherical curve
|
||||
// has the highest variability without an awful spot shape.
|
||||
//
|
||||
// gaussian_beam_min_sigma affects scanline sharpness/aliasing in dim areas, and its
|
||||
// difference from gaussian_beam_max_sigma affects beam width variability. It only
|
||||
// affects clipping [for pure Gaussians] if gaussian_beam_spot_power > 1.0 (which is
|
||||
// a conservative estimate for a more complex constraint).
|
||||
//
|
||||
// gaussian_beam_max_sigma affects clipping and increasing scanline width/softness
|
||||
// as color increases. The wider this is, the more scanlines need to be
|
||||
// evaluated to avoid distortion. For a pure Gaussian, the max_beam_sigma
|
||||
// at which the first unused scanline always has a weight < 1.0/255.0 is:
|
||||
// num scanlines = 2, max_beam_sigma = 0.2089; distortions begin ~0.34
|
||||
// num scanlines = 3, max_beam_sigma = 0.3879; distortions begin ~0.52
|
||||
// num scanlines = 4, max_beam_sigma = 0.5723; distortions begin ~0.70
|
||||
// num scanlines = 5, max_beam_sigma = 0.7591; distortions begin ~0.89
|
||||
// num scanlines = 6, max_beam_sigma = 0.9483; distortions begin ~1.08
|
||||
// Generalized Gaussians permit more leeway here as steepness increases.
|
||||
if(beam_spot_shape_function < 0.5)
|
||||
{
|
||||
// Use a power function:
|
||||
return gaussian_beam_min_sigma + sigma_range * pow(color, gaussian_beam_spot_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a spherical function:
|
||||
const float color_minus_1 = color - 1;
|
||||
return gaussian_beam_min_sigma + sigma_range * sqrt(1.0 - color_minus_1*color_minus_1);
|
||||
}
|
||||
}
|
||||
|
||||
float get_generalized_gaussian_beta(const float color, const float shape_range)
|
||||
{
|
||||
// Requires: Globals:
|
||||
// 1.) gaussian_beam_min_shape and gaussian_beam_max_shape are global floats
|
||||
// containing the desired min/max generalized Gaussian
|
||||
// beta parameters, for dim and bright colors respectively.
|
||||
// 2.) gaussian_beam_max_shape must be >= 2.0
|
||||
// 3.) gaussian_beam_min_shape must be in [2.0, gaussian_beam_max_shape]
|
||||
// 4.) gaussian_beam_shape_power must be defined as a global float.
|
||||
// Parameters:
|
||||
// 1.) color is the underlying source color along a scanline
|
||||
// 2.) shape_range = gaussian_beam_max_shape - gaussian_beam_min_shape; we take
|
||||
// shape_range as a parameter to avoid repeated computation
|
||||
// when beam_{min, max}_shape are runtime shader parameters
|
||||
// Returns: The type-I generalized Gaussian "shape" parameter beta for
|
||||
// the given color.
|
||||
// Details/Discussion:
|
||||
// Beta affects the scanline distribution as follows:
|
||||
// a.) beta < 2.0 narrows the peak to a spike with a discontinuous slope
|
||||
// b.) beta == 2.0 just degenerates to a Gaussian
|
||||
// c.) beta > 2.0 flattens and widens the peak, then drops off more steeply
|
||||
// than a Gaussian. Whereas high sigmas widen and soften peaks, high
|
||||
// beta widen and sharpen peaks at the risk of aliasing.
|
||||
// Unlike high gaussian_beam_spot_powers, high gaussian_beam_shape_powers actually soften shape
|
||||
// transitions, whereas lower ones sharpen them (at the risk of aliasing).
|
||||
return gaussian_beam_min_shape + shape_range * pow(color, gaussian_beam_shape_power);
|
||||
}
|
||||
|
||||
float3 get_raw_interpolated_color(const float3 color0,
|
||||
const float3 color1, const float3 color2, const float3 color3,
|
||||
const float4 weights)
|
||||
{
|
||||
// Use max to avoid bizarre artifacts from negative colors:
|
||||
const float4x3 mtrx = float4x3(color0, color1, color2, color3);
|
||||
const float3 m = mul(weights, mtrx);
|
||||
return max(m, 0.0);
|
||||
}
|
||||
|
||||
float3 get_interpolated_linear_color(const float3 color0, const float3 color1,
|
||||
const float3 color2, const float3 color3, const float4 weights)
|
||||
{
|
||||
// Requires: 1.) Requirements of include/gamma-management.h must be met:
|
||||
// intermediate_gamma must be globally defined, and input
|
||||
// colors are interpreted as linear RGB unless you #define
|
||||
// GAMMA_ENCODE_EVERY_FBO (in which case they are
|
||||
// interpreted as gamma-encoded with intermediate_gamma).
|
||||
// 2.) color0-3 are colors sampled from a texture with tex2D().
|
||||
// They are interpreted as defined in requirement 1.
|
||||
// 3.) weights contains weights for each color, summing to 1.0.
|
||||
// 4.) beam_horiz_linear_rgb_weight must be defined as a global
|
||||
// float in [0.0, 1.0] describing how much blending should
|
||||
// be done in linear RGB (rest is gamma-corrected RGB).
|
||||
// 5.) _RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE must be #defined
|
||||
// if beam_horiz_linear_rgb_weight is anything other than a
|
||||
// static constant, or we may try branching at runtime
|
||||
// without dynamic branches allowed (slow).
|
||||
// Returns: Return an interpolated color lookup between the four input
|
||||
// colors based on the weights in weights. The final color will
|
||||
// be a linear RGB value, but the blending will be done as
|
||||
// indicated above.
|
||||
const float intermediate_gamma = get_intermediate_gamma();
|
||||
const float inv_intermediate_gamma = 1.0 / intermediate_gamma;
|
||||
// Branch if beam_horiz_linear_rgb_weight is static (for free) or if the
|
||||
// profile allows dynamic branches (faster than computing extra pows):
|
||||
#if !_RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
|
||||
#define SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
|
||||
#else
|
||||
#if _DRIVERS_ALLOW_DYNAMIC_BRANCHES
|
||||
#define SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
|
||||
// beam_horiz_linear_rgb_weight is static, so we can branch:
|
||||
#ifdef GAMMA_ENCODE_EVERY_FBO
|
||||
const float3 gamma_mixed_color = pow(
|
||||
get_raw_interpolated_color(color0, color1, color2, color3, weights),
|
||||
intermediate_gamma);
|
||||
if(beam_horiz_linear_rgb_weight > 0.0)
|
||||
{
|
||||
const float3 linear_mixed_color = get_raw_interpolated_color(
|
||||
pow(color0, intermediate_gamma),
|
||||
pow(color1, intermediate_gamma),
|
||||
pow(color2, intermediate_gamma),
|
||||
pow(color3, intermediate_gamma),
|
||||
weights);
|
||||
return lerp(gamma_mixed_color, linear_mixed_color, beam_horiz_linear_rgb_weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
return gamma_mixed_color;
|
||||
}
|
||||
#else
|
||||
const float3 linear_mixed_color = get_raw_interpolated_color(
|
||||
color0, color1, color2, color3, weights);
|
||||
if(beam_horiz_linear_rgb_weight < 1.0)
|
||||
{
|
||||
const float3 gamma_mixed_color = get_raw_interpolated_color(
|
||||
pow(color0, inv_intermediate_gamma),
|
||||
pow(color1, inv_intermediate_gamma),
|
||||
pow(color2, inv_intermediate_gamma),
|
||||
pow(color3, inv_intermediate_gamma),
|
||||
weights);
|
||||
return lerp(gamma_mixed_color, linear_mixed_color, beam_horiz_linear_rgb_weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
return linear_mixed_color;
|
||||
}
|
||||
#endif // GAMMA_ENCODE_EVERY_FBO
|
||||
#else
|
||||
#ifdef GAMMA_ENCODE_EVERY_FBO
|
||||
// Inputs: color0-3 are colors in gamma-encoded RGB.
|
||||
const float3 gamma_mixed_color = pow(get_raw_interpolated_color(
|
||||
color0, color1, color2, color3, weights), intermediate_gamma);
|
||||
const float3 linear_mixed_color = get_raw_interpolated_color(
|
||||
pow(color0, intermediate_gamma),
|
||||
pow(color1, intermediate_gamma),
|
||||
pow(color2, intermediate_gamma),
|
||||
pow(color3, intermediate_gamma),
|
||||
weights);
|
||||
return lerp(gamma_mixed_color, linear_mixed_color, beam_horiz_linear_rgb_weight);
|
||||
#else
|
||||
// Inputs: color0-3 are colors in linear RGB.
|
||||
const float3 linear_mixed_color = get_raw_interpolated_color(
|
||||
color0, color1, color2, color3, weights);
|
||||
const float3 gamma_mixed_color = get_raw_interpolated_color(
|
||||
pow(color0, inv_intermediate_gamma),
|
||||
pow(color1, inv_intermediate_gamma),
|
||||
pow(color2, inv_intermediate_gamma),
|
||||
pow(color3, inv_intermediate_gamma),
|
||||
weights);
|
||||
// wtf fixme
|
||||
// const float beam_horiz_linear_rgb_weight1 = 1.0;
|
||||
return lerp(gamma_mixed_color, linear_mixed_color,
|
||||
beam_horiz_linear_rgb_weight);
|
||||
#endif // GAMMA_ENCODE_EVERY_FBO
|
||||
#endif // SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
|
||||
}
|
||||
|
||||
float3 get_scanline_color(const sampler2D tex, const float2 scanline_uv,
|
||||
const float2 uv_step_x, const float4 weights)
|
||||
{
|
||||
// Requires: 1.) scanline_uv must be vertically snapped to the caller's
|
||||
// desired line or scanline and horizontally snapped to the
|
||||
// texel just left of the output pixel (color1)
|
||||
// 2.) uv_step_x must contain the horizontal uv distance
|
||||
// between texels.
|
||||
// 3.) weights must contain interpolation filter weights for
|
||||
// color0, color1, color2, and color3, where color1 is just
|
||||
// left of the output pixel.
|
||||
// Returns: Return a horizontally interpolated texture lookup using 2-4
|
||||
// nearby texels, according to weights and the conventions of
|
||||
// get_interpolated_linear_color().
|
||||
// We can ignore the outside texture lookups for Quilez resampling.
|
||||
const float3 color1 = tex2D_linearize(tex, scanline_uv, get_input_gamma()).rgb;
|
||||
const float3 color2 = tex2D_linearize(tex, scanline_uv + uv_step_x, get_input_gamma()).rgb;
|
||||
float3 color0 = float3(0.0, 0.0, 0.0);
|
||||
float3 color3 = float3(0.0, 0.0, 0.0);
|
||||
if(beam_horiz_filter > 0.5)
|
||||
{
|
||||
color0 = tex2D_linearize(tex, scanline_uv - uv_step_x, get_input_gamma()).rgb;
|
||||
color3 = tex2D_linearize(tex, scanline_uv + 2.0 * uv_step_x, get_input_gamma()).rgb;
|
||||
}
|
||||
// Sample the texture as-is, whether it's linear or gamma-encoded:
|
||||
// get_interpolated_linear_color() will handle the difference.
|
||||
return get_interpolated_linear_color(color0, color1, color2, color3, weights);
|
||||
}
|
||||
|
||||
float3 sample_single_scanline_horizontal(const sampler2D tex,
|
||||
const float2 tex_uv, const float2 tex_size,
|
||||
const float2 texture_size_inv)
|
||||
{
|
||||
// TODO: Add function requirements.
|
||||
// Snap to the previous texel and get sample dists from 2/4 nearby texels:
|
||||
const float2 curr_texel = tex_uv * tex_size;
|
||||
// Use under_half to fix a rounding bug right around exact texel locations.
|
||||
const float2 prev_texel = floor(curr_texel - under_half) + 0.5;
|
||||
const float2 prev_texel_hor = float2(prev_texel.x, curr_texel.y);
|
||||
const float2 prev_texel_hor_uv = prev_texel_hor * texture_size_inv;
|
||||
const float prev_dist = curr_texel.x - prev_texel_hor.x;
|
||||
const float4 sample_dists = float4(1.0 + prev_dist, prev_dist,
|
||||
1.0 - prev_dist, 2.0 - prev_dist);
|
||||
// Get Quilez, Lanczos2, or Gaussian resize weights for 2/4 nearby texels:
|
||||
float4 weights;
|
||||
if (beam_horiz_filter < 0.5) {
|
||||
// None:
|
||||
weights = float4(0, 1, 0, 0);
|
||||
}
|
||||
else if(beam_horiz_filter < 1.5)
|
||||
{
|
||||
// Quilez:
|
||||
const float x = sample_dists.y;
|
||||
const float w2 = x*x*x*(x*(x*6.0 - 15.0) + 10.0);
|
||||
weights = float4(0.0, 1.0 - w2, w2, 0.0);
|
||||
}
|
||||
else if(beam_horiz_filter < 2.5)
|
||||
{
|
||||
// Gaussian:
|
||||
float inner_denom_inv = 1.0/(2.0*beam_horiz_sigma*beam_horiz_sigma);
|
||||
weights = exp(-(sample_dists*sample_dists)*inner_denom_inv);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lanczos2:
|
||||
const float4 pi_dists = FIX_ZERO(sample_dists * pi);
|
||||
weights = 2.0 * sin(pi_dists) * sin(pi_dists * 0.5) /
|
||||
(pi_dists * pi_dists);
|
||||
}
|
||||
// Ensure the weight sum == 1.0:
|
||||
const float4 final_weights = weights/dot(weights, float4(1.0, 1.0, 1.0, 1.0));
|
||||
// Get the interpolated horizontal scanline color:
|
||||
const float2 uv_step_x = float2(texture_size_inv.x, 0.0);
|
||||
return get_scanline_color(
|
||||
tex, prev_texel_hor_uv, uv_step_x, final_weights);
|
||||
}
|
||||
|
||||
float3 sample_rgb_scanline(
|
||||
const sampler2D tex,
|
||||
const float2 tex_uv, const float2 tex_size,
|
||||
const float2 texture_size_inv
|
||||
) {
|
||||
if (beam_misconvergence) {
|
||||
const float3 convergence_offsets_rgb_x = get_convergence_offsets_x_vector();
|
||||
const float3 convergence_offsets_rgb_y = get_convergence_offsets_y_vector();
|
||||
|
||||
const float3 offset_u_rgb = convergence_offsets_rgb_x * texture_size_inv.x;
|
||||
const float3 offset_v_rgb = convergence_offsets_rgb_y * texture_size_inv.y;
|
||||
|
||||
const float2 scanline_uv_r = tex_uv - float2(offset_u_rgb.r, offset_v_rgb.r);
|
||||
const float2 scanline_uv_g = tex_uv - float2(offset_u_rgb.g, offset_v_rgb.g);
|
||||
const float2 scanline_uv_b = tex_uv - float2(offset_u_rgb.b, offset_v_rgb.b);
|
||||
|
||||
/**/
|
||||
const float4 sample_r = tex2D(tex, scanline_uv_r);
|
||||
const float4 sample_g = tex2D(tex, scanline_uv_g);
|
||||
const float4 sample_b = tex2D(tex, scanline_uv_b);
|
||||
/**/
|
||||
|
||||
/*
|
||||
const float3 sample_r = sample_single_scanline_horizontal(
|
||||
tex, scanline_uv_r, tex_size, texture_size_inv);
|
||||
const float3 sample_g = sample_single_scanline_horizontal(
|
||||
tex, scanline_uv_g, tex_size, texture_size_inv);
|
||||
const float3 sample_b = sample_single_scanline_horizontal(
|
||||
tex, scanline_uv_b, tex_size, texture_size_inv);
|
||||
*/
|
||||
|
||||
return float3(sample_r.r, sample_g.g, sample_b.b);
|
||||
}
|
||||
else {
|
||||
// return tex2D(tex, tex_uv).rgb;
|
||||
return sample_single_scanline_horizontal(tex, tex_uv, tex_size, texture_size_inv);
|
||||
}
|
||||
}
|
||||
|
||||
float3 sample_rgb_scanline_horizontal(const sampler2D tex,
|
||||
const float2 tex_uv, const float2 tex_size,
|
||||
const float2 texture_size_inv)
|
||||
{
|
||||
// TODO: Add function requirements.
|
||||
// Rely on a helper to make convergence easier.
|
||||
if(beam_misconvergence)
|
||||
{
|
||||
const float3 convergence_offsets_rgb = get_convergence_offsets_x_vector();
|
||||
const float3 offset_u_rgb = convergence_offsets_rgb * texture_size_inv.xxx;
|
||||
const float2 scanline_uv_r = tex_uv - float2(offset_u_rgb.r, 0.0);
|
||||
const float2 scanline_uv_g = tex_uv - float2(offset_u_rgb.g, 0.0);
|
||||
const float2 scanline_uv_b = tex_uv - float2(offset_u_rgb.b, 0.0);
|
||||
const float3 sample_r = sample_single_scanline_horizontal(
|
||||
tex, scanline_uv_r, tex_size, texture_size_inv);
|
||||
const float3 sample_g = sample_single_scanline_horizontal(
|
||||
tex, scanline_uv_g, tex_size, texture_size_inv);
|
||||
const float3 sample_b = sample_single_scanline_horizontal(
|
||||
tex, scanline_uv_b, tex_size, texture_size_inv);
|
||||
return float3(sample_r.r, sample_g.g, sample_b.b);
|
||||
}
|
||||
else
|
||||
{
|
||||
return sample_single_scanline_horizontal(tex, tex_uv, tex_size, texture_size_inv);
|
||||
}
|
||||
}
|
||||
|
||||
float3 get_averaged_scanline_sample(
|
||||
sampler2D tex, const float2 texcoord,
|
||||
const float scanline_start_y, const float v_step_y,
|
||||
const float input_gamma
|
||||
) {
|
||||
// Sample `scanline_thickness` vertically-contiguous pixels and average them.
|
||||
float3 interpolated_line = 0.0;
|
||||
for (int i = 0; i < scanline_thickness; i++) {
|
||||
float4 coord = float4(texcoord.x, scanline_start_y + i * v_step_y, 0, 0);
|
||||
interpolated_line += tex2Dlod_linearize(tex, coord, input_gamma).rgb;
|
||||
}
|
||||
interpolated_line /= float(scanline_thickness);
|
||||
|
||||
return interpolated_line;
|
||||
}
|
||||
|
||||
float get_beam_strength(float dist, float color,
|
||||
const float sigma_range, const float shape_range)
|
||||
{
|
||||
// entry point in original is scanline_contrib()
|
||||
// this is based on scanline_gaussian_sampled_contrib() from original
|
||||
|
||||
// See scanline_gaussian_integral_contrib() for detailed comments!
|
||||
// gaussian sample = 1/(sigma*sqrt(2*pi)) * e**(-(x**2)/(2*sigma**2))
|
||||
const float sigma = get_gaussian_sigma(color, sigma_range);
|
||||
// Avoid repeated divides:
|
||||
const float sigma_inv = 1.0 / sigma;
|
||||
const float inner_denom_inv = 0.5 * sigma_inv * sigma_inv;
|
||||
const float outer_denom_inv = sigma_inv/sqrt(2.0*pi);
|
||||
|
||||
return color*exp(-(dist*dist)*inner_denom_inv)*outer_denom_inv;
|
||||
}
|
||||
|
||||
float get_gaussian_beam_strength(
|
||||
float dist,
|
||||
float color,
|
||||
const float sigma_range,
|
||||
const float shape_range
|
||||
) {
|
||||
// entry point in original is scanline_contrib()
|
||||
// this is based on scanline_generalized_gaussian_sampled_contrib() from original
|
||||
|
||||
// See scanline_generalized_gaussian_integral_contrib() for details!
|
||||
// generalized sample =
|
||||
// beta/(2*alpha*gamma(1/beta)) * e**(-(|x|/alpha)**beta)
|
||||
const float alpha = sqrt(2.0) * get_gaussian_sigma(color, sigma_range);
|
||||
const float beta = get_generalized_gaussian_beta(color, shape_range);
|
||||
// Avoid repeated divides:
|
||||
const float alpha_inv = 1.0 / alpha;
|
||||
const float beta_inv = 1.0 / beta;
|
||||
const float scale = color * beta * 0.5 * alpha_inv / gamma_impl(beta_inv, beta);
|
||||
|
||||
return scale * exp(-pow(abs(dist*alpha_inv), beta));
|
||||
}
|
||||
|
||||
float get_linear_beam_strength(
|
||||
const float dist,
|
||||
const float color,
|
||||
const float num_pixels,
|
||||
const bool interlaced
|
||||
) {
|
||||
const float p = color * (1 - abs(dist));
|
||||
return clamp(p, 0, color);
|
||||
}
|
||||
|
||||
|
||||
#endif // _SCANLINE_FUNCTIONS_H
|
||||
@@ -1,504 +0,0 @@
|
||||
#ifndef _SPECIAL_FUNCTIONS_H
|
||||
#define _SPECIAL_FUNCTIONS_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2014 TroggleMonkey
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
|
||||
///////////////////////////////// DESCRIPTION ////////////////////////////////
|
||||
|
||||
// This file implements the following mathematical special functions:
|
||||
// 1.) erf() = 2/sqrt(pi) * indefinite_integral(e**(-x**2))
|
||||
// 2.) gamma(s), a real-numbered extension of the integer factorial function
|
||||
// It also implements normalized_ligamma(s, z), a normalized lower incomplete
|
||||
// gamma function for s < 0.5 only. Both gamma() and normalized_ligamma() can
|
||||
// be called with an _impl suffix to use an implementation version with a few
|
||||
// extra precomputed parameters (which may be useful for the caller to reuse).
|
||||
// See below for details.
|
||||
//
|
||||
// Design Rationale:
|
||||
// Pretty much every line of code in this file is duplicated four times for
|
||||
// different input types (float4/float3/float2/float). This is unfortunate,
|
||||
// but Cg doesn't allow function templates. Macros would be far less verbose,
|
||||
// but they would make the code harder to document and read. I don't expect
|
||||
// these functions will require a whole lot of maintenance changes unless
|
||||
// someone ever has need for more robust incomplete gamma functions, so code
|
||||
// duplication seems to be the lesser evil in this case.
|
||||
|
||||
|
||||
/////////////////////////// GAUSSIAN ERROR FUNCTION //////////////////////////
|
||||
|
||||
float4 erf6(float4 x)
|
||||
{
|
||||
// Requires: x is the standard parameter to erf().
|
||||
// Returns: Return an Abramowitz/Stegun approximation of erf(), where:
|
||||
// erf(x) = 2/sqrt(pi) * integral(e**(-x**2))
|
||||
// This approximation has a max absolute error of 2.5*10**-5
|
||||
// with solid numerical robustness and efficiency. See:
|
||||
// https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions
|
||||
const float4 sign_x = sign(x);
|
||||
const float4 t = 1.0/(1.0 + 0.47047*abs(x));
|
||||
const float4 result = 1.0 - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
|
||||
exp(-(x*x));
|
||||
return result * sign_x;
|
||||
}
|
||||
|
||||
float3 erf6(const float3 x)
|
||||
{
|
||||
// Float3 version:
|
||||
const float3 sign_x = sign(x);
|
||||
const float3 t = 1.0/(1.0 + 0.47047*abs(x));
|
||||
const float3 result = 1.0 - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
|
||||
exp(-(x*x));
|
||||
return result * sign_x;
|
||||
}
|
||||
|
||||
float2 erf6(const float2 x)
|
||||
{
|
||||
// Float2 version:
|
||||
const float2 sign_x = sign(x);
|
||||
const float2 t = 1.0/(1.0 + 0.47047*abs(x));
|
||||
const float2 result = 1.0 - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
|
||||
exp(-(x*x));
|
||||
return result * sign_x;
|
||||
}
|
||||
|
||||
float erf6(const float x)
|
||||
{
|
||||
// Float version:
|
||||
const float sign_x = sign(x);
|
||||
const float t = 1.0/(1.0 + 0.47047*abs(x));
|
||||
const float result = 1.0 - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
|
||||
exp(-(x*x));
|
||||
return result * sign_x;
|
||||
}
|
||||
|
||||
float4 erft(const float4 x)
|
||||
{
|
||||
// Requires: x is the standard parameter to erf().
|
||||
// Returns: Approximate erf() with the hyperbolic tangent. The error is
|
||||
// visually noticeable, but it's blazing fast and perceptually
|
||||
// close...at least on ATI hardware. See:
|
||||
// http://www.maplesoft.com/applications/view.aspx?SID=5525&view=html
|
||||
// Warning: Only use this if your hardware drivers correctly implement
|
||||
// tanh(): My nVidia 8800GTS returns garbage output.
|
||||
return tanh(1.202760580 * x);
|
||||
}
|
||||
|
||||
float3 erft(const float3 x)
|
||||
{
|
||||
// Float3 version:
|
||||
return tanh(1.202760580 * x);
|
||||
}
|
||||
|
||||
float2 erft(const float2 x)
|
||||
{
|
||||
// Float2 version:
|
||||
return tanh(1.202760580 * x);
|
||||
}
|
||||
|
||||
float erft(const float x)
|
||||
{
|
||||
// Float version:
|
||||
return tanh(1.202760580 * x);
|
||||
}
|
||||
|
||||
float4 erf(const float4 x)
|
||||
{
|
||||
// Requires: x is the standard parameter to erf().
|
||||
// Returns: Some approximation of erf(x), depending on user settings.
|
||||
#ifdef ERF_FAST_APPROXIMATION
|
||||
return erft(x);
|
||||
#else
|
||||
return erf6(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
float3 erf(const float3 x)
|
||||
{
|
||||
// Float3 version:
|
||||
#ifdef ERF_FAST_APPROXIMATION
|
||||
return erft(x);
|
||||
#else
|
||||
return erf6(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
float2 erf(const float2 x)
|
||||
{
|
||||
// Float2 version:
|
||||
#ifdef ERF_FAST_APPROXIMATION
|
||||
return erft(x);
|
||||
#else
|
||||
return erf6(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
float erf(const float x)
|
||||
{
|
||||
// Float version:
|
||||
#ifdef ERF_FAST_APPROXIMATION
|
||||
return erft(x);
|
||||
#else
|
||||
return erf6(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////// COMPLETE GAMMA FUNCTION //////////////////////////
|
||||
|
||||
float4 gamma_impl(const float4 s, const float4 s_inv)
|
||||
{
|
||||
// Requires: 1.) s is the standard parameter to the gamma function, and
|
||||
// it should lie in the [0, 36] range.
|
||||
// 2.) s_inv = 1.0/s. This implementation function requires
|
||||
// the caller to precompute this value, giving users the
|
||||
// opportunity to reuse it.
|
||||
// Returns: Return approximate gamma function (real-numbered factorial)
|
||||
// output using the Lanczos approximation with two coefficients
|
||||
// calculated using Paul Godfrey's method here:
|
||||
// http://my.fit.edu/~gabdo/gamma.txt
|
||||
// An optimal g value for s in [0, 36] is ~1.12906830989, with
|
||||
// a maximum relative error of 0.000463 for 2**16 equally
|
||||
// evals. We could use three coeffs (0.0000346 error) without
|
||||
// hurting latency, but this allows more parallelism with
|
||||
// outside instructions.
|
||||
static const float g = 1.12906830989;
|
||||
static const float c0 = 0.8109119309638332633713423362694399653724431;
|
||||
static const float c1 = 0.4808354605142681877121661197951496120000040;
|
||||
static const float e = 2.71828182845904523536028747135266249775724709;
|
||||
const float4 sph = s + 0.5;
|
||||
const float4 lanczos_sum = c0 + c1/(s + 1.0);
|
||||
const float4 base = (sph + g)/e; // or (s + g + float4(0.5))/e
|
||||
// gamma(s + 1) = base**sph * lanczos_sum; divide by s for gamma(s).
|
||||
// This has less error for small s's than (s -= 1.0) at the beginning.
|
||||
return (pow(base, sph) * lanczos_sum) * s_inv;
|
||||
}
|
||||
|
||||
float3 gamma_impl(const float3 s, const float3 s_inv)
|
||||
{
|
||||
// Float3 version:
|
||||
static const float g = 1.12906830989;
|
||||
static const float c0 = 0.8109119309638332633713423362694399653724431;
|
||||
static const float c1 = 0.4808354605142681877121661197951496120000040;
|
||||
static const float e = 2.71828182845904523536028747135266249775724709;
|
||||
const float3 sph = s + 0.5;
|
||||
const float3 lanczos_sum = c0 + c1/(s + 1.0);
|
||||
const float3 base = (sph + g)/e;
|
||||
return (pow(base, sph) * lanczos_sum) * s_inv;
|
||||
}
|
||||
|
||||
float2 gamma_impl(const float2 s, const float2 s_inv)
|
||||
{
|
||||
// Float2 version:
|
||||
static const float g = 1.12906830989;
|
||||
static const float c0 = 0.8109119309638332633713423362694399653724431;
|
||||
static const float c1 = 0.4808354605142681877121661197951496120000040;
|
||||
static const float e = 2.71828182845904523536028747135266249775724709;
|
||||
const float2 sph = s + 0.5;
|
||||
const float2 lanczos_sum = c0 + c1/(s + 1.0);
|
||||
const float2 base = (sph + g)/e;
|
||||
return (pow(base, sph) * lanczos_sum) * s_inv;
|
||||
}
|
||||
|
||||
float gamma_impl(const float s, const float s_inv)
|
||||
{
|
||||
// Float version:
|
||||
static const float g = 1.12906830989;
|
||||
static const float c0 = 0.8109119309638332633713423362694399653724431;
|
||||
static const float c1 = 0.4808354605142681877121661197951496120000040;
|
||||
static const float e = 2.71828182845904523536028747135266249775724709;
|
||||
const float sph = s + 0.5;
|
||||
const float lanczos_sum = c0 + c1/(s + 1.0);
|
||||
const float base = (sph + g)/e;
|
||||
return (pow(base, sph) * lanczos_sum) * s_inv;
|
||||
}
|
||||
|
||||
float4 gamma(const float4 s)
|
||||
{
|
||||
// Requires: s is the standard parameter to the gamma function, and it
|
||||
// should lie in the [0, 36] range.
|
||||
// Returns: Return approximate gamma function output with a maximum
|
||||
// relative error of 0.000463. See gamma_impl for details.
|
||||
return gamma_impl(s, 1.0/s);
|
||||
}
|
||||
|
||||
float3 gamma(const float3 s)
|
||||
{
|
||||
// Float3 version:
|
||||
return gamma_impl(s, 1.0/s);
|
||||
}
|
||||
|
||||
float2 gamma(const float2 s)
|
||||
{
|
||||
// Float2 version:
|
||||
return gamma_impl(s, 1.0/s);
|
||||
}
|
||||
|
||||
float gamma(const float s)
|
||||
{
|
||||
// Float version:
|
||||
return gamma_impl(s, 1.0/s);
|
||||
}
|
||||
|
||||
|
||||
//////////////// INCOMPLETE GAMMA FUNCTIONS (RESTRICTED INPUT) ///////////////
|
||||
|
||||
// Lower incomplete gamma function for small s and z (implementation):
|
||||
float4 ligamma_small_z_impl(const float4 s, const float4 z, const float4 s_inv)
|
||||
{
|
||||
// Requires: 1.) s < ~0.5
|
||||
// 2.) z <= ~0.775075
|
||||
// 3.) s_inv = 1.0/s (precomputed for outside reuse)
|
||||
// Returns: A series representation for the lower incomplete gamma
|
||||
// function for small s and small z (4 terms).
|
||||
// The actual "rolled up" summation looks like:
|
||||
// last_sign = 1.0; last_pow = 1.0; last_factorial = 1.0;
|
||||
// sum = last_sign * last_pow / ((s + k) * last_factorial)
|
||||
// for(int i = 0; i < 4; ++i)
|
||||
// {
|
||||
// last_sign *= -1.0; last_pow *= z; last_factorial *= i;
|
||||
// sum += last_sign * last_pow / ((s + k) * last_factorial);
|
||||
// }
|
||||
// Unrolled, constant-unfolded and arranged for madds and parallelism:
|
||||
const float4 scale = pow(z, s);
|
||||
float4 sum = s_inv; // Summation iteration 0 result
|
||||
// Summation iterations 1, 2, and 3:
|
||||
const float4 z_sq = z*z;
|
||||
const float4 denom1 = s + 1.0;
|
||||
const float4 denom2 = 2.0*s + 4.0;
|
||||
const float4 denom3 = 6.0*s + 18.0;
|
||||
//float4 denom4 = 24.0*s + float4(96.0);
|
||||
sum -= z/denom1;
|
||||
sum += z_sq/denom2;
|
||||
sum -= z * z_sq/denom3;
|
||||
//sum += z_sq * z_sq / denom4;
|
||||
// Scale and return:
|
||||
return scale * sum;
|
||||
}
|
||||
|
||||
float3 ligamma_small_z_impl(const float3 s, const float3 z, const float3 s_inv)
|
||||
{
|
||||
// Float3 version:
|
||||
const float3 scale = pow(z, s);
|
||||
float3 sum = s_inv;
|
||||
const float3 z_sq = z*z;
|
||||
const float3 denom1 = s + 1.0;
|
||||
const float3 denom2 = 2.0*s + 4.0;
|
||||
const float3 denom3 = 6.0*s + 18.0;
|
||||
sum -= z/denom1;
|
||||
sum += z_sq/denom2;
|
||||
sum -= z * z_sq/denom3;
|
||||
return scale * sum;
|
||||
}
|
||||
|
||||
float2 ligamma_small_z_impl(const float2 s, const float2 z, const float2 s_inv)
|
||||
{
|
||||
// Float2 version:
|
||||
const float2 scale = pow(z, s);
|
||||
float2 sum = s_inv;
|
||||
const float2 z_sq = z*z;
|
||||
const float2 denom1 = s + 1.0;
|
||||
const float2 denom2 = 2.0*s + 4.0;
|
||||
const float2 denom3 = 6.0*s + 18.0;
|
||||
sum -= z/denom1;
|
||||
sum += z_sq/denom2;
|
||||
sum -= z * z_sq/denom3;
|
||||
return scale * sum;
|
||||
}
|
||||
|
||||
float ligamma_small_z_impl(const float s, const float z, const float s_inv)
|
||||
{
|
||||
// Float version:
|
||||
const float scale = pow(z, s);
|
||||
float sum = s_inv;
|
||||
const float z_sq = z*z;
|
||||
const float denom1 = s + 1.0;
|
||||
const float denom2 = 2.0*s + 4.0;
|
||||
const float denom3 = 6.0*s + 18.0;
|
||||
sum -= z/denom1;
|
||||
sum += z_sq/denom2;
|
||||
sum -= z * z_sq/denom3;
|
||||
return scale * sum;
|
||||
}
|
||||
|
||||
// Upper incomplete gamma function for small s and large z (implementation):
|
||||
float4 uigamma_large_z_impl(const float4 s, const float4 z)
|
||||
{
|
||||
// Requires: 1.) s < ~0.5
|
||||
// 2.) z > ~0.775075
|
||||
// Returns: Gauss's continued fraction representation for the upper
|
||||
// incomplete gamma function (4 terms).
|
||||
// The "rolled up" continued fraction looks like this. The denominator
|
||||
// is truncated, and it's calculated "from the bottom up:"
|
||||
// denom = float4('inf');
|
||||
// float4 one = float4(1.0);
|
||||
// for(int i = 4; i > 0; --i)
|
||||
// {
|
||||
// denom = ((i * 2.0) - one) + z - s + (i * (s - i))/denom;
|
||||
// }
|
||||
// Unrolled and constant-unfolded for madds and parallelism:
|
||||
const float4 numerator = pow(z, s) * exp(-z);
|
||||
float4 denom = 7.0 + z - s;
|
||||
denom = 5.0 + z - s + (3.0*s - 9.0)/denom;
|
||||
denom = 3.0 + z - s + (2.0*s - 4.0)/denom;
|
||||
denom = 1.0 + z - s + (s - 1.0)/denom;
|
||||
return numerator / denom;
|
||||
}
|
||||
|
||||
float3 uigamma_large_z_impl(const float3 s, const float3 z)
|
||||
{
|
||||
// Float3 version:
|
||||
const float3 numerator = pow(z, s) * exp(-z);
|
||||
float3 denom = 7.0 + z - s;
|
||||
denom = 5.0 + z - s + (3.0*s - 9.0)/denom;
|
||||
denom = 3.0 + z - s + (2.0*s - 4.0)/denom;
|
||||
denom = 1.0 + z - s + (s - 1.0)/denom;
|
||||
return numerator / denom;
|
||||
}
|
||||
|
||||
float2 uigamma_large_z_impl(const float2 s, const float2 z)
|
||||
{
|
||||
// Float2 version:
|
||||
const float2 numerator = pow(z, s) * exp(-z);
|
||||
float2 denom = 7.0 + z - s;
|
||||
denom = 5.0 + z - s + (3.0*s - 9.0)/denom;
|
||||
denom = 3.0 + z - s + (2.0*s - 4.0)/denom;
|
||||
denom = 1.0 + z - s + (s - 1.0)/denom;
|
||||
return numerator / denom;
|
||||
}
|
||||
|
||||
float uigamma_large_z_impl(const float s, const float z)
|
||||
{
|
||||
// Float version:
|
||||
const float numerator = pow(z, s) * exp(-z);
|
||||
float denom = 7.0 + z - s;
|
||||
denom = 5.0 + z - s + (3.0*s - 9.0)/denom;
|
||||
denom = 3.0 + z - s + (2.0*s - 4.0)/denom;
|
||||
denom = 1.0 + z - s + (s - 1.0)/denom;
|
||||
return numerator / denom;
|
||||
}
|
||||
|
||||
// Normalized lower incomplete gamma function for small s (implementation):
|
||||
float4 normalized_ligamma_impl(const float4 s, const float4 z,
|
||||
const float4 s_inv, const float4 gamma_s_inv)
|
||||
{
|
||||
// Requires: 1.) s < ~0.5
|
||||
// 2.) s_inv = 1/s (precomputed for outside reuse)
|
||||
// 3.) gamma_s_inv = 1/gamma(s) (precomputed for outside reuse)
|
||||
// Returns: Approximate the normalized lower incomplete gamma function
|
||||
// for s < 0.5. Since we only care about s < 0.5, we only need
|
||||
// to evaluate two branches (not four) based on z. Each branch
|
||||
// uses four terms, with a max relative error of ~0.00182. The
|
||||
// branch threshold and specifics were adapted for fewer terms
|
||||
// from Gil/Segura/Temme's paper here:
|
||||
// http://oai.cwi.nl/oai/asset/20433/20433B.pdf
|
||||
// Evaluate both branches: Real branches test slower even when available.
|
||||
static const float thresh = 0.775075;
|
||||
int4 z_is_large;
|
||||
z_is_large.x = int(z.x > thresh);
|
||||
z_is_large.y = int(z.y > thresh);
|
||||
z_is_large.z = int(z.z > thresh);
|
||||
z_is_large.w = int(z.w > thresh);
|
||||
const float4 large_z = 1.0 - uigamma_large_z_impl(s, z) * gamma_s_inv;
|
||||
const float4 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
|
||||
// Combine the results from both branches:
|
||||
int4 inverse_z_is_large = saturate(~(z_is_large));
|
||||
return large_z * float4(z_is_large) + small_z * float4(inverse_z_is_large);
|
||||
}
|
||||
|
||||
float3 normalized_ligamma_impl(const float3 s, const float3 z,
|
||||
const float3 s_inv, const float3 gamma_s_inv)
|
||||
{
|
||||
// Float3 version:
|
||||
static const float thresh = 0.775075;
|
||||
int3 z_is_large;
|
||||
z_is_large.x = int(z.x > thresh);
|
||||
z_is_large.y = int(z.y > thresh);
|
||||
z_is_large.z = int(z.z > thresh);
|
||||
const float3 large_z = 1.0 - uigamma_large_z_impl(s, z) * gamma_s_inv;
|
||||
const float3 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
|
||||
int3 inverse_z_is_large = saturate(~(z_is_large));
|
||||
return large_z * float3(z_is_large) + small_z * float3(inverse_z_is_large);
|
||||
}
|
||||
|
||||
float2 normalized_ligamma_impl(const float2 s, const float2 z,
|
||||
const float2 s_inv, const float2 gamma_s_inv)
|
||||
{
|
||||
// Float2 version:
|
||||
static const float thresh = 0.775075;
|
||||
int2 z_is_large;
|
||||
z_is_large.x = int(z.x > thresh);
|
||||
z_is_large.y = int(z.y > thresh);
|
||||
const float2 large_z = 1.0 - uigamma_large_z_impl(s, z) * gamma_s_inv;
|
||||
const float2 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
|
||||
int2 inverse_z_is_large = saturate(~(z_is_large));
|
||||
return large_z * float2(z_is_large) + small_z * float2(inverse_z_is_large);
|
||||
}
|
||||
|
||||
float normalized_ligamma_impl(const float s, const float z,
|
||||
const float s_inv, const float gamma_s_inv)
|
||||
{
|
||||
// Float version:
|
||||
static const float thresh = 0.775075;
|
||||
const bool z_is_large = z > thresh;
|
||||
const float large_z = 1.0 - uigamma_large_z_impl(s, z) * gamma_s_inv;
|
||||
const float small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
|
||||
return large_z * float(z_is_large) + small_z * float(!z_is_large);
|
||||
}
|
||||
|
||||
// Normalized lower incomplete gamma function for small s:
|
||||
float4 normalized_ligamma(const float4 s, const float4 z)
|
||||
{
|
||||
// Requires: s < ~0.5
|
||||
// Returns: Approximate the normalized lower incomplete gamma function
|
||||
// for s < 0.5. See normalized_ligamma_impl() for details.
|
||||
const float4 s_inv = 1.0/s;
|
||||
const float4 gamma_s_inv = 1.0/gamma_impl(s, s_inv);
|
||||
return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
|
||||
}
|
||||
|
||||
float3 normalized_ligamma(const float3 s, const float3 z)
|
||||
{
|
||||
// Float3 version:
|
||||
const float3 s_inv = 1.0/s;
|
||||
const float3 gamma_s_inv = 1.0/gamma_impl(s, s_inv);
|
||||
return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
|
||||
}
|
||||
|
||||
float2 normalized_ligamma(const float2 s, const float2 z)
|
||||
{
|
||||
// Float2 version:
|
||||
const float2 s_inv = 1.0/s;
|
||||
const float2 gamma_s_inv = 1.0/gamma_impl(s, s_inv);
|
||||
return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
|
||||
}
|
||||
|
||||
float normalized_ligamma(const float s, const float z)
|
||||
{
|
||||
// Float version:
|
||||
const float s_inv = 1.0/s;
|
||||
const float gamma_s_inv = 1.0/gamma_impl(s, s_inv);
|
||||
return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
|
||||
}
|
||||
|
||||
#endif // _SPECIAL_FUNCTIONS_H
|
||||