Compare commits
497 Commits
bjd/debugg
...
v1.30.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31d9da38fd | ||
|
|
e6854148d7 | ||
|
|
001daf0350 | ||
|
|
d26c48110d | ||
|
|
15a070f0c9 | ||
|
|
93230b06cf | ||
|
|
4c55fc3c48 | ||
|
|
a4797a631e | ||
|
|
5868e857aa | ||
|
|
32ba063bd7 | ||
|
|
02f0839f9b | ||
|
|
e50f3c4c91 | ||
|
|
e2384f59a2 | ||
|
|
7ca15bfc16 | ||
|
|
f619b62877 | ||
|
|
22e5d15a17 | ||
|
|
77fcf4d260 | ||
|
|
46a8b242a8 | ||
|
|
901d255026 | ||
|
|
b3cf555eb2 | ||
|
|
594cce35c7 | ||
|
|
8b96af8e3f | ||
|
|
641a0bda9e | ||
|
|
b1e438e141 | ||
|
|
a61338ff8b | ||
|
|
82da7dc999 | ||
|
|
9f7bb14bd1 | ||
|
|
6ec5fd86fa | ||
|
|
cf16bbe64b | ||
|
|
3da450a019 | ||
|
|
66276710f4 | ||
|
|
b7b7afb62a | ||
|
|
957380b258 | ||
|
|
b8ff6a9ad9 | ||
|
|
fe3f16924d | ||
|
|
a1dcb4f259 | ||
|
|
ffc3128377 | ||
|
|
c3501393fd | ||
|
|
c05e2ec47d | ||
|
|
9768f49714 | ||
|
|
6c54cfe88a | ||
|
|
a03de75a4e | ||
|
|
0c3d59aba3 | ||
|
|
ce1987f291 | ||
|
|
7eae926ed7 | ||
|
|
606af52eda | ||
|
|
8ea30aea80 | ||
|
|
72dea695ba | ||
|
|
1c0cf56ed0 | ||
|
|
bcb4eb35cd | ||
|
|
bce2676335 | ||
|
|
510097d722 | ||
|
|
5784118a12 | ||
|
|
b5de0f2d23 | ||
|
|
04df3f4dad | ||
|
|
093ca4d623 | ||
|
|
a3ed1558d3 | ||
|
|
fe379070ae | ||
|
|
ead0a2f597 | ||
|
|
5dbc593f90 | ||
|
|
d47dc12bf0 | ||
|
|
4392f63e57 | ||
|
|
f64b7aca79 | ||
|
|
3762ec5750 | ||
|
|
4591fdd9c0 | ||
|
|
d3068d2a0e | ||
|
|
ca0a4bc23a | ||
|
|
433c163c61 | ||
|
|
c867fda883 | ||
|
|
566540ae6d | ||
|
|
759f490dae | ||
|
|
867d4d44f5 | ||
|
|
65747d5877 | ||
|
|
bd357f6076 | ||
|
|
9e960b7d45 | ||
|
|
0c54d4a6a1 | ||
|
|
526e846a81 | ||
|
|
8bcfa373d4 | ||
|
|
db9a0f2c1f | ||
|
|
646b1e2193 | ||
|
|
41bd30f81d | ||
|
|
bd626aea27 | ||
|
|
8a03f75485 | ||
|
|
dc9594fbdf | ||
|
|
fad0b533c0 | ||
|
|
4d773e9453 | ||
|
|
e0c610b013 | ||
|
|
0da4f36c33 | ||
|
|
11d17e1db3 | ||
|
|
b8c318d923 | ||
|
|
e563cc6f5e | ||
|
|
cb8914ab96 | ||
|
|
2fecda7bdc | ||
|
|
543d8efb25 | ||
|
|
396b1079a7 | ||
|
|
eedcd9f8cb | ||
|
|
ab252b210c | ||
|
|
1071b8ea90 | ||
|
|
a9c5bbf185 | ||
|
|
8dd4bff7a7 | ||
|
|
77c54446af | ||
|
|
4a0bc0af57 | ||
|
|
a171e75e70 | ||
|
|
f5ffa092fe | ||
|
|
8de5fdd551 | ||
|
|
ecca3abe98 | ||
|
|
8570e35224 | ||
|
|
84df9f9a03 | ||
|
|
5f93fb9613 | ||
|
|
75f77fdbdd | ||
|
|
7825d582c2 | ||
|
|
5deb0ba933 | ||
|
|
18e917aaf2 | ||
|
|
a165f3890a | ||
|
|
f88b6d9c97 | ||
|
|
db8ecd9952 | ||
|
|
b5ec06c2d2 | ||
|
|
dfbac8385e | ||
|
|
eaab737b2c | ||
|
|
45991cda0a | ||
|
|
09a016bb6f | ||
|
|
31607d355d | ||
|
|
a67d50b9e2 | ||
|
|
8d42f53c80 | ||
|
|
5e21a55bce | ||
|
|
85930ea2e8 | ||
|
|
4b3cde8b39 | ||
|
|
eedfa85355 | ||
|
|
bb54c6c807 | ||
|
|
c23f905858 | ||
|
|
8c7be0a1d0 | ||
|
|
878497b3d5 | ||
|
|
a155561769 | ||
|
|
8b86a0ed2e | ||
|
|
26f9a9b122 | ||
|
|
6e5f6978fb | ||
|
|
0d31d7b2de | ||
|
|
dd862b7e0a | ||
|
|
52065f2cbd | ||
|
|
77c02d5831 | ||
|
|
f7e4c8d16d | ||
|
|
b7410474ff | ||
|
|
384cc4ebf6 | ||
|
|
7c0643f122 | ||
|
|
58abae3067 | ||
|
|
4742693869 | ||
|
|
6c39e474ea | ||
|
|
5c8977c906 | ||
|
|
6b3cc2e2f3 | ||
|
|
76b2edd6ea | ||
|
|
8ebb37d011 | ||
|
|
3366db83ef | ||
|
|
5415254aac | ||
|
|
caacc61602 | ||
|
|
e902df19b2 | ||
|
|
40b372dda7 | ||
|
|
fd330a98aa | ||
|
|
90c23a7d5d | ||
|
|
5710304114 | ||
|
|
0f684820bc | ||
|
|
e1d2d6ade6 | ||
|
|
e0b6f2ca71 | ||
|
|
2a35ee279b | ||
|
|
5abf780360 | ||
|
|
181f158ea9 | ||
|
|
f4087fc81d | ||
|
|
82793f9b82 | ||
|
|
537576e84a | ||
|
|
375d1f55e3 | ||
|
|
597218963f | ||
|
|
0d29b3ddc8 | ||
|
|
e0e3b42623 | ||
|
|
0995ca6614 | ||
|
|
3d741fc8d4 | ||
|
|
c20772b458 | ||
|
|
4a6b659098 | ||
|
|
2b93f08ca5 | ||
|
|
fca62b8fff | ||
|
|
dee6d9de2c | ||
|
|
574e3e7521 | ||
|
|
29fdf82ac5 | ||
|
|
c8cf2a54e8 | ||
|
|
bfd32e67d4 | ||
|
|
95915367fa | ||
|
|
b769cfda62 | ||
|
|
40ac88dfed | ||
|
|
6d96082f07 | ||
|
|
21f913db1c | ||
|
|
699a578966 | ||
|
|
babbfa1394 | ||
|
|
73f0d58e10 | ||
|
|
9cb4b74bbd | ||
|
|
f2c8456971 | ||
|
|
e571600c30 | ||
|
|
e84c94d3eb | ||
|
|
e791d4818f | ||
|
|
cdadb43e50 | ||
|
|
edaff60fbf | ||
|
|
3f64e46557 | ||
|
|
32dab23bc6 | ||
|
|
362de7dd31 | ||
|
|
6b01fbb903 | ||
|
|
4934d9f7bc | ||
|
|
ed73955b00 | ||
|
|
3f1f2726c4 | ||
|
|
1a7bd7ea8d | ||
|
|
946ea43436 | ||
|
|
7f42385f5f | ||
|
|
8845ac2b75 | ||
|
|
da85001d4d | ||
|
|
8d15079937 | ||
|
|
adc542b5cd | ||
|
|
72feb044a3 | ||
|
|
c0ba260ddf | ||
|
|
2da215e8e7 | ||
|
|
4d0368b5f1 | ||
|
|
d11c78857d | ||
|
|
e829d90c4a | ||
|
|
a8006acd33 | ||
|
|
86ec502040 | ||
|
|
b19a73cc50 | ||
|
|
a99c695932 | ||
|
|
8cd720b53a | ||
|
|
04df79e58f | ||
|
|
a4b3717762 | ||
|
|
1035e442ee | ||
|
|
60d3638f15 | ||
|
|
3e7d3c9035 | ||
|
|
eb360be2ad | ||
|
|
485ac8704d | ||
|
|
dc74540423 | ||
|
|
96219c22db | ||
|
|
f3b7048775 | ||
|
|
aaed6fb376 | ||
|
|
35a5d3310f | ||
|
|
9da79a1d2d | ||
|
|
595b355d1b | ||
|
|
3a67d769f4 | ||
|
|
6fb536a937 | ||
|
|
bb460d78d8 | ||
|
|
838835a715 | ||
|
|
63acd53e23 | ||
|
|
fcd2d0457b | ||
|
|
58fc26461b | ||
|
|
fd82f6b04e | ||
|
|
cef3200533 | ||
|
|
634500c398 | ||
|
|
b3e294ac54 | ||
|
|
2bf7535ad0 | ||
|
|
3315f75de9 | ||
|
|
bbe7dbfa92 | ||
|
|
5697922a65 | ||
|
|
4da83df2b9 | ||
|
|
8f156d6588 | ||
|
|
cec0871c11 | ||
|
|
41a809368b | ||
|
|
ea53eb9290 | ||
|
|
05875057c9 | ||
|
|
44125926d1 | ||
|
|
60734349de | ||
|
|
fbfd5ec0ec | ||
|
|
a74a95cc65 | ||
|
|
bc0ea16ff0 | ||
|
|
b2dc8aa84c | ||
|
|
9987e8b6ab | ||
|
|
0d9bdcc008 | ||
|
|
b5c634045e | ||
|
|
1f05531d53 | ||
|
|
88f382f0e3 | ||
|
|
3e59925900 | ||
|
|
ea404f8d4f | ||
|
|
602a550d93 | ||
|
|
12abbe2d23 | ||
|
|
fb0ee97588 | ||
|
|
56ef48c9c3 | ||
|
|
47c3dd3dd1 | ||
|
|
c181648bfa | ||
|
|
0cf78b3abe | ||
|
|
22889a7ad9 | ||
|
|
a14451d0ac | ||
|
|
5dfdab10b7 | ||
|
|
d6f2e3b8e9 | ||
|
|
df30517743 | ||
|
|
8f80643c1a | ||
|
|
5aea9be2fb | ||
|
|
ad02e483d0 | ||
|
|
f463d53036 | ||
|
|
b8d4408524 | ||
|
|
fef70be848 | ||
|
|
bdb12d9b24 | ||
|
|
43ad283a83 | ||
|
|
2e4936afc4 | ||
|
|
891ffabd11 | ||
|
|
e2c19498b4 | ||
|
|
c32630b265 | ||
|
|
bf21e78d02 | ||
|
|
525d4e08a3 | ||
|
|
2e9bf6d694 | ||
|
|
e845f01d85 | ||
|
|
bef48be7b4 | ||
|
|
b54fdc9e6e | ||
|
|
cedbf2e30b | ||
|
|
592f8d1b0d | ||
|
|
29612a684e | ||
|
|
e6d5807399 | ||
|
|
fa2553251f | ||
|
|
7387718852 | ||
|
|
a503a6209a | ||
|
|
ce3e5f74e8 | ||
|
|
f37112358e | ||
|
|
f368b14621 | ||
|
|
6960b1148a | ||
|
|
3cc23aac25 | ||
|
|
11dc8740f2 | ||
|
|
4b797cff88 | ||
|
|
fe1c1736cd | ||
|
|
4058ef5f09 | ||
|
|
d25ca01624 | ||
|
|
d96f87dbbf | ||
|
|
8a2e31023f | ||
|
|
1ea8e171d9 | ||
|
|
e2be3dd0ac | ||
|
|
1c51164e7b | ||
|
|
f190f03530 | ||
|
|
055fc7cbc1 | ||
|
|
9073fc3dc3 | ||
|
|
2409dc9bc4 | ||
|
|
6586c8d70b | ||
|
|
ac0c94da69 | ||
|
|
d19d6a72b0 | ||
|
|
c81b5d98ef | ||
|
|
756866675f | ||
|
|
ebcd4925f7 | ||
|
|
13bed4fdf9 | ||
|
|
1dae5c6b6c | ||
|
|
8e6663e4b0 | ||
|
|
ba804444b8 | ||
|
|
58cfb85004 | ||
|
|
ab46481b45 | ||
|
|
4296782399 | ||
|
|
ef375a7103 | ||
|
|
fd258b7765 | ||
|
|
147de8d372 | ||
|
|
eb2a1928b6 | ||
|
|
35b033102f | ||
|
|
7bc65421a9 | ||
|
|
736514cf37 | ||
|
|
db0158dae8 | ||
|
|
e706695ed1 | ||
|
|
e8877ffe2d | ||
|
|
1fd5d9dae6 | ||
|
|
cd48089318 | ||
|
|
6379ab22c9 | ||
|
|
0bf02b75d5 | ||
|
|
c4259b5598 | ||
|
|
6b3c1179bc | ||
|
|
c1a0e61e8e | ||
|
|
fc06298ed4 | ||
|
|
4ca87b188c | ||
|
|
f1f60c3e0d | ||
|
|
76d21b56af | ||
|
|
0ab0e50a4f | ||
|
|
34f4c06a5c | ||
|
|
6de36f1e53 | ||
|
|
2a9a3b1ac2 | ||
|
|
84b73a3770 | ||
|
|
662a10e273 | ||
|
|
ecce02502e | ||
|
|
d17875aea1 | ||
|
|
b8897a68f9 | ||
|
|
84efd4871e | ||
|
|
85ea5a6b70 | ||
|
|
77891acb92 | ||
|
|
74fe102035 | ||
|
|
25cc554925 | ||
|
|
d787a521b5 | ||
|
|
46e52c71e1 | ||
|
|
1dad27a172 | ||
|
|
60d230b380 | ||
|
|
d7cb38e706 | ||
|
|
ce00cca6ee | ||
|
|
d627d57bad | ||
|
|
8ffc776f1c | ||
|
|
be032b52c1 | ||
|
|
4388e81e5f | ||
|
|
71a185d139 | ||
|
|
d2cf5985ac | ||
|
|
debcbb8e5c | ||
|
|
b9dd62c7d3 | ||
|
|
dc2b430f34 | ||
|
|
e5ef4e8868 | ||
|
|
c0d6cd3ac3 | ||
|
|
b63ab2dc19 | ||
|
|
5d8dad561c | ||
|
|
8933be1ae2 | ||
|
|
6b66b48b1d | ||
|
|
9c23eb6e33 | ||
|
|
baea54a3fc | ||
|
|
d9f800454c | ||
|
|
f9ee0de07a | ||
|
|
2786d0a9f7 | ||
|
|
491e8032e6 | ||
|
|
ef3f13f5d3 | ||
|
|
bcb5b2d790 | ||
|
|
02de3f2e2a | ||
|
|
0e7bb53c07 | ||
|
|
759109d478 | ||
|
|
54d5af6edf | ||
|
|
38fbe47ced | ||
|
|
f066c925ba | ||
|
|
994fdf4e1d | ||
|
|
50b50d65e3 | ||
|
|
0aaa985649 | ||
|
|
29564f8eae | ||
|
|
c15db68a5b | ||
|
|
3452fb3e56 | ||
|
|
35eb8e7be1 | ||
|
|
834b774128 | ||
|
|
5aa0eb9f9d | ||
|
|
d9a6e2e649 | ||
|
|
cb823b16a1 | ||
|
|
0bd41e877e | ||
|
|
ecc3e73967 | ||
|
|
464b4c24f9 | ||
|
|
32367516e8 | ||
|
|
1709a55606 | ||
|
|
58b4455979 | ||
|
|
ea1dede19c | ||
|
|
20ea3381fa | ||
|
|
7aa6fccd7c | ||
|
|
adbd54f4f8 | ||
|
|
9d54261f18 | ||
|
|
a97757c9ae | ||
|
|
7c79d9f89d | ||
|
|
bf0914f813 | ||
|
|
b96bc30fbd | ||
|
|
62b50eb8ba | ||
|
|
b4932e384a | ||
|
|
5e68dc5f8d | ||
|
|
f222f1b925 | ||
|
|
22e4a54782 | ||
|
|
1289922c5f | ||
|
|
2839c352b8 | ||
|
|
6a01cbc312 | ||
|
|
6193156556 | ||
|
|
fe23aa917d | ||
|
|
eb8a29a332 | ||
|
|
0626902530 | ||
|
|
042bfe2597 | ||
|
|
97133f3591 | ||
|
|
d06cc4390e | ||
|
|
6047d3235f | ||
|
|
2cda6e35bd | ||
|
|
8f8d51e17b | ||
|
|
6919e3b274 | ||
|
|
10bf944410 | ||
|
|
9a2f6fdb53 | ||
|
|
761977d385 | ||
|
|
21248f15b5 | ||
|
|
4f32817f6d | ||
|
|
cc9e05e711 | ||
|
|
419d68d4db | ||
|
|
8450232448 | ||
|
|
cc51726590 | ||
|
|
318e22af51 | ||
|
|
68ac87dc24 | ||
|
|
acb8f00075 | ||
|
|
06d9183aaa | ||
|
|
75af25419d | ||
|
|
f6b90d2a31 | ||
|
|
a3822f4af0 | ||
|
|
bcdad769ff | ||
|
|
be4fb4fdbb | ||
|
|
65394f6301 | ||
|
|
b0beee03bc | ||
|
|
fe1de41b8e | ||
|
|
a37b431e87 | ||
|
|
98107016b9 | ||
|
|
8bccfc2863 | ||
|
|
f54a0a3452 | ||
|
|
6778ab0624 | ||
|
|
269d636785 | ||
|
|
39862c91ce | ||
|
|
523f4026b4 | ||
|
|
a6bf162431 | ||
|
|
826e8d181c | ||
|
|
16dfadbba0 | ||
|
|
5cbb97551f | ||
|
|
defee767c3 | ||
|
|
9560318521 | ||
|
|
ef09feb048 | ||
|
|
39f323fe09 | ||
|
|
11b95304ea | ||
|
|
b7c30a7916 | ||
|
|
4cae48fc77 | ||
|
|
d1a93f0557 | ||
|
|
b93059fad7 |
106
.github/workflows/release.yml
vendored
106
.github/workflows/release.yml
vendored
@@ -45,18 +45,23 @@ jobs:
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
- name: Run build script
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
run: |
|
||||
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
|
||||
cd build/$WORKFLOW_OS && printf "y" | ./build.sh release
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
cd ../..
|
||||
if [ -f out/filament-release-darwin.tgz ]; then mv out/filament-release-darwin.tgz out/filament-${TAG}-mac.tgz; fi;
|
||||
if [ -f out/filament-release-linux.tgz ]; then mv out/filament-release-linux.tgz out/filament-${TAG}-linux.tgz; fi;
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
- uses: actions/github-script@v6
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
|
||||
with:
|
||||
script: |
|
||||
const upload = require('./build/common/upload-release-assets');
|
||||
const { TAG } = process.env;
|
||||
const globber = await glob.create('out/*.tgz');
|
||||
await upload({ github, context }, await globber.glob(), TAG);
|
||||
|
||||
build-web:
|
||||
name: build-web
|
||||
@@ -75,16 +80,21 @@ jobs:
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/web && printf "y" | ./build.sh release
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
mv out/filament-release-web.tgz out/filament-${TAG}-web.tgz
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
|
||||
run: |
|
||||
cd build/web && printf "y" | ./build.sh release
|
||||
cd ../..
|
||||
mv out/filament-release-web.tgz out/filament-${TAG}-web.tgz
|
||||
- uses: actions/github-script@v6
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
with:
|
||||
script: |
|
||||
const upload = require('./build/common/upload-release-assets');
|
||||
const { TAG } = process.env;
|
||||
const globber = await glob.create('out/*.tgz');
|
||||
await upload({ github, context }, await globber.glob(), TAG);
|
||||
|
||||
build-android:
|
||||
name: build-android
|
||||
@@ -103,8 +113,16 @@ jobs:
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
- name: Run build script
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
run: |
|
||||
cd build/android && printf "y" | ./build.sh release
|
||||
cd ../..
|
||||
mv out/filament-android-release.aar out/filament-${TAG}-android.aar
|
||||
mv out/filamat-android-release.aar out/filamat-${TAG}-android.aar
|
||||
mv out/filamat-android-lite-release.aar out/filamat-${TAG}-lite-android.aar
|
||||
mv out/gltfio-android-release.aar out/gltfio-${TAG}-android.aar
|
||||
mv out/filament-utils-android-release.aar out/filament-utils-${TAG}-android.aar
|
||||
- name: Sign sample-gltf-viewer
|
||||
run: |
|
||||
echo "${APK_KEYSTORE_BASE64}" > filament.jks.base64
|
||||
@@ -119,18 +137,15 @@ jobs:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
APK_KEYSTORE_BASE64: ${{ secrets.APK_KEYSTORE_BASE64 }}
|
||||
APK_KEYSTORE_PASS: ${{ secrets.APK_KEYSTORE_PASS }}
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
mv out/filament-android-release.aar out/filament-${TAG}-android.aar
|
||||
mv out/filamat-android-release.aar out/filamat-${TAG}-android.aar
|
||||
mv out/filamat-android-lite-release.aar out/filamat-${TAG}-lite-android.aar
|
||||
mv out/gltfio-android-release.aar out/gltfio-${TAG}-android.aar
|
||||
mv out/filament-utils-android-release.aar out/filament-utils-${TAG}-android.aar
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.aar out/*.apk
|
||||
- uses: actions/github-script@v6
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
|
||||
with:
|
||||
script: |
|
||||
const upload = require('./build/common/upload-release-assets');
|
||||
const { TAG } = process.env;
|
||||
const globber = await glob.create(['out/*.aar', 'out/*.apk'].join('\n'));
|
||||
await upload({ github, context }, await globber.glob(), TAG);
|
||||
|
||||
build-ios:
|
||||
name: build-ios
|
||||
@@ -149,16 +164,21 @@ jobs:
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/ios && printf "y" | ./build.sh release
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
mv out/filament-release-ios.tgz out/filament-${TAG}-ios.tgz
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
|
||||
run: |
|
||||
cd build/ios && printf "y" | ./build.sh release
|
||||
cd ../..
|
||||
mv out/filament-release-ios.tgz out/filament-${TAG}-ios.tgz
|
||||
- uses: actions/github-script@v6
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
with:
|
||||
script: |
|
||||
const upload = require('./build/common/upload-release-assets');
|
||||
const { TAG } = process.env;
|
||||
const globber = await glob.create('out/*.tgz');
|
||||
await upload({ github, context }, await globber.glob(), TAG);
|
||||
|
||||
build-windows:
|
||||
name: build-windows
|
||||
@@ -178,15 +198,19 @@ jobs:
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
- name: Run build script
|
||||
run: |
|
||||
build\windows\build-github.bat release
|
||||
shell: cmd
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
pip3 install PyGithub
|
||||
mv out/filament-windows.tgz out/filament-${TAG}-windows.tgz
|
||||
python build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
shell: bash
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
|
||||
run: |
|
||||
build\windows\build-github.bat release
|
||||
cd ..\..
|
||||
move out\filament-windows.tgz out\filament-%TAG%-windows.tgz
|
||||
shell: cmd
|
||||
- uses: actions/github-script@v6
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
with:
|
||||
script: |
|
||||
const upload = require('./build/common/upload-release-assets');
|
||||
const { TAG } = process.env;
|
||||
const globber = await glob.create('out/*.tgz');
|
||||
await upload({ github, context }, await globber.glob(), TAG);
|
||||
|
||||
@@ -74,18 +74,18 @@ if (CCACHE_PROGRAM)
|
||||
configure_file(build/launch-cxx.in launch-cxx)
|
||||
|
||||
execute_process(COMMAND chmod a+rx
|
||||
"${CMAKE_BINARY_DIR}/launch-c"
|
||||
"${CMAKE_BINARY_DIR}/launch-cxx"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/launch-c"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/launch-cxx"
|
||||
)
|
||||
|
||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
|
||||
else()
|
||||
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-c")
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -99,6 +99,10 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
# ==================================================================================================
|
||||
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL)
|
||||
set(LINUX TRUE)
|
||||
else()
|
||||
# since cmake 3.25 LINUX is automatically set based on CMAKE_SYSTEM_NAME, which the android
|
||||
# cmake files are setting to "Linux".
|
||||
set(LINUX FALSE)
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.28.2'
|
||||
implementation 'com.google.android.filament:filament-android:1.30.0'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```
|
||||
pod 'Filament', '~> 1.28.2'
|
||||
pod 'Filament', '~> 1.30.0'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
@@ -117,9 +117,9 @@ steps:
|
||||
- Image-based lighting
|
||||
- Physically-based camera (shutter speed, sensitivity and aperture)
|
||||
- Physical light units
|
||||
- Point lights, spot lights and directional light
|
||||
- Point lights, spot lights, and directional light
|
||||
- Specular anti-aliasing
|
||||
- Spot and directional light shadows
|
||||
- Point, spot, and directional light shadows
|
||||
- Cascaded shadows
|
||||
- EVSM, PCSS, DPCF, or PCF shadows
|
||||
- Transparent shadows
|
||||
|
||||
@@ -5,10 +5,19 @@ A new header is inserted each time a *tag* is created.
|
||||
|
||||
## main branch
|
||||
|
||||
## v1.30.0
|
||||
|
||||
- engine: optimize per-shadow UBO [⚠️ **Recompile Materials**]
|
||||
- engine: fix potential memory corruption with larger scenes
|
||||
- engine: VSM's MSAA setting is now per-view instead of per-light [⚠️ **API Change**]
|
||||
|
||||
## v1.29.0
|
||||
|
||||
- gltfio: calculate primitive's AABB correctly.
|
||||
- gltfio: recompute bounding boxes with morph targets
|
||||
- engine: add missing getters on `MaterialInstance`
|
||||
- WebGL: add missing `ColorGrading` JS bindings
|
||||
- engine: improvements/cleanup of Shadow mapping code [⚠️ **Recompile Materials**]
|
||||
|
||||
## v1.28.3
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
|
||||
jfloat shadowFarHint, jboolean stable, jboolean lispsm,
|
||||
jfloat polygonOffsetConstant, jfloat polygonOffsetSlope,
|
||||
jboolean screenSpaceContactShadows, jint stepCount,
|
||||
jfloat maxShadowDistance, jint vsmMsaaSamples, jboolean elvsm, jfloat blurWidth, jfloat shadowBulbRadius) {
|
||||
jfloat maxShadowDistance, jboolean elvsm, jfloat blurWidth, jfloat shadowBulbRadius) {
|
||||
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
|
||||
LightManager::ShadowOptions shadowOptions {
|
||||
.mapSize = (uint32_t)mapSize,
|
||||
@@ -97,7 +97,6 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
|
||||
.stepCount = uint8_t(stepCount),
|
||||
.maxShadowDistance = maxShadowDistance,
|
||||
.vsm = {
|
||||
.msaaSamples = (uint8_t) vsmMsaaSamples,
|
||||
.elvsm = (bool)elvsm,
|
||||
.blurWidth = blurWidth
|
||||
},
|
||||
|
||||
@@ -349,20 +349,6 @@ public class LightManager {
|
||||
* @see View#setShadowType
|
||||
*/
|
||||
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Warning: This API is still experimental and subject to change.</strong>
|
||||
* </p>
|
||||
*/
|
||||
@IntRange(from = 1)
|
||||
public int vsmMsaaSamples = 1;
|
||||
|
||||
|
||||
/**
|
||||
* When elvsm is set to true, "Exponential Layered VSM without Layers" are used. It is
|
||||
* an improvement to the default EVSM which suffers important light leaks. Enabling
|
||||
@@ -519,7 +505,7 @@ public class LightManager {
|
||||
options.shadowFarHint, options.stable, options.lispsm,
|
||||
options.polygonOffsetConstant, options.polygonOffsetSlope,
|
||||
options.screenSpaceContactShadows,
|
||||
options.stepCount, options.maxShadowDistance, options.vsmMsaaSamples,
|
||||
options.stepCount, options.maxShadowDistance,
|
||||
options.elvsm, options.blurWidth, options.shadowBulbRadius);
|
||||
return this;
|
||||
}
|
||||
@@ -1185,7 +1171,7 @@ public class LightManager {
|
||||
boolean stable, boolean lispsm,
|
||||
float polygonOffsetConstant, float polygonOffsetSlope,
|
||||
boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance,
|
||||
int vsmMsaaSamples, boolean elvsm, float blurWidth, float shadowBulbRadius);
|
||||
boolean elvsm, float blurWidth, float shadowBulbRadius);
|
||||
private static native void nBuilderCastLight(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderPosition(long nativeBuilder, float x, float y, float z);
|
||||
private static native void nBuilderDirection(long nativeBuilder, float x, float y, float z);
|
||||
|
||||
@@ -1817,6 +1817,13 @@ public class View {
|
||||
* Whether to generate mipmaps for all VSM shadow maps.
|
||||
*/
|
||||
public boolean mipmapping = false;
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*/
|
||||
public int msaaSamples = 1;
|
||||
/**
|
||||
* Whether to use a 32-bits or 16-bits texture format for VSM shadow maps. 32-bits
|
||||
* precision is rarely needed, but it does reduces light leaks as well as "fading"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.28.2
|
||||
VERSION_NAME=1.30.0
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
setuptools==58.0.4
|
||||
wheel==0.37.1
|
||||
certifi==2022.9.24
|
||||
cffi==1.15.1
|
||||
charset-normalizer==2.1.1
|
||||
Deprecated==1.2.13
|
||||
idna==3.4
|
||||
pycparser==2.21
|
||||
PyGithub==1.56
|
||||
PyJWT==2.6.0
|
||||
PyNaCl==1.5.0
|
||||
requests==2.28.1
|
||||
urllib3==1.26.12
|
||||
wrapt==1.14.1
|
||||
@@ -1,93 +0,0 @@
|
||||
# Copyright (C) 2019 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# requirements.txt created via:
|
||||
#
|
||||
# pip3 install virtualenv
|
||||
# python3 -m venv env
|
||||
# pip3 install PyGithub
|
||||
# pip3 install wheel
|
||||
# --all includes wheel and setuputils, which is needed for GitHub Actions
|
||||
# pip3 freeze --all > requirements.txt
|
||||
# Manually move 'setuptools' and 'wheel' lines to the beginning of the file.
|
||||
# Manually remove the 'pip' line.
|
||||
#
|
||||
# Requirements are installed in GitHub Actions via:
|
||||
# xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
# xargs must be used because the ordering of the dependencies matters (namely, setuptools).
|
||||
# sudo must be used to uninstall non-matching versions of packages.
|
||||
# pip is removed to avoid conflicts with the pre-installed pip version on Actions.
|
||||
# This technique does not work with Windows, unfortunately.
|
||||
|
||||
from github import Github
|
||||
import os, sys
|
||||
|
||||
def print_usage():
|
||||
print('Upload assets to a Filament GitHub release.')
|
||||
print()
|
||||
print('Usage:')
|
||||
print(' upload-assets.py <tag> <asset>...')
|
||||
print()
|
||||
print('Notes:')
|
||||
print(' The GitHub release must already be created prior to running this script. This is typically done')
|
||||
print(' through the GitHub web UI.')
|
||||
print()
|
||||
print(' <tag> is the Git tag for the desired release to attach assets to, for example, "v1.4.2".')
|
||||
print()
|
||||
print(' <asset> is a path to the asset file to upload. The file name will be used as the name of the')
|
||||
print(' asset.')
|
||||
print()
|
||||
print(' The GITHUB_API_KEY environment variable must be set to a valid authentication token for a')
|
||||
print(' collaborator account of the Filament repository.')
|
||||
|
||||
# The first argument is the path to this script.
|
||||
if len(sys.argv) < 3:
|
||||
print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
tag = sys.argv[1]
|
||||
assets = sys.argv[2:]
|
||||
|
||||
authentication_token = os.environ.get('GITHUB_API_KEY')
|
||||
if not authentication_token:
|
||||
sys.stderr.write('Error: the GITHUB_API_KEY is not set.\n')
|
||||
sys.exit(1)
|
||||
|
||||
g = Github(authentication_token)
|
||||
|
||||
FILAMENT_REPO = "google/filament"
|
||||
filament = g.get_repo(FILAMENT_REPO)
|
||||
|
||||
def find_release_from_tag(repo, tag):
|
||||
""" Find a release in the repo for the given Git tag string. """
|
||||
releases = repo.get_releases()
|
||||
for r in releases:
|
||||
if r.tag_name == tag:
|
||||
return r
|
||||
return None
|
||||
|
||||
release = find_release_from_tag(filament, tag)
|
||||
if not release:
|
||||
sys.stderr.write(f"Error: Could not find release with tag '{tag}'.\n")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Found release with tag '{tag}'.")
|
||||
|
||||
for asset_path in assets:
|
||||
sys.stdout.write(f'Uploding asset: {asset_path}... ')
|
||||
asset_name = os.path.basename(asset_path)
|
||||
asset = release.upload_asset(asset_path, name=asset_name)
|
||||
if asset:
|
||||
sys.stdout.write('Success!\n')
|
||||
78
build/common/upload-release-assets/index.js
Normal file
78
build/common/upload-release-assets/index.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const uploadReleaseAssets = async ({github, context}, assetPathsToUpload, releaseTag) => {
|
||||
const fs = require('fs/promises');
|
||||
const path = require('path');
|
||||
|
||||
const filesToUpload = assetPathsToUpload.map(assetPath => ({
|
||||
buffer: fs.readFile(assetPath),
|
||||
assetName: path.basename(assetPath)
|
||||
}));
|
||||
|
||||
const findReleaseMatchingTag = async tag => {
|
||||
const { data: releases } = await github.rest.repos.listReleases(context.repo);
|
||||
const release = releases.find(release => release.tag_name === releaseTag);
|
||||
if (!release) {
|
||||
throw new Error(`Could not locate release with tag '${releaseTag}'`);
|
||||
}
|
||||
return release;
|
||||
};
|
||||
|
||||
const release = await findReleaseMatchingTag(releaseTag);
|
||||
|
||||
console.log(`Found release named '${release.name}' matching tag '${release.tag_name}'.`);
|
||||
|
||||
const uploadPromises = [];
|
||||
for (const file of filesToUpload) {
|
||||
console.log(`Uploading asset ${file.assetName}.`);
|
||||
const p = github.rest.repos.uploadReleaseAsset({
|
||||
...context.repo,
|
||||
release_id: release.id,
|
||||
name: file.assetName,
|
||||
data: await file.buffer
|
||||
});
|
||||
uploadPromises.push(p);
|
||||
}
|
||||
|
||||
await Promise.all(uploadPromises);
|
||||
console.log("Done!");
|
||||
}
|
||||
|
||||
module.exports = uploadReleaseAssets;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// To test this script locally, uncomment the code below and run:
|
||||
//
|
||||
// npm install
|
||||
// node index.js
|
||||
|
||||
// const { Octokit } = require("@octokit/rest");
|
||||
// const glob = require("@actions/glob");
|
||||
// (async () => {
|
||||
// const github = new Octokit({
|
||||
// auth: "" // <-- paste GitHub auth token here
|
||||
// });
|
||||
// const context = {
|
||||
// repo: {
|
||||
// owner: "bejado",
|
||||
// repo: "filament",
|
||||
// },
|
||||
// };
|
||||
// const globber = await glob.create('*.txt');
|
||||
// await uploadReleaseAssets({ github, context }, await globber.glob(), 'vtest-28');
|
||||
// })();
|
||||
546
build/common/upload-release-assets/package-lock.json
generated
Normal file
546
build/common/upload-release-assets/package-lock.json
generated
Normal file
@@ -0,0 +1,546 @@
|
||||
{
|
||||
"name": "upload-release-assets",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@actions/glob": "^0.3.0",
|
||||
"@octokit/rest": "^19.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
|
||||
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.3.0.tgz",
|
||||
"integrity": "sha512-tJP1ZhF87fd6LBnaXWlahkyvdgvsLl7WnreW1EZaC8JWjpMXmzqWzQVe/IEYslrkT9ymibVrKyJN4UMD7uQM2w==",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.6",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz",
|
||||
"integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz",
|
||||
"integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^3.0.0",
|
||||
"@octokit/graphql": "^5.0.0",
|
||||
"@octokit/request": "^6.0.0",
|
||||
"@octokit/request-error": "^3.0.0",
|
||||
"@octokit/types": "^8.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz",
|
||||
"integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz",
|
||||
"integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^6.0.0",
|
||||
"@octokit/types": "^8.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz",
|
||||
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz",
|
||||
"integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz",
|
||||
"integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"deprecation": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
|
||||
"integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^7.0.0",
|
||||
"@octokit/request-error": "^3.0.0",
|
||||
"@octokit/types": "^8.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz",
|
||||
"integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "19.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz",
|
||||
"integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^4.1.0",
|
||||
"@octokit/plugin-paginate-rest": "^5.0.0",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^6.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz",
|
||||
"integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
|
||||
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
|
||||
"requires": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
},
|
||||
"@actions/glob": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.3.0.tgz",
|
||||
"integrity": "sha512-tJP1ZhF87fd6LBnaXWlahkyvdgvsLl7WnreW1EZaC8JWjpMXmzqWzQVe/IEYslrkT9ymibVrKyJN4UMD7uQM2w==",
|
||||
"requires": {
|
||||
"@actions/core": "^1.2.6",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"@actions/http-client": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||
"requires": {
|
||||
"tunnel": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"@octokit/auth-token": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz",
|
||||
"integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz",
|
||||
"integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^3.0.0",
|
||||
"@octokit/graphql": "^5.0.0",
|
||||
"@octokit/request": "^6.0.0",
|
||||
"@octokit/request-error": "^3.0.0",
|
||||
"@octokit/types": "^8.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz",
|
||||
"integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz",
|
||||
"integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==",
|
||||
"requires": {
|
||||
"@octokit/request": "^6.0.0",
|
||||
"@octokit/types": "^8.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/openapi-types": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz",
|
||||
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw=="
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz",
|
||||
"integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
|
||||
"requires": {}
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz",
|
||||
"integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
|
||||
"integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^7.0.0",
|
||||
"@octokit/request-error": "^3.0.0",
|
||||
"@octokit/types": "^8.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz",
|
||||
"integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==",
|
||||
"requires": {
|
||||
"@octokit/types": "^8.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "19.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz",
|
||||
"integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==",
|
||||
"requires": {
|
||||
"@octokit/core": "^4.1.0",
|
||||
"@octokit/plugin-paginate-rest": "^5.0.0",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^6.7.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz",
|
||||
"integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^14.0.0"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
15
build/common/upload-release-assets/package.json
Normal file
15
build/common/upload-release-assets/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "upload-release-assets",
|
||||
"version": "1.0.0",
|
||||
"description": "Upload Filament release assets",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Google",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@actions/glob": "^0.3.0",
|
||||
"@octokit/rest": "^19.0.5"
|
||||
}
|
||||
}
|
||||
@@ -2360,8 +2360,10 @@ void OpenGLDriver::beginRenderPass(Handle<HwRenderTarget> rth,
|
||||
mRenderPassDepthWrite = any(clearFlags & TargetBufferFlags::DEPTH);
|
||||
mRenderPassStencilWrite = any(clearFlags & TargetBufferFlags::STENCIL);
|
||||
|
||||
static_assert(sizeof(GLsizei) >= sizeof(uint32_t));
|
||||
gl.viewport(params.viewport.left, params.viewport.bottom,
|
||||
(GLsizei)params.viewport.width, (GLsizei)params.viewport.height);
|
||||
(GLsizei)std::min(uint32_t(std::numeric_limits<int32_t>::max()), params.viewport.width),
|
||||
(GLsizei)std::min(uint32_t(std::numeric_limits<int32_t>::max()), params.viewport.height));
|
||||
|
||||
gl.depthRange(params.depthRange.near, params.depthRange.far);
|
||||
|
||||
|
||||
@@ -105,16 +105,16 @@ void OpenGLProgram::compileShaders(OpenGLContext& context,
|
||||
GLuint shaderIds[Program::SHADER_TYPE_COUNT],
|
||||
std::array<CString, Program::SHADER_TYPE_COUNT>& outShaderSourceCode) noexcept {
|
||||
|
||||
std::string specificationConstantString;
|
||||
std::string specializationConstantString;
|
||||
for (auto const& sc : specializationConstants) {
|
||||
specificationConstantString += "#define SPIRV_CROSS_CONSTANT_ID_" + std::to_string(sc.id) + ' ';
|
||||
specificationConstantString += std::visit([](auto&& arg) {
|
||||
specializationConstantString += "#define SPIRV_CROSS_CONSTANT_ID_" + std::to_string(sc.id) + ' ';
|
||||
specializationConstantString += std::visit([](auto&& arg) {
|
||||
return std::to_string(arg);
|
||||
}, sc.value);
|
||||
specificationConstantString += '\n';
|
||||
specializationConstantString += '\n';
|
||||
}
|
||||
if (!specificationConstantString.empty()) {
|
||||
specificationConstantString += '\n';
|
||||
if (!specializationConstantString.empty()) {
|
||||
specializationConstantString += '\n';
|
||||
}
|
||||
|
||||
// build all shaders
|
||||
@@ -143,14 +143,14 @@ void OpenGLProgram::compileShaders(OpenGLContext& context,
|
||||
|
||||
const std::array<const char*, 4> sources = {
|
||||
prolog.data(),
|
||||
specificationConstantString.c_str(),
|
||||
specializationConstantString.c_str(),
|
||||
packingFunctions.data(),
|
||||
body.data()
|
||||
};
|
||||
|
||||
const std::array<GLint, 4> lengths = {
|
||||
(GLint)prolog.length(),
|
||||
(GLint)specificationConstantString.length(),
|
||||
(GLint)specializationConstantString.length(),
|
||||
(GLint)packingFunctions.length(),
|
||||
(GLint)body.length() - 1 // null terminated
|
||||
};
|
||||
@@ -286,13 +286,15 @@ bool OpenGLProgram::checkProgramStatus(const char* name,
|
||||
for (size_t i = 0; i < Program::SHADER_TYPE_COUNT; i++) {
|
||||
const ShaderStage type = static_cast<ShaderStage>(i);
|
||||
const GLuint shader = shaderIds[i];
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
logCompilationError(slog.e, type, name, shader, shaderSourceCode[i]);
|
||||
if (shader) {
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
logCompilationError(slog.e, type, name, shader, shaderSourceCode[i]);
|
||||
}
|
||||
glDetachShader(program, shader);
|
||||
glDeleteShader(shader);
|
||||
shaderIds[i] = 0;
|
||||
}
|
||||
glDetachShader(program, shader);
|
||||
glDeleteShader(shader);
|
||||
shaderIds[i] = 0;
|
||||
}
|
||||
// log the link error as well
|
||||
logProgramLinkError(slog.e, name, program);
|
||||
|
||||
@@ -340,14 +340,6 @@ public:
|
||||
* @see View::setShadowType
|
||||
*/
|
||||
struct Vsm {
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*/
|
||||
uint8_t msaaSamples = 1;
|
||||
|
||||
/**
|
||||
* When elvsm is set to true, "Exponential Layered VSM without Layers" are used. It is
|
||||
* an improvement to the default EVSM which suffers important light leaks. Enabling
|
||||
|
||||
@@ -390,6 +390,14 @@ struct VsmShadowOptions {
|
||||
*/
|
||||
bool mipmapping = false;
|
||||
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*/
|
||||
uint8_t msaaSamples = 1;
|
||||
|
||||
/**
|
||||
* Whether to use a 32-bits or 16-bits texture format for VSM shadow maps. 32-bits
|
||||
* precision is rarely needed, but it does reduces light leaks as well as "fading"
|
||||
|
||||
@@ -35,8 +35,8 @@ AtlasAllocator::AtlasAllocator(size_t maxTextureSize) noexcept {
|
||||
mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - utils::clz(maxTextureSize);
|
||||
}
|
||||
|
||||
Viewport AtlasAllocator::allocate(size_t textureSize) noexcept {
|
||||
Viewport result{};
|
||||
AtlasAllocator::Allocation AtlasAllocator::allocate(size_t textureSize) noexcept {
|
||||
Allocation result{};
|
||||
const size_t powerOfTwo = (sizeof(textureSize) * 8 - 1u) - utils::clz(textureSize);
|
||||
|
||||
// asked for a texture size too large
|
||||
@@ -45,22 +45,24 @@ Viewport AtlasAllocator::allocate(size_t textureSize) noexcept {
|
||||
}
|
||||
|
||||
// asked for a texture size too small
|
||||
if (UTILS_UNLIKELY(mMaxTextureSizePot - powerOfTwo >= QuadTree::height())) {
|
||||
if (UTILS_UNLIKELY(mMaxTextureSizePot - powerOfTwo >= QUAD_TREE_DEPTH)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const size_t layer = mMaxTextureSizePot - powerOfTwo;
|
||||
const NodeId loc = allocateInLayer(layer);
|
||||
const size_t layer = (mMaxTextureSizePot - powerOfTwo);
|
||||
const NodeId loc = allocateInLayer(LAYERS_DEPTH + layer);
|
||||
if (loc.l >= 0) {
|
||||
assert_invariant(loc.l == int8_t(layer));
|
||||
size_t dimension = 1u << powerOfTwo;
|
||||
assert_invariant(loc.l - LAYERS_DEPTH == int8_t(layer));
|
||||
const size_t dimension = 1u << powerOfTwo;
|
||||
// find the location of in the texture from the morton code (quadtree position)
|
||||
auto [x, y] = unmorton(loc.code);
|
||||
const auto [x, y] = unmorton(loc.code);
|
||||
// scale to our maximum allocation size
|
||||
result.left = int32_t(x) << powerOfTwo;
|
||||
result.bottom = int32_t(y) << powerOfTwo;
|
||||
result.width = dimension;
|
||||
result.height = dimension;
|
||||
const uint32_t mask = (1u << layer) - 1u;
|
||||
result.viewport.left = int32_t(x & mask) << powerOfTwo;
|
||||
result.viewport.bottom = int32_t(y & mask) << powerOfTwo;
|
||||
result.viewport.width = dimension;
|
||||
result.viewport.height = dimension;
|
||||
result.layer = loc.code >> (2 * layer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -108,9 +110,9 @@ AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t maxHeight) noexcep
|
||||
}
|
||||
|
||||
// We only want to find a fitting node that already has siblings, in order
|
||||
// to accomplish a "best fit" allocation. So if we're a parent of a 'fitting'
|
||||
// node and don't have children, we skip the children recursion.
|
||||
if (curr.l == n - 1 && !node.hasChildren()) {
|
||||
// to accomplish a "best fit" allocation. So if a parent (of what we're looking for)
|
||||
// has no children, we skip the whole tree below it.
|
||||
if (!node.hasChildren()) {
|
||||
return QuadTree::TraversalResult::SKIP_CHILDREN;
|
||||
}
|
||||
|
||||
@@ -121,6 +123,8 @@ AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t maxHeight) noexcep
|
||||
if (candidate.l >= 0) {
|
||||
const size_t i = index(candidate.l, candidate.code);
|
||||
Node& allocation = mQuadTree[i];
|
||||
assert_invariant(!allocation.isAllocated());
|
||||
assert_invariant(!allocation.hasChildren());
|
||||
|
||||
if (candidate.l == n) {
|
||||
allocation.allocated = true;
|
||||
@@ -132,26 +136,38 @@ AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t maxHeight) noexcep
|
||||
assert_invariant(parent.hasChildren());
|
||||
assert_invariant(!parent.hasAllChildren());
|
||||
parent.children++;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// check that all the parents are not allocated and have at least 1 child.
|
||||
NodeId ppp = candidate;
|
||||
while (ppp.l > 0) {
|
||||
const size_t pi = QuadTreeUtils::parent(ppp.l, ppp.code);
|
||||
ppp = NodeId{ int8_t(ppp.l - 1), uint8_t(ppp.code >> 2) };
|
||||
Node& node = mQuadTree[pi];
|
||||
assert_invariant(!node.isAllocated());
|
||||
assert_invariant(node.hasChildren());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (candidate.l < int8_t(QuadTree::height())) {
|
||||
// we need to create the hierarchy down to the level we need
|
||||
assert_invariant(!allocation.isAllocated());
|
||||
assert_invariant(!allocation.hasChildren());
|
||||
|
||||
NodeId found{};
|
||||
NodeId found{ -1, 0 };
|
||||
QuadTree::traverse(candidate.l, candidate.code,
|
||||
[this, n, &found](NodeId const& curr) -> QuadTree::TraversalResult {
|
||||
size_t i = index(curr.l, curr.code);
|
||||
Node& node = mQuadTree[i];
|
||||
if (curr.l == n) {
|
||||
found = curr;
|
||||
assert_invariant(!node.hasChildren());
|
||||
node.allocated = true;
|
||||
return QuadTree::TraversalResult::EXIT;
|
||||
}
|
||||
assert_invariant(!node.hasAllChildren());
|
||||
node.children++;
|
||||
return QuadTree::TraversalResult::RECURSE;
|
||||
});
|
||||
|
||||
assert_invariant(found.l != -1);
|
||||
candidate = found;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
|
||||
class AtlasAllocator_AllocateFirstLevel_Test;
|
||||
class AtlasAllocator_AllocateSecondLevel_Test;
|
||||
class AtlasAllocator_AllocateMixed0_Test;
|
||||
@@ -53,8 +55,18 @@ class AtlasAllocator {
|
||||
uint8_t children : 3; // 0, 1, 2, 3, 4
|
||||
};
|
||||
|
||||
// this determines the number of layers we can use (3 layers == 64 quadtree entries)
|
||||
static constexpr size_t LAYERS_DEPTH = 3u;
|
||||
|
||||
// this determines how many "sub-sizes" we can have from the base size.
|
||||
// e.g. with a max texture size of 1024, we can allocate 1024, 512, 256 and 128 textures.
|
||||
static constexpr size_t QUAD_TREE_DEPTH = 4u;
|
||||
using QuadTree = utils::QuadTreeArray<Node, QUAD_TREE_DEPTH>;
|
||||
|
||||
// LAYERS_DEPTH limits the number of layers
|
||||
static_assert(CONFIG_MAX_SHADOW_LAYERS <= 1u << (LAYERS_DEPTH * 2u));
|
||||
|
||||
// QuadTreeArray is limited to a maximum depth of 7
|
||||
using QuadTree = utils::QuadTreeArray<Node, LAYERS_DEPTH + QUAD_TREE_DEPTH>;
|
||||
using NodeId = QuadTree::NodeId;
|
||||
|
||||
public:
|
||||
@@ -62,14 +74,18 @@ public:
|
||||
* Create allocator and specify the maximum texture size. Must be a power of two.
|
||||
* Allocations size allowed are the four power-of-two smaller or equal to this size.
|
||||
*/
|
||||
explicit AtlasAllocator(size_t maxTextureSize = 1024) noexcept;
|
||||
explicit AtlasAllocator(size_t maxTextureSize) noexcept;
|
||||
|
||||
/*
|
||||
* Allocates a square of size `textureSize`. Must be one of the power-of-two allowed
|
||||
* (see above).
|
||||
* Returns the location of the allocation within the maxTextureSize^2 square.
|
||||
*/
|
||||
Viewport allocate(size_t textureSize) noexcept;
|
||||
struct Allocation {
|
||||
int32_t layer = -1;
|
||||
Viewport viewport;
|
||||
};
|
||||
Allocation allocate(size_t textureSize) noexcept;
|
||||
|
||||
/*
|
||||
* Frees all allocations and reset the maximum texture size.
|
||||
|
||||
@@ -92,7 +92,6 @@ private:
|
||||
|
||||
template<size_t POOL_SIZE, size_t ALIGNMENT, typename AllocatorPolicy, typename LockingPolicy>
|
||||
BufferPoolAllocator<POOL_SIZE, ALIGNMENT, AllocatorPolicy, LockingPolicy>::~BufferPoolAllocator() noexcept {
|
||||
assert_invariant(mOutstandingBuffers == mEntries.size());
|
||||
clearInternal();
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ void PerShadowMapUniforms::prepareLodBias(Transaction const& transaction,
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport,
|
||||
backend::Viewport const& viewport,
|
||||
uint32_t xoffset, uint32_t yoffset) noexcept {
|
||||
const float w = float(viewport.width);
|
||||
const float h = float(viewport.height);
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
float bias) noexcept;
|
||||
|
||||
static void prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport, uint32_t xoffset, uint32_t yoffset) noexcept;
|
||||
backend::Viewport const& viewport, uint32_t xoffset, uint32_t yoffset) noexcept;
|
||||
|
||||
static void prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
|
||||
@@ -290,14 +290,10 @@ void PerViewUniforms::prepareShadowMapping(bool highPrecision) noexcept {
|
||||
|
||||
void PerViewUniforms::prepareShadowSampling(PerViewUib& uniforms,
|
||||
ShadowMappingUniforms const& shadowMappingUniforms) noexcept {
|
||||
uniforms.lightFromWorldMatrix = shadowMappingUniforms.lightFromWorldMatrix;
|
||||
uniforms.cascadeSplits = shadowMappingUniforms.cascadeSplits;
|
||||
uniforms.shadowBulbRadiusLs = shadowMappingUniforms.shadowBulbRadiusLs;
|
||||
uniforms.shadowBias = shadowMappingUniforms.shadowBias;
|
||||
uniforms.ssContactShadowDistance = shadowMappingUniforms.ssContactShadowDistance;
|
||||
uniforms.directionalShadows = shadowMappingUniforms.directionalShadows;
|
||||
uniforms.cascades = shadowMappingUniforms.cascades;
|
||||
uniforms.cascades |= uint32_t(shadowMappingUniforms.elvsm) << 31u;
|
||||
}
|
||||
|
||||
void PerViewUniforms::prepareShadowVSM(Handle<HwTexture> texture,
|
||||
|
||||
@@ -707,6 +707,11 @@ void RenderPass::Executor::overrideScissor(backend::Viewport const* scissor) noe
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::Executor::overrideScissor(backend::Viewport const& scissor) noexcept {
|
||||
mScissorOverride = true;
|
||||
mScissor = scissor;
|
||||
}
|
||||
|
||||
void RenderPass::Executor::execute(FEngine& engine, const char* name) const noexcept {
|
||||
execute(engine.getDriverApi(), mCommands.begin(), mCommands.end());
|
||||
}
|
||||
@@ -750,6 +755,11 @@ void RenderPass::Executor::execute(backend::DriverApi& driver,
|
||||
continue;
|
||||
}
|
||||
|
||||
// primitiveHandle may be invalid if no geometry was set on the renderable.
|
||||
if (UTILS_UNLIKELY(!first->primitive.primitiveHandle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// per-renderable uniform
|
||||
const PrimitiveInfo info = first->primitive;
|
||||
pipeline.rasterState = info.rasterState;
|
||||
|
||||
@@ -349,6 +349,7 @@ public:
|
||||
|
||||
// if non-null, overrides the material's scissor
|
||||
void overrideScissor(backend::Viewport const* scissor) noexcept;
|
||||
void overrideScissor(backend::Viewport const& scissor) noexcept;
|
||||
|
||||
void execute(FEngine& engine, const char* name) const noexcept;
|
||||
};
|
||||
|
||||
@@ -368,8 +368,9 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
|
||||
|
||||
// Computes St the transform to use in the shader to access the shadow map texture
|
||||
// i.e. it transforms a world-space vertex to a texture coordinate in the shadowmap
|
||||
const mat4 MbMt = getTextureCoordsMapping(shadowMapInfo);
|
||||
const mat4f St = mat4f(MbMt * S);
|
||||
const backend::Viewport viewport = getViewport();
|
||||
const auto [Mt, Mn] = ShadowMap::getTextureCoordsMapping(shadowMapInfo, viewport);
|
||||
const mat4f St = math::highPrecisionMultiply(Mt, S);
|
||||
|
||||
ShadowMap::ShaderParameters shaderParameters;
|
||||
|
||||
@@ -377,7 +378,7 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
|
||||
// L * Mp * Mv is a rigid transform for directional lights, and doesn't matter.
|
||||
// if Wp[3][1] is 0, then LISPSM was cancelled.
|
||||
if (useLispsm && Wp[3][1] != 0.0f) {
|
||||
shaderParameters.texelSizeAtOneMeterWs = texelSizeWorldSpace(Wp, mat4f(MbMt * F),
|
||||
shaderParameters.texelSizeAtOneMeterWs = texelSizeWorldSpace(Wp, mat4f(Mt * F),
|
||||
shadowMapInfo.shadowDimension);
|
||||
} else {
|
||||
// We know we're using an ortho projection
|
||||
@@ -390,6 +391,8 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
|
||||
shaderParameters.lightSpace = computeVsmLightSpaceMatrix(St, Mv, znear, zfar);
|
||||
}
|
||||
|
||||
shaderParameters.scissorNormalized = getViewportNormalized(shadowMapInfo);
|
||||
|
||||
// We apply the constant bias in world space (as opposed to light-space) to account
|
||||
// for perspective and lispsm shadow maps. This also allows us to do this at zero-cost
|
||||
// by baking it in the shadow-map itself.
|
||||
@@ -404,8 +407,8 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
|
||||
// The model matrix below is in fact inverted to get the view matrix and passed to the
|
||||
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
|
||||
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
mCamera->setModelMatrix(mat4{ FCamera::rigidTransformInverse(Mv * b) });
|
||||
mCamera->setCustomProjection(mat4(F * W * L * Mp), znear, zfar);
|
||||
mCamera->setModelMatrix(FCamera::rigidTransformInverse(math::highPrecisionMultiplyd(Mv, b)));
|
||||
mCamera->setCustomProjection(mat4(Mn * F * W * L * Mp), znear, zfar);
|
||||
|
||||
// for the debug camera, we need to undo the world origin
|
||||
mDebugCamera->setCustomProjection(mat4(S * b * camera.worldOrigin), znear, zfar);
|
||||
@@ -413,48 +416,18 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
|
||||
return shaderParameters;
|
||||
}
|
||||
|
||||
ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
|
||||
const FScene::LightSoa& lightData, size_t index,
|
||||
filament::CameraInfo const& camera,
|
||||
const ShadowMapInfo& shadowMapInfo,
|
||||
FScene const& scene, SceneInfo sceneInfo) noexcept {
|
||||
ShadowMap::ShaderParameters ShadowMap::updatePunctual(
|
||||
mat4f const& Mv, float outerConeAngle, float nearPlane, float farPlane,
|
||||
const ShadowMapInfo& shadowMapInfo, const FLightManager::ShadowParams& params) noexcept {
|
||||
const mat4f Mp = mat4f::perspective(outerConeAngle * f::RAD_TO_DEG * 2.0f, 1.0f, nearPlane, farPlane);
|
||||
|
||||
ShaderParameters shaderParameters;
|
||||
|
||||
auto& lcm = engine.getLightManager();
|
||||
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
|
||||
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
|
||||
auto direction = lightData.elementAt<FScene::DIRECTION>(index);
|
||||
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
|
||||
auto outerConeAngle = lcm.getSpotLightOuterCone(li);
|
||||
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
|
||||
|
||||
/*
|
||||
* Compute the light model matrix.
|
||||
*/
|
||||
|
||||
// Choose a reasonable value for the near plane.
|
||||
const mat4f Mv = getDirectionalLightViewMatrix(direction, position);
|
||||
|
||||
// find decent near/far
|
||||
ShadowMap::updateSceneInfoSpot(Mv, scene, sceneInfo);
|
||||
|
||||
// if the scene was empty, near > far
|
||||
mHasVisibleShadows = -sceneInfo.lsNearFar[0] < -sceneInfo.lsNearFar[1];
|
||||
|
||||
// FIXME: we need a configuration for minimum near plane (for now hardcoded to 1cm)
|
||||
float nearPlane = std::max(0.01f, -sceneInfo.lsNearFar[0]);
|
||||
float farPlane = std::min(radius, -sceneInfo.lsNearFar[1]);
|
||||
|
||||
float outerConeAngleDegrees = outerConeAngle * f::RAD_TO_DEG;
|
||||
const mat4f Mp = mat4f::perspective(outerConeAngleDegrees * 2.0f, 1.0f, nearPlane, farPlane);
|
||||
const mat4f MpMv(math::highPrecisionMultiply(Mp, Mv));
|
||||
assert_invariant(shadowMapInfo.textureDimension == mOptions->mapSize);
|
||||
|
||||
// Final shadow transform
|
||||
const mat4f S = MpMv;
|
||||
|
||||
const mat4 MbMt = getTextureCoordsMapping(shadowMapInfo);
|
||||
const mat4f St = mat4f(MbMt * S);
|
||||
const backend::Viewport viewport = getViewport();
|
||||
const mat4f S = math::highPrecisionMultiply(Mp, Mv);
|
||||
const auto [Mt, Mn] = ShadowMap::getTextureCoordsMapping(shadowMapInfo, viewport);
|
||||
const mat4f St = math::highPrecisionMultiply(Mt, S);
|
||||
|
||||
// TODO: focus projection
|
||||
// 1) focus on the casters
|
||||
@@ -469,7 +442,9 @@ ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
|
||||
// = zInLightSpace * texelSizeAtOneMeter
|
||||
// = zInLightSpace * (2*tan(halfConeAngle)/dimension)
|
||||
// Note: this would not work with LISPSM, which warps the texture space.
|
||||
shaderParameters.texelSizeAtOneMeterWs = (2.0f * std::tan(outerConeAngle) / float(shadowMapInfo.shadowDimension));
|
||||
ShaderParameters shaderParameters;
|
||||
shaderParameters.texelSizeAtOneMeterWs =
|
||||
(2.0f * std::tan(outerConeAngle) / float(shadowMapInfo.shadowDimension));
|
||||
shaderParameters.lightFromWorldZ = -transpose(Mv)[2]; // negate because camera looks in -Z
|
||||
|
||||
if (!shadowMapInfo.vsm) {
|
||||
@@ -478,9 +453,11 @@ ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
|
||||
shaderParameters.lightSpace = computeVsmLightSpaceMatrix(St, Mv, nearPlane, farPlane);
|
||||
}
|
||||
|
||||
shaderParameters.scissorNormalized = getViewportNormalized(shadowMapInfo);
|
||||
|
||||
const float3 direction = -transpose(Mv)[2].xyz;
|
||||
const float constantBias = shadowMapInfo.vsm ? 0.0f : params.options.constantBias;
|
||||
const mat4f b = mat4f::translation(direction * constantBias);
|
||||
const mat4f Sb = S * b;
|
||||
|
||||
// It's important to set the light camera's model matrix separately from its projection, so that
|
||||
// the cameraPosition uniform gets set correctly.
|
||||
@@ -490,22 +467,47 @@ ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
|
||||
// The model matrix below is in fact inverted to get the view matrix and passed to the
|
||||
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
|
||||
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
mCamera->setModelMatrix(mat4{ FCamera::rigidTransformInverse(Mv * b) });
|
||||
mCamera->setCustomProjection(mat4(Mp), nearPlane, farPlane);
|
||||
|
||||
// for the debug camera, we need to undo the world origin
|
||||
mDebugCamera->setCustomProjection(mat4(Sb * camera.worldOrigin), nearPlane, radius);
|
||||
mCamera->setModelMatrix(FCamera::rigidTransformInverse(math::highPrecisionMultiplyd(Mv, b)));
|
||||
mCamera->setCustomProjection(math::highPrecisionMultiplyd(Mn, Mp), nearPlane, farPlane);
|
||||
|
||||
return shaderParameters;
|
||||
}
|
||||
|
||||
ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine,
|
||||
const FScene::LightSoa& lightData, size_t index,
|
||||
filament::CameraInfo const& camera,
|
||||
const ShadowMapInfo& shadowMapInfo,
|
||||
FScene const& scene, SceneInfo sceneInfo) noexcept {
|
||||
|
||||
auto& lcm = engine.getLightManager();
|
||||
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
|
||||
auto direction = lightData.elementAt<FScene::DIRECTION>(index);
|
||||
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
|
||||
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
|
||||
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
|
||||
const mat4f Mv = getDirectionalLightViewMatrix(direction, position);
|
||||
|
||||
// find decent near/far
|
||||
ShadowMap::updateSceneInfoSpot(Mv, scene, sceneInfo);
|
||||
|
||||
// if the scene was empty, near > far
|
||||
mHasVisibleShadows = -sceneInfo.lsNearFar[0] < -sceneInfo.lsNearFar[1];
|
||||
if (!mHasVisibleShadows) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: we need a configuration for minimum near plane (for now hardcoded to 1cm)
|
||||
float nearPlane = std::max(0.01f, -sceneInfo.lsNearFar[0]);
|
||||
float farPlane = std::min(radius, -sceneInfo.lsNearFar[1]);
|
||||
auto outerConeAngle = lcm.getSpotLightOuterCone(li);
|
||||
return updatePunctual(Mv, outerConeAngle, nearPlane, farPlane, shadowMapInfo, params);
|
||||
}
|
||||
|
||||
ShadowMap::ShaderParameters ShadowMap::updatePoint(FEngine& engine,
|
||||
const FScene::LightSoa& lightData, size_t index,
|
||||
filament::CameraInfo const& camera, const ShadowMapInfo& shadowMapInfo, FScene const& scene,
|
||||
SceneInfo, uint8_t face) noexcept {
|
||||
|
||||
ShaderParameters shaderParameters;
|
||||
|
||||
// check if this shadow map has anything to render
|
||||
mHasVisibleShadows = false;
|
||||
FScene::RenderableSoa const& UTILS_RESTRICT soa = scene.getRenderableData();
|
||||
@@ -518,53 +520,16 @@ ShadowMap::ShaderParameters ShadowMap::updatePoint(FEngine& engine,
|
||||
}
|
||||
}
|
||||
if (!mHasVisibleShadows) {
|
||||
return shaderParameters;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto& lcm = engine.getLightManager();
|
||||
|
||||
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
|
||||
auto position = lightData.elementAt<FScene::POSITION_RADIUS>(index).xyz;
|
||||
auto radius = lightData.elementAt<FScene::POSITION_RADIUS>(index).w;
|
||||
auto li = lightData.elementAt<FScene::LIGHT_INSTANCE>(index);
|
||||
const FLightManager::ShadowParams& params = lcm.getShadowParams(li);
|
||||
|
||||
/*
|
||||
* Compute the light model matrix.
|
||||
*/
|
||||
|
||||
const mat4f Mv = getPointLightViewMatrix(TextureCubemapFace(face), position);
|
||||
const float3 direction = -transpose(Mv)[2].xyz;
|
||||
|
||||
// TODO: don't hardcode near plane
|
||||
// Choose a reasonable value for the near plane.
|
||||
float nearPlane = 0.01f;
|
||||
float farPlane = radius;
|
||||
const mat4f Mp = mat4f::perspective(90.0f, 1.0f, nearPlane, farPlane);
|
||||
|
||||
// For calculating the point light normal bias, we need the texel size in world space at the
|
||||
// sample location. Using Thales's theorem, we find:
|
||||
// texelSize(zInLightSpace) = zInLightSpace * texelSizeOnTheNearPlane / near
|
||||
// = zInLightSpace * texelSizeAtOneMeter
|
||||
// = zInLightSpace * (2*tan(halfConeAngle)/dimension)
|
||||
// Note: this would not work with LISPSM, which warps the texture space.
|
||||
shaderParameters.texelSizeAtOneMeterWs =
|
||||
(2.0f * std::tan(f::PI_4) / float(shadowMapInfo.shadowDimension));
|
||||
|
||||
const float constantBias = shadowMapInfo.vsm ? 0.0f : params.options.constantBias;
|
||||
const mat4f b = mat4f::translation(direction * constantBias);
|
||||
|
||||
// It's important to set the light camera's model matrix separately from its projection, so that
|
||||
// the cameraPosition uniform gets set correctly.
|
||||
// mLightSpace is used in the shader to access the shadow map texture, and has the model matrix
|
||||
// baked in.
|
||||
|
||||
// The model matrix below is in fact inverted to get the view matrix and passed to the
|
||||
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
|
||||
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
mCamera->setModelMatrix(mat4{ FCamera::rigidTransformInverse(Mv * b) });
|
||||
mCamera->setCustomProjection(mat4(Mp), nearPlane, farPlane);
|
||||
|
||||
return shaderParameters;
|
||||
return updatePunctual(Mv, 45.0f * f::DEG_TO_RAD, 0.01f, radius, shadowMapInfo, params);
|
||||
}
|
||||
|
||||
mat4f ShadowMap::applyLISPSM(mat4f& Wp,
|
||||
@@ -646,7 +611,8 @@ mat4f ShadowMap::applyLISPSM(mat4f& Wp,
|
||||
|
||||
|
||||
// Apply these remapping in double to maintain a high precision for the depth axis
|
||||
mat4 ShadowMap::getTextureCoordsMapping(ShadowMapInfo const& info) noexcept {
|
||||
ShadowMap::TextureCoordsMapping ShadowMap::getTextureCoordsMapping(ShadowMapInfo const& info,
|
||||
backend::Viewport const& viewport) noexcept {
|
||||
// remapping from NDC to texture coordinates (i.e. [-1,1] -> [0, 1])
|
||||
// ([1, 0] for depth mapping)
|
||||
const mat4f Mt(info.clipSpaceFlipped ? mat4f::row_major_init{
|
||||
@@ -661,22 +627,12 @@ mat4 ShadowMap::getTextureCoordsMapping(ShadowMapInfo const& info) noexcept {
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
});
|
||||
|
||||
// the shadow map texture might be larger than the shadow map dimension, so we add a scaling
|
||||
// factor
|
||||
const float v = float(info.textureDimension) / float(info.atlasDimension);
|
||||
// apply the viewport transform
|
||||
const float2 o = float2{ viewport.left, viewport.bottom } / float(info.atlasDimension);
|
||||
const float2 s = float2{ viewport.width, viewport.height } / float(info.atlasDimension);
|
||||
const mat4f Mv(mat4f::row_major_init{
|
||||
v, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, v, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
});
|
||||
|
||||
// apply the 1-texel border viewport transform
|
||||
const float o = 1.0f / float(info.atlasDimension);
|
||||
const float s = 1.0f - 2.0f * (1.0f / float(info.textureDimension));
|
||||
const mat4f Mb(mat4f::row_major_init{
|
||||
s, 0.0f, 0.0f, o,
|
||||
0.0f, s, 0.0f, o,
|
||||
s.x, 0.0f, 0.0f, o.x,
|
||||
0.0f, s.y, 0.0f, o.y,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
});
|
||||
@@ -688,8 +644,8 @@ mat4 ShadowMap::getTextureCoordsMapping(ShadowMapInfo const& info) noexcept {
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
}) : mat4f();
|
||||
|
||||
// Compute shadow-map texture access transform
|
||||
return mat4(Mf * Mb * Mv * Mt);
|
||||
// Compute shadow-map texture access and viewport transform
|
||||
return { Mf * (Mv * Mt), inverse(Mt) * (Mv * Mt) };
|
||||
}
|
||||
|
||||
mat4f ShadowMap::computeVsmLightSpaceMatrix(const mat4f& lightSpacePcf,
|
||||
@@ -1245,26 +1201,40 @@ void ShadowMap::updateSceneInfoSpot(mat4f const& Mv, FScene const& scene,
|
||||
);
|
||||
}
|
||||
|
||||
filament::Viewport ShadowMap::getViewport() const noexcept {
|
||||
backend::Viewport ShadowMap::getViewport() const noexcept {
|
||||
// We set a viewport with a 1-texel border for when we index outside the
|
||||
// texture.
|
||||
// DON'T CHANGE this unless ShadowMap::getTextureCoordsMapping() is updated too.
|
||||
// see: ShadowMap::getTextureCoordsMapping()
|
||||
//
|
||||
// For floating-point depth textures, the 1-texel border could be set to
|
||||
// FLOAT_MAX to avoid clamping in the shadow shader (see sampleDepth inside
|
||||
// shadowing.fs). Unfortunately, the APIs don't seem let us clear depth
|
||||
// attachments to anything greater than 1.0, so we'd need a way to do this other
|
||||
// than clearing.
|
||||
// texture. This can only happen for the directional light when "focus shadow casters is used".
|
||||
const uint32_t dim = mOptions->mapSize;
|
||||
if (isPointShadow()) {
|
||||
// for point-light we don't have a border
|
||||
return { 0, 0, dim, dim };
|
||||
} else {
|
||||
return { 1, 1, dim - 2, dim - 2 };
|
||||
const uint16_t border = 1u;
|
||||
return { border, border, dim - 2u * border, dim - 2u * border };
|
||||
}
|
||||
|
||||
backend::Viewport ShadowMap::getScissor() const noexcept {
|
||||
// We set a viewport with a 1-texel border for when we index outside the
|
||||
// texture. This can only happen for the directional light when "focus shadow casters is used".
|
||||
const uint32_t dim = mOptions->mapSize;
|
||||
const uint16_t border = 1u;
|
||||
|
||||
switch (mShadowType) {
|
||||
case ShadowType::DIRECTIONAL:
|
||||
return { border, border, dim - 2u * border, dim - 2u * border };
|
||||
case ShadowType::SPOT:
|
||||
case ShadowType::POINT:
|
||||
default:
|
||||
return { 0, 0, dim, dim };
|
||||
}
|
||||
}
|
||||
|
||||
math::float4 ShadowMap::getViewportNormalized(ShadowMapInfo const& shadowMapInfo) const noexcept {
|
||||
const auto [l, b, w, h] = getViewport();
|
||||
const float texel = 1.0f / float(shadowMapInfo.atlasDimension);
|
||||
const float4 v = float4{ l, b, l + w, b + h } * texel;
|
||||
if (shadowMapInfo.textureSpaceFlipped) {
|
||||
return { v.x, 1.0f - v.w, v.z, 1.0f - v.y };
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void ShadowMap::prepareCamera(Transaction const& transaction,
|
||||
@@ -1274,7 +1244,7 @@ void ShadowMap::prepareCamera(Transaction const& transaction,
|
||||
}
|
||||
|
||||
void ShadowMap::prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport) noexcept {
|
||||
backend::Viewport const& viewport) noexcept {
|
||||
PerShadowMapUniforms::prepareViewport(transaction, viewport, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "details/Camera.h"
|
||||
#include "details/Scene.h"
|
||||
|
||||
#include "private/backend/DriverApi.h"
|
||||
#include <backend/DriverApiForward.h>
|
||||
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
@@ -130,6 +130,7 @@ public:
|
||||
struct ShaderParameters {
|
||||
math::mat4f lightSpace{};
|
||||
math::float4 lightFromWorldZ{};
|
||||
math::float4 scissorNormalized{};
|
||||
float texelSizeAtOneMeterWs{};
|
||||
};
|
||||
|
||||
@@ -174,13 +175,14 @@ public:
|
||||
static void updateSceneInfoSpot(const math::mat4f& Mv, FScene const& scene,
|
||||
SceneInfo& sceneInfo);
|
||||
|
||||
filament::Viewport getViewport() const noexcept;
|
||||
|
||||
LightManager::ShadowOptions const* getShadowOptions() const noexcept { return mOptions; }
|
||||
size_t getLightIndex() const { return mLightIndex; }
|
||||
uint16_t getShadowIndex() const { return mShadowIndex; }
|
||||
void setLayer(uint8_t layer) noexcept { mLayer = layer; }
|
||||
uint8_t getLayer() const noexcept { return mLayer; }
|
||||
backend::Viewport getViewport() const noexcept;
|
||||
backend::Viewport getScissor() const noexcept;
|
||||
|
||||
bool isDirectionalShadow() const noexcept { return mShadowType == ShadowType::DIRECTIONAL; }
|
||||
bool isSpotShadow() const noexcept { return mShadowType == ShadowType::SPOT; }
|
||||
bool isPointShadow() const noexcept { return mShadowType == ShadowType::POINT; }
|
||||
@@ -192,7 +194,7 @@ public:
|
||||
static void prepareCamera(Transaction const& transaction,
|
||||
FEngine& engine, const CameraInfo& cameraInfo) noexcept;
|
||||
static void prepareViewport(Transaction const& transaction,
|
||||
const filament::Viewport& viewport) noexcept;
|
||||
backend::Viewport const& viewport) noexcept;
|
||||
static void prepareTime(Transaction const& transaction,
|
||||
FEngine& engine, math::float4 const& userTime) noexcept;
|
||||
static void prepareShadowMapping(Transaction const& transaction,
|
||||
@@ -214,6 +216,11 @@ private:
|
||||
// 8 corners, 12 segments w/ 2 intersection max -- all of this twice (8 + 12 * 2) * 2 (768 bytes)
|
||||
using FrustumBoxIntersection = std::array<math::float3, 64>;
|
||||
|
||||
ShaderParameters updatePunctual(
|
||||
math::mat4f const& Mv, float outerConeAngle, float nearPlane, float farPlane,
|
||||
const ShadowMapInfo& shadowMapInfo,
|
||||
const FLightManager::ShadowParams& params) noexcept;
|
||||
|
||||
static math::mat4f applyLISPSM(math::mat4f& Wp,
|
||||
filament::CameraInfo const& camera, FLightManager::ShadowParams const& params,
|
||||
const math::mat4f& LMpMv,
|
||||
@@ -273,11 +280,18 @@ private:
|
||||
|
||||
static math::mat4f directionalLightFrustum(float n, float f) noexcept;
|
||||
|
||||
static math::mat4 getTextureCoordsMapping(ShadowMapInfo const& info) noexcept;
|
||||
struct TextureCoordsMapping {
|
||||
math::mat4f clipToTexture;
|
||||
math::mat4f clipToNdc;
|
||||
};
|
||||
static TextureCoordsMapping getTextureCoordsMapping(ShadowMapInfo const& info,
|
||||
backend::Viewport const& viewport) noexcept;
|
||||
|
||||
static math::mat4f computeVsmLightSpaceMatrix(const math::mat4f& lightSpacePcf,
|
||||
const math::mat4f& Mv, float znear, float zfar) noexcept;
|
||||
|
||||
math::float4 getViewportNormalized(ShadowMapInfo const& shadowMapInfo) const noexcept;
|
||||
|
||||
float texelSizeWorldSpace(const math::mat3f& worldToShadowTexture,
|
||||
uint16_t shadowDimension) const noexcept;
|
||||
|
||||
|
||||
@@ -97,8 +97,10 @@ void ShadowMapManager::setDirectionalShadowMap(size_t lightIndex,
|
||||
LightManager::ShadowOptions const* options) noexcept {
|
||||
assert_invariant(options->shadowCascades <= CONFIG_MAX_SHADOW_CASCADES);
|
||||
for (size_t c = 0; c < options->shadowCascades; c++) {
|
||||
auto* pShadowMap = getCascadeShadowMap(c);
|
||||
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, c, 0, options);
|
||||
const size_t i = c;
|
||||
assert_invariant(i < CONFIG_MAX_SHADOW_CASCADES);
|
||||
auto* pShadowMap = getShadowMap(i);
|
||||
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, i, 0, options);
|
||||
mCascadeShadowMaps.push_back(pShadowMap);
|
||||
}
|
||||
}
|
||||
@@ -107,17 +109,19 @@ void ShadowMapManager::addShadowMap(size_t lightIndex, bool spotlight,
|
||||
LightManager::ShadowOptions const* options) noexcept {
|
||||
if (spotlight) {
|
||||
const size_t c = mSpotShadowMaps.size();
|
||||
assert_invariant(c < CONFIG_MAX_SHADOWMAPS);
|
||||
auto* pShadowMap = getPointOrSpotShadowMap(c);
|
||||
pShadowMap->initialize(lightIndex, ShadowType::SPOT, c, 0, options);
|
||||
const size_t i = c + CONFIG_MAX_SHADOW_CASCADES;
|
||||
assert_invariant(i < CONFIG_MAX_SHADOWMAPS);
|
||||
auto* pShadowMap = getShadowMap(i);
|
||||
pShadowMap->initialize(lightIndex, ShadowType::SPOT, i, 0, options);
|
||||
mSpotShadowMaps.push_back(pShadowMap);
|
||||
} else {
|
||||
// point-light, generate 6 independent shadowmaps
|
||||
for (size_t face = 0; face < 6; face++) {
|
||||
const size_t c = mSpotShadowMaps.size();
|
||||
assert_invariant(c < CONFIG_MAX_SHADOWMAPS);
|
||||
auto* pShadowMap = getPointOrSpotShadowMap(c);
|
||||
pShadowMap->initialize(lightIndex, ShadowType::POINT, c, face, options);
|
||||
const size_t i = c + CONFIG_MAX_SHADOW_CASCADES;
|
||||
assert_invariant(i < CONFIG_MAX_SHADOWMAPS);
|
||||
auto* pShadowMap = getShadowMap(i);
|
||||
pShadowMap->initialize(lightIndex, ShadowType::POINT, i, face, options);
|
||||
mSpotShadowMaps.push_back(pShadowMap);
|
||||
}
|
||||
}
|
||||
@@ -155,6 +159,8 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
utils::FixedCapacityVector<ShadowPass> passList;
|
||||
};
|
||||
|
||||
VsmShadowOptions const& vsmShadowOptions = view.getVsmShadowOptions();
|
||||
|
||||
auto& prepareShadowPass = fg.addPass<PrepareShadowPassData>("Prepare Shadow Pass",
|
||||
[&](FrameGraph::Builder& builder, auto& data) {
|
||||
data.passList.reserve(CONFIG_MAX_SHADOWMAPS);
|
||||
@@ -199,7 +205,8 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
// "read" from one of its resource (only writes), so the FrameGraph culls it.
|
||||
builder.sideEffect();
|
||||
},
|
||||
[this, &engine, &view, scene, mainCameraInfo, userTime, passTemplate = pass](
|
||||
[this, &engine, &view, vsmShadowOptions,
|
||||
scene, mainCameraInfo, userTime, passTemplate = pass](
|
||||
FrameGraphResources const& resources, auto const& data, DriverApi& driver) {
|
||||
|
||||
// Note: we could almost parallel_for the loop below, the problem currently is
|
||||
@@ -247,7 +254,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
ShadowMap::prepareViewport(transaction, shadowMap.getViewport());
|
||||
ShadowMap::prepareTime(transaction, engine, userTime);
|
||||
ShadowMap::prepareShadowMapping(transaction,
|
||||
view.getVsmShadowOptions().highPrecision);
|
||||
vsmShadowOptions.highPrecision);
|
||||
shadowMap.commit(transaction, driver);
|
||||
|
||||
// updatePrimitivesLod must be run before RenderPass::appendCommands.
|
||||
@@ -273,11 +280,6 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
};
|
||||
entry.executor.overridePolygonOffset(&polygonOffset);
|
||||
}
|
||||
|
||||
constexpr const backend::Viewport disabledScissor{ 0, 0,
|
||||
(uint32_t)std::numeric_limits<int32_t>::max(),
|
||||
(uint32_t)std::numeric_limits<int32_t>::max() };
|
||||
entry.executor.overrideScissor(&disabledScissor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,6 +308,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
|
||||
const uint8_t layer = entry.shadowMap->getLayer();
|
||||
const auto* options = entry.shadowMap->getShadowOptions();
|
||||
const auto msaaSamples = textureRequirements.msaaSamples;
|
||||
|
||||
auto& shadowPass = fg.addPass<ShadowPassData>("Shadow Pass",
|
||||
[&](FrameGraph::Builder& builder, auto& data) {
|
||||
@@ -324,7 +327,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
// We specify the sample count here because we don't need automatic resolve.
|
||||
auto depth = builder.createTexture("Temporary VSM Depth Texture", {
|
||||
.width = textureRequirements.size, .height = textureRequirements.size,
|
||||
.samples = options->vsm.msaaSamples,
|
||||
.samples = msaaSamples,
|
||||
.format = TextureFormat::DEPTH16,
|
||||
});
|
||||
|
||||
@@ -347,7 +350,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
TargetBufferFlags::COLOR | TargetBufferFlags::DEPTH;
|
||||
// we need to clear the shadow map with the max EVSM moments
|
||||
renderTargetDesc.clearColor = vsmClearColor;
|
||||
renderTargetDesc.samples = options->vsm.msaaSamples;
|
||||
renderTargetDesc.samples = msaaSamples;
|
||||
|
||||
if (blur) {
|
||||
data.tempBlurSrc = builder.write(data.tempBlurSrc,
|
||||
@@ -358,7 +361,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
.color = { data.tempBlurSrc },
|
||||
.depth = depth },
|
||||
.clearColor = vsmClearColor,
|
||||
.samples = options->vsm.msaaSamples,
|
||||
.samples = msaaSamples,
|
||||
.clearFlags = TargetBufferFlags::COLOR
|
||||
| TargetBufferFlags::DEPTH
|
||||
});
|
||||
@@ -389,11 +392,11 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
// initialized, as this happens in an `execute` block.
|
||||
|
||||
auto rt = resources.getRenderPassInfo(data.rt);
|
||||
rt.params.viewport = entry.shadowMap->getViewport();
|
||||
|
||||
engine.flush();
|
||||
driver.beginRenderPass(rt.target, rt.params);
|
||||
entry.shadowMap->bind(driver);
|
||||
entry.executor.overrideScissor(entry.shadowMap->getScissor());
|
||||
entry.executor.execute(engine, "Shadow Pass");
|
||||
driver.endRenderPass();
|
||||
});
|
||||
@@ -455,7 +458,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
|
||||
// entire camera frustum, as if we only had a single cascade.
|
||||
ShadowMap& shadowMap = *mCascadeShadowMaps[0];
|
||||
|
||||
auto shaderParameters = shadowMap.updateDirectional(mEngine,
|
||||
shadowMap.updateDirectional(mEngine,
|
||||
lightData, 0, cameraInfo, shadowMapInfo, *scene, sceneInfo);
|
||||
|
||||
hasVisibleShadows = shadowMap.hasVisibleShadows();
|
||||
@@ -464,18 +467,6 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
|
||||
Frustum const& frustum = shadowMap.getCamera().getCullingFrustum();
|
||||
FView::cullRenderables(engine.getJobSystem(), renderableData, frustum,
|
||||
VISIBLE_DIR_SHADOW_RENDERABLE_BIT);
|
||||
|
||||
// Set shadowBias, using the first directional cascade.
|
||||
// when computing the required bias we need a half-texel size, so we multiply by 0.5 here.
|
||||
// note: normalBias is set to zero for VSM
|
||||
const float normalBias = shadowMapInfo.vsm ? 0.0f : 0.5f * lcm.getShadowNormalBias(0);
|
||||
// Texel size is constant for directional light (although that's not true when LISPSM
|
||||
// is used, but in that case we're pretending it is).
|
||||
const float wsTexelSize = shaderParameters.texelSizeAtOneMeterWs;
|
||||
mShadowMappingUniforms.shadowBias = normalBias * wsTexelSize;
|
||||
mShadowMappingUniforms.shadowBulbRadiusLs =
|
||||
mSoftShadowOptions.penumbraScale * options.shadowBulbRadius / wsTexelSize;
|
||||
mShadowMappingUniforms.elvsm = options.vsm.elvsm;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,6 +519,10 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
|
||||
|
||||
mShadowMappingUniforms.cascadeSplits = wsSplitPositionUniform;
|
||||
|
||||
// when computing the required bias we need a half-texel size, so we multiply by 0.5 here.
|
||||
// note: normalBias is set to zero for VSM
|
||||
const float normalBias = shadowMapInfo.vsm ? 0.0f : 0.5f * lcm.getShadowNormalBias(0);
|
||||
|
||||
for (size_t i = 0, c = mCascadeShadowMaps.size(); i < c; i++) {
|
||||
assert_invariant(mCascadeShadowMaps[i]);
|
||||
|
||||
@@ -541,7 +536,23 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
|
||||
lightData, 0, cameraInfo, shadowMapInfo, *scene, sceneInfo);
|
||||
|
||||
if (shadowMap.hasVisibleShadows()) {
|
||||
mShadowMappingUniforms.lightFromWorldMatrix[i] = shaderParameters.lightSpace;
|
||||
const size_t shadowIndex = shadowMap.getShadowIndex();
|
||||
assert_invariant(shadowIndex == i);
|
||||
|
||||
// Texel size is constant for directional light (although that's not true when LISPSM
|
||||
// is used, but in that case we're pretending it is).
|
||||
const float wsTexelSize = shaderParameters.texelSizeAtOneMeterWs;
|
||||
|
||||
auto& s = mShadowUb.edit();
|
||||
s.shadows[shadowIndex].layer = shadowMap.getLayer();
|
||||
s.shadows[shadowIndex].lightFromWorldMatrix = shaderParameters.lightSpace;
|
||||
s.shadows[shadowIndex].scissorNormalized = shaderParameters.scissorNormalized;
|
||||
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSize;
|
||||
s.shadows[shadowIndex].texelSizeAtOneMeter = wsTexelSize;
|
||||
s.shadows[shadowIndex].elvsm = options.vsm.elvsm;
|
||||
s.shadows[shadowIndex].bulbRadiusLs =
|
||||
mSoftShadowOptions.penumbraScale * options.shadowBulbRadius / wsTexelSize;
|
||||
|
||||
shadowTechnique |= ShadowTechnique::SHADOW_MAP;
|
||||
cascadeHasVisibleShadows |= 0x1u << i;
|
||||
}
|
||||
@@ -621,7 +632,7 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
|
||||
// compute shadow map frustum for culling
|
||||
const mat4f Mv = ShadowMap::getDirectionalLightViewMatrix(direction, position);
|
||||
const mat4f Mp = mat4f::perspective(outerConeAngle * f::RAD_TO_DEG * 2.0f, 1.0f, 0.01f, radius);
|
||||
const mat4f MpMv(math::highPrecisionMultiply(Mp, Mv));
|
||||
const mat4f MpMv = math::highPrecisionMultiply(Mp, Mv);
|
||||
const Frustum frustum(MpMv);
|
||||
|
||||
// Cull shadow casters
|
||||
@@ -669,8 +680,9 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
|
||||
auto& s = mShadowUb.edit();
|
||||
const double n = shadowMap.getCamera().getNear();
|
||||
const double f = shadowMap.getCamera().getCullingFar();
|
||||
s.shadows[shadowIndex].layer = shadowMap.getLayer();
|
||||
s.shadows[shadowIndex].lightFromWorldMatrix = shaderParameters.lightSpace;
|
||||
s.shadows[shadowIndex].direction = direction;
|
||||
s.shadows[shadowIndex].scissorNormalized = shaderParameters.scissorNormalized;
|
||||
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSizeAtOneMeter;
|
||||
s.shadows[shadowIndex].lightFromWorldZ = shaderParameters.lightFromWorldZ;
|
||||
s.shadows[shadowIndex].texelSizeAtOneMeter = wsTexelSizeAtOneMeter;
|
||||
@@ -678,7 +690,8 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
|
||||
s.shadows[shadowIndex].elvsm = options->vsm.elvsm;
|
||||
s.shadows[shadowIndex].bulbRadiusLs =
|
||||
mSoftShadowOptions.penumbraScale * options->shadowBulbRadius
|
||||
/ wsTexelSizeAtOneMeter;
|
||||
/ wsTexelSizeAtOneMeter;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,7 +753,6 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
|
||||
|
||||
|
||||
// and if we need to generate it, update all the UBO data
|
||||
// Note: this below is done for all six faces even if it sets identical values each time
|
||||
if (shadowMap.hasVisibleShadows()) {
|
||||
const size_t shadowIndex = shadowMap.getShadowIndex();
|
||||
const float wsTexelSizeAtOneMeter = shaderParameters.texelSizeAtOneMeterWs;
|
||||
@@ -750,16 +762,11 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
|
||||
auto& s = mShadowUb.edit();
|
||||
const double n = shadowMap.getCamera().getNear();
|
||||
const double f = shadowMap.getCamera().getCullingFar();
|
||||
|
||||
s.shadows[shadowIndex].lightFromWorldMatrix = {}; // no texture matrix for point lights
|
||||
s.shadows[shadowIndex].direction = {}; // no direction of point lights
|
||||
s.shadows[shadowIndex].layer = shadowMap.getLayer();
|
||||
s.shadows[shadowIndex].lightFromWorldMatrix = shaderParameters.lightSpace;
|
||||
s.shadows[shadowIndex].scissorNormalized = shaderParameters.scissorNormalized;
|
||||
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSizeAtOneMeter;
|
||||
s.shadows[shadowIndex].lightFromWorldZ = {
|
||||
-((n + f) / (f - n)) * 0.5f + 0.5f,
|
||||
(f * n) / (f - n),
|
||||
-n / (f - n),
|
||||
1.0f / (f - n),
|
||||
};
|
||||
s.shadows[shadowIndex].lightFromWorldZ = shaderParameters.lightFromWorldZ;
|
||||
s.shadows[shadowIndex].texelSizeAtOneMeter = wsTexelSizeAtOneMeter;
|
||||
s.shadows[shadowIndex].nearOverFarMinusNear = float(n / (f - n));
|
||||
s.shadows[shadowIndex].elvsm = options->vsm.elvsm;
|
||||
@@ -779,14 +786,12 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine
|
||||
shadowTechnique |= ShadowTechnique::SHADOW_MAP;
|
||||
for (auto const* pShadowMap : mSpotShadowMaps) {
|
||||
const size_t lightIndex = pShadowMap->getLightIndex();
|
||||
|
||||
// FIXME: currently we have one slot per shadowmap in the UBO, but we now have up to
|
||||
// 6 shadowmap per light. So for now, we only write the data of the face 0,
|
||||
// and the shader will figure out where to find the other face (layer+face)
|
||||
// gather the per-light (not per shadow map) information. For point lights we will
|
||||
// "see" 6 shadowmaps (one per face), we must use the first face one, the shader
|
||||
// knows how to find the entry for other faces (they're guaranteed to be sequential).
|
||||
if (pShadowMap->getFace() == 0) {
|
||||
shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly?
|
||||
shadowInfo[lightIndex].index = pShadowMap->getShadowIndex();
|
||||
shadowInfo[lightIndex].layer = pShadowMap->getLayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -837,6 +842,8 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view
|
||||
const bool useMipmapping = view.hasVSM() &&
|
||||
((vsmShadowOptions.anisotropy > 0) || vsmShadowOptions.mipmapping);
|
||||
|
||||
const uint8_t msaaSamples = vsmShadowOptions.msaaSamples;
|
||||
|
||||
TextureFormat format = TextureFormat::DEPTH16;
|
||||
if (view.hasVSM()) {
|
||||
if (vsmShadowOptions.highPrecision) {
|
||||
@@ -868,6 +875,7 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view
|
||||
(uint16_t)maxDimension,
|
||||
layersNeeded,
|
||||
mipLevels,
|
||||
msaaSamples,
|
||||
format
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,14 +45,10 @@ class FrameGraph;
|
||||
class RenderPass;
|
||||
|
||||
struct ShadowMappingUniforms {
|
||||
std::array<math::mat4f, CONFIG_MAX_SHADOW_CASCADES> lightFromWorldMatrix;
|
||||
math::float4 cascadeSplits;
|
||||
float shadowBulbRadiusLs;
|
||||
float shadowBias;
|
||||
float ssContactShadowDistance;
|
||||
uint32_t directionalShadows;
|
||||
uint32_t cascades;
|
||||
bool elvsm;
|
||||
};
|
||||
|
||||
class ShadowMapManager {
|
||||
@@ -93,23 +89,13 @@ public:
|
||||
FrameGraphId<FrameGraphTexture> render(FEngine& engine, FrameGraph& fg, RenderPass const& pass,
|
||||
FView& view, CameraInfo const& mainCameraInfo, math::float4 const& userTime) noexcept;
|
||||
|
||||
ShadowMap* getCascadeShadowMap(size_t cascade) noexcept {
|
||||
assert_invariant(cascade < CONFIG_MAX_SHADOW_CASCADES);
|
||||
return std::launder(reinterpret_cast<ShadowMap*>(&mShadowMapCache[cascade]));
|
||||
}
|
||||
|
||||
ShadowMap const* getCascadeShadowMap(size_t cascade) const noexcept {
|
||||
return const_cast<ShadowMapManager*>(this)->getCascadeShadowMap(cascade);
|
||||
}
|
||||
|
||||
ShadowMap* getPointOrSpotShadowMap(size_t index) noexcept {
|
||||
ShadowMap* getShadowMap(size_t index) noexcept {
|
||||
assert_invariant(index < CONFIG_MAX_SHADOWMAPS);
|
||||
return std::launder(reinterpret_cast<ShadowMap*>(
|
||||
&mShadowMapCache[CONFIG_MAX_SHADOW_CASCADES + index]));
|
||||
return std::launder(reinterpret_cast<ShadowMap*>(&mShadowMapCache[index]));
|
||||
}
|
||||
|
||||
ShadowMap const* getPointOrSpotShadowMap(size_t spot) const noexcept {
|
||||
return const_cast<ShadowMapManager*>(this)->getPointOrSpotShadowMap(spot);
|
||||
ShadowMap const* getShadowMap(size_t index) const noexcept {
|
||||
return const_cast<ShadowMapManager*>(this)->getShadowMap(index);
|
||||
}
|
||||
|
||||
// valid after calling update() above
|
||||
@@ -194,6 +180,7 @@ private:
|
||||
uint16_t size = 0;
|
||||
uint8_t layers = 0;
|
||||
uint8_t levels = 0;
|
||||
uint8_t msaaSamples = 1;
|
||||
backend::TextureFormat format = backend::TextureFormat::DEPTH16;
|
||||
} mTextureAtlasRequirements;
|
||||
|
||||
@@ -215,13 +202,13 @@ private:
|
||||
|
||||
utils::FixedCapacityVector<ShadowMap*> mSpotShadowMaps{
|
||||
utils::FixedCapacityVector<ShadowMap*>::with_capacity(
|
||||
CONFIG_MAX_SHADOWMAPS) };
|
||||
CONFIG_MAX_SHADOWMAPS - CONFIG_MAX_SHADOW_CASCADES) };
|
||||
|
||||
// inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
|
||||
// because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
|
||||
// Each ShadowMap is currently 40 bytes (total of 2.5KB for 64 shadow maps)
|
||||
using ShadowMapStorage = std::aligned_storage<sizeof(ShadowMap), alignof(ShadowMap)>::type;
|
||||
std::array<ShadowMapStorage, CONFIG_MAX_SHADOW_CASCADES + CONFIG_MAX_SHADOWMAPS> mShadowMapCache;
|
||||
std::array<ShadowMapStorage, CONFIG_MAX_SHADOWMAPS> mShadowMapCache;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -240,7 +240,6 @@ void FLightManager::setShadowOptions(Instance i, ShadowOptions const& options) n
|
||||
params.options.shadowFar = std::max(options.shadowFar, 0.0f);
|
||||
params.options.shadowNearHint = std::max(options.shadowNearHint, 0.0f);
|
||||
params.options.shadowFarHint = std::max(options.shadowFarHint, 0.0f);
|
||||
params.options.vsm.msaaSamples = std::max(uint8_t(0), options.vsm.msaaSamples);
|
||||
params.options.vsm.blurWidth = std::max(0.0f, options.vsm.blurWidth);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace filament {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
FScene::FScene(FEngine& engine) :
|
||||
mEngine(engine) {
|
||||
mEngine(engine), mSharedState(std::make_shared<SharedState>()) {
|
||||
}
|
||||
|
||||
FScene::~FScene() noexcept = default;
|
||||
@@ -268,7 +268,8 @@ void FScene::updateUBOs(
|
||||
PerRenderableData* buffer = [&]{
|
||||
if (count >= MAX_STREAM_ALLOCATION_COUNT) {
|
||||
// use the heap allocator
|
||||
return (PerRenderableData*)mBufferPoolAllocator.get(count * sizeof(PerRenderableData));
|
||||
auto& bufferPoolAllocator = mSharedState->mBufferPoolAllocator;
|
||||
return (PerRenderableData*)bufferPoolAllocator.get(count * sizeof(PerRenderableData));
|
||||
} else {
|
||||
// allocate space into the command stream directly
|
||||
return driver.allocatePod<PerRenderableData>(count);
|
||||
@@ -281,16 +282,24 @@ void FScene::updateUBOs(
|
||||
buffer[i] = uboData[i];
|
||||
}
|
||||
|
||||
// We capture state shared between Scene and the update buffer callback, because the Scene could
|
||||
// be destroyed before the callback executes.
|
||||
std::weak_ptr<SharedState>* const weakShared = new std::weak_ptr<SharedState>(mSharedState);
|
||||
|
||||
// update the UBO
|
||||
driver.resetBufferObject(renderableUbh);
|
||||
driver.updateBufferObjectUnsynchronized(renderableUbh, {
|
||||
buffer, count * sizeof(PerRenderableData),
|
||||
+[](void* p, size_t s, void* user) {
|
||||
std::weak_ptr<SharedState>* const weakShared =
|
||||
static_cast<std::weak_ptr<SharedState>*>(user);
|
||||
if (s >= MAX_STREAM_ALLOCATION_COUNT * sizeof(PerRenderableData)) {
|
||||
FScene* const that = static_cast<FScene*>(user);
|
||||
that->mBufferPoolAllocator.put(p);
|
||||
if (auto state = weakShared->lock()) {
|
||||
state->mBufferPoolAllocator.put(p);
|
||||
}
|
||||
}
|
||||
}, this
|
||||
delete weakShared;
|
||||
}, weakShared
|
||||
}, 0);
|
||||
|
||||
// update skybox
|
||||
@@ -343,9 +352,10 @@ void FScene::prepareDynamicLights(const CameraInfo& camera, ArenaScope& rootAren
|
||||
lp[gpuIndex].typeShadow = LightsUib::packTypeShadow(
|
||||
lcm.isPointLight(li) ? 0u : 1u,
|
||||
shadowInfo[i].contactShadows,
|
||||
shadowInfo[i].index,
|
||||
shadowInfo[i].layer);
|
||||
lp[gpuIndex].channels = LightsUib::packChannels(lcm.getLightChannels(li), shadowInfo[i].castsShadows);
|
||||
shadowInfo[i].index);
|
||||
lp[gpuIndex].channels = LightsUib::packChannels(
|
||||
lcm.getLightChannels(li),
|
||||
shadowInfo[i].castsShadows);
|
||||
}
|
||||
|
||||
driver.updateBufferObject(lightUbh, { lp, positionalLightCount * sizeof(LightsUib) }, 0);
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
#include <tsl/robin_set.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace filament {
|
||||
|
||||
struct CameraInfo;
|
||||
@@ -155,7 +157,6 @@ public:
|
||||
bool castsShadows = false; // whether this light casts shadows
|
||||
bool contactShadows = false; // whether this light casts contact shadows
|
||||
uint8_t index = 0; // an index into the arrays in the Shadows uniform buffer
|
||||
uint8_t layer = 0; // which layer of the shadow texture array to sample from
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -179,7 +180,8 @@ public:
|
||||
LightSoa const& getLightData() const noexcept { return mLightData; }
|
||||
LightSoa& getLightData() noexcept { return mLightData; }
|
||||
|
||||
void updateUBOs(utils::Range<uint32_t> visibleRenderables, backend::Handle<backend::HwBufferObject> renderableUbh) noexcept;
|
||||
void updateUBOs(utils::Range<uint32_t> visibleRenderables,
|
||||
backend::Handle<backend::HwBufferObject> renderableUbh) noexcept;
|
||||
|
||||
bool hasContactShadows() const noexcept;
|
||||
|
||||
@@ -221,7 +223,12 @@ private:
|
||||
LightSoa mLightData;
|
||||
backend::Handle<backend::HwBufferObject> mRenderableViewUbh; // This is actually owned by the view.
|
||||
bool mHasContactShadows = false;
|
||||
BufferPoolAllocator<3> mBufferPoolAllocator;
|
||||
|
||||
// State shared between Scene and driver callbacks.
|
||||
struct SharedState {
|
||||
BufferPoolAllocator<3> mBufferPoolAllocator = {};
|
||||
};
|
||||
std::shared_ptr<SharedState> mSharedState;
|
||||
};
|
||||
|
||||
FILAMENT_DOWNCAST(Scene)
|
||||
|
||||
@@ -294,7 +294,7 @@ void FView::prepareShadowing(FEngine& engine, DriverApi& driver,
|
||||
}
|
||||
|
||||
// Find all shadow-casting spotlights.
|
||||
size_t shadowMapCount = 0;
|
||||
size_t shadowMapCount = CONFIG_MAX_SHADOW_CASCADES;
|
||||
|
||||
// We allow a max of CONFIG_MAX_SHADOWMAPS point/spotlight shadows. Any additional
|
||||
// shadow-casting spotlights are ignored.
|
||||
@@ -314,16 +314,16 @@ void FView::prepareShadowing(FEngine& engine, DriverApi& driver,
|
||||
continue; // doesn't cast shadows
|
||||
}
|
||||
|
||||
const auto& shadowOptions = lcm.getShadowOptions(li);
|
||||
mShadowMapManager.addShadowMap(l, lcm.isSpotLight(li), &shadowOptions);
|
||||
const bool spotLight = lcm.isSpotLight(li);
|
||||
|
||||
if (lcm.isSpotLight(li)) {
|
||||
shadowMapCount += 6;
|
||||
} else {
|
||||
shadowMapCount += 1;
|
||||
const size_t shadowMapCountNeeded = spotLight ? 1 : 6;
|
||||
if (shadowMapCount + shadowMapCountNeeded <= CONFIG_MAX_SHADOWMAPS) {
|
||||
shadowMapCount += shadowMapCountNeeded;
|
||||
const auto& shadowOptions = lcm.getShadowOptions(li);
|
||||
mShadowMapManager.addShadowMap(l, spotLight, &shadowOptions);
|
||||
}
|
||||
|
||||
if (shadowMapCount > CONFIG_MAX_SHADOWMAPS - 1) {
|
||||
if (shadowMapCount >= CONFIG_MAX_SHADOWMAPS) {
|
||||
break; // we ran out of spotlight shadow casting
|
||||
}
|
||||
}
|
||||
@@ -994,6 +994,10 @@ void FView::setAmbientOcclusionOptions(AmbientOcclusionOptions options) noexcept
|
||||
options.ssct.rayCount = math::clamp((unsigned)options.ssct.rayCount, 1u, 255u);
|
||||
mAmbientOcclusionOptions = options;
|
||||
}
|
||||
void FView::setVsmShadowOptions(VsmShadowOptions options) noexcept {
|
||||
options.msaaSamples = std::max(uint8_t(0), options.msaaSamples);
|
||||
mVsmShadowOptions = options;
|
||||
}
|
||||
|
||||
void FView::setSoftShadowOptions(SoftShadowOptions options) noexcept {
|
||||
options.penumbraScale = std::max(0.0f, options.penumbraScale);
|
||||
|
||||
@@ -187,7 +187,7 @@ public:
|
||||
bool isStencilBufferEnabled() const noexcept { return mStencilBufferEnabled; }
|
||||
|
||||
FCamera const* getDirectionalLightCamera() const noexcept {
|
||||
return &mShadowMapManager.getCascadeShadowMap(0)->getDebugCamera();
|
||||
return &mShadowMapManager.getShadowMap(0)->getDebugCamera();
|
||||
}
|
||||
|
||||
void setRenderTarget(FRenderTarget* renderTarget) noexcept {
|
||||
@@ -305,9 +305,7 @@ public:
|
||||
mShadowType = shadow;
|
||||
}
|
||||
|
||||
void setVsmShadowOptions(VsmShadowOptions const& options) noexcept {
|
||||
mVsmShadowOptions = options;
|
||||
}
|
||||
void setVsmShadowOptions(VsmShadowOptions options) noexcept;
|
||||
|
||||
VsmShadowOptions getVsmShadowOptions() const noexcept {
|
||||
return mVsmShadowOptions;
|
||||
|
||||
@@ -22,7 +22,7 @@ using namespace filament;
|
||||
|
||||
TEST(AtlasAllocator, AllocateFirstLevel) {
|
||||
|
||||
AtlasAllocator allocator;
|
||||
AtlasAllocator allocator(1024);
|
||||
|
||||
auto a = allocator.allocateInLayer(0);
|
||||
EXPECT_TRUE(a.l == 0 && a.code == 0);
|
||||
@@ -39,7 +39,7 @@ TEST(AtlasAllocator, AllocateFirstLevel) {
|
||||
|
||||
TEST(AtlasAllocator, AllocateSecondLevel) {
|
||||
|
||||
AtlasAllocator allocator;
|
||||
AtlasAllocator allocator(1024);
|
||||
|
||||
auto d0 = allocator.allocateInLayer(1);
|
||||
EXPECT_TRUE(d0.l == 1 && d0.code == 0);
|
||||
@@ -55,7 +55,7 @@ TEST(AtlasAllocator, AllocateSecondLevel) {
|
||||
}
|
||||
|
||||
TEST(AtlasAllocator, AllocateMixed0) {
|
||||
AtlasAllocator allocator;
|
||||
AtlasAllocator allocator(1024);
|
||||
|
||||
auto e0 = allocator.allocateInLayer(1);
|
||||
EXPECT_TRUE(e0.l == 1 && e0.code == 0);
|
||||
@@ -74,7 +74,7 @@ TEST(AtlasAllocator, AllocateMixed0) {
|
||||
}
|
||||
|
||||
TEST(AtlasAllocator, AllocateMixed1) {
|
||||
AtlasAllocator allocator;
|
||||
AtlasAllocator allocator(1024);
|
||||
|
||||
auto e0 = allocator.allocateInLayer(1);
|
||||
EXPECT_TRUE(e0.l == 1 && e0.code == 0);
|
||||
@@ -90,7 +90,7 @@ TEST(AtlasAllocator, AllocateMixed1) {
|
||||
}
|
||||
|
||||
TEST(AtlasAllocator, AllocateMixed2) {
|
||||
AtlasAllocator allocator;
|
||||
AtlasAllocator allocator(1024);
|
||||
|
||||
auto e0 = allocator.allocateInLayer(1);
|
||||
EXPECT_TRUE(e0.l == 1 && e0.code == 0);
|
||||
@@ -122,10 +122,11 @@ TEST(AtlasAllocator, AllocateBySize) {
|
||||
|
||||
Viewport vp(0,0,256,256);
|
||||
auto vp0 = allocator.allocate(256);
|
||||
EXPECT_EQ(vp0, vp);
|
||||
EXPECT_EQ(vp0.viewport, vp);
|
||||
EXPECT_EQ(vp0.layer, 0);
|
||||
|
||||
auto vp1 = allocator.allocate(128);
|
||||
EXPECT_TRUE(vp1.empty());
|
||||
EXPECT_EQ(vp1.layer, 1);
|
||||
}
|
||||
|
||||
TEST(AtlasAllocator, AllocateBySizeOneOfEach) {
|
||||
@@ -140,10 +141,35 @@ TEST(AtlasAllocator, AllocateBySizeOneOfEach) {
|
||||
auto vp2 = allocator.allocate(32);
|
||||
auto vp3 = allocator.allocate(16);
|
||||
|
||||
EXPECT_EQ(vp0, r0);
|
||||
EXPECT_EQ(vp1, r1);
|
||||
EXPECT_EQ(vp2, r2);
|
||||
EXPECT_TRUE(vp3.empty());
|
||||
EXPECT_EQ(vp0.layer, 0);
|
||||
EXPECT_EQ(vp1.layer, 0);
|
||||
EXPECT_EQ(vp2.layer, 0);
|
||||
|
||||
EXPECT_EQ(vp0.viewport, r0);
|
||||
EXPECT_EQ(vp1.viewport, r1);
|
||||
EXPECT_EQ(vp2.viewport, r2);
|
||||
EXPECT_TRUE(vp3.viewport.empty());
|
||||
|
||||
}
|
||||
|
||||
TEST(AtlasAllocator, AllocateBySizeFullLayers) {
|
||||
AtlasAllocator allocator(512);
|
||||
|
||||
Viewport r(0,0,512,512);
|
||||
|
||||
auto vp0 = allocator.allocate(512);
|
||||
auto vp1 = allocator.allocate(512);
|
||||
auto vp2 = allocator.allocate(512);
|
||||
auto vp3 = allocator.allocate(512);
|
||||
|
||||
EXPECT_EQ(vp0.layer, 0);
|
||||
EXPECT_EQ(vp1.layer, 1);
|
||||
EXPECT_EQ(vp2.layer, 2);
|
||||
EXPECT_EQ(vp3.layer, 3);
|
||||
|
||||
EXPECT_EQ(vp0.viewport, r);
|
||||
EXPECT_EQ(vp1.viewport, r);
|
||||
EXPECT_EQ(vp2.viewport, r);
|
||||
EXPECT_EQ(vp3.viewport, r);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.28.2"
|
||||
spec.version = "1.30.0"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.28.2/filament-v1.28.2-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.30.0/filament-v1.30.0-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
namespace filament {
|
||||
|
||||
// update this when a new version of filament wouldn't work with older materials
|
||||
static constexpr size_t MATERIAL_VERSION = 28;
|
||||
static constexpr size_t MATERIAL_VERSION = 30;
|
||||
|
||||
/**
|
||||
* Supported shading models
|
||||
|
||||
@@ -124,12 +124,10 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
// bit 0-3: cascade count
|
||||
// bit 4: visualize cascades
|
||||
// bit 8-11: cascade has visible shadows
|
||||
// bit 31: elvsm
|
||||
uint32_t cascades;
|
||||
float shadowBulbRadiusLs; // light radius in light-space
|
||||
float shadowBias; // normal bias
|
||||
float reserved0;
|
||||
float reserved1; // normal bias
|
||||
float shadowPenumbraRatioScale; // For DPCF or PCSS, scale penumbra ratio for artistic use
|
||||
std::array<math::mat4f, CONFIG_MAX_SHADOW_CASCADES> lightFromWorldMatrix;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// VSM shadows [variant: VSM]
|
||||
@@ -164,7 +162,7 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
float ssrStride; // ssr texel stride, >= 1.0
|
||||
|
||||
// bring PerViewUib to 2 KiB
|
||||
math::float4 reserved[47];
|
||||
math::float4 reserved[63];
|
||||
};
|
||||
|
||||
// 2 KiB == 128 float4s
|
||||
@@ -229,11 +227,11 @@ struct LightsUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
math::float2 spotScaleOffset; // { scale, offset }
|
||||
float reserved3; // 0
|
||||
float intensity; // float
|
||||
uint32_t typeShadow; // 0x00.ll.ii.ct (t: 0=point, 1=spot, c:contact, ii: index, ll: layer)
|
||||
uint32_t typeShadow; // 0x00.00.ii.ct (t: 0=point, 1=spot, c:contact, ii: index)
|
||||
uint32_t channels; // 0x000c00ll (ll: light channels, c: caster)
|
||||
|
||||
static uint32_t packTypeShadow(uint8_t type, bool contactShadow, uint8_t index, uint8_t layer) noexcept {
|
||||
return (type & 0xF) | (contactShadow ? 0x10 : 0x00) | (index << 8) | (layer << 16);
|
||||
static uint32_t packTypeShadow(uint8_t type, bool contactShadow, uint8_t index) noexcept {
|
||||
return (type & 0xF) | (contactShadow ? 0x10 : 0x00) | (index << 8);
|
||||
}
|
||||
static uint32_t packChannels(uint8_t lightChannels, bool castShadows) noexcept {
|
||||
return lightChannels | (castShadows ? 0x10000 : 0);
|
||||
@@ -249,15 +247,17 @@ static_assert(sizeof(LightsUib) == 64,
|
||||
struct ShadowUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
static constexpr std::string_view _name{ "ShadowUniforms" };
|
||||
struct alignas(16) ShadowData {
|
||||
math::mat4f lightFromWorldMatrix; // 64 - unused for point lights
|
||||
math::float3 direction; // 12 - unused for point lights
|
||||
float normalBias; // 4 - unused for point lights
|
||||
math::float4 lightFromWorldZ; // 16 - point lights { depth reconstruction values }
|
||||
|
||||
math::mat4f lightFromWorldMatrix; // 64
|
||||
math::float4 lightFromWorldZ; // 16
|
||||
math::float4 scissorNormalized; // 16
|
||||
float texelSizeAtOneMeter; // 4
|
||||
float bulbRadiusLs; // 4
|
||||
float nearOverFarMinusNear; // 4
|
||||
float normalBias; // 4
|
||||
bool elvsm; // 4
|
||||
uint32_t layer; // 4
|
||||
uint32_t reserved1; // 4
|
||||
uint32_t reserved2; // 4
|
||||
};
|
||||
ShadowData shadows[CONFIG_MAX_SHADOWMAPS];
|
||||
};
|
||||
|
||||
@@ -35,6 +35,11 @@ Variant Variant::filterUserVariant(
|
||||
if (filterMask & (uint32_t)UserVariantFilterBit::FOG) {
|
||||
variant.key &= ~(filterMask & FOG);
|
||||
}
|
||||
} else {
|
||||
// depth variants can have their VSM bit filtered
|
||||
if (filterMask & (uint32_t)UserVariantFilterBit::VSM) {
|
||||
variant.key &= ~(filterMask & VSM);
|
||||
}
|
||||
}
|
||||
if (!isSSRVariant(variant)) {
|
||||
// SSR variant needs to be handled separately
|
||||
@@ -53,8 +58,6 @@ Variant Variant::filterUserVariant(
|
||||
return variant;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
// compile time sanity-check tests
|
||||
|
||||
@@ -105,10 +105,9 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
|
||||
|
||||
{ "cascadeSplits", 0, Type::FLOAT4, Precision::HIGH },
|
||||
{ "cascades", 0, Type::UINT },
|
||||
{ "shadowBulbRadiusLs", 0, Type::FLOAT },
|
||||
{ "shadowBias", 0, Type::FLOAT },
|
||||
{ "reserved0", 0, Type::FLOAT },
|
||||
{ "reserved1", 0, Type::FLOAT },
|
||||
{ "shadowPenumbraRatioScale", 0, Type::FLOAT },
|
||||
{ "lightFromWorldMatrix", 4, Type::MAT4, Precision::HIGH },
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// VSM shadows [variant: VSM]
|
||||
|
||||
@@ -121,8 +121,8 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
|
||||
|
||||
// specification constants
|
||||
out << '\n';
|
||||
generateSpecificationConstant(out, "BACKEND_FEATURE_LEVEL", 0, 1);
|
||||
generateSpecificationConstant(out, "CONFIG_MAX_INSTANCES", 1, (int)CONFIG_MAX_INSTANCES);
|
||||
generateSpecializationConstant(out, "BACKEND_FEATURE_LEVEL", 0, 1);
|
||||
generateSpecializationConstant(out, "CONFIG_MAX_INSTANCES", 1, (int)CONFIG_MAX_INSTANCES);
|
||||
|
||||
out << '\n';
|
||||
out << SHADERS_COMMON_DEFINES_GLSL_DATA;
|
||||
@@ -597,7 +597,7 @@ io::sstream& CodeGenerator::generateIndexedDefine(io::sstream& out, const char*
|
||||
return out;
|
||||
}
|
||||
|
||||
utils::io::sstream& CodeGenerator::generateSpecificationConstant(utils::io::sstream& out,
|
||||
utils::io::sstream& CodeGenerator::generateSpecializationConstant(utils::io::sstream& out,
|
||||
const char* name, uint32_t id, std::variant<int, float, bool> value) const {
|
||||
static const char* types[] = { "int", "float", "bool" };
|
||||
if (mTargetLanguage == MaterialBuilderBase::TargetLanguage::SPIRV) {
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
static utils::io::sstream& generateIndexedDefine(utils::io::sstream& out, const char* name,
|
||||
uint32_t index, uint32_t value);
|
||||
|
||||
utils::io::sstream& generateSpecificationConstant(utils::io::sstream& out,
|
||||
utils::io::sstream& generateSpecializationConstant(utils::io::sstream& out,
|
||||
const char* name, uint32_t id, std::variant<int, float, bool> value) const;
|
||||
|
||||
static utils::io::sstream& generatePostProcessGetters(utils::io::sstream& out, ShaderStage type);
|
||||
|
||||
@@ -287,6 +287,10 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_RENDERABLE, UibGenerator::getPerRenderableUib());
|
||||
if (litVariants && filament::Variant::isShadowReceiverVariant(variant)) {
|
||||
cg.generateUniforms(vs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::SHADOW, UibGenerator::getShadowUib());
|
||||
}
|
||||
if (variant.hasSkinningOrMorphing()) {
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_RENDERABLE_BONES,
|
||||
|
||||
@@ -145,11 +145,10 @@ void FFilamentInstance::recomputeBoundingBoxes() {
|
||||
}
|
||||
|
||||
const cgltf_accessor* targetAccessor = targetAttribute.data;
|
||||
const cgltf_size targetCount = targetAccessor->count;
|
||||
const cgltf_size targetDim = cgltf_num_components(targetAccessor->type);
|
||||
|
||||
assert_invariant(targetCount == accessor->count);
|
||||
assert_invariant(targetDim == dim);
|
||||
assert_invariant(targetAccessor);
|
||||
assert_invariant(targetAccessor->count == accessor->count);
|
||||
assert_invariant(cgltf_num_components(targetAccessor->type) == dim);
|
||||
|
||||
cgltf_accessor_unpack_floats(targetAccessor, unpacked.data(), unpacked.size());
|
||||
|
||||
|
||||
@@ -588,6 +588,26 @@ constexpr mat4f highPrecisionMultiply(mat4f const& lhs, mat4f const& rhs) noexce
|
||||
};
|
||||
}
|
||||
|
||||
// mat4 * float4, with double precision intermediates
|
||||
constexpr double4 highPrecisionMultiplyd(mat4f const& lhs, float4 const& rhs) noexcept {
|
||||
double4 result{};
|
||||
result += lhs[0] * rhs[0];
|
||||
result += lhs[1] * rhs[1];
|
||||
result += lhs[2] * rhs[2];
|
||||
result += lhs[3] * rhs[3];
|
||||
return result;
|
||||
}
|
||||
|
||||
// mat4 * mat4, with double precision intermediates
|
||||
constexpr mat4 highPrecisionMultiplyd(mat4f const& lhs, mat4f const& rhs) noexcept {
|
||||
return {
|
||||
highPrecisionMultiplyd(lhs, rhs[0]),
|
||||
highPrecisionMultiplyd(lhs, rhs[1]),
|
||||
highPrecisionMultiplyd(lhs, rhs[2]),
|
||||
highPrecisionMultiplyd(lhs, rhs[3])
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
} // namespace math
|
||||
} // namespace filament
|
||||
|
||||
@@ -87,11 +87,11 @@ static_assert(size(4) == 85);
|
||||
/**
|
||||
* A Quad-tree encoded as an array.
|
||||
* @tparam T Type of the quad-tree nodes
|
||||
* @tparam HEIGHT Height of the quad-tree, muse be <= 4
|
||||
* @tparam HEIGHT Height of the quad-tree
|
||||
*/
|
||||
template<typename T, size_t HEIGHT>
|
||||
class QuadTreeArray : public std::array<T, QuadTreeUtils::size(HEIGHT)> {
|
||||
static_assert(HEIGHT <= 4, "QuadTreeArray height must be <= 4");
|
||||
static_assert(HEIGHT <= 7, "QuadTreeArray height must be <= 7 (16-bits morton)");
|
||||
|
||||
// Simple fixed capacity stack
|
||||
template<typename TYPE, size_t CAPACITY,
|
||||
|
||||
@@ -320,9 +320,7 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "msaaSamples") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->msaaSamples);
|
||||
} else if (compare(tok, jsonChunk, "elvsm") == 0) {
|
||||
if (compare(tok, jsonChunk, "elvsm") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->elvsm);
|
||||
} else if (compare(tok, jsonChunk, "blurWidth") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->blurWidth);
|
||||
@@ -678,7 +676,6 @@ static std::ostream& operator<<(std::ostream& out, const LightManager::ShadowOpt
|
||||
math::float3 splitsVector = { splits[0], splits[1], splits[2] };
|
||||
return out << "{\n"
|
||||
<< "\"vsm\": {\n"
|
||||
<< "\"msaaSamples\": " << int(in.vsm.msaaSamples) << ",\n"
|
||||
<< "\"elvsm\": " << to_string(in.vsm.elvsm) << ",\n"
|
||||
<< "\"blurWidth\": " << in.vsm.blurWidth << "\n"
|
||||
<< "},\n"
|
||||
|
||||
@@ -800,6 +800,8 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, VsmShadowOption
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->anisotropy);
|
||||
} else if (compare(tok, jsonChunk, "mipmapping") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->mipmapping);
|
||||
} else if (compare(tok, jsonChunk, "msaaSamples") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->msaaSamples);
|
||||
} else if (compare(tok, jsonChunk, "highPrecision") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->highPrecision);
|
||||
} else if (compare(tok, jsonChunk, "minVarianceScale") == 0) {
|
||||
@@ -822,6 +824,7 @@ std::ostream& operator<<(std::ostream& out, const VsmShadowOptions& in) {
|
||||
return out << "{\n"
|
||||
<< "\"anisotropy\": " << int(in.anisotropy) << ",\n"
|
||||
<< "\"mipmapping\": " << to_string(in.mipmapping) << ",\n"
|
||||
<< "\"msaaSamples\": " << int(in.msaaSamples) << ",\n"
|
||||
<< "\"highPrecision\": " << to_string(in.highPrecision) << ",\n"
|
||||
<< "\"minVarianceScale\": " << (in.minVarianceScale) << ",\n"
|
||||
<< "\"lightBleedReduction\": " << (in.lightBleedReduction) << "\n"
|
||||
|
||||
@@ -846,7 +846,7 @@ void ViewerGui::updateUserInterface() {
|
||||
char label[32];
|
||||
snprintf(label, 32, "%d", 1 << mVsmMsaaSamplesLog2);
|
||||
ImGui::SliderInt("VSM MSAA samples", &mVsmMsaaSamplesLog2, 0, 3, label);
|
||||
light.shadowOptions.vsm.msaaSamples =
|
||||
mSettings.view.vsmShadowOptions.msaaSamples =
|
||||
static_cast<uint8_t>(1u << mVsmMsaaSamplesLog2);
|
||||
|
||||
int vsmAnisotropy = mSettings.view.vsmShadowOptions.anisotropy;
|
||||
|
||||
@@ -2,14 +2,14 @@ struct Light {
|
||||
vec4 colorIntensity; // rgb, pre-exposed intensity
|
||||
vec3 l;
|
||||
float attenuation;
|
||||
vec3 worldPosition;
|
||||
highp vec3 worldPosition;
|
||||
float NoL;
|
||||
highp vec3 direction;
|
||||
float zLight;
|
||||
bool castsShadows;
|
||||
bool contactShadows;
|
||||
uint type;
|
||||
uint shadowIndex;
|
||||
uint shadowLayer;
|
||||
uint channels;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
*/
|
||||
|
||||
highp vec4 computeLightSpacePosition(highp vec3 p, const highp vec3 n,
|
||||
const highp vec3 l, const float b, const highp mat4 lightFromWorldMatrix) {
|
||||
const highp vec3 dir, const float b, const highp mat4 lightFromWorldMatrix) {
|
||||
|
||||
#if !defined(VARIANT_HAS_VSM)
|
||||
highp float NoL = saturate(dot(n, l));
|
||||
highp float sinTheta = sqrt(1.0 - NoL * NoL);
|
||||
highp float cosTheta = saturate(dot(n, dir));
|
||||
highp float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
p += n * (sinTheta * b);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,13 +2,16 @@
|
||||
// UBOs, which is is the case here.
|
||||
struct ShadowData {
|
||||
highp mat4 lightFromWorldMatrix;
|
||||
highp vec3 direction;
|
||||
float normalBias;
|
||||
highp vec4 lightFromWorldZ;
|
||||
float texelSizeAtOneMeter;
|
||||
float bulbRadiusLs;
|
||||
float nearOverFarMinusNear;
|
||||
highp vec4 scissorNormalized;
|
||||
mediump float texelSizeAtOneMeter;
|
||||
mediump float bulbRadiusLs;
|
||||
mediump float nearOverFarMinusNear;
|
||||
mediump float normalBias;
|
||||
bool elvsm;
|
||||
mediump uint layer;
|
||||
mediump uint reserved1;
|
||||
mediump uint reserved2;
|
||||
};
|
||||
|
||||
struct BoneData {
|
||||
|
||||
@@ -94,9 +94,8 @@ highp vec3 getNormalizedViewportCoord2() {
|
||||
}
|
||||
|
||||
#if defined(VARIANT_HAS_SHADOWING) && defined(VARIANT_HAS_DYNAMIC_LIGHTING)
|
||||
highp vec4 getSpotLightSpacePosition(uint index, highp float zLight) {
|
||||
highp vec4 getSpotLightSpacePosition(uint index, highp vec3 dir, highp float zLight) {
|
||||
highp mat4 lightFromWorldMatrix = shadowUniforms.shadows[index].lightFromWorldMatrix;
|
||||
highp vec3 dir = shadowUniforms.shadows[index].direction;
|
||||
|
||||
// for spotlights, the bias depends on z
|
||||
float bias = shadowUniforms.shadows[index].normalBias * zLight;
|
||||
@@ -134,8 +133,9 @@ highp vec4 getCascadeLightSpacePosition(uint cascade) {
|
||||
}
|
||||
|
||||
return computeLightSpacePosition(getWorldPosition(), getWorldNormalVector(),
|
||||
frameUniforms.lightDirection, frameUniforms.shadowBias,
|
||||
frameUniforms.lightFromWorldMatrix[cascade]);
|
||||
frameUniforms.lightDirection,
|
||||
shadowUniforms.shadows[cascade].normalBias,
|
||||
shadowUniforms.shadows[cascade].lightFromWorldMatrix);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,10 +13,6 @@ int getInstanceIndex() {
|
||||
// Uniforms access
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
mat4 getLightFromWorldMatrix() {
|
||||
return frameUniforms.lightFromWorldMatrix[0];
|
||||
}
|
||||
|
||||
PerRenderableData getObjectUniforms() {
|
||||
#if defined(MATERIAL_HAS_INSTANCES)
|
||||
// the material manages instancing, all instances share the same uniform block.
|
||||
|
||||
@@ -56,9 +56,8 @@ void evaluateDirectionalLight(const MaterialInputs material,
|
||||
bool cascadeHasVisibleShadows = bool(frameUniforms.cascades & ((1u << cascade) << 8u));
|
||||
bool hasDirectionalShadows = bool(frameUniforms.directionalShadows & 1u);
|
||||
if (hasDirectionalShadows && cascadeHasVisibleShadows) {
|
||||
uint layer = cascade;
|
||||
highp vec4 shadowPosition = getShadowPosition(true, 0u, cascade, 0.0f);
|
||||
visibility = shadow(true, light_shadowMap, layer, 0u, shadowPosition, 0.0f);
|
||||
highp vec4 shadowPosition = getShadowPosition(cascade);
|
||||
visibility = shadow(true, light_shadowMap, cascade, shadowPosition, 0.0f);
|
||||
}
|
||||
if ((frameUniforms.directionalShadows & 0x2u) != 0u && visibility > 0.0) {
|
||||
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
|
||||
|
||||
@@ -150,6 +150,7 @@ Light getLight(const uint lightIndex) {
|
||||
light.colorIntensity.w = computePreExposedIntensity(intensity, frameUniforms.exposure);
|
||||
light.l = normalize(posToLight);
|
||||
light.attenuation = getDistanceAttenuation(posToLight, positionFalloff.w);
|
||||
light.direction = direction;
|
||||
light.NoL = saturate(dot(shading_normal, light.l));
|
||||
light.worldPosition = positionFalloff.xyz;
|
||||
light.channels = channels;
|
||||
@@ -158,7 +159,6 @@ Light getLight(const uint lightIndex) {
|
||||
light.type = (typeShadow & 0x1u);
|
||||
#if defined(VARIANT_HAS_SHADOWING)
|
||||
light.shadowIndex = (typeShadow >> 8u) & 0xFFu;
|
||||
light.shadowLayer = (typeShadow >> 16u) & 0xFFu;
|
||||
light.castsShadows = bool(channels & 0x10000u);
|
||||
if (light.type == LIGHT_TYPE_SPOT) {
|
||||
light.zLight = dot(shadowUniforms.shadows[light.shadowIndex].lightFromWorldZ, vec4(worldPosition, 1.0));
|
||||
@@ -211,19 +211,17 @@ void evaluatePunctualLights(const MaterialInputs material,
|
||||
#if defined(VARIANT_HAS_SHADOWING)
|
||||
if (light.NoL > 0.0) {
|
||||
if (light.castsShadows) {
|
||||
uint layer = light.shadowLayer;
|
||||
highp vec4 shadowPosition;
|
||||
uint shadowIndex = light.shadowIndex;
|
||||
if (light.type == LIGHT_TYPE_POINT) {
|
||||
// point-light shadows are sampled from a direction
|
||||
highp vec3 r = getWorldPosition() - light.worldPosition;
|
||||
highp vec4 nf = shadowUniforms.shadows[light.shadowIndex].lightFromWorldZ;
|
||||
// getShadowPosition returns zLight which is needed for PCSS/DPCF
|
||||
shadowPosition = getShadowPosition(r, nf, layer, light.zLight);
|
||||
} else {
|
||||
// getShadowPosition needs zLight for applying the normal bias
|
||||
shadowPosition = getShadowPosition(false, light.shadowIndex, 0u, light.zLight);
|
||||
uint face = getPointLightFace(r);
|
||||
shadowIndex += face;
|
||||
light.zLight = dot(shadowUniforms.shadows[shadowIndex].lightFromWorldZ,
|
||||
vec4(getWorldPosition(), 1.0));
|
||||
}
|
||||
visibility = shadow(false, light_shadowMap, layer, light.shadowIndex,
|
||||
highp vec4 shadowPosition = getShadowPosition(shadowIndex, light.direction, light.zLight);
|
||||
visibility = shadow(false, light_shadowMap, shadowIndex,
|
||||
shadowPosition, light.zLight);
|
||||
}
|
||||
if (light.contactShadows && visibility > 0.0) {
|
||||
|
||||
@@ -143,7 +143,9 @@ void main() {
|
||||
#if defined(VARIANT_HAS_SHADOWING) && defined(VARIANT_HAS_DIRECTIONAL_LIGHTING)
|
||||
vertex_lightSpacePosition = computeLightSpacePosition(
|
||||
vertex_worldPosition.xyz, vertex_worldNormal,
|
||||
frameUniforms.lightDirection, frameUniforms.shadowBias, getLightFromWorldMatrix());
|
||||
frameUniforms.lightDirection,
|
||||
shadowUniforms.shadows[0].normalBias,
|
||||
shadowUniforms.shadows[0].lightFromWorldMatrix);
|
||||
#endif
|
||||
|
||||
#endif // !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER)
|
||||
|
||||
@@ -50,9 +50,8 @@ vec4 evaluateMaterial(const MaterialInputs material) {
|
||||
bool cascadeHasVisibleShadows = bool(frameUniforms.cascades & ((1u << cascade) << 8u));
|
||||
bool hasDirectionalShadows = bool(frameUniforms.directionalShadows & 1u);
|
||||
if (hasDirectionalShadows && cascadeHasVisibleShadows) {
|
||||
uint layer = cascade;
|
||||
highp vec4 shadowPosition = getShadowPosition(true, 0u, cascade, 0.0f);
|
||||
visibility = shadow(true, light_shadowMap, layer, 0u, shadowPosition, 0.0f);
|
||||
highp vec4 shadowPosition = getShadowPosition(cascade);
|
||||
visibility = shadow(true, light_shadowMap, cascade, shadowPosition, 0.0f);
|
||||
}
|
||||
if ((frameUniforms.directionalShadows & 0x2u) != 0u && visibility > 0.0) {
|
||||
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {
|
||||
|
||||
@@ -17,27 +17,33 @@
|
||||
// PCF Shadow Sampling
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
float sampleDepth(const mediump sampler2DArrayShadow map, const uint layer,
|
||||
const highp vec2 uv, float depth) {
|
||||
// depth must be clamped to support floating-point depth formats. This is to avoid comparing a
|
||||
// value from the depth texture (which is never greater than 1.0) with a greater-than-one
|
||||
// comparison value (which is possible with floating-point formats).
|
||||
float sampleDepth(const mediump sampler2DArrayShadow map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, highp vec2 uv, float depth) {
|
||||
|
||||
// clamp needed for directional lights and/or large kernels
|
||||
uv = clamp(uv, scissorNormalized.xy, scissorNormalized.zw);
|
||||
|
||||
// depth must be clamped to support floating-point depth formats which are always in
|
||||
// the range [0, 1].
|
||||
return texture(map, vec4(uv, layer, saturate(depth)));
|
||||
}
|
||||
|
||||
#if SHADOW_SAMPLING_METHOD == SHADOW_SAMPLING_PCF_HARD
|
||||
// use hardware assisted PCF
|
||||
float ShadowSample_PCF_Hard(const mediump sampler2DArrayShadow map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, const highp vec4 shadowPosition) {
|
||||
highp vec3 position = shadowPosition.xyz * (1.0 / shadowPosition.w);
|
||||
// note: shadowPosition.z is in the [1, 0] range (reversed Z)
|
||||
return sampleDepth(map, layer, position.xy, position.z);
|
||||
return sampleDepth(map, scissorNormalized, layer, position.xy, position.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SHADOW_SAMPLING_METHOD == SHADOW_SAMPLING_PCF_LOW
|
||||
// use hardware assisted PCF + 3x3 gaussian filter
|
||||
float ShadowSample_PCF_Low(const mediump sampler2DArrayShadow map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, const highp vec4 shadowPosition) {
|
||||
highp vec3 position = shadowPosition.xyz * (1.0 / shadowPosition.w);
|
||||
// note: shadowPosition.z is in the [1, 0] range (reversed Z)
|
||||
@@ -65,31 +71,35 @@ float ShadowSample_PCF_Low(const mediump sampler2DArrayShadow map,
|
||||
v *= texelSize.y;
|
||||
|
||||
float sum = 0.0;
|
||||
sum += uw.x * vw.x * sampleDepth(map, layer, base + vec2(u.x, v.x), depth);
|
||||
sum += uw.y * vw.x * sampleDepth(map, layer, base + vec2(u.y, v.x), depth);
|
||||
sum += uw.x * vw.y * sampleDepth(map, layer, base + vec2(u.x, v.y), depth);
|
||||
sum += uw.y * vw.y * sampleDepth(map, layer, base + vec2(u.y, v.y), depth);
|
||||
sum += uw.x * vw.x * sampleDepth(map, scissorNormalized, layer, base + vec2(u.x, v.x), depth);
|
||||
sum += uw.y * vw.x * sampleDepth(map, scissorNormalized, layer, base + vec2(u.y, v.x), depth);
|
||||
sum += uw.x * vw.y * sampleDepth(map, scissorNormalized, layer, base + vec2(u.x, v.y), depth);
|
||||
sum += uw.y * vw.y * sampleDepth(map, scissorNormalized, layer, base + vec2(u.y, v.y), depth);
|
||||
return sum * (1.0 / 16.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// use manual PCF
|
||||
float ShadowSample_PCF(const mediump sampler2DArray map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, const highp vec4 shadowPosition) {
|
||||
highp vec3 position = shadowPosition.xyz * (1.0 / shadowPosition.w);
|
||||
// note: shadowPosition.z is in the [1, 0] range (reversed Z)
|
||||
highp vec2 size = vec2(textureSize(map, 0));
|
||||
highp vec2 st = position.xy * size - 0.5;
|
||||
highp vec2 tc = clamp(position.xy, scissorNormalized.xy, scissorNormalized.zw);
|
||||
highp vec2 st = tc.xy * size - 0.5;
|
||||
|
||||
vec4 d;
|
||||
#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER)
|
||||
d = textureGather(map, vec3(position.xy, layer), 0); // 01, 11, 10, 00
|
||||
d = textureGather(map, vec3(tc, layer), 0); // 01, 11, 10, 00
|
||||
#else
|
||||
highp ivec3 tc = ivec3(st, layer);
|
||||
d[0] = texelFetchOffset(map, tc, 0, ivec2(0, 1)).r;
|
||||
d[1] = texelFetchOffset(map, tc, 0, ivec2(1, 1)).r;
|
||||
d[2] = texelFetchOffset(map, tc, 0, ivec2(1, 0)).r;
|
||||
d[3] = texelFetchOffset(map, tc, 0, ivec2(0, 0)).r;
|
||||
// we must use texelFetchOffset before texelLodOffset filters
|
||||
d[0] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(0, 1)).r;
|
||||
d[1] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(1, 1)).r;
|
||||
d[2] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(1, 0)).r;
|
||||
d[3] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(0, 0)).r;
|
||||
#endif
|
||||
|
||||
vec4 pcf = step(0.0, position.zzzz - d);
|
||||
highp vec2 grad = fract(st);
|
||||
return mix(mix(pcf.w, pcf.z, grad.x), mix(pcf.x, pcf.y, grad.x), grad.y);
|
||||
@@ -161,7 +171,7 @@ float getPenumbraLs(const bool DIRECTIONAL, const uint index, const highp float
|
||||
float penumbra;
|
||||
// This conditional is resolved at compile time
|
||||
if (DIRECTIONAL) {
|
||||
penumbra = frameUniforms.shadowBulbRadiusLs;
|
||||
penumbra = shadowUniforms.shadows[index].bulbRadiusLs;
|
||||
} else {
|
||||
// the penumbra radius depends on the light-space z for spotlights
|
||||
penumbra = shadowUniforms.shadows[index].bulbRadiusLs / zLight;
|
||||
@@ -192,14 +202,17 @@ float getPenumbraRatio(const bool DIRECTIONAL, const uint index,
|
||||
}
|
||||
|
||||
void blockerSearchAndFilter(out float occludedCount, out float z_occSum,
|
||||
const mediump sampler2DArray map, const highp vec2 uv, const float z_rec, const uint layer,
|
||||
const mediump sampler2DArray map, const highp vec4 scissorNormalized, const highp vec2 uv,
|
||||
const float z_rec, const uint layer,
|
||||
const highp vec2 filterRadii, const mat2 R, const highp vec2 dz_duv,
|
||||
const uint tapCount) {
|
||||
occludedCount = 0.0;
|
||||
z_occSum = 0.0;
|
||||
for (uint i = 0u; i < tapCount; i++) {
|
||||
highp vec2 duv = R * (poissonDisk[i] * filterRadii);
|
||||
float z_occ = textureLod(map, vec3(uv + duv, layer), 0.0).r;
|
||||
highp vec2 tc = clamp(uv + duv, scissorNormalized.xy, scissorNormalized.zw);
|
||||
|
||||
float z_occ = textureLod(map, vec3(tc, layer), 0.0).r;
|
||||
|
||||
// note: z_occ and z_rec are not necessarily linear here, comparing them is always okay for
|
||||
// the regular PCF, but the "distance" is meaningless unless they are actually linear
|
||||
@@ -217,7 +230,9 @@ void blockerSearchAndFilter(out float occludedCount, out float z_occSum,
|
||||
}
|
||||
}
|
||||
|
||||
float filterPCSS(const mediump sampler2DArray map, const highp vec2 size,
|
||||
float filterPCSS(const mediump sampler2DArray map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const highp vec2 size,
|
||||
const highp vec2 uv, const float z_rec, const uint layer,
|
||||
const highp vec2 filterRadii, const mat2 R, const highp vec2 dz_duv,
|
||||
const uint tapCount) {
|
||||
@@ -228,11 +243,14 @@ float filterPCSS(const mediump sampler2DArray map, const highp vec2 size,
|
||||
|
||||
// sample the shadow map with a 2x2 PCF, this helps a lot in low resolution areas
|
||||
vec4 d;
|
||||
highp vec2 st = (uv + duv) * size - 0.5;
|
||||
highp vec2 tc = clamp(uv + duv, scissorNormalized.xy, scissorNormalized.zw);
|
||||
highp vec2 st = tc.xy * size - 0.5;
|
||||
highp vec2 grad = fract(st);
|
||||
|
||||
#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER)
|
||||
d = textureGather(map, vec3(uv + duv, layer), 0); // 01, 11, 10, 00
|
||||
d = textureGather(map, vec3(tc, layer), 0); // 01, 11, 10, 00
|
||||
#else
|
||||
// we must use texelFetchOffset before texelLodOffset filters
|
||||
d[0] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(0, 1)).r;
|
||||
d[1] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(1, 1)).r;
|
||||
d[2] = texelFetchOffset(map, ivec3(st, layer), 0, ivec2(1, 0)).r;
|
||||
@@ -253,7 +271,9 @@ float filterPCSS(const mediump sampler2DArray map, const highp vec2 size,
|
||||
* see "Shadow of Cold War", A scalable approach to shadowing -- by Kevin Myers
|
||||
*/
|
||||
float ShadowSample_DPCF(const bool DIRECTIONAL,
|
||||
const mediump sampler2DArray map, const uint layer, const uint index,
|
||||
const mediump sampler2DArray map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, const uint index,
|
||||
const highp vec4 shadowPosition, const highp float zLight) {
|
||||
highp vec3 position = shadowPosition.xyz * (1.0 / shadowPosition.w);
|
||||
highp vec2 texelSize = vec2(1.0) / vec2(textureSize(map, 0));
|
||||
@@ -271,7 +291,7 @@ float ShadowSample_DPCF(const bool DIRECTIONAL,
|
||||
float z_occSum = 0.0;
|
||||
|
||||
blockerSearchAndFilter(occludedCount, z_occSum,
|
||||
map, position.xy, position.z, layer, texelSize * penumbra, R, dz_duv,
|
||||
map, scissorNormalized, position.xy, position.z, layer, texelSize * penumbra, R, dz_duv,
|
||||
DPCF_SHADOW_TAP_COUNT);
|
||||
|
||||
// early exit if there is no occluders at all, also avoids a divide-by-zero below.
|
||||
@@ -298,7 +318,9 @@ float ShadowSample_DPCF(const bool DIRECTIONAL,
|
||||
}
|
||||
|
||||
float ShadowSample_PCSS(const bool DIRECTIONAL,
|
||||
const mediump sampler2DArray map, const uint layer, const uint index,
|
||||
const mediump sampler2DArray map,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, const uint index,
|
||||
const highp vec4 shadowPosition, const highp float zLight) {
|
||||
highp vec2 size = vec2(textureSize(map, 0));
|
||||
highp vec2 texelSize = vec2(1.0) / size;
|
||||
@@ -317,7 +339,7 @@ float ShadowSample_PCSS(const bool DIRECTIONAL,
|
||||
float z_occSum = 0.0;
|
||||
|
||||
blockerSearchAndFilter(occludedCount, z_occSum,
|
||||
map, position.xy, position.z, layer, texelSize * penumbra, R, dz_duv,
|
||||
map, scissorNormalized, position.xy, position.z, layer, texelSize * penumbra, R, dz_duv,
|
||||
PCSS_SHADOW_BLOCKER_SEARCH_TAP_COUNT);
|
||||
|
||||
// early exit if there is no occluders at all, also avoids a divide-by-zero below.
|
||||
@@ -327,7 +349,8 @@ float ShadowSample_PCSS(const bool DIRECTIONAL,
|
||||
|
||||
float penumbraRatio = getPenumbraRatio(DIRECTIONAL, index, position.z, z_occSum / occludedCount);
|
||||
|
||||
float percentageOccluded = filterPCSS(map, size, position.xy, position.z, layer,
|
||||
float percentageOccluded = filterPCSS(map, scissorNormalized, size,
|
||||
position.xy, position.z, layer,
|
||||
texelSize * (penumbra * penumbraRatio),
|
||||
R, dz_duv, PCSS_SHADOW_FILTER_TAP_COUNT);
|
||||
|
||||
@@ -444,6 +467,7 @@ float evaluateShadowVSM(const highp vec2 moments, const highp float depth) {
|
||||
}
|
||||
|
||||
float ShadowSample_VSM(const bool ELVSM, const mediump sampler2DArray shadowMap,
|
||||
const highp vec4 scissorNormalized,
|
||||
const uint layer, const highp vec4 shadowPosition) {
|
||||
|
||||
// note: shadowPosition.z is in linear light-space normalized to [0, 1]
|
||||
@@ -451,6 +475,10 @@ float ShadowSample_VSM(const bool ELVSM, const mediump sampler2DArray shadowMap,
|
||||
// see: computeLightSpacePosition() in common_shadowing.fs
|
||||
highp vec3 position = vec3(shadowPosition.xy * (1.0 / shadowPosition.w), shadowPosition.z);
|
||||
|
||||
// Note: we don't need to clamp to `scissorNormalized` in the VSM case because this is only
|
||||
// needed when the shadow casters and receivers are different, which is never the case with VSM
|
||||
// (see ShadowMap.cpp).
|
||||
|
||||
// Read the shadow map with all available filtering
|
||||
highp vec4 moments = texture(shadowMap, vec3(position.xy, layer));
|
||||
highp float depth = position.z;
|
||||
@@ -478,107 +506,75 @@ float ShadowSample_VSM(const bool ELVSM, const mediump sampler2DArray shadowMap,
|
||||
*/
|
||||
|
||||
// get texture coordinate for directional and spot shadow maps
|
||||
highp vec4 getShadowPosition(const bool DIRECTIONAL,
|
||||
const uint index, const uint cascade, const highp float zLight) {
|
||||
highp vec4 p;
|
||||
// This conditional is resolved at compile time
|
||||
if (DIRECTIONAL) {
|
||||
#if defined(VARIANT_HAS_DIRECTIONAL_LIGHTING)
|
||||
p = getCascadeLightSpacePosition(cascade);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(VARIANT_HAS_DYNAMIC_LIGHTING)
|
||||
p = getSpotLightSpacePosition(index, zLight);
|
||||
#endif
|
||||
}
|
||||
return p;
|
||||
highp vec4 getShadowPosition(const uint cascade) {
|
||||
return getCascadeLightSpacePosition(cascade);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get {texture coordinate, layer} for point shadow maps
|
||||
highp vec4 getShadowPosition(const highp vec3 r, const highp vec4 nf,
|
||||
inout uint layer, out highp float d) {
|
||||
#if defined(VARIANT_HAS_DYNAMIC_LIGHTING)
|
||||
highp vec4 getShadowPosition(const uint index, const highp vec3 dir, const highp float zLight) {
|
||||
return getSpotLightSpacePosition(index, dir, zLight);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint getPointLightFace(const highp vec3 r) {
|
||||
highp vec4 tc;
|
||||
highp float rx = abs(r.x);
|
||||
highp float ry = abs(r.y);
|
||||
highp float rz = abs(r.z);
|
||||
d = max(rx, max(ry, rz));
|
||||
highp float ma = 1.0 / d;
|
||||
highp float d = max(rx, max(ry, rz));
|
||||
if (d == rx) {
|
||||
tc.x = r.x >= 0.0 ? r.z : -r.z;
|
||||
tc.y = r.y;
|
||||
layer += (r.x >= 0.0 ? 0u : 1u);
|
||||
return (r.x >= 0.0 ? 0u : 1u);
|
||||
} else if (d == ry) {
|
||||
tc.x = r.y >= 0.0 ? r.x : -r.x;
|
||||
tc.y = r.z;
|
||||
layer += (r.y >= 0.0 ? 2u : 3u);
|
||||
return (r.y >= 0.0 ? 2u : 3u);
|
||||
} else {
|
||||
tc.x = r.z >= 0.0 ? -r.x : r.x;
|
||||
tc.y = r.y;
|
||||
layer += (r.z >= 0.0 ? 4u : 5u);
|
||||
return (r.z >= 0.0 ? 4u : 5u);
|
||||
}
|
||||
|
||||
// ma is guaranteed to be >= sc and tc
|
||||
tc.xy = (tc.xy * ma + vec2(1.0)) * 0.5;
|
||||
|
||||
// z coordinate of the normalized fragment position in light-space
|
||||
// i.e.: remap [near, far] to [0,1] : d = (d - n) / (f - n)
|
||||
d = nf[2] + nf[3] * d;
|
||||
|
||||
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_EVSM) {
|
||||
// for VSM, the depth metric is linear normalized in light-space
|
||||
tc.z = d;
|
||||
} else {
|
||||
// for other types of shadows it's clip-space depth. Below is an optimized version of
|
||||
// (lightProjection * position).z
|
||||
tc.z = nf[0] + nf[1] * ma;
|
||||
}
|
||||
|
||||
// FIXME: the normal bias is not applied
|
||||
|
||||
tc.w = 1.0;
|
||||
return tc;
|
||||
}
|
||||
|
||||
// PCF sampling
|
||||
float shadow(const bool DIRECTIONAL,
|
||||
const mediump sampler2DArrayShadow shadowMap,
|
||||
const uint layer, const uint index, highp vec4 shadowPosition, highp float zLight) {
|
||||
const uint index, highp vec4 shadowPosition, highp float zLight) {
|
||||
highp vec4 scissorNormalized = shadowUniforms.shadows[index].scissorNormalized;
|
||||
uint layer = shadowUniforms.shadows[index].layer;
|
||||
#if SHADOW_SAMPLING_METHOD == SHADOW_SAMPLING_PCF_HARD
|
||||
return ShadowSample_PCF_Hard(shadowMap, layer, shadowPosition);
|
||||
return ShadowSample_PCF_Hard(shadowMap, scissorNormalized, layer, shadowPosition);
|
||||
#elif SHADOW_SAMPLING_METHOD == SHADOW_SAMPLING_PCF_LOW
|
||||
return ShadowSample_PCF_Low(shadowMap, layer, shadowPosition);
|
||||
return ShadowSample_PCF_Low(shadowMap, scissorNormalized, layer, shadowPosition);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Shadow requiring a sampler2D sampler (VSM, DPCF and PCSS)
|
||||
float shadow(const bool DIRECTIONAL,
|
||||
const mediump sampler2DArray shadowMap,
|
||||
const uint layer, const uint index, highp vec4 shadowPosition, highp float zLight) {
|
||||
|
||||
const uint index, highp vec4 shadowPosition, highp float zLight) {
|
||||
highp vec4 scissorNormalized = shadowUniforms.shadows[index].scissorNormalized;
|
||||
uint layer = shadowUniforms.shadows[index].layer;
|
||||
// This conditional is resolved at compile time
|
||||
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_EVSM) {
|
||||
bool elvsm = false;
|
||||
if (DIRECTIONAL) {
|
||||
elvsm = bool((frameUniforms.cascades >> 31u) & 1u);
|
||||
} else {
|
||||
elvsm = shadowUniforms.shadows[index].elvsm;
|
||||
}
|
||||
return ShadowSample_VSM(elvsm, shadowMap, layer, shadowPosition);
|
||||
bool elvsm = shadowUniforms.shadows[index].elvsm;
|
||||
return ShadowSample_VSM(elvsm, shadowMap, scissorNormalized, layer,
|
||||
shadowPosition);
|
||||
}
|
||||
|
||||
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_DPCF) {
|
||||
return ShadowSample_DPCF(DIRECTIONAL, shadowMap, layer, index, shadowPosition, zLight);
|
||||
return ShadowSample_DPCF(DIRECTIONAL, shadowMap, scissorNormalized, layer, index,
|
||||
shadowPosition, zLight);
|
||||
}
|
||||
|
||||
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_PCSS) {
|
||||
return ShadowSample_PCSS(DIRECTIONAL, shadowMap, layer, index, shadowPosition, zLight);
|
||||
return ShadowSample_PCSS(DIRECTIONAL, shadowMap, scissorNormalized, layer, index,
|
||||
shadowPosition, zLight);
|
||||
}
|
||||
|
||||
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_PCF) {
|
||||
// This is here mostly for debugging at this point.
|
||||
// Note: In this codepath, the normal bias is not applied because we're in the VSM variant.
|
||||
// (see: get{Cascade|Spot}LightSpacePosition)
|
||||
return ShadowSample_PCF(shadowMap, layer, shadowPosition);
|
||||
return ShadowSample_PCF(shadowMap, scissorNormalized,
|
||||
layer, shadowPosition);
|
||||
}
|
||||
|
||||
// should not happen
|
||||
|
||||
12
third_party/libsdl2/include/SDL_syswm.h
vendored
12
third_party/libsdl2/include/SDL_syswm.h
vendored
@@ -33,12 +33,6 @@
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_version.h"
|
||||
|
||||
#include "begin_code.h"
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file SDL_syswm.h
|
||||
*
|
||||
@@ -110,6 +104,12 @@ typedef void *EGLSurface;
|
||||
#include "SDL_egl.h"
|
||||
#endif
|
||||
|
||||
#include "begin_code.h"
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* These are the various supported windowing subsystems
|
||||
*/
|
||||
|
||||
@@ -164,6 +164,7 @@ Filament.loadGeneratedExtensions = function() {
|
||||
const options = {
|
||||
anisotropy: 0,
|
||||
mipmapping: false,
|
||||
msaaSamples: 1,
|
||||
highPrecision: false,
|
||||
minVarianceScale: 0.5,
|
||||
lightBleedReduction: 0.15,
|
||||
|
||||
7
web/filament-js/filament.d.ts
vendored
7
web/filament-js/filament.d.ts
vendored
@@ -1678,6 +1678,13 @@ export interface View$VsmShadowOptions {
|
||||
* Whether to generate mipmaps for all VSM shadow maps.
|
||||
*/
|
||||
mipmapping?: boolean;
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*/
|
||||
msaaSamples?: number;
|
||||
/**
|
||||
* Whether to use a 32-bits or 16-bits texture format for VSM shadow maps. 32-bits
|
||||
* precision is rarely needed, but it does reduces light leaks as well as "fading"
|
||||
|
||||
@@ -135,6 +135,7 @@ value_object<View::GuardBandOptions>("View$GuardBandOptions")
|
||||
value_object<View::VsmShadowOptions>("View$VsmShadowOptions")
|
||||
.field("anisotropy", &View::VsmShadowOptions::anisotropy)
|
||||
.field("mipmapping", &View::VsmShadowOptions::mipmapping)
|
||||
.field("msaaSamples", &View::VsmShadowOptions::msaaSamples)
|
||||
.field("highPrecision", &View::VsmShadowOptions::highPrecision)
|
||||
.field("minVarianceScale", &View::VsmShadowOptions::minVarianceScale)
|
||||
.field("lightBleedReduction", &View::VsmShadowOptions::lightBleedReduction)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.28.2",
|
||||
"version": "1.30.0",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user