Compare commits
256 Commits
MapAsyncEx
...
rc/1.69.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd7baedcdc | ||
|
|
69fe9f6596 | ||
|
|
712f1edc1e | ||
|
|
5b631056b1 | ||
|
|
caa334730a | ||
|
|
261f74a1e9 | ||
|
|
f10a7d9bbc | ||
|
|
358d594f34 | ||
|
|
b06b6b5c42 | ||
|
|
ac41a15191 | ||
|
|
ef42c55f56 | ||
|
|
bd67c9c67e | ||
|
|
8f19826fe4 | ||
|
|
afd0e67fb0 | ||
|
|
f1b14d6f65 | ||
|
|
09b5172962 | ||
|
|
39f0ea1706 | ||
|
|
ec4b9113df | ||
|
|
2a51b70a74 | ||
|
|
4ba2c7d65c | ||
|
|
3af28968ed | ||
|
|
2f36ab71c9 | ||
|
|
b40530ad3c | ||
|
|
0131949aff | ||
|
|
b85d52f727 | ||
|
|
53e6cd3126 | ||
|
|
69ae8c491b | ||
|
|
c35ae6571f | ||
|
|
4c621b83e9 | ||
|
|
4abf7cdaba | ||
|
|
9808aa5460 | ||
|
|
5c15d56cf5 | ||
|
|
ef24164464 | ||
|
|
a1abfa30b8 | ||
|
|
b5abcd9bc1 | ||
|
|
8d34af2004 | ||
|
|
db0524d59b | ||
|
|
6193f489a3 | ||
|
|
fb31759c27 | ||
|
|
375e3a03ec | ||
|
|
11bf3a4493 | ||
|
|
7c64fb9cf3 | ||
|
|
d3de9efc33 | ||
|
|
e9dcf2a63a | ||
|
|
8008d21782 | ||
|
|
852ecf048a | ||
|
|
3c91c74232 | ||
|
|
8d20d7abec | ||
|
|
2f1266f7dd | ||
|
|
05be4b0acc | ||
|
|
9d9c3d34f8 | ||
|
|
491531c76b | ||
|
|
bf4ea771be | ||
|
|
dd5882760b | ||
|
|
1707dda62a | ||
|
|
c4d3eded72 | ||
|
|
ca4b0650fa | ||
|
|
33d22b3146 | ||
|
|
e2dd47bf42 | ||
|
|
60b1951f90 | ||
|
|
6ce06b1b60 | ||
|
|
e21d4a5326 | ||
|
|
7fd9e728ae | ||
|
|
b66736b8cc | ||
|
|
ea8f6a3c92 | ||
|
|
adcdbb45f9 | ||
|
|
cff958587d | ||
|
|
9ab2326f15 | ||
|
|
8785acd352 | ||
|
|
57767b7f27 | ||
|
|
febcfc8f2d | ||
|
|
c04c387a89 | ||
|
|
78ac9467f8 | ||
|
|
73b60d4db8 | ||
|
|
7266fd67db | ||
|
|
469f2c94da | ||
|
|
d4e0d051b1 | ||
|
|
df74a5a352 | ||
|
|
21fd32266a | ||
|
|
cd7c7b369b | ||
|
|
65ed7099c0 | ||
|
|
af34572883 | ||
|
|
1f6a67b2a2 | ||
|
|
7701e7a65a | ||
|
|
65a91832a8 | ||
|
|
acb47ffed5 | ||
|
|
13c0304d84 | ||
|
|
febdf3974c | ||
|
|
390acec928 | ||
|
|
ff806f8c3e | ||
|
|
06c4faabc3 | ||
|
|
92aec16fa3 | ||
|
|
f1ffb783d8 | ||
|
|
b708300586 | ||
|
|
f88d757d06 | ||
|
|
4d96f188d1 | ||
|
|
2d943f40bb | ||
|
|
92c058a736 | ||
|
|
ba819bcfca | ||
|
|
e22f1adfa7 | ||
|
|
f2bca03360 | ||
|
|
5f07d701f0 | ||
|
|
496a50bc89 | ||
|
|
6ccb6c4cce | ||
|
|
42c78fd0a9 | ||
|
|
3d0e2923ae | ||
|
|
408b2371f0 | ||
|
|
6ea08b40a8 | ||
|
|
5eb0f7d3ec | ||
|
|
d465d59c3a | ||
|
|
af9a60d175 | ||
|
|
8e0f0c92ce | ||
|
|
5a14fb4b5d | ||
|
|
22a1aacb21 | ||
|
|
e5b6c11399 | ||
|
|
85ebd67a28 | ||
|
|
f33a779668 | ||
|
|
1b5916b655 | ||
|
|
d8720cd858 | ||
|
|
44636bddaa | ||
|
|
1741723687 | ||
|
|
ad2c291d4a | ||
|
|
52ffd80041 | ||
|
|
44dde744ea | ||
|
|
c18ddf929e | ||
|
|
5661365248 | ||
|
|
bcb9d258c2 | ||
|
|
53a94c4547 | ||
|
|
928ffe94a7 | ||
|
|
dcb78c7144 | ||
|
|
43dd8fa1cc | ||
|
|
91a5f00d30 | ||
|
|
0eff54b807 | ||
|
|
68eb0ce3f1 | ||
|
|
023318c08d | ||
|
|
c0e3aa2b0a | ||
|
|
a6d1b9188f | ||
|
|
43193c5ac5 | ||
|
|
35c58047ee | ||
|
|
2190f3544f | ||
|
|
fd8ea78e04 | ||
|
|
7fc336a6d9 | ||
|
|
3cc6fae5c0 | ||
|
|
f4f75da016 | ||
|
|
bdeba1aa86 | ||
|
|
8991be4eea | ||
|
|
940b93ceb8 | ||
|
|
00eb3d0d4f | ||
|
|
7f61eb7a0a | ||
|
|
53f506670c | ||
|
|
9fe7ab31ed | ||
|
|
008534b8a2 | ||
|
|
2c5842f908 | ||
|
|
a8ee9d473e | ||
|
|
1e3ab83e6a | ||
|
|
9720da2c68 | ||
|
|
ee74e2d50c | ||
|
|
6171009add | ||
|
|
d299a444fa | ||
|
|
107276e9cc | ||
|
|
fe00cbf106 | ||
|
|
02d0ddbcfe | ||
|
|
c4802f7683 | ||
|
|
b582b2d64e | ||
|
|
9c4edf56ca | ||
|
|
e24fdb3a9d | ||
|
|
05f24516dd | ||
|
|
a3708b2616 | ||
|
|
ee514df722 | ||
|
|
924c416644 | ||
|
|
597cf9a3ae | ||
|
|
316c8376d3 | ||
|
|
672ddddafc | ||
|
|
a8ee48c4b7 | ||
|
|
c300f77151 | ||
|
|
16734fc767 | ||
|
|
f701c1e1b5 | ||
|
|
98cec207ce | ||
|
|
3ecdf71917 | ||
|
|
ebba65e558 | ||
|
|
177d23b3ac | ||
|
|
cfd402f424 | ||
|
|
b7e492d674 | ||
|
|
d7e0202f37 | ||
|
|
4227d04eb7 | ||
|
|
272ed14737 | ||
|
|
223a754200 | ||
|
|
af480a58c4 | ||
|
|
192738ecb9 | ||
|
|
27c268f865 | ||
|
|
32fcc1a81b | ||
|
|
621eca340e | ||
|
|
ee6c8c3e76 | ||
|
|
dcf7621c35 | ||
|
|
6a8193ea80 | ||
|
|
d4efef9a9b | ||
|
|
cdffc9eaa0 | ||
|
|
a162a65dce | ||
|
|
369bab4744 | ||
|
|
c98038b2d7 | ||
|
|
849c4bb8c5 | ||
|
|
ee64322d76 | ||
|
|
79d65a768a | ||
|
|
37610dc8f3 | ||
|
|
2e31dc20e4 | ||
|
|
ae3d98fb47 | ||
|
|
a938a790fa | ||
|
|
71d556dddf | ||
|
|
d61227b2fd | ||
|
|
612a6b00e4 | ||
|
|
b3353b518c | ||
|
|
0b44761d43 | ||
|
|
c7979e4023 | ||
|
|
e00904e100 | ||
|
|
96e2366569 | ||
|
|
e76624862d | ||
|
|
c5c83a61d3 | ||
|
|
ccf0d6205f | ||
|
|
f482c1d702 | ||
|
|
a4c056e822 | ||
|
|
f5071b2aae | ||
|
|
0fa13ee43d | ||
|
|
1d2b8a08fa | ||
|
|
0c06744450 | ||
|
|
4ada29fbc3 | ||
|
|
76182231dd | ||
|
|
8cd6915b9d | ||
|
|
f90de26bc2 | ||
|
|
cc2e661aab | ||
|
|
3a92cdab3a | ||
|
|
b367982c23 | ||
|
|
a4f4dc617e | ||
|
|
2eb0f11d05 | ||
|
|
6694df991c | ||
|
|
8b2bfa7e9d | ||
|
|
7386220325 | ||
|
|
000faeaca7 | ||
|
|
3f9783ac02 | ||
|
|
4e6dc67ae8 | ||
|
|
666140bb73 | ||
|
|
56050de5cd | ||
|
|
772136decd | ||
|
|
f664601c51 | ||
|
|
f06b27b7fb | ||
|
|
ef53ce88d4 | ||
|
|
ef18030e1a | ||
|
|
f07176c0a2 | ||
|
|
15db141c7a | ||
|
|
d4bbb7c591 | ||
|
|
92e620d2ad | ||
|
|
311104da97 | ||
|
|
3127632f96 | ||
|
|
59f611bfde | ||
|
|
2d556bdca2 | ||
|
|
65e7dba8b8 | ||
|
|
6550a63056 |
2
.github/actions/mac-prereq/action.yml
vendored
@@ -15,7 +15,7 @@ runs:
|
||||
uses: actions/cache@v4 # Use a specific version
|
||||
with:
|
||||
path: ~/Library/Caches/Homebrew
|
||||
key: ${{ runner.os }}-brew-20250424
|
||||
key: ${{ runner.os }}-brew-20251211
|
||||
- name: Install Mac Prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
25
.github/workflows/android-continuous.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: Android
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-android:
|
||||
name: build-android
|
||||
# We intentially use a larger runner here to enable larger disk space
|
||||
# (standard linux runner will fail on disk space and faster build time).
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- name: Run Android Continuous
|
||||
uses: ./.github/actions/android-continuous
|
||||
with:
|
||||
build-abi: armeabi-v7a,arm64-v8a,x86_64
|
||||
29
.github/workflows/ios-continuous.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: iOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-ios:
|
||||
name: build-ios
|
||||
runs-on: macos-14-xlarge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/mac-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/ios && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-ios
|
||||
path: out/filament-release-ios.tgz
|
||||
- name: Build iOS samples
|
||||
run: |
|
||||
cd build/ios && ./build-samples.sh continuous
|
||||
26
.github/workflows/linux-continuous.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Linux
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
name: build-linux
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/linux && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-linux
|
||||
path: out/filament-release-linux.tgz
|
||||
29
.github/workflows/mac-continuous.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: macOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-mac:
|
||||
name: build-mac
|
||||
runs-on: macos-14-xlarge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/mac-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/mac && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-mac
|
||||
path: out/filament-release-darwin.tgz
|
||||
- name: Check public headers
|
||||
run: |
|
||||
test/check-headers/test.sh out/release/filament/include
|
||||
59
.github/workflows/postsubmit-main.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: 'Postsubmit Tasks'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
update-renderdiff-goldens:
|
||||
name: update-renderdiff-goldens
|
||||
runs-on: 'ubuntu-24.04-4core'
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- id: get_commit_msg
|
||||
uses: ./.github/actions/get-commit-msg
|
||||
- name: Prerequisites
|
||||
run: pip install tifffile numpy
|
||||
- name: Run update script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||
COMMIT_MESSAGE: ${{ steps.get_commit_msg.outputs.msg }}
|
||||
run: |
|
||||
GOLDEN_BRANCH=$(echo "${COMMIT_MESSAGE}" | python3 test/renderdiff/src/commit_msg.py)
|
||||
COMMIT_HASH="${{ steps.get_commit_msg.outputs.hash }}"
|
||||
if [[ "${GOLDEN_BRANCH}" != "main" ]]; then
|
||||
git config --global user.email "filament.bot@gmail.com"
|
||||
git config --global user.name "Filament Bot"
|
||||
git config --global credential.helper cache
|
||||
echo "branch==${GOLDEN_BRANCH}"
|
||||
echo "hash==${COMMIT_HASH}"
|
||||
python3 test/renderdiff/src/update_golden.py --branch=${GOLDEN_BRANCH} \
|
||||
--merge-to-main --filament-tag=${COMMIT_HASH} --golden-repo-token=${GH_TOKEN}
|
||||
fi
|
||||
|
||||
update-docs:
|
||||
name: update-docs
|
||||
runs-on: 'ubuntu-24.04-4core'
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- id: get_commit_msg
|
||||
uses: ./.github/actions/get-commit-msg
|
||||
- name: Prerequisites
|
||||
run: pip install selenium
|
||||
- name: Run update script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||
run: |
|
||||
bash docs_src/build/install_mdbook.sh && source ~/.bashrc
|
||||
COMMIT_HASH="${{ steps.get_commit_msg.outputs.hash }}"
|
||||
git config --global user.email "filament.bot@gmail.com"
|
||||
git config --global user.name "Filament Bot"
|
||||
git config --global credential.helper cache
|
||||
bash docs_src/build/postsubmit.sh ${COMMIT_HASH} ${GH_TOKEN}
|
||||
145
.github/workflows/postsubmit.yml
vendored
@@ -1,58 +1,115 @@
|
||||
name: 'Post-submit tasks'
|
||||
name: 'Postsubmit CI'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
update-renderdiff-goldens:
|
||||
name: update-renderdiff-goldens
|
||||
runs-on: 'ubuntu-24.04-4core'
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- id: get_commit_msg
|
||||
uses: ./.github/actions/get-commit-msg
|
||||
- name: Prerequisites
|
||||
run: pip install tifffile numpy
|
||||
- name: Run update script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||
run: |
|
||||
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 test/renderdiff/src/commit_msg.py)
|
||||
COMMIT_HASH="${{ steps.get_commit_msg.outputs.hash }}"
|
||||
if [[ "${GOLDEN_BRANCH}" != "main" ]]; then
|
||||
git config --global user.email "filament.bot@gmail.com"
|
||||
git config --global user.name "Filament Bot"
|
||||
git config --global credential.helper cache
|
||||
echo "branch==${GOLDEN_BRANCH}"
|
||||
echo "hash==${COMMIT_HASH}"
|
||||
python3 test/renderdiff/src/update_golden.py --branch=${GOLDEN_BRANCH} \
|
||||
--merge-to-main --filament-tag=${COMMIT_HASH} --golden-repo-token=${GH_TOKEN}
|
||||
fi
|
||||
build-android:
|
||||
name: build-android
|
||||
# We intentially use a larger runner here to enable larger disk space
|
||||
# (standard linux runner will fail on disk space and faster build time).
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
update-docs:
|
||||
name: update-docs
|
||||
runs-on: 'ubuntu-24.04-4core'
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- id: get_commit_msg
|
||||
uses: ./.github/actions/get-commit-msg
|
||||
- name: Prerequisites
|
||||
run: pip install selenium
|
||||
- name: Run update script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||
- name: Run Android Continuous
|
||||
uses: ./.github/actions/android-continuous
|
||||
with:
|
||||
build-abi: armeabi-v7a,arm64-v8a,x86_64
|
||||
|
||||
build-ios:
|
||||
name: build-ios
|
||||
runs-on: macos-14-xlarge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/mac-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
bash docs_src/build/install_mdbook.sh && source ~/.bashrc
|
||||
COMMIT_HASH="${{ steps.get_commit_msg.outputs.hash }}"
|
||||
git config --global user.email "filament.bot@gmail.com"
|
||||
git config --global user.name "Filament Bot"
|
||||
git config --global credential.helper cache
|
||||
bash docs_src/build/postsubmit.sh ${COMMIT_HASH} ${GH_TOKEN}
|
||||
cd build/ios && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-ios
|
||||
path: out/filament-release-ios.tgz
|
||||
- name: Build iOS samples
|
||||
run: |
|
||||
cd build/ios && ./build-samples.sh continuous
|
||||
|
||||
build-linux:
|
||||
name: build-linux
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/linux && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-linux
|
||||
path: out/filament-release-linux.tgz
|
||||
|
||||
build-mac:
|
||||
name: build-mac
|
||||
runs-on: macos-14-xlarge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/mac-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/mac && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-mac
|
||||
path: out/filament-release-darwin.tgz
|
||||
- name: Check public headers
|
||||
run: |
|
||||
test/check-headers/test.sh out/release/filament/include
|
||||
|
||||
build-web:
|
||||
name: build-web
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- uses: ./.github/actions/web-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/web && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-web
|
||||
path: out/filament-release-web.tgz
|
||||
|
||||
build-windows:
|
||||
name: build-windows
|
||||
runs-on: windows-2022-32core
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Run build script
|
||||
run: |
|
||||
build\windows\build-github.bat continuous
|
||||
shell: cmd
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-windows
|
||||
path: out/filament-windows.tgz
|
||||
|
||||
16
.github/workflows/presubmit.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Presubmit
|
||||
name: 'Presubmit CI'
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- uses: ./.github/actions/mac-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/mac && printf "y" | ./build.sh presubmit
|
||||
cd build/mac && printf "y" | ./build.sh presubmit-with-test
|
||||
- name: Test material parser
|
||||
run: |
|
||||
out/cmake-release/filament/test/test_material_parser
|
||||
@@ -134,18 +134,17 @@ jobs:
|
||||
env:
|
||||
COMMIT_MESSAGE: ${{ steps.get_commit_msg.outputs.msg }}
|
||||
run: |
|
||||
ls ./gltf/Models
|
||||
TEST_DIR=test/renderdiff
|
||||
source ${TEST_DIR}/src/preamble.sh
|
||||
start_
|
||||
set -eux
|
||||
GOLDEN_BRANCH=$(echo "${COMMIT_MESSAGE}" | python3 ${TEST_DIR}/src/commit_msg.py)
|
||||
bash ${TEST_DIR}/generate.sh && \
|
||||
python3 ${TEST_DIR}/src/golden_manager.py \
|
||||
bash ${TEST_DIR}/generate.sh
|
||||
python3 ${TEST_DIR}/src/golden_manager.py \
|
||||
--branch=${GOLDEN_BRANCH} \
|
||||
--output=${GOLDEN_OUTPUT_DIR}
|
||||
|
||||
# Note that we need to upload the output even if comparison fails, so we undo `set -ex`
|
||||
end_
|
||||
# Note that we need to upload the output even if comparison fails, so we undo `set -eux`
|
||||
set +eux
|
||||
|
||||
python3 ${TEST_DIR}/src/compare.py \
|
||||
--src=${GOLDEN_OUTPUT_DIR} \
|
||||
@@ -158,6 +157,7 @@ jobs:
|
||||
cat compare_output.txt >> "$GITHUB_OUTPUT"
|
||||
echo "$DELIMITER" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
shell: bash
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: presubmit-renderdiff-result
|
||||
|
||||
7
.github/workflows/release.yml
vendored
@@ -163,9 +163,7 @@ jobs:
|
||||
mv out/filamat-android-release.aar out/filamat-${TAG}-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
|
||||
cd out/android-release/filament
|
||||
tar -czf ../../filament-${TAG}-android-native.tgz .
|
||||
cd ../../..
|
||||
mv out/filament-android-release-linux.tgz out/filament-${TAG}-android-native.tgz
|
||||
- name: Sign sample-gltf-viewer
|
||||
run: |
|
||||
echo "${APK_KEYSTORE_BASE64}" > filament.jks.base64
|
||||
@@ -245,7 +243,8 @@ jobs:
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
run: |
|
||||
build\windows\build-github.bat release
|
||||
@REMARK 'call' is required to ensure control returns to this script after the batch file finishes.
|
||||
call build\windows\build-github.bat release
|
||||
echo on
|
||||
move out\filament-windows.tgz out\filament-%TAG%-windows.tgz
|
||||
shell: cmd
|
||||
|
||||
27
.github/workflows/web-continuous.yml
vendored
@@ -1,27 +0,0 @@
|
||||
name: Web
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-web:
|
||||
name: build-web
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- uses: ./.github/actions/web-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/web && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-web
|
||||
path: out/filament-release-web.tgz
|
||||
24
.github/workflows/windows-continuous.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- release
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
name: build-windows
|
||||
runs-on: windows-2022-32core
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Run build script
|
||||
run: |
|
||||
build\windows\build-github.bat continuous
|
||||
shell: cmd
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: filament-windows
|
||||
path: out/filament-windows.tgz
|
||||
75
BUILDING.md
@@ -1,6 +1,6 @@
|
||||
## Building Filament
|
||||
# Building Filament
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
To build Filament, you must first install the following tools:
|
||||
|
||||
@@ -18,7 +18,7 @@ To build Filament for Android you must also install the following:
|
||||
- Android NDK 25.1 or higher
|
||||
- Java 17
|
||||
|
||||
### Environment variables
|
||||
## Environment variables
|
||||
|
||||
To build Filament for Android, make sure the environment variable `ANDROID_HOME` points to the
|
||||
location of your Android SDK.
|
||||
@@ -30,7 +30,7 @@ When building for WebGL, you'll also need to set `EMSDK`. See [WebAssembly](#web
|
||||
We recommend using CLion to develop for Filament. Simply open the root directory's CMakeLists.txt
|
||||
in CLion to obtain a usable project.
|
||||
|
||||
### Easy build
|
||||
## Easy build
|
||||
|
||||
Once the required OS specific dependencies listed below are installed, you can use the script
|
||||
located in `build.sh` to build Filament easily on macOS and Linux.
|
||||
@@ -67,7 +67,7 @@ For more specialized options, please also consider the following pages:
|
||||
- `-t`: [`fgviewer`](https://google.github.io/filament/dup/fgviewer.html)
|
||||
- `-b` and `-y`: [ASAN/UBSAN builds](https://google.github.io/filament/notes/asan_ubsan.html)
|
||||
|
||||
### Filament-specific CMake Options
|
||||
## Filament-specific CMake Options
|
||||
|
||||
The following CMake options are boolean options specific to Filament:
|
||||
|
||||
@@ -89,7 +89,7 @@ cmake . -DOPTION=ON # Replace OPTION with the option name, set to ON / OFF
|
||||
|
||||
Options can also be set with the CMake GUI.
|
||||
|
||||
### Linux
|
||||
## Linux
|
||||
|
||||
Make sure you've installed the following dependencies:
|
||||
|
||||
@@ -148,7 +148,7 @@ ninja
|
||||
|
||||
This will build Filament, its tests and samples, and various host tools.
|
||||
|
||||
### macOS
|
||||
## macOS
|
||||
|
||||
To compile Filament you must have the most recent version of Xcode installed and you need to
|
||||
make sure the command line tools are setup by running:
|
||||
@@ -169,7 +169,7 @@ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/fila
|
||||
ninja
|
||||
```
|
||||
|
||||
### iOS
|
||||
## iOS
|
||||
|
||||
The easiest way to build Filament for iOS is to use `build.sh` and the
|
||||
`-p ios` flag. For instance to build the debug target:
|
||||
@@ -180,9 +180,9 @@ The easiest way to build Filament for iOS is to use `build.sh` and the
|
||||
|
||||
See [ios/samples/README.md](./ios/samples/README.md) for more information.
|
||||
|
||||
### Windows
|
||||
## Windows
|
||||
|
||||
#### Building on Windows with Visual Studio 2019 or later
|
||||
### Building on Windows with Visual Studio 2019 or later
|
||||
|
||||
Install the following components:
|
||||
|
||||
@@ -225,7 +225,7 @@ You can also use CMake to invoke the build without opening Visual Studio. For ex
|
||||
cmake --build . --target gltf_viewer --config Release
|
||||
```
|
||||
|
||||
### Android
|
||||
## Android
|
||||
|
||||
Before building Filament for Android, make sure to build Filament for your host. Some of the
|
||||
host tools are required to successfully build for Android.
|
||||
@@ -242,7 +242,13 @@ foremost for `arm64-v8a`.
|
||||
|
||||
To build Android on Windows machines, see [android/Windows.md](android/Windows.md).
|
||||
|
||||
#### Easy Android build
|
||||
### Important: SDK location
|
||||
|
||||
Either ensure your `ANDROID_HOME` environment variable is set or make sure the root project
|
||||
contains a `local.properties` file with the `sdk.dir` property pointing to your installation of
|
||||
the Android SDK.
|
||||
|
||||
### Easy Android build
|
||||
|
||||
The easiest way to build Filament for Android is to use `build.sh` and the
|
||||
`-p android` flag. For instance to build the release target:
|
||||
@@ -251,9 +257,46 @@ The easiest way to build Filament for Android is to use `build.sh` and the
|
||||
./build.sh -p android release
|
||||
```
|
||||
|
||||
To build a sample (such as `android/samples/sample-hello-triangle`) for an ARM 64-bit phone, you would run
|
||||
```shell
|
||||
./build.sh -p android -q arm64-v8a -k sample-hello-triangle release
|
||||
```
|
||||
|
||||
The output APK can be found in `android/samples/sample-hello-triangle/build/outputs/apk/release/sample-hello-triangle-release-unsigned.apk`
|
||||
|
||||
Run `build.sh -h` for more information.
|
||||
|
||||
#### Manual builds
|
||||
### Android Studio
|
||||
|
||||
You must use the latest stable release of Android Studio.
|
||||
|
||||
The Android build of filament is separated into java/kotlin client APIs, a layer of jni bindings
|
||||
that bridges java/kotlin with native code, and Filament and other component code that have been compiled
|
||||
into architecture-specific libraries. Our default Android Studio gradle setup can compile java/kotlin and
|
||||
the jni bindings for you, but it will treat the filament libraries as already compiled and present on
|
||||
the system.
|
||||
|
||||
Therefore, before compiling the sample app or any other targets, you must
|
||||
make sure that the native filament libraries have been compiled and are located at a prescribed location
|
||||
so that the jni bindings can link against them. You can do so by using the easy build script
|
||||
|
||||
```shell
|
||||
./build.sh -p android release -q arm64-v8a
|
||||
```
|
||||
|
||||
Note that the above step will also install host machine tools into prescribed locations. These tools are
|
||||
required for compiling Filament assets such as materials and environment maps.
|
||||
|
||||
Now we are ready to compile the apps. To open the project, point Studio to the `android` folder.
|
||||
After opening the project and syncing with Gradle, select the sample of your choice
|
||||
using the drop-down widget in the toolbar. Additionally, you will need to select a deployment target.
|
||||
By doing so, Android Studio will automatically try to compile the app only for that specific
|
||||
device's architecture. So if you are targeting a new Pixel phone, make sure that the step above
|
||||
(compiling the library) is targeting ARM 64-bit (`-q arm64-v8a` ), and if you are running the app on
|
||||
an emulator on a Linux machine with an x86 64-bit chipset, you would indicate (`-q x86_64`) in the above step.
|
||||
|
||||
|
||||
### Manual builds
|
||||
|
||||
Invoke CMake in a build directory of your choice, inside of filament's directory. The commands
|
||||
below show how to build Filament for ARM 64-bit (`aarch64`).
|
||||
@@ -281,7 +324,7 @@ This will generate Filament's Android binaries in `out/android-release`. This lo
|
||||
to build the Android Studio projects located in `filament/android`. After install, the library
|
||||
binaries should be found in `out/android-release/filament/lib/arm64-v8a`.
|
||||
|
||||
#### AAR
|
||||
### AAR
|
||||
|
||||
Before you attempt to build the AAR, make sure you've compiled and installed the native libraries
|
||||
as explained in the sections above. You must have the following ABIs built in
|
||||
@@ -313,7 +356,7 @@ Alternatively you can build the AAR from the command line by executing the follo
|
||||
The `-Pcom.google.android.filament.dist-dir` can be used to specify a different installation
|
||||
directory (it must match the CMake install prefix used in the previous steps).
|
||||
|
||||
#### Using Filament's AAR
|
||||
### Using Filament's AAR
|
||||
|
||||
Create a new module in your project and select _Import .JAR or .AAR Package_ when prompted. Make
|
||||
sure to add the newly created module as a dependency to your application.
|
||||
@@ -354,7 +397,7 @@ productFlavors {
|
||||
}
|
||||
```
|
||||
|
||||
### WebAssembly
|
||||
## WebAssembly
|
||||
|
||||
The core Filament library can be cross-compiled to WebAssembly from either macOS or Linux. To get
|
||||
started, follow the instructions for building Filament on your platform ([macOS](#macos) or
|
||||
|
||||
@@ -10,6 +10,7 @@ cmake_minimum_required(VERSION 3.22.1)
|
||||
# ==================================================================================================
|
||||
# Toolchain configuration
|
||||
# ==================================================================================================
|
||||
# On iOS, the deployment target is set inside third_party/clang/ios.cmake
|
||||
if (APPLE AND NOT IOS)
|
||||
# This must be set before project() is called
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "")
|
||||
@@ -48,8 +49,6 @@ option(FILAMENT_ENABLE_COVERAGE "Enable LLVM code coverage" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_FEATURE_LEVEL_0 "Enable Feature Level 0" ON)
|
||||
|
||||
option(FILAMENT_ENABLE_MULTIVIEW "Enable multiview for Filament" OFF)
|
||||
|
||||
option(FILAMENT_SUPPORTS_OSMESA "Enable OSMesa (headless GL context) for Filament" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
|
||||
@@ -367,14 +366,22 @@ endif()
|
||||
|
||||
if (LINUX)
|
||||
option(USE_STATIC_LIBCXX "Link against the static runtime libraries." ON)
|
||||
|
||||
# Add this step to support both glibc-based Linux distributions (e.g., Ubuntu, Debian)
|
||||
# and musl-based distributions (e.g., Alpine).
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists(__GLIBC__ "features.h" CLANG_WITH_GLIBC)
|
||||
|
||||
if (${USE_STATIC_LIBCXX})
|
||||
if (FILAMENT_USING_GCC)
|
||||
link_libraries("-static-libgcc -static-libstdc++")
|
||||
else ()
|
||||
elseif (CLANG_WITH_GLIBC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
link_libraries("-static-libgcc -static-libstdc++")
|
||||
link_libraries(libc++.a)
|
||||
link_libraries(libc++abi.a)
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -473,7 +480,7 @@ endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
|
||||
|
||||
if (FILAMENT_ENABLE_COVERAGE)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-instr-generate -fcoverage-mapping")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping -Wno-pass-failed")
|
||||
endif()
|
||||
|
||||
# Disable the stack check for macOS to workaround a known issue in clang 11.0.0.
|
||||
@@ -563,6 +570,10 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_WEBGPU)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
endif()
|
||||
|
||||
# Build with Metal support on non-WebGL Apple platforms.
|
||||
if (APPLE AND NOT WEBGL)
|
||||
option(FILAMENT_SUPPORTS_METAL "Include the Metal backend" ON)
|
||||
@@ -574,7 +585,7 @@ if (FILAMENT_SUPPORTS_METAL)
|
||||
endif()
|
||||
|
||||
# Building filamat increases build times and isn't required for web, so turn it off by default.
|
||||
if (NOT WEBGL AND NOT IOS)
|
||||
if (NOT WEBGL)
|
||||
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" ON)
|
||||
else()
|
||||
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" OFF)
|
||||
@@ -594,23 +605,6 @@ else()
|
||||
option(FILAMENT_DISABLE_MATOPT "Disable material optimizations" ON)
|
||||
endif()
|
||||
|
||||
# This only affects the prebuilt shader files in gltfio and samples, not filament library.
|
||||
# The value can be either "instanced", "multiview", or "none"
|
||||
set(FILAMENT_SAMPLES_STEREO_TYPE "none" CACHE STRING
|
||||
"Stereoscopic type that shader files in gltfio and samples are built for."
|
||||
)
|
||||
string(TOLOWER "${FILAMENT_SAMPLES_STEREO_TYPE}" FILAMENT_SAMPLES_STEREO_TYPE)
|
||||
if (NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced"
|
||||
AND NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview"
|
||||
AND NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "none")
|
||||
message(FATAL_ERROR "Invalid stereo type: \"${FILAMENT_SAMPLES_STEREO_TYPE}\" choose either \"instanced\", \"multiview\", or \"none\" ")
|
||||
endif ()
|
||||
|
||||
# Compiling samples for multiview implies enabling multiview feature as well.
|
||||
if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview")
|
||||
set(FILAMENT_ENABLE_MULTIVIEW ON)
|
||||
endif ()
|
||||
|
||||
# Define backend flag for debug only
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FILAMENT_BACKEND_DEBUG_FLAG STREQUAL "")
|
||||
add_definitions(-DFILAMENT_BACKEND_DEBUG_FLAG=${FILAMENT_BACKEND_DEBUG_FLAG})
|
||||
@@ -864,6 +858,7 @@ add_subdirectory(${LIBRARIES}/gltfio)
|
||||
add_subdirectory(${LIBRARIES}/ibl)
|
||||
add_subdirectory(${LIBRARIES}/iblprefilter)
|
||||
add_subdirectory(${LIBRARIES}/image)
|
||||
add_subdirectory(${LIBRARIES}/imagediff)
|
||||
add_subdirectory(${LIBRARIES}/ktxreader)
|
||||
add_subdirectory(${LIBRARIES}/math)
|
||||
add_subdirectory(${LIBRARIES}/mathio)
|
||||
@@ -872,7 +867,9 @@ add_subdirectory(${LIBRARIES}/utils)
|
||||
add_subdirectory(${LIBRARIES}/viewer)
|
||||
add_subdirectory(${FILAMENT}/shaders)
|
||||
add_subdirectory(${EXTERNAL}/abseil/tnt)
|
||||
add_subdirectory(${EXTERNAL}/basisu/tnt)
|
||||
# Add zstd before basisu to force it to use the external zstd target,
|
||||
# preventing a duplicate symbol conflict with its bundled version.
|
||||
add_subdirectory(${EXTERNAL}/zstd/tnt)
|
||||
add_subdirectory(${EXTERNAL}/civetweb/tnt)
|
||||
add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
add_subdirectory(${EXTERNAL}/robin-map/tnt)
|
||||
@@ -886,8 +883,10 @@ add_subdirectory(${EXTERNAL}/jsmn/tnt)
|
||||
add_subdirectory(${EXTERNAL}/stb/tnt)
|
||||
add_subdirectory(${EXTERNAL}/getopt)
|
||||
add_subdirectory(${EXTERNAL}/perfetto/tnt)
|
||||
add_subdirectory(${EXTERNAL}/zstd/tnt)
|
||||
add_subdirectory(${EXTERNAL}/basisu/tnt)
|
||||
|
||||
# imageio-lite is needed for viewer
|
||||
add_subdirectory(${LIBRARIES}/imageio-lite)
|
||||
|
||||
# Note that this has to be placed after mikktspace in order for combine_static_libs to work.
|
||||
add_subdirectory(${LIBRARIES}/geometry)
|
||||
@@ -913,7 +912,6 @@ endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
add_subdirectory(${EXTERNAL}/libwebp/tnt)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
@@ -971,6 +969,7 @@ if (IS_HOST_PLATFORM)
|
||||
add_subdirectory(${TOOLS}/roughness-prefilter)
|
||||
add_subdirectory(${TOOLS}/specular-color)
|
||||
add_subdirectory(${TOOLS}/uberz)
|
||||
add_subdirectory(${TOOLS}/specgen)
|
||||
endif()
|
||||
|
||||
# Generate exported executables for cross-compiled builds (Android, WebGL, and iOS)
|
||||
|
||||
@@ -6,7 +6,3 @@
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- engine: add `View::getLastDynamicResolutionScale()` (b/457753622)
|
||||
|
||||
- materials: Make Material Instances' UBO descriptor use dynamic offsets. [⚠️ **Recompile Materials**]
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.67.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.69.2'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.67.0'
|
||||
pod 'Filament', '~> 1.69.2'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,6 +7,44 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.69.2
|
||||
|
||||
- engine: fix shader compilation failure in TAA material
|
||||
- engine: fix stereo & parallel shader compilation
|
||||
|
||||
## v1.69.1
|
||||
|
||||
|
||||
## v1.69.0
|
||||
|
||||
- engine: Support custom attributes morphing, and allow for omitting position and/or normal data. [⚠️ **Recompile Materials**]
|
||||
|
||||
## v1.68.5
|
||||
|
||||
- engine: "native" Streams are officially deprecated. Use "acquired" streams instead.
|
||||
- engine: add "engine.skip_frame_when_cpu_ahead_of_display" feature [b/474599530]
|
||||
|
||||
## v1.68.4
|
||||
|
||||
- gltfio: Add optional support for webp textures (EXT_texture_webp), controlled via FILAMENT_SUPPORTS_WEBP_TEXTURES cmake option
|
||||
|
||||
## v1.68.3
|
||||
|
||||
- materials: added support for the glTF `KHR_materials_dispersion` extension, which adds dispersion for refractive objects
|
||||
|
||||
## v1.68.2
|
||||
|
||||
- Support `setPresentationTime` with the Metal backend.
|
||||
|
||||
## v1.68.1
|
||||
|
||||
|
||||
## v1.68.0
|
||||
|
||||
- engine: add `View::getLastDynamicResolutionScale()` (b/457753622)
|
||||
- Metal: report GPU errors to the platform via `debugUpdateStat` (b/431665753).
|
||||
- materials: Make Material Instances' UBO descriptor use dynamic offsets. [⚠️ **Recompile Materials**]
|
||||
|
||||
## v1.67.1
|
||||
|
||||
- Metal: Add support for the `SwapChain::CONFIG_MSAA_4_SAMPLES` flag.
|
||||
|
||||
@@ -100,7 +100,7 @@ buildscript {
|
||||
'kotlin': '2.0.21',
|
||||
'kotlin_coroutines': '1.9.0',
|
||||
'buildTools': '35.0.0',
|
||||
'ndk': '27.0.11718014',
|
||||
'ndk': '29.0.14206865',
|
||||
'androidx_core': '1.13.1',
|
||||
'androidx_annotations': '1.9.0'
|
||||
]
|
||||
@@ -124,6 +124,7 @@ buildscript {
|
||||
|
||||
ext.cmakeArgs = [
|
||||
"--no-warn-unused-cli",
|
||||
"-DANDROID_WEAK_API_DEFS=ON",
|
||||
"-DANDROID_PIE=ON",
|
||||
"-DANDROID_PLATFORM=21",
|
||||
"-DANDROID_STL=c++_static",
|
||||
@@ -193,7 +194,7 @@ subprojects {
|
||||
google()
|
||||
}
|
||||
|
||||
if (!name.startsWith("sample")) {
|
||||
if (!name.startsWith("sample") && name != "filament-tools") {
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
|
||||
@@ -335,6 +335,13 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderRefract
|
||||
builder->refractionMode((MaterialBuilder::RefractionMode) mode);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderReflectionMode(JNIEnv* env,
|
||||
jclass, jlong nativeBuilder, jint mode) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
builder->reflectionMode((MaterialBuilder::ReflectionMode) mode);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderRefractionType(JNIEnv* env,
|
||||
jclass, jlong nativeBuilder, jint type) {
|
||||
|
||||
@@ -177,6 +177,11 @@ public class MaterialBuilder {
|
||||
SCREEN_SPACE
|
||||
}
|
||||
|
||||
public enum ReflectionMode {
|
||||
DEFAULT,
|
||||
SCREEN_SPACE
|
||||
}
|
||||
|
||||
public enum RefractionType {
|
||||
SOLID,
|
||||
THIN
|
||||
@@ -403,6 +408,12 @@ public class MaterialBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder reflectionMode(ReflectionMode mode) {
|
||||
nMaterialBuilderReflectionMode(mNativeObject, mode.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder refractionType(RefractionType type) {
|
||||
nMaterialBuilderRefractionType(mNativeObject, type.ordinal());
|
||||
@@ -604,6 +615,7 @@ public class MaterialBuilder {
|
||||
private static native void nMaterialBuilderSpecularAntiAliasingThreshold(long mNativeObject,
|
||||
float threshold);
|
||||
private static native void nMaterialBuilderRefractionMode(long nativeBuilder, int mode);
|
||||
private static native void nMaterialBuilderReflectionMode(long nativeBuilder, int mode);
|
||||
private static native void nMaterialBuilderRefractionType(long nativeBuilder, int type);
|
||||
private static native void nMaterialBuilderClearCoatIorChange(long mNativeObject,
|
||||
boolean clearCoatIorChange);
|
||||
|
||||
@@ -134,6 +134,7 @@ target_include_directories(filament-jni PRIVATE
|
||||
../../filament/backend/include
|
||||
../../third_party/robin-map
|
||||
../../third_party/perfetto
|
||||
../../libs/bluevk/include
|
||||
../../libs/utils/include)
|
||||
|
||||
# Ordering is significant in the following list. The PRIVATE qualifier prevents transitive deps.
|
||||
@@ -167,3 +168,9 @@ target_link_libraries(filament-jni
|
||||
|
||||
# Force a relink when the version script is changed:
|
||||
set_target_properties(filament-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
||||
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_VULKAN=1)
|
||||
else()
|
||||
add_definitions(-DFILAMENT_SUPPORTS_VULKAN=0)
|
||||
endif()
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <filament/Camera.h>
|
||||
|
||||
|
||||
#include <utils/Entity.h>
|
||||
|
||||
#include <math/mat4.h>
|
||||
@@ -40,6 +41,13 @@ Java_com_google_android_filament_Camera_nSetProjectionFov(JNIEnv*, jclass ,
|
||||
camera->setProjection(fovInDegrees, aspect, near, far, (Camera::Fov) fov);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jdouble JNICALL
|
||||
Java_com_google_android_filament_Camera_nGetFieldOfViewInDegrees(JNIEnv*, jclass,
|
||||
jlong nativeCamera, jint direction) {
|
||||
Camera *camera = (Camera *) nativeCamera;
|
||||
return camera->getFieldOfViewInDegrees((Camera::Fov) direction);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nSetLensProjection(JNIEnv*, jclass,
|
||||
jlong nativeCamera, jdouble focalLength, jdouble aspect, jdouble near, jdouble far) {
|
||||
@@ -62,6 +70,21 @@ Java_com_google_android_filament_Camera_nSetCustomProjection(JNIEnv *env, jclass
|
||||
env->ReleaseDoubleArrayElements(inProjectionForCulling_, inProjectionForCulling, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nSetCustomEyeProjection(JNIEnv *env, jclass,
|
||||
jlong nativeCamera, jdoubleArray inProjection_, jint count, jdoubleArray inProjectionForCulling_,
|
||||
jdouble near, jdouble far) {
|
||||
Camera *camera = (Camera *) nativeCamera;
|
||||
jdouble *inProjection = env->GetDoubleArrayElements(inProjection_, NULL);
|
||||
jdouble *inProjectionForCulling = env->GetDoubleArrayElements(inProjectionForCulling_, NULL);
|
||||
camera->setCustomEyeProjection(
|
||||
reinterpret_cast<const filament::math::mat4 *>(inProjection), (size_t) count,
|
||||
*reinterpret_cast<const filament::math::mat4 *>(inProjectionForCulling),
|
||||
near, far);
|
||||
env->ReleaseDoubleArrayElements(inProjection_, inProjection, JNI_ABORT);
|
||||
env->ReleaseDoubleArrayElements(inProjectionForCulling_, inProjectionForCulling, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nSetScaling(JNIEnv* env, jclass,
|
||||
jlong nativeCamera, jdouble x, jdouble y) {
|
||||
@@ -76,6 +99,17 @@ Java_com_google_android_filament_Camera_nSetShift(JNIEnv* env, jclass,
|
||||
camera->setShift({(double)x, (double)y});
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nGetShift(JNIEnv* env, jclass,
|
||||
jlong nativeCamera, jdoubleArray out_) {
|
||||
Camera *camera = (Camera *) nativeCamera;
|
||||
jdouble *out = env->GetDoubleArrayElements(out_, NULL);
|
||||
filament::math::double2 s = camera->getShift();
|
||||
out[0] = s.x;
|
||||
out[1] = s.y;
|
||||
env->ReleaseDoubleArrayElements(out_, out, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nLookAt(JNIEnv*, jclass, jlong nativeCamera,
|
||||
jdouble eye_x, jdouble eye_y, jdouble eye_z, jdouble center_x, jdouble center_y,
|
||||
@@ -115,6 +149,15 @@ Java_com_google_android_filament_Camera_nSetModelMatrixFp64(JNIEnv *env, jclass,
|
||||
env->ReleaseDoubleArrayElements(in_, in, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nSetEyeModelMatrix(JNIEnv *env, jclass,
|
||||
jlong nativeCamera, jint eyeId, jdoubleArray model_) {
|
||||
Camera* camera = (Camera *) nativeCamera;
|
||||
jdouble *model = env->GetDoubleArrayElements(model_, NULL);
|
||||
camera->setEyeModelMatrix((uint8_t)eyeId, *reinterpret_cast<const filament::math::mat4*>(model));
|
||||
env->ReleaseDoubleArrayElements(model_, model, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Camera_nGetProjectionMatrix(JNIEnv *env, jclass,
|
||||
jlong nativeCamera, jdoubleArray out_) {
|
||||
@@ -280,3 +323,5 @@ Java_com_google_android_filament_Camera_nComputeEffectiveFov(JNIEnv*, jclass,
|
||||
jdouble fovInDegrees, jdouble focusDistance) {
|
||||
return Camera::computeEffectiveFov(fovInDegrees, focusDistance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/MorphTargetBuffer.h>
|
||||
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/EntityManager.h>
|
||||
@@ -207,6 +208,14 @@ Java_com_google_android_filament_Engine_nDestroySkinningBuffer(JNIEnv*, jclass,
|
||||
return engine->destroy(skinningBuffer);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Engine_nDestroyMorphTargetBuffer(JNIEnv*, jclass,
|
||||
jlong nativeEngine, jlong nativeMorphTargetBuffer) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
MorphTargetBuffer* mtb = (MorphTargetBuffer*) nativeMorphTargetBuffer;
|
||||
return engine->destroy(mtb);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Engine_nDestroyIndirectLight(JNIEnv*, jclass,
|
||||
jlong nativeEngine, jlong nativeIndirectLight) {
|
||||
@@ -328,6 +337,13 @@ Java_com_google_android_filament_Engine_nIsValidSkinningBuffer(JNIEnv*, jclass,
|
||||
return (jboolean)engine->isValid((SkinningBuffer*)nativeSkinningBuffer);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Engine_nIsValidMorphTargetBuffer(JNIEnv*, jclass,
|
||||
jlong nativeEngine, jlong nativeMorphTargetBuffer) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jboolean) engine->isValid((MorphTargetBuffer*) nativeMorphTargetBuffer);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Engine_nIsValidIndirectLight(JNIEnv*, jclass,
|
||||
jlong nativeEngine, jlong nativeIndirectLight) {
|
||||
|
||||
@@ -25,7 +25,7 @@ using namespace filament;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
|
||||
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount, jint shadowQuality) {
|
||||
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount, jint shadowQuality, jint uboBatchingMode) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, buffer_, size);
|
||||
auto builder = Material::Builder();
|
||||
@@ -33,6 +33,7 @@ Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
|
||||
builder.sphericalHarmonicsBandCount(shBandCount);
|
||||
}
|
||||
builder.shadowSamplingQuality((Material::Builder::ShadowSamplingQuality)shadowQuality);
|
||||
builder.uboBatching((Material::UboBatchingMode)uboBatchingMode);
|
||||
Material* material = builder
|
||||
.package(buffer.getData(), buffer.getSize())
|
||||
.build(*engine);
|
||||
@@ -95,6 +96,14 @@ Java_com_google_android_filament_Material_nGetBlendingMode(JNIEnv*, jclass,
|
||||
return (jint) material->getBlendingMode();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Material_nGetTransparencyMode(JNIEnv*, jclass,
|
||||
jlong nativeMaterial) {
|
||||
Material* material = (Material*) nativeMaterial;
|
||||
return (jint) material->getTransparencyMode();
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
|
||||
@@ -564,3 +564,19 @@ Java_com_google_android_filament_MaterialInstance_nGetDepthFunc(JNIEnv* env, jcl
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return (jint)instance->getDepthFunc();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetTransparencyMode(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jint mode) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setTransparencyMode((MaterialInstance::TransparencyMode) mode);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetTransparencyMode(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
return (jint) instance->getTransparencyMode();
|
||||
}
|
||||
|
||||
@@ -58,6 +58,27 @@ Java_com_google_android_filament_MorphTargetBuffer_nBuilderCount(JNIEnv*, jclass
|
||||
builder->count((size_t) count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nBuilderWithPositions(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jboolean enabled) {
|
||||
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder*) nativeBuilder;
|
||||
builder->withPositions(enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nBuilderWithTangents(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jboolean enabled) {
|
||||
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder*) nativeBuilder;
|
||||
builder->withTangents(enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nBuilderEnableCustomMorphing(JNIEnv*,
|
||||
jclass, jlong nativeBuilder, jboolean enabled) {
|
||||
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder*) nativeBuilder;
|
||||
builder->enableCustomMorphing(enabled);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nBuilderBuild(JNIEnv*, jclass,
|
||||
@@ -112,3 +133,24 @@ Java_com_google_android_filament_MorphTargetBuffer_nGetCount(JNIEnv*, jclass,
|
||||
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
|
||||
return (jint)morphTargetBuffer->getCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nHasPositions(JNIEnv*, jclass,
|
||||
jlong nativeObject) {
|
||||
MorphTargetBuffer* morphTargetBuffer = (MorphTargetBuffer*) nativeObject;
|
||||
return (jboolean) morphTargetBuffer->hasPositions();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nHasTangents(JNIEnv*, jclass,
|
||||
jlong nativeObject) {
|
||||
MorphTargetBuffer* morphTargetBuffer = (MorphTargetBuffer*) nativeObject;
|
||||
return (jboolean) morphTargetBuffer->hasTangents();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MorphTargetBuffer_nIsCustomMorphingEnabled(JNIEnv*, jclass,
|
||||
jlong nativeObject) {
|
||||
MorphTargetBuffer* morphTargetBuffer = (MorphTargetBuffer*) nativeObject;
|
||||
return (jboolean) morphTargetBuffer->isCustomMorphingEnabled();
|
||||
}
|
||||
|
||||
@@ -366,6 +366,13 @@ Java_com_google_android_filament_RenderableManager_nSetPriority(JNIEnv*, jclass,
|
||||
rm->setPriority((RenderableManager::Instance) i, (uint8_t) priority);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetPriority(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jint) rm->getPriority((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetChannel(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint channel) {
|
||||
@@ -373,6 +380,13 @@ Java_com_google_android_filament_RenderableManager_nSetChannel(JNIEnv*, jclass,
|
||||
rm->setChannel((RenderableManager::Instance) i, (uint8_t) channel);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetChannel(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jint) rm->getChannel((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetCulling(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jboolean enabled) {
|
||||
@@ -380,6 +394,13 @@ Java_com_google_android_filament_RenderableManager_nSetCulling(JNIEnv*, jclass,
|
||||
rm->setCulling((RenderableManager::Instance) i, enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nIsCullingEnabled(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jboolean) rm->isCullingEnabled((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetFogEnabled(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jboolean enabled) {
|
||||
@@ -429,6 +450,13 @@ Java_com_google_android_filament_RenderableManager_nIsShadowReceiver(JNIEnv*, jc
|
||||
return (jboolean) rm->isShadowReceiver((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nIsScreenSpaceContactShadowsEnabled(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jboolean) rm->isScreenSpaceContactShadowsEnabled((RenderableManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetAxisAlignedBoundingBox(JNIEnv* env,
|
||||
jclass, jlong nativeRenderableManager, jint i, jfloatArray center_,
|
||||
@@ -500,6 +528,13 @@ Java_com_google_android_filament_RenderableManager_nSetBlendOrderAt(JNIEnv*, jcl
|
||||
(uint16_t) blendOrder);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetBlendOrderAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jint) rm->getBlendOrderAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetGlobalBlendOrderEnabledAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex, jboolean enabled) {
|
||||
@@ -508,6 +543,13 @@ Java_com_google_android_filament_RenderableManager_nSetGlobalBlendOrderEnabledAt
|
||||
(bool) enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nIsGlobalBlendOrderEnabledAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
return (jboolean) rm->isGlobalBlendOrderEnabledAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nGetEnabledAttributesAt(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
|
||||
|
||||
@@ -63,6 +63,14 @@ Java_com_google_android_filament_Skybox_nBuilderColor(JNIEnv *, jclass,
|
||||
builder->color({r, g, b, a});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Skybox_nBuilderPriority(JNIEnv *, jclass,
|
||||
jlong nativeSkyBoxBuilder, jint priority) {
|
||||
Skybox::Builder *builder = (Skybox::Builder *) nativeSkyBoxBuilder;
|
||||
builder->priority(uint8_t(priority));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Skybox_nBuilderBuild(JNIEnv *env, jclass type,
|
||||
jlong nativeSkyBoxBuilder, jlong nativeEngine) {
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/bitmap.h>
|
||||
#include <android/hardware_buffer_jni.h>
|
||||
#include <backend/platforms/PlatformEGLAndroid.h>
|
||||
# if FILAMENT_SUPPORTS_VULKAN
|
||||
# include <backend/platforms/VulkanPlatformAndroid.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <filament/Engine.h>
|
||||
@@ -168,6 +173,13 @@ Java_com_google_android_filament_Texture_nBuilderSwizzle(JNIEnv *, jclass ,
|
||||
(Texture::Swizzle)r, (Texture::Swizzle)g, (Texture::Swizzle)b, (Texture::Swizzle)a);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Texture_nBuilderSamples(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint samples) {
|
||||
Texture::Builder *builder = (Texture::Builder *) nativeBuilder;
|
||||
builder->samples((uint8_t) samples);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Texture_nBuilderImportTexture(JNIEnv*, jclass, jlong nativeBuilder, jlong id) {
|
||||
@@ -388,6 +400,57 @@ Java_com_google_android_filament_Texture_nSetExternalImage(JNIEnv*, jclass, jlon
|
||||
texture->setExternalImage(*engine, (void*)eglImage);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Texture_nSetExternalImageByAHB(JNIEnv *env, jclass clazz,
|
||||
jlong nativeTexture, jlong nativeEngine, jobject ahb) {
|
||||
Texture *texture = (Texture *) nativeTexture;
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
Platform* platform = engine->getPlatform();
|
||||
AHardwareBuffer* nativeBuffer = nullptr;
|
||||
if (__builtin_available(android 26, *)) {
|
||||
nativeBuffer = AHardwareBuffer_fromHardwareBuffer(env, ahb);
|
||||
}
|
||||
if (!nativeBuffer) {
|
||||
// either we're not on Android 26, or ahb wasn't a AHardwareBuffer
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (engine->getBackend() == Backend::OPENGL) {
|
||||
// CAVEAT: we assume that Backend::OPENGL on Android implies PlatformEGLAndroid.
|
||||
#if UTILS_HAS_RTTI
|
||||
if (!dynamic_cast<PlatformEGLAndroid*>(platform)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
#endif
|
||||
auto* eglPlatform = (PlatformEGLAndroid*) platform;
|
||||
auto ref = eglPlatform->createExternalImage(nativeBuffer, false);
|
||||
texture->setExternalImage(*engine, ref);
|
||||
}
|
||||
|
||||
#if FILAMENT_SUPPORTS_VULKAN
|
||||
else if (engine->getBackend() == Backend::VULKAN) {
|
||||
// CAVEAT: we assume that Backend::VULKAN on Android implies VulkanPlatformAndroid.
|
||||
#if UTILS_HAS_RTTI
|
||||
if (!dynamic_cast<VulkanPlatformAndroid*>(platform)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
#endif
|
||||
auto* vulkanPlatform = (VulkanPlatformAndroid*) platform;
|
||||
auto ref = vulkanPlatform->createExternalImage(nativeBuffer, false);
|
||||
texture->setExternalImage(*engine, ref);
|
||||
}
|
||||
#endif // FILAMENT_SUPPORTS_VULKAN
|
||||
// success!
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
// other platforms could come here
|
||||
return JNI_FALSE;
|
||||
#endif // __ANDROID__
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Texture_nSetExternalStream(JNIEnv*, jclass,
|
||||
jlong nativeTexture, jlong nativeEngine, jlong nativeStream) {
|
||||
@@ -607,3 +670,4 @@ Java_com_google_android_filament_android_TextureHelper_nSetBitmapWithCallback(JN
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ Java_com_google_android_filament_ToneMapper_nCreatePBRNeutralToneMapper(JNIEnv*,
|
||||
return (jlong) new PBRNeutralToneMapper();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_ToneMapper_nCreateGT7ToneMapper(JNIEnv*, jclass) {
|
||||
return (jlong) new GT7ToneMapper();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_ToneMapper_nCreateAgxToneMapper(JNIEnv*, jclass, jint look) {
|
||||
return (jlong) new AgxToneMapper(AgxToneMapper::AgxLook(look));
|
||||
|
||||
@@ -76,6 +76,12 @@ Java_com_google_android_filament_View_nSetVisibleLayers(JNIEnv*, jclass, jlong n
|
||||
view->setVisibleLayers((uint8_t) select, (uint8_t) value);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_View_nGetVisibleLayers(JNIEnv*, jclass, jlong nativeView) {
|
||||
View* view = (View*) nativeView;
|
||||
return view->getVisibleLayers();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetShadowingEnabled(JNIEnv*, jclass, jlong nativeView, jboolean enabled) {
|
||||
View* view = (View*) nativeView;
|
||||
@@ -440,6 +446,18 @@ Java_com_google_android_filament_View_nIsShadowingEnabled(JNIEnv *, jclass, jlon
|
||||
return (jboolean)view->isShadowingEnabled();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetFrustumCullingEnabled(JNIEnv*, jclass, jlong nativeView, jboolean enabled) {
|
||||
View* view = (View*) nativeView;
|
||||
view->setFrustumCullingEnabled(enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_View_nIsFrustumCullingEnabled(JNIEnv*, jclass, jlong nativeView) {
|
||||
View* view = (View*) nativeView;
|
||||
return (jboolean)view->isFrustumCullingEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetScreenSpaceRefractionEnabled(JNIEnv *, jclass,
|
||||
|
||||
@@ -136,4 +136,13 @@ final class Asserts {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 4");
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Size(min = 2)
|
||||
static double[] assertDouble2(@Nullable double[] out) {
|
||||
if (out == null) out = new double[2];
|
||||
else if (out.length < 2) {
|
||||
throw new ArrayIndexOutOfBoundsException("Array length must be at least 2");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +343,27 @@ public class Camera {
|
||||
nSetScaling(getNativeObject(), xscaling, yscaling);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom projection matrix for each eye.
|
||||
*
|
||||
* @param inProjection An array of projection matrices, one for each eye.
|
||||
* Must have at least 16 * count elements.
|
||||
* @param count Number of eyes to set.
|
||||
* @param inProjectionForCulling Custom projection matrix for culling, must encompass all eyes.
|
||||
* @param near Distance to the near plane.
|
||||
* @param far Distance to the far plane.
|
||||
*/
|
||||
public void setCustomEyeProjection(
|
||||
@NonNull double[] inProjection, int count,
|
||||
@NonNull @Size(min = 16) double[] inProjectionForCulling,
|
||||
double near, double far) {
|
||||
Asserts.assertMat4dIn(inProjectionForCulling);
|
||||
if (inProjection.length < 16 * count) {
|
||||
throw new IllegalArgumentException("inProjection array too small for the given count");
|
||||
}
|
||||
nSetCustomEyeProjection(getNativeObject(), inProjection, count, inProjectionForCulling, near, far);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an additional matrix that scales the projection matrix.
|
||||
*
|
||||
@@ -399,6 +420,31 @@ public class Camera {
|
||||
nSetShift(getNativeObject(), xshift, yshift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shift amount used to translate the projection matrix.
|
||||
*
|
||||
* @param out A 2-double array where the shift will be stored, or null.
|
||||
* @return A 2-double array containing the x and y shift.
|
||||
*/
|
||||
@NonNull @Size(min = 2)
|
||||
public double[] getShift(@Nullable @Size(min = 2) double[] out) {
|
||||
out = Asserts.assertDouble2(out);
|
||||
nGetShift(getNativeObject(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the camera's field of view in degrees.
|
||||
*
|
||||
* @param direction The direction of the FOV (VERTICAL or HORIZONTAL).
|
||||
* @return The field of view in degrees.
|
||||
*/
|
||||
public double getFieldOfViewInDegrees(@NonNull Fov direction) {
|
||||
return nGetFieldOfViewInDegrees(getNativeObject(), direction.ordinal());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets the camera's model matrix.
|
||||
* <p>
|
||||
@@ -745,6 +791,17 @@ public class Camera {
|
||||
return mEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model matrix for a specific eye.
|
||||
*
|
||||
* @param eyeId The index of the eye.
|
||||
* @param model The model matrix for the eye.
|
||||
*/
|
||||
public void setEyeModelMatrix(int eyeId, @NonNull @Size(min = 16) double[] model) {
|
||||
Asserts.assertMat4dIn(model);
|
||||
nSetEyeModelMatrix(getNativeObject(), eyeId, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to compute the effective focal length taking into account the focus distance
|
||||
*
|
||||
@@ -784,8 +841,13 @@ public class Camera {
|
||||
private static native void nSetCustomProjection(long nativeCamera, double[] inProjection, double[] inProjectionForCulling, double near, double far);
|
||||
private static native void nSetScaling(long nativeCamera, double x, double y);
|
||||
private static native void nSetShift(long nativeCamera, double x, double y);
|
||||
private static native void nGetShift(long nativeCamera, double[] out);
|
||||
private static native void nSetModelMatrix(long nativeCamera, float[] in);
|
||||
private static native void nSetModelMatrixFp64(long nativeCamera, double[] in);
|
||||
private static native void nSetEyeModelMatrix(long nativeCamera, int eyeId, double[] model);
|
||||
private static native void nSetCustomEyeProjection(long nativeCamera, double[] inProjection, int count, double[] inProjectionForCulling, double near, double far);
|
||||
private static native double nGetFieldOfViewInDegrees(long nativeCamera, int direction);
|
||||
|
||||
private static native void nLookAt(long nativeCamera, double eyeX, double eyeY, double eyeZ, double centerX, double centerY, double centerZ, double upX, double upY, double upZ);
|
||||
private static native double nGetNear(long nativeCamera);
|
||||
private static native double nGetCullingFar(long nativeCamera);
|
||||
|
||||
@@ -939,6 +939,15 @@ public class Engine {
|
||||
return nIsValidSkinningBuffer(getNativeObject(), object.getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the object is valid.
|
||||
* @param object Object to check for validity
|
||||
* @return returns true if the specified object is valid.
|
||||
*/
|
||||
public boolean isValidMorphTargetBuffer(@NonNull MorphTargetBuffer object) {
|
||||
return nIsValidMorphTargetBuffer(getNativeObject(), object.getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the object is valid.
|
||||
* @param object Object to check for validity
|
||||
@@ -1192,6 +1201,15 @@ public class Engine {
|
||||
skinningBuffer.clearNativeObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a {@link MorphTargetBuffer} and frees all its associated resources.
|
||||
* @param morphTargetBuffer the {@link MorphTargetBuffer} to destroy
|
||||
*/
|
||||
public void destroyMorphTargetBuffer(@NonNull MorphTargetBuffer morphTargetBuffer) {
|
||||
assertDestroy(nDestroyMorphTargetBuffer(getNativeObject(), morphTargetBuffer.getNativeObject()));
|
||||
morphTargetBuffer.clearNativeObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a {@link IndirectLight} and frees all its associated resources.
|
||||
* @param ibl the {@link IndirectLight} to destroy
|
||||
@@ -1483,6 +1501,7 @@ public class Engine {
|
||||
private static native boolean nDestroyIndexBuffer(long nativeEngine, long nativeIndexBuffer);
|
||||
private static native boolean nDestroyVertexBuffer(long nativeEngine, long nativeVertexBuffer);
|
||||
private static native boolean nDestroySkinningBuffer(long nativeEngine, long nativeSkinningBuffer);
|
||||
private static native boolean nDestroyMorphTargetBuffer(long nativeEngine, long nativeMorphTargetBuffer);
|
||||
private static native boolean nDestroyIndirectLight(long nativeEngine, long nativeIndirectLight);
|
||||
private static native boolean nDestroyMaterial(long nativeEngine, long nativeMaterial);
|
||||
private static native boolean nDestroyMaterialInstance(long nativeEngine, long nativeMaterialInstance);
|
||||
@@ -1499,6 +1518,7 @@ public class Engine {
|
||||
private static native boolean nIsValidIndexBuffer(long nativeEngine, long nativeIndexBuffer);
|
||||
private static native boolean nIsValidVertexBuffer(long nativeEngine, long nativeVertexBuffer);
|
||||
private static native boolean nIsValidSkinningBuffer(long nativeEngine, long nativeSkinningBuffer);
|
||||
private static native boolean nIsValidMorphTargetBuffer(long nativeEngine, long nativeMorphTargetBuffer);
|
||||
private static native boolean nIsValidIndirectLight(long nativeEngine, long nativeIndirectLight);
|
||||
private static native boolean nIsValidMaterial(long nativeEngine, long nativeMaterial);
|
||||
private static native boolean nIsValidMaterialInstance(long nativeEngine, long nativeMaterial, long nativeMaterialInstance);
|
||||
|
||||
@@ -54,6 +54,7 @@ public class Material {
|
||||
static final CullingMode[] sCullingModeValues = CullingMode.values();
|
||||
static final VertexBuffer.VertexAttribute[] sVertexAttributeValues =
|
||||
VertexBuffer.VertexAttribute.values();
|
||||
static final TransparencyMode[] sTransparencyModeValues = TransparencyMode.values();
|
||||
}
|
||||
|
||||
private long mNativeObject;
|
||||
@@ -160,6 +161,31 @@ public class Material {
|
||||
SCREEN,
|
||||
}
|
||||
|
||||
/**
|
||||
* How transparent objects are handled
|
||||
*
|
||||
* @see
|
||||
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:transparencymode">
|
||||
* Blending and transparency: transparencyMode</a>
|
||||
*/
|
||||
public enum TransparencyMode {
|
||||
/** The transparent object is drawn honoring the raster state. */
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* The transparent object is first drawn in the depth buffer,
|
||||
* then in the color buffer, honoring the culling mode, but ignoring the depth test function.
|
||||
*/
|
||||
TWO_PASSES_ONE_SIDE,
|
||||
|
||||
/**
|
||||
* The transparent object is drawn twice in the color buffer,
|
||||
* first with back faces only, then with front faces; the culling
|
||||
* mode is ignored. Can be combined with two-sided lighting.
|
||||
*/
|
||||
TWO_PASSES_TWO_SIDES
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported refraction modes
|
||||
*
|
||||
@@ -261,6 +287,20 @@ public class Material {
|
||||
LOW
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether a material instance should use UBO batching or not.
|
||||
*/
|
||||
public enum UboBatchingMode {
|
||||
/**
|
||||
* For default, it follows the engine settings.
|
||||
* If UBO batching is enabled on the engine and the material domain is SURFACE, it
|
||||
* turns on the UBO batching. Otherwise, it turns off the UBO batching.
|
||||
*/
|
||||
DEFAULT,
|
||||
/** Disable the Ubo Batching for this material */
|
||||
DISABLED
|
||||
}
|
||||
|
||||
public static class UserVariantFilterBit {
|
||||
/** Directional lighting */
|
||||
public static int DIRECTIONAL_LIGHTING = 0x01;
|
||||
@@ -372,6 +412,7 @@ public class Material {
|
||||
private int mSize;
|
||||
private int mShBandCount = 0;
|
||||
private ShadowSamplingQuality mShadowSamplingQuality = ShadowSamplingQuality.LOW;
|
||||
private UboBatchingMode mUboBatchingMode = UboBatchingMode.DEFAULT;
|
||||
|
||||
|
||||
/**
|
||||
@@ -416,6 +457,17 @@ public class Material {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the batching mode of the instances created from this material.
|
||||
* @param uboBatchingMode
|
||||
* @return Reference to this Builder for chaining calls.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder uboBatching(UboBatchingMode mode) {
|
||||
mUboBatchingMode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the Material object.
|
||||
*
|
||||
@@ -428,7 +480,7 @@ public class Material {
|
||||
@NonNull
|
||||
public Material build(@NonNull Engine engine) {
|
||||
long nativeMaterial = nBuilderBuild(engine.getNativeObject(),
|
||||
mBuffer, mSize, mShBandCount, mShadowSamplingQuality.ordinal());
|
||||
mBuffer, mSize, mShBandCount, mShadowSamplingQuality.ordinal(), mUboBatchingMode.ordinal());
|
||||
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
|
||||
return new Material(nativeMaterial);
|
||||
}
|
||||
@@ -561,6 +613,18 @@ public class Material {
|
||||
return EnumCache.sBlendingModeValues[nGetBlendingMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transparency mode of this material.
|
||||
* This value only makes sense when the blending mode is transparent or fade.
|
||||
*
|
||||
* @see
|
||||
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:transparencymode">
|
||||
* Blending and transparency: transparencyMode</a>
|
||||
*/
|
||||
public TransparencyMode getTransparencyMode() {
|
||||
return EnumCache.sTransparencyModeValues[nGetTransparencyMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the refraction mode of this material.
|
||||
*
|
||||
@@ -1094,7 +1158,7 @@ public class Material {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount, int shadowQuality);
|
||||
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount, int shadowQuality, int uboBatchingMode);
|
||||
private static native long nCreateInstance(long nativeMaterial);
|
||||
private static native long nCreateInstanceWithName(long nativeMaterial, @NonNull String name);
|
||||
private static native long nGetDefaultInstance(long nativeMaterial);
|
||||
@@ -1104,6 +1168,7 @@ public class Material {
|
||||
private static native int nGetShading(long nativeMaterial);
|
||||
private static native int nGetInterpolation(long nativeMaterial);
|
||||
private static native int nGetBlendingMode(long nativeMaterial);
|
||||
private static native int nGetTransparencyMode(long nativeMaterial);
|
||||
private static native int nGetVertexDomain(long nativeMaterial);
|
||||
private static native int nGetCullingMode(long nativeMaterial);
|
||||
private static native boolean nIsColorWriteEnabled(long nativeMaterial);
|
||||
|
||||
@@ -537,6 +537,14 @@ public class MaterialInstance {
|
||||
nSetDoubleSided(getNativeObject(), doubleSided);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transparency mode for this material instance.
|
||||
* @see Material.TransparencyMode
|
||||
*/
|
||||
public void setTransparencyMode(@NonNull Material.TransparencyMode mode) {
|
||||
nSetTransparencyMode(getNativeObject(), mode.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether double-sided lighting is enabled when the parent Material has double-sided
|
||||
* capability.
|
||||
@@ -545,6 +553,14 @@ public class MaterialInstance {
|
||||
return nIsDoubleSided(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transparency mode.
|
||||
*/
|
||||
@NonNull
|
||||
public Material.TransparencyMode getTransparencyMode() {
|
||||
return Material.EnumCache.sTransparencyModeValues[nGetTransparencyMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material.
|
||||
*
|
||||
@@ -982,4 +998,6 @@ public class MaterialInstance {
|
||||
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsDepthCullingEnabled(long nativeMaterialInstance);
|
||||
private static native int nGetDepthFunc(long nativeMaterialInstance);
|
||||
private static native void nSetTransparencyMode(long nativeMaterialInstance, int mode);
|
||||
private static native int nGetTransparencyMode(long nativeMaterialInstance);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,45 @@ public class MorphTargetBuffer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to enable or disable the built-in position morphing buffer.
|
||||
* Default is true.
|
||||
*
|
||||
* @param enabled true to enable, false to disable
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder withPositions(boolean enabled) {
|
||||
nBuilderWithPositions(mNativeBuilder, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to enable or disable the built-in tangent morphing buffer.
|
||||
* Default is true.
|
||||
*
|
||||
* @param enabled true to enable, false to disable
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder withTangents(boolean enabled) {
|
||||
nBuilderWithTangents(mNativeBuilder, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to enable or disable custom morphing.
|
||||
* Default is false.
|
||||
*
|
||||
* @param enabled true to enable, false to disable
|
||||
* @return this <code>Builder</code> object for chaining calls
|
||||
*/
|
||||
@NonNull
|
||||
public Builder enableCustomMorphing(boolean enabled) {
|
||||
nBuilderEnableCustomMorphing(mNativeBuilder, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the <code>MorphTargetBuffer</code> object.
|
||||
*
|
||||
@@ -156,6 +195,27 @@ public class MorphTargetBuffer {
|
||||
return nGetCount(mNativeObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this MorphTargetBuffer has a position buffer.
|
||||
*/
|
||||
public boolean hasPositions() {
|
||||
return nHasPositions(mNativeObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this MorphTargetBuffer has a tangent buffer.
|
||||
*/
|
||||
public boolean hasTangents() {
|
||||
return nHasTangents(mNativeObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if custom morphing is enabled.
|
||||
*/
|
||||
public boolean isCustomMorphingEnabled() {
|
||||
return nIsCustomMorphingEnabled(mNativeObject);
|
||||
}
|
||||
|
||||
public long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Calling method on destroyed MorphTargetBuffer");
|
||||
@@ -171,10 +231,16 @@ public class MorphTargetBuffer {
|
||||
private static native void nDestroyBuilder(long nativeBuilder);
|
||||
private static native void nBuilderVertexCount(long nativeBuilder, int vertexCount);
|
||||
private static native void nBuilderCount(long nativeBuilder, int count);
|
||||
private static native void nBuilderWithPositions(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderWithTangents(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderEnableCustomMorphing(long nativeBuilder, boolean enabled);
|
||||
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
|
||||
|
||||
private static native int nSetPositionsAt(long nativeObject, long nativeEngine, int targetIndex, float[] positions, int count);
|
||||
private static native int nSetTangentsAt(long nativeObject, long nativeEngine, int targetIndex, short[] tangents, int count);
|
||||
private static native int nGetVertexCount(long nativeObject);
|
||||
private static native int nGetCount(long nativeObject);
|
||||
private static native boolean nHasPositions(long nativeObject);
|
||||
private static native boolean nHasTangents(long nativeObject);
|
||||
private static native boolean nIsCustomMorphingEnabled(long nativeObject);
|
||||
}
|
||||
|
||||
@@ -346,8 +346,8 @@ public class RenderableManager {
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
* @see Builder::blendOrder()
|
||||
* @see Builder::priority()
|
||||
* @see Builder#blendOrder()
|
||||
* @see Builder#priority()
|
||||
* @see RenderableManager::setBlendOrderAt()
|
||||
*/
|
||||
@NonNull
|
||||
@@ -725,6 +725,10 @@ public class RenderableManager {
|
||||
nSetPriority(mNativeObject, i, priority);
|
||||
}
|
||||
|
||||
public int getPriority(@EntityInstance int i) {
|
||||
return nGetPriority(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the channel of a renderable
|
||||
*
|
||||
@@ -734,6 +738,10 @@ public class RenderableManager {
|
||||
nSetChannel(mNativeObject, i, channel);
|
||||
}
|
||||
|
||||
public int getChannel(@EntityInstance int i) {
|
||||
return nGetChannel(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes whether or not frustum culling is on.
|
||||
*
|
||||
@@ -743,6 +751,10 @@ public class RenderableManager {
|
||||
nSetCulling(mNativeObject, i, enabled);
|
||||
}
|
||||
|
||||
public boolean isCullingEnabled(@EntityInstance int i) {
|
||||
return nIsCullingEnabled(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes whether or not the large-scale fog is applied to this renderable
|
||||
* @see Builder#fog
|
||||
@@ -812,6 +824,10 @@ public class RenderableManager {
|
||||
nSetScreenSpaceContactShadows(mNativeObject, i, enabled);
|
||||
}
|
||||
|
||||
public boolean isScreenSpaceContactShadowsEnabled(@EntityInstance int i) {
|
||||
return nIsScreenSpaceContactShadowsEnabled(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the renderable can cast shadows.
|
||||
*
|
||||
@@ -932,6 +948,10 @@ public class RenderableManager {
|
||||
nSetBlendOrderAt(mNativeObject, instance, primitiveIndex, blendOrder);
|
||||
}
|
||||
|
||||
public int getBlendOrderAt(@EntityInstance int instance, @IntRange(from = 0) int primitiveIndex) {
|
||||
return nGetBlendOrderAt(mNativeObject, instance, primitiveIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes whether the blend order is global or local to this Renderable (by default).
|
||||
*
|
||||
@@ -946,6 +966,10 @@ public class RenderableManager {
|
||||
nSetGlobalBlendOrderEnabledAt(mNativeObject, instance, primitiveIndex, enabled);
|
||||
}
|
||||
|
||||
public boolean isGlobalBlendOrderEnabledAt(@EntityInstance int instance, @IntRange(from = 0) int primitiveIndex) {
|
||||
return nIsGlobalBlendOrderEnabledAt(mNativeObject, instance, primitiveIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the set of enabled attribute slots in the given primitive's VertexBuffer.
|
||||
*/
|
||||
@@ -1013,8 +1037,11 @@ public class RenderableManager {
|
||||
private static native void nSetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float cx, float cy, float cz, float ex, float ey, float ez);
|
||||
private static native void nSetLayerMask(long nativeRenderableManager, int i, int select, int value);
|
||||
private static native void nSetPriority(long nativeRenderableManager, int i, int priority);
|
||||
private static native int nGetPriority(long nativeRenderableManager, int i);
|
||||
private static native void nSetChannel(long nativeRenderableManager, int i, int channel);
|
||||
private static native int nGetChannel(long nativeRenderableManager, int i);
|
||||
private static native void nSetCulling(long nativeRenderableManager, int i, boolean enabled);
|
||||
private static native boolean nIsCullingEnabled(long nativeRenderableManager, int i);
|
||||
private static native void nSetFogEnabled(long nativeRenderableManager, int i, boolean enabled);
|
||||
private static native boolean nGetFogEnabled(long nativeRenderableManager, int i);
|
||||
private static native void nSetLightChannel(long nativeRenderableManager, int i, int channel, boolean enable);
|
||||
@@ -1022,6 +1049,7 @@ public class RenderableManager {
|
||||
private static native void nSetCastShadows(long nativeRenderableManager, int i, boolean enabled);
|
||||
private static native void nSetReceiveShadows(long nativeRenderableManager, int i, boolean enabled);
|
||||
private static native void nSetScreenSpaceContactShadows(long nativeRenderableManager, int i, boolean enabled);
|
||||
private static native boolean nIsScreenSpaceContactShadowsEnabled(long nativeRenderableManager, int i);
|
||||
private static native boolean nIsShadowCaster(long nativeRenderableManager, int i);
|
||||
private static native boolean nIsShadowReceiver(long nativeRenderableManager, int i);
|
||||
private static native void nGetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float[] center, float[] halfExtent);
|
||||
@@ -1032,6 +1060,8 @@ public class RenderableManager {
|
||||
private static native long nGetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
private static native void nSetGeometryAt(long nativeRenderableManager, int i, int primitiveIndex, int primitiveType, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int count);
|
||||
private static native void nSetBlendOrderAt(long nativeRenderableManager, int i, int primitiveIndex, int blendOrder);
|
||||
private static native int nGetBlendOrderAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
private static native void nSetGlobalBlendOrderEnabledAt(long nativeRenderableManager, int i, int primitiveIndex, boolean enabled);
|
||||
private static native boolean nIsGlobalBlendOrderEnabledAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
private static native int nGetEnabledAttributesAt(long nativeRenderableManager, int i, int primitiveIndex);
|
||||
}
|
||||
|
||||
@@ -155,6 +155,24 @@ public class Skybox {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rendering priority of the Skybox. By default, it is set to the lowest
|
||||
* priority (7) such that the Skybox is always rendered after the opaque objects,
|
||||
* to reduce overdraw when depth culling is enabled.
|
||||
*
|
||||
* @param priority clamped to the range [0..7], defaults to 4; 7 is lowest priority
|
||||
* (rendered last).
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
* @see RenderableManager.Builder#priority
|
||||
*/
|
||||
@NonNull
|
||||
public Builder priority(@IntRange(from = 0, to = 7) int priority) {
|
||||
nBuilderPriority(mNativeBuilder, priority);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>Skybox</code> object
|
||||
*
|
||||
@@ -262,6 +280,7 @@ public class Skybox {
|
||||
private static native void nBuilderShowSun(long nativeSkyboxBuilder, boolean show);
|
||||
private static native void nBuilderIntensity(long nativeSkyboxBuilder, float intensity);
|
||||
private static native void nBuilderColor(long nativeSkyboxBuilder, float r, float g, float b, float a);
|
||||
private static native void nBuilderPriority(long nativeSkyboxBuilder, int priority);
|
||||
private static native long nBuilderBuild(long nativeSkyboxBuilder, long nativeEngine);
|
||||
private static native void nSetLayerMask(long nativeSkybox, int select, int value);
|
||||
private static native int nGetLayerMask(long nativeSkybox);
|
||||
|
||||
@@ -71,6 +71,16 @@ import static com.google.android.filament.Texture.Type.COMPRESSED;
|
||||
* @see MaterialInstance#setParameter(String, Texture, TextureSampler)
|
||||
*/
|
||||
public class Texture {
|
||||
|
||||
private static Class<?> HardwareBufferClass = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
HardwareBufferClass = Class.forName("android.hardware.HardwareBuffer");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Sampler[] sSamplerValues = Sampler.values();
|
||||
private static final InternalFormat[] sInternalFormatValues = InternalFormat.values();
|
||||
|
||||
@@ -785,6 +795,17 @@ public class Texture {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the number of samples for multisample anti-aliasing.
|
||||
* @param samples number of samples, must be at least 1. Default is 1.
|
||||
* @return This Builder, for chaining calls.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder samples(@IntRange(from = 1) int samples) {
|
||||
nBuilderSamples(mNativeBuilder, samples);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the texture's internal format.
|
||||
* <p>The internal format specifies how texels are stored (which may be different from how
|
||||
@@ -1172,6 +1193,38 @@ public class Texture {
|
||||
nSetExternalImage(getNativeObject(), engine.getNativeObject(), eglImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the external image to associate with this <code>Texture</code>.
|
||||
*
|
||||
* <p>Typically, the external image is OS specific, and can be a video or camera frame.
|
||||
* There are many restrictions when using an external image as a texture, such as:</p>
|
||||
* <ul>
|
||||
* <li> only the level of detail (lod) 0 can be specified</li>
|
||||
* <li> only nearest or linear filtering is supported</li>
|
||||
* <li> the size and format of the texture is defined by the external image</li>
|
||||
* <li> only the CLAMP_TO_EDGE wrap mode is supported</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param engine {@link Engine} this texture is associated to. Must be the
|
||||
* instance passed to {@link Builder#build Builder.build()}.
|
||||
* @param externalImageRef An OS specific Object. On Android it must be a
|
||||
* <code>android.hardware.HardwareBuffer</code>
|
||||
*/
|
||||
public void setExternalImage(@NonNull Engine engine, Object externalImageRef) {
|
||||
if (HardwareBufferClass != null) {
|
||||
if (!HardwareBufferClass.isInstance(externalImageRef)) {
|
||||
throw new IllegalArgumentException("externalImageRef must be a AHardwareBuffer");
|
||||
}
|
||||
if (!nSetExternalImageByAHB(getNativeObject(), engine.getNativeObject(), externalImageRef)) {
|
||||
throw new IllegalStateException("Error setting AHardwareBuffer as external image");
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"setExternalImage(Engine, Object) not supported on this platform");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the external stream to associate with this <code>Texture</code>.
|
||||
*
|
||||
@@ -1328,6 +1381,7 @@ public class Texture {
|
||||
private static native void nBuilderFormat(long nativeBuilder, int format);
|
||||
private static native void nBuilderUsage(long nativeBuilder, int flags);
|
||||
private static native void nBuilderSwizzle(long nativeBuilder, int r, int g, int b, int a);
|
||||
private static native void nBuilderSamples(long nativeBuilder, int samples);
|
||||
private static native void nBuilderImportTexture(long nativeBuilder, long id);
|
||||
private static native void nBuilderExternal(long nativeBuilder);
|
||||
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
|
||||
@@ -1364,6 +1418,8 @@ public class Texture {
|
||||
private static native void nSetExternalImage(
|
||||
long nativeObject, long nativeEngine, long eglImage);
|
||||
|
||||
private static native boolean nSetExternalImageByAHB(long nativeTexture, long nativeObject, Object ahb);
|
||||
|
||||
private static native void nSetExternalStream(long nativeTexture,
|
||||
long nativeEngine, long nativeStream);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ package com.google.android.filament;
|
||||
* <li>ACESLegacyToneMapper</li>
|
||||
* <li>FilmicToneMapper</li>
|
||||
* <li>PBRNeutralToneMapper</li>
|
||||
* <li>GT7ToneMapper</li>
|
||||
* </ul>
|
||||
* <li>Debug/validation tone mapping operators</li>
|
||||
* <ul>
|
||||
@@ -111,6 +112,19 @@ public class ToneMapper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gran Turismo 7 tone mapping operator. This tone mapper was designed
|
||||
* to preserve the appearance of materials across lighting conditions while
|
||||
* avoiding artifacts in the highlights in high dynamic range conditions.
|
||||
* This tone mapper targets an SDR paper white value of 250 nits, with a
|
||||
* reference luminance of 100 cd/m^2 (a value of 1.0 in the HDR framebuffer).
|
||||
*/
|
||||
public static class GT7ToneMapper extends ToneMapper {
|
||||
public GT7ToneMapper() {
|
||||
super(nCreateGT7ToneMapper());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AgX tone mapping operator.
|
||||
*/
|
||||
@@ -244,6 +258,7 @@ public class ToneMapper {
|
||||
private static native long nCreateACESLegacyToneMapper();
|
||||
private static native long nCreateFilmicToneMapper();
|
||||
private static native long nCreatePBRNeutralToneMapper();
|
||||
private static native long nCreateGT7ToneMapper();
|
||||
private static native long nCreateAgxToneMapper(int look);
|
||||
private static native long nCreateGenericToneMapper(
|
||||
float contrast, float midGrayIn, float midGrayOut, float hdrMax);
|
||||
|
||||
@@ -350,6 +350,26 @@ public class View {
|
||||
nSetVisibleLayers(getNativeObject(), select & 0xFF, values & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the visible layers.
|
||||
*
|
||||
* @return a bitmask specifying which layer is visible.
|
||||
*/
|
||||
public int getVisibleLayers() {
|
||||
return nGetVisibleLayers(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables a specific layer.
|
||||
*
|
||||
* @param layer Index of the layer to enable or disable, must be between 0 and 7.
|
||||
* @param enabled True to enable the layer, false to disable it.
|
||||
*/
|
||||
public void setLayerEnabled(@IntRange(from = 0, to = 7) int layer, boolean enabled) {
|
||||
int mask = 1 << layer;
|
||||
setVisibleLayers(mask, enabled ? mask : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables shadow mapping. Enabled by default.
|
||||
*
|
||||
@@ -368,6 +388,22 @@ public class View {
|
||||
return nIsShadowingEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables frustum culling. Enabled by default.
|
||||
*
|
||||
* @param enabled true enables frustum culling, false disables it.
|
||||
*/
|
||||
public void setFrustumCullingEnabled(boolean enabled) {
|
||||
nSetFrustumCullingEnabled(getNativeObject(), enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether frustum culling is enabled
|
||||
*/
|
||||
public boolean isFrustumCullingEnabled() {
|
||||
return nIsFrustumCullingEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables screen space refraction. Enabled by default.
|
||||
*
|
||||
@@ -1322,6 +1358,9 @@ public class View {
|
||||
private static native boolean nHasCamera(long nativeView);
|
||||
private static native void nSetViewport(long nativeView, int left, int bottom, int width, int height);
|
||||
private static native void nSetVisibleLayers(long nativeView, int select, int value);
|
||||
private static native int nGetVisibleLayers(long nativeView);
|
||||
private static native void nSetFrustumCullingEnabled(long nativeView, boolean enabled);
|
||||
private static native boolean nIsFrustumCullingEnabled(long nativeView);
|
||||
private static native void nSetShadowingEnabled(long nativeView, boolean enabled);
|
||||
private static native void nSetRenderTarget(long nativeView, long nativeRenderTarget);
|
||||
private static native void nSetSampleCount(long nativeView, int count);
|
||||
@@ -1406,65 +1445,59 @@ public class View {
|
||||
* by lowering the resolution of a View, or to increase the quality when the
|
||||
* rendering is faster than the target frame rate.
|
||||
*
|
||||
* This structure can be used to specify the minimum scale factor used when
|
||||
* <p>This structure can be used to specify the minimum scale factor used when
|
||||
* lowering the resolution of a View, and the maximum scale factor used when
|
||||
* increasing the resolution for higher quality rendering. The scale factors
|
||||
* can be controlled on each X and Y axis independently. By default, all scale
|
||||
* factors are set to 1.0.
|
||||
* factors are set to 1.0.</p>
|
||||
*
|
||||
* enabled: enable or disables dynamic resolution on a View
|
||||
* <ul>
|
||||
* <li>enabled: enable or disables dynamic resolution on a View</li>
|
||||
*
|
||||
* homogeneousScaling: by default the system scales the major axis first. Set this to true
|
||||
* to force homogeneous scaling.
|
||||
* <li>homogeneousScaling: by default the system scales the major axis first. Set this to true
|
||||
* to force homogeneous scaling.</li>
|
||||
*
|
||||
* minScale: the minimum scale in X and Y this View should use
|
||||
* <li>minScale: the minimum scale in X and Y this View should use</li>
|
||||
*
|
||||
* maxScale: the maximum scale in X and Y this View should use
|
||||
* <li>maxScale: the maximum scale in X and Y this View should use</li>
|
||||
*
|
||||
* quality: upscaling quality.
|
||||
* LOW: 1 bilinear tap, Medium: 4 bilinear taps, High: 9 bilinear taps (tent)
|
||||
* <li>quality: upscaling quality.
|
||||
* LOW: 1 bilinear tap, Medium: 4 bilinear taps, High: 9 bilinear taps (tent)</li>
|
||||
* </ul>
|
||||
*
|
||||
* \note
|
||||
* <p>Note:
|
||||
* Dynamic resolution is only supported on platforms where the time to render
|
||||
* a frame can be measured accurately. On platforms where this is not supported,
|
||||
* Dynamic Resolution can't be enabled unless minScale == maxScale.
|
||||
* Dynamic Resolution can't be enabled unless <code>minScale == maxScale</code>.</p>
|
||||
*
|
||||
* @see Renderer::FrameRateOptions
|
||||
* @see Renderer.FrameRateOptions
|
||||
*
|
||||
*/
|
||||
public static class DynamicResolutionOptions {
|
||||
/**
|
||||
* minimum scale factors in x and y
|
||||
*/
|
||||
/** minimum scale factors in x and y */
|
||||
public float minScale = 0.5f;
|
||||
/**
|
||||
* maximum scale factors in x and y
|
||||
*/
|
||||
/** maximum scale factors in x and y */
|
||||
public float maxScale = 1.0f;
|
||||
/**
|
||||
* sharpness when QualityLevel::MEDIUM or higher is used [0 (disabled), 1 (sharpest)]
|
||||
*/
|
||||
/** sharpness when QualityLevel::MEDIUM or higher is used [0 (disabled), 1 (sharpest)] */
|
||||
public float sharpness = 0.9f;
|
||||
/**
|
||||
* enable or disable dynamic resolution
|
||||
*/
|
||||
/** enable or disable dynamic resolution */
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* set to true to force homogeneous scaling
|
||||
*/
|
||||
/** set to true to force homogeneous scaling */
|
||||
public boolean homogeneousScaling = false;
|
||||
/**
|
||||
* Upscaling quality
|
||||
* LOW: bilinear filtered blit. Fastest, poor quality
|
||||
* MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0
|
||||
* HIGH: AMD FidelityFX FSR1 w/ mobile optimizations
|
||||
* ULTRA: AMD FidelityFX FSR1
|
||||
* <ul>
|
||||
* <li>LOW: bilinear filtered blit. Fastest, poor quality</li>
|
||||
* <li>MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0</li>
|
||||
* <li>HIGH: AMD FidelityFX FSR1 w/ mobile optimizations</li>
|
||||
* <li>ULTRA: AMD FidelityFX FSR1</li>
|
||||
* </ul>
|
||||
* FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene.
|
||||
* Avoid FXAA and dithering.
|
||||
*
|
||||
* The default upscaling quality is set to LOW.
|
||||
* <p>The default upscaling quality is set to LOW.</p>
|
||||
*
|
||||
* caveat: currently, 'quality' is always set to LOW if the View is TRANSLUCENT.
|
||||
* <p>caveat: currently, <code>quality</code> is always set to LOW if the View is TRANSLUCENT.</p>
|
||||
*/
|
||||
@NonNull
|
||||
public QualityLevel quality = QualityLevel.LOW;
|
||||
@@ -1473,134 +1506,98 @@ public class View {
|
||||
/**
|
||||
* Options to control the bloom effect
|
||||
*
|
||||
* enabled: Enable or disable the bloom post-processing effect. Disabled by default.
|
||||
* <ul>
|
||||
* <li>enabled: Enable or disable the bloom post-processing effect. Disabled by default.</li>
|
||||
*
|
||||
* levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
|
||||
* <li>levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
|
||||
* maximum is 12. This value together with resolution influences the spread of the
|
||||
* blur effect. This value can be silently reduced to accommodate the original
|
||||
* image size.
|
||||
* image size.</li>
|
||||
*
|
||||
* resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
|
||||
* <li>resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
|
||||
* the maximum is lower of the original resolution and 4096. This parameter is
|
||||
* silently clamped to the minimum and maximum.
|
||||
* It is highly recommended that this value be smaller than the target resolution
|
||||
* after dynamic resolution is applied (horizontally and vertically).
|
||||
* after dynamic resolution is applied (horizontally and vertically).</li>
|
||||
*
|
||||
* strength: how much of the bloom is added to the original image. Between 0 and 1.
|
||||
* <li>strength: how much of the bloom is added to the original image. Between 0 and 1.</li>
|
||||
*
|
||||
* blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
|
||||
* image (true).
|
||||
* <li>blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
|
||||
* image (true).</li>
|
||||
*
|
||||
* threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
|
||||
* useful for artistic reasons and is usually needed when a dirt texture is used.
|
||||
* <li>threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
|
||||
* useful for artistic reasons and is usually needed when a dirt texture is used.</li>
|
||||
*
|
||||
* dirt: A dirt/scratch/smudges texture (that can be RGB), which gets added to the
|
||||
* <li>dirt: A dirt/scratch/smudges texture (that can be RGB), which gets added to the
|
||||
* bloom effect. Smudges are visible where bloom occurs. Threshold must be
|
||||
* enabled for the dirt effect to work properly.
|
||||
* enabled for the dirt effect to work properly.</li>
|
||||
*
|
||||
* dirtStrength: Strength of the dirt texture.
|
||||
* <li>dirtStrength: Strength of the dirt texture.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static class BloomOptions {
|
||||
public enum BlendMode {
|
||||
/**
|
||||
* Bloom is modulated by the strength parameter and added to the scene
|
||||
*/
|
||||
/** Bloom is modulated by the strength parameter and added to the scene */
|
||||
ADD,
|
||||
/**
|
||||
* Bloom is interpolated with the scene using the strength parameter
|
||||
*/
|
||||
/** Bloom is interpolated with the scene using the strength parameter */
|
||||
INTERPOLATE,
|
||||
}
|
||||
|
||||
/**
|
||||
* user provided dirt texture
|
||||
*/
|
||||
/** user provided dirt texture */
|
||||
@Nullable
|
||||
public Texture dirt = null;
|
||||
/**
|
||||
* strength of the dirt texture
|
||||
*/
|
||||
/** strength of the dirt texture */
|
||||
public float dirtStrength = 0.2f;
|
||||
/**
|
||||
* bloom's strength between 0.0 and 1.0
|
||||
*/
|
||||
/** bloom's strength between 0.0 and 1.0 */
|
||||
public float strength = 0.10f;
|
||||
/**
|
||||
* resolution of vertical axis (2^levels to 2048)
|
||||
*/
|
||||
/** resolution of vertical axis (2^levels to 2048) */
|
||||
public int resolution = 384;
|
||||
/**
|
||||
* number of blur levels (1 to 11)
|
||||
*/
|
||||
/** number of blur levels (1 to 11) */
|
||||
public int levels = 6;
|
||||
/**
|
||||
* how the bloom effect is applied
|
||||
*/
|
||||
/** how the bloom effect is applied */
|
||||
@NonNull
|
||||
public BloomOptions.BlendMode blendMode = BloomOptions.BlendMode.ADD;
|
||||
/**
|
||||
* whether to threshold the source
|
||||
*/
|
||||
/** whether to threshold the source */
|
||||
public boolean threshold = true;
|
||||
/**
|
||||
* enable or disable bloom
|
||||
*/
|
||||
/** enable or disable bloom */
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* limit highlights to this value before bloom [10, +inf]
|
||||
*/
|
||||
/** limit highlights to this value before bloom [10, +inf] */
|
||||
public float highlight = 1000.0f;
|
||||
/**
|
||||
* Bloom quality level.
|
||||
* LOW (default): use a more optimized down-sampling filter, however there can be artifacts
|
||||
* with dynamic resolution, this can be alleviated by using the homogenous mode.
|
||||
* MEDIUM: Good balance between quality and performance.
|
||||
* HIGH: In this mode the bloom resolution is automatically increased to avoid artifacts.
|
||||
* <ul>
|
||||
* <li>LOW (default): use a more optimized down-sampling filter, however there can be artifacts
|
||||
* with dynamic resolution, this can be alleviated by using the homogenous mode.</li>
|
||||
* <li>MEDIUM: Good balance between quality and performance.</li>
|
||||
* <li>HIGH: In this mode the bloom resolution is automatically increased to avoid artifacts.
|
||||
* This mode can be significantly slower on mobile, especially at high resolution.
|
||||
* This mode greatly improves the anamorphic bloom.
|
||||
* This mode greatly improves the anamorphic bloom.</li>
|
||||
* </ul>
|
||||
*/
|
||||
@NonNull
|
||||
public QualityLevel quality = QualityLevel.LOW;
|
||||
/**
|
||||
* enable screen-space lens flare
|
||||
*/
|
||||
/** enable screen-space lens flare */
|
||||
public boolean lensFlare = false;
|
||||
/**
|
||||
* enable starburst effect on lens flare
|
||||
*/
|
||||
/** enable starburst effect on lens flare */
|
||||
public boolean starburst = true;
|
||||
/**
|
||||
* amount of chromatic aberration
|
||||
*/
|
||||
/** amount of chromatic aberration */
|
||||
public float chromaticAberration = 0.005f;
|
||||
/**
|
||||
* number of flare "ghosts"
|
||||
*/
|
||||
/** number of flare "ghosts" */
|
||||
public int ghostCount = 4;
|
||||
/**
|
||||
* spacing of the ghost in screen units [0, 1[
|
||||
*/
|
||||
/** spacing of the ghost in screen units [0, 1[ */
|
||||
public float ghostSpacing = 0.6f;
|
||||
/**
|
||||
* hdr threshold for the ghosts
|
||||
*/
|
||||
/** hdr threshold for the ghosts */
|
||||
public float ghostThreshold = 10.0f;
|
||||
/**
|
||||
* thickness of halo in vertical screen units, 0 to disable
|
||||
*/
|
||||
/** thickness of halo in vertical screen units, 0 to disable */
|
||||
public float haloThickness = 0.1f;
|
||||
/**
|
||||
* radius of halo in vertical screen units [0, 0.5]
|
||||
*/
|
||||
/** radius of halo in vertical screen units [0, 0.5] */
|
||||
public float haloRadius = 0.4f;
|
||||
/**
|
||||
* hdr threshold for the halo
|
||||
*/
|
||||
/** hdr threshold for the halo */
|
||||
public float haloThreshold = 10.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to control large-scale fog in the scene. Materials can enable the `linearFog` property,
|
||||
* Options to control large-scale fog in the scene. Materials can enable the <code>linearFog</code> property,
|
||||
* which uses a simplified, linear equation for fog calculation; in this mode, the heightFalloff
|
||||
* is ignored as well as the mipmap selection in IBL or skyColor mode.
|
||||
*/
|
||||
@@ -1614,12 +1611,12 @@ public class View {
|
||||
* This can be used to exclude the skybox, which is desirable if it already contains clouds or
|
||||
* fog. The default value is +infinity which applies the fog to everything.
|
||||
*
|
||||
* Note: The SkyBox is typically at a distance of 1e19 in world space (depending on the near
|
||||
* plane distance and projection used though).
|
||||
* <p>Note: The SkyBox is typically at a distance of 1e19 in world space (depending on the near
|
||||
* plane distance and projection used though).</p>
|
||||
*/
|
||||
public float cutOffDistance = Float.POSITIVE_INFINITY;
|
||||
/**
|
||||
* fog's maximum opacity between 0 and 1. Ignored in `linearFog` mode.
|
||||
* fog's maximum opacity between 0 and 1. Ignored in <code>linearFog</code> mode.
|
||||
*/
|
||||
public float maximumOpacity = 1.0f;
|
||||
/**
|
||||
@@ -1631,11 +1628,11 @@ public class View {
|
||||
* It can be expressed as 1/H, where H is the altitude change in world units [m] that causes a
|
||||
* factor 2.78 (e) change in fog density.
|
||||
*
|
||||
* A falloff of 0 means the fog density is constant everywhere and may result is slightly
|
||||
* faster computations.
|
||||
* <p>A falloff of 0 means the fog density is constant everywhere and may result is slightly
|
||||
* faster computations.</p>
|
||||
*
|
||||
* In `linearFog` mode, only use to compute the slope of the linear equation. Completely
|
||||
* ignored if set to 0.
|
||||
* <p>In <code>linearFog</code> mode, only use to compute the slope of the linear equation. Completely
|
||||
* ignored if set to 0.</p>
|
||||
*/
|
||||
public float heightFalloff = 1.0f;
|
||||
/**
|
||||
@@ -1645,11 +1642,11 @@ public class View {
|
||||
* above one are allowed but could create a non energy-conservative fog (this is dependant
|
||||
* on the IBL's intensity as well).
|
||||
*
|
||||
* We assume that our fog has no absorption and therefore all the light it scatters out
|
||||
* <p>We assume that our fog has no absorption and therefore all the light it scatters out
|
||||
* becomes ambient light in-scattering and has lost all directionality, i.e.: scattering is
|
||||
* isotropic. This somewhat simulates Rayleigh scattering.
|
||||
* isotropic. This somewhat simulates Rayleigh scattering.</p>
|
||||
*
|
||||
* This value is used as a tint instead, when fogColorFromIbl is enabled.
|
||||
* <p>This value is used as a tint instead, when fogColorFromIbl is enabled.</p>
|
||||
*
|
||||
* @see #fogColorFromIbl
|
||||
*/
|
||||
@@ -1660,20 +1657,20 @@ public class View {
|
||||
* light is absorbed and out-scattered per unit of distance. Each unit of extinction reduces
|
||||
* the incoming light to 37% of its original value.
|
||||
*
|
||||
* Note: The extinction factor is related to the fog density, it's usually some constant K times
|
||||
* <p>Note: The extinction factor is related to the fog density, it's usually some constant K times
|
||||
* the density at sea level (more specifically at fog height). The constant K depends on
|
||||
* the composition of the fog/atmosphere.
|
||||
* the composition of the fog/atmosphere.</p>
|
||||
*
|
||||
* For historical reason this parameter is called `density`.
|
||||
* <p>For historical reason this parameter is called <code>density</code>.</p>
|
||||
*
|
||||
* In `linearFog` mode this is the slope of the linear equation if heightFalloff is set to 0.
|
||||
* <p>In <code>linearFog</code> mode this is the slope of the linear equation if heightFalloff is set to 0.
|
||||
* Otherwise, heightFalloff affects the slope calculation such that it matches the slope of
|
||||
* the standard equation at the camera height.
|
||||
* the standard equation at the camera height.</p>
|
||||
*/
|
||||
public float density = 0.1f;
|
||||
/**
|
||||
* Distance in world units [m] from the camera where the Sun in-scattering starts.
|
||||
* Ignored in `linearFog` mode.
|
||||
* Ignored in <code>linearFog</code> mode.
|
||||
*/
|
||||
public float inScatteringStart = 0.0f;
|
||||
/**
|
||||
@@ -1681,16 +1678,16 @@ public class View {
|
||||
* is scattered (by the fog) towards the camera.
|
||||
* Size of the Sun in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
|
||||
* Smaller values result is a larger scattering size.
|
||||
* Ignored in `linearFog` mode.
|
||||
* Ignored in <code>linearFog</code> mode.
|
||||
*/
|
||||
public float inScatteringSize = -1.0f;
|
||||
/**
|
||||
* The fog color will be sampled from the IBL in the view direction and tinted by `color`.
|
||||
* The fog color will be sampled from the IBL in the view direction and tinted by <code>color</code>.
|
||||
* Depending on the scene this can produce very convincing results.
|
||||
*
|
||||
* This simulates a more anisotropic phase-function.
|
||||
* <p>This simulates a more anisotropic phase-function.</p>
|
||||
*
|
||||
* `fogColorFromIbl` is ignored when skyTexture is specified.
|
||||
* <p><code>fogColorFromIbl</code> is ignored when skyTexture is specified.</p>
|
||||
*
|
||||
* @see #skyColor
|
||||
*/
|
||||
@@ -1703,11 +1700,11 @@ public class View {
|
||||
* level with a strong gaussian filter or even an irradiance filter and then generate mip
|
||||
* levels as usual. How blurred the base level is somewhat of an artistic decision.
|
||||
*
|
||||
* This simulates a more anisotropic phase-function.
|
||||
* <p>This simulates a more anisotropic phase-function.</p>
|
||||
*
|
||||
* `fogColorFromIbl` is ignored when skyTexture is specified.
|
||||
* <p><code>fogColorFromIbl</code> is ignored when skyTexture is specified.</p>
|
||||
*
|
||||
* In `linearFog` mode mipmap level 0 is always used.
|
||||
* <p>In <code>linearFog</code> mode mipmap level 0 is always used.</p>
|
||||
*
|
||||
* @see Texture
|
||||
* @see #fogColorFromIbl
|
||||
@@ -1723,9 +1720,9 @@ public class View {
|
||||
/**
|
||||
* Options to control Depth of Field (DoF) effect in the scene.
|
||||
*
|
||||
* cocScale can be used to set the depth of field blur independently of the camera
|
||||
* <p>cocScale can be used to set the depth of field blur independently of the camera
|
||||
* aperture, e.g. for artistic reasons. This can be achieved by setting:
|
||||
* cocScale = cameraAperture / desiredDoFAperture
|
||||
* cocScale = cameraAperture / desiredDoFAperture</p>
|
||||
*
|
||||
* @see Camera
|
||||
*/
|
||||
@@ -1736,59 +1733,24 @@ public class View {
|
||||
MEDIAN,
|
||||
}
|
||||
|
||||
/**
|
||||
* circle of confusion scale factor (amount of blur)
|
||||
*/
|
||||
/** circle of confusion scale factor (amount of blur) */
|
||||
public float cocScale = 1.0f;
|
||||
/**
|
||||
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
*/
|
||||
/** width/height aspect ratio of the circle of confusion (simulate anamorphic lenses) */
|
||||
public float cocAspectRatio = 1.0f;
|
||||
/**
|
||||
* maximum aperture diameter in meters (zero to disable rotation)
|
||||
*/
|
||||
/** maximum aperture diameter in meters (zero to disable rotation) */
|
||||
public float maxApertureDiameter = 0.01f;
|
||||
/**
|
||||
* enable or disable depth of field effect
|
||||
*/
|
||||
/** enable or disable depth of field effect */
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* filter to use for filling gaps in the kernel
|
||||
*/
|
||||
/** filter to use for filling gaps in the kernel */
|
||||
@NonNull
|
||||
public DepthOfFieldOptions.Filter filter = DepthOfFieldOptions.Filter.MEDIAN;
|
||||
/**
|
||||
* perform DoF processing at native resolution
|
||||
*/
|
||||
/** perform DoF processing at native resolution */
|
||||
public boolean nativeResolution = false;
|
||||
/**
|
||||
* Number of of rings used by the gather kernels. The number of rings affects quality
|
||||
* and performance. The actual number of sample per pixel is defined
|
||||
* as (ringCount * 2 - 1)^2. Here are a few commonly used values:
|
||||
* 3 rings : 25 ( 5x 5 grid)
|
||||
* 4 rings : 49 ( 7x 7 grid)
|
||||
* 5 rings : 81 ( 9x 9 grid)
|
||||
* 17 rings : 1089 (33x33 grid)
|
||||
*
|
||||
* With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings.
|
||||
*
|
||||
* Usually all three settings below are set to the same value, however, it is often
|
||||
* acceptable to use a lower ring count for the "fast tiles", which improves performance.
|
||||
* Fast tiles are regions of the screen where every pixels have a similar
|
||||
* circle-of-confusion radius.
|
||||
*
|
||||
* A value of 0 means default, which is 5 on desktop and 3 on mobile.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** number of kernel rings for foreground tiles */
|
||||
public int foregroundRingCount = 0;
|
||||
/**
|
||||
* number of kernel rings for background tiles
|
||||
*/
|
||||
/** number of kernel rings for background tiles */
|
||||
public int backgroundRingCount = 0;
|
||||
/**
|
||||
* number of kernel rings for fast tiles
|
||||
*/
|
||||
/** number of kernel rings for fast tiles */
|
||||
public int fastGatherRingCount = 0;
|
||||
/**
|
||||
* maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range.
|
||||
@@ -1806,26 +1768,16 @@ public class View {
|
||||
* Options to control the vignetting effect.
|
||||
*/
|
||||
public static class VignetteOptions {
|
||||
/**
|
||||
* high values restrict the vignette closer to the corners, between 0 and 1
|
||||
*/
|
||||
/** high values restrict the vignette closer to the corners, between 0 and 1 */
|
||||
public float midPoint = 0.5f;
|
||||
/**
|
||||
* controls the shape of the vignette, from a rounded rectangle (0.0), to an oval (0.5), to a circle (1.0)
|
||||
*/
|
||||
/** controls the shape of the vignette, from a rounded rectangle (0.0), to an oval (0.5), to a circle (1.0) */
|
||||
public float roundness = 0.5f;
|
||||
/**
|
||||
* softening amount of the vignette effect, between 0 and 1
|
||||
*/
|
||||
/** softening amount of the vignette effect, between 0 and 1 */
|
||||
public float feather = 0.5f;
|
||||
/**
|
||||
* color of the vignette effect, alpha is currently ignored
|
||||
*/
|
||||
/** color of the vignette effect, alpha is currently ignored */
|
||||
@NonNull @Size(min = 4)
|
||||
public float[] color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
/**
|
||||
* enables or disables the vignette effect
|
||||
*/
|
||||
/** enables or disables the vignette effect */
|
||||
public boolean enabled = false;
|
||||
}
|
||||
|
||||
@@ -1839,11 +1791,11 @@ public class View {
|
||||
/**
|
||||
* Sets the quality of the HDR color buffer.
|
||||
*
|
||||
* A quality of HIGH or ULTRA means using an RGB16F or RGBA16F color buffer. This means
|
||||
* <p>A quality of HIGH or ULTRA means using an RGB16F or RGBA16F color buffer. This means
|
||||
* colors in the LDR range (0..1) have a 10 bit precision. A quality of LOW or MEDIUM means
|
||||
* using an R11G11B10F opaque color buffer or an RGBA16F transparent color buffer. With
|
||||
* R11G11B10F colors in the LDR range have a precision of either 6 bits (red and green
|
||||
* channels) or 5 bits (blue channel).
|
||||
* channels) or 5 bits (blue channel).</p>
|
||||
*/
|
||||
@NonNull
|
||||
public QualityLevel hdrColorBuffer = QualityLevel.HIGH;
|
||||
@@ -1855,72 +1807,44 @@ public class View {
|
||||
*/
|
||||
public static class AmbientOcclusionOptions {
|
||||
public enum AmbientOcclusionType {
|
||||
/**
|
||||
* use Scalable Ambient Occlusion
|
||||
*/
|
||||
/** use Scalable Ambient Occlusion */
|
||||
SAO,
|
||||
/**
|
||||
* use Ground Truth-Based Ambient Occlusion
|
||||
*/
|
||||
/** use Ground Truth-Based Ambient Occlusion */
|
||||
GTAO,
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of ambient occlusion algorithm.
|
||||
*/
|
||||
/** Type of ambient occlusion algorithm. */
|
||||
@NonNull
|
||||
public AmbientOcclusionOptions.AmbientOcclusionType aoType = AmbientOcclusionOptions.AmbientOcclusionType.SAO;
|
||||
/**
|
||||
* Ambient Occlusion radius in meters, between 0 and ~10.
|
||||
*/
|
||||
/** Ambient Occlusion radius in meters, between 0 and ~10. */
|
||||
public float radius = 0.3f;
|
||||
/**
|
||||
* Controls ambient occlusion's contrast. Must be positive.
|
||||
*/
|
||||
/** Controls ambient occlusion's contrast. Must be positive. */
|
||||
public float power = 1.0f;
|
||||
/**
|
||||
* Self-occlusion bias in meters. Use to avoid self-occlusion.
|
||||
* Between 0 and a few mm. No effect when aoType set to GTAO
|
||||
*/
|
||||
public float bias = 0.0005f;
|
||||
/**
|
||||
* How each dimension of the AO buffer is scaled. Must be either 0.5 or 1.0.
|
||||
*/
|
||||
/** How each dimension of the AO buffer is scaled. Must be either 0.5 or 1.0. */
|
||||
public float resolution = 0.5f;
|
||||
/**
|
||||
* Strength of the Ambient Occlusion effect.
|
||||
*/
|
||||
/** Strength of the Ambient Occlusion effect. */
|
||||
public float intensity = 1.0f;
|
||||
/**
|
||||
* depth distance that constitute an edge for filtering
|
||||
*/
|
||||
/** depth distance that constitute an edge for filtering */
|
||||
public float bilateralThreshold = 0.05f;
|
||||
/**
|
||||
* affects # of samples used for AO and params for filtering
|
||||
*/
|
||||
/** affects # of samples used for AO and params for filtering */
|
||||
@NonNull
|
||||
public QualityLevel quality = QualityLevel.LOW;
|
||||
/**
|
||||
* affects AO smoothness. Recommend setting to HIGH when aoType set to GTAO.
|
||||
*/
|
||||
/** affects AO smoothness. Recommend setting to HIGH when aoType set to GTAO. */
|
||||
@NonNull
|
||||
public QualityLevel lowPassFilter = QualityLevel.MEDIUM;
|
||||
/**
|
||||
* affects AO buffer upsampling quality
|
||||
*/
|
||||
/** affects AO buffer upsampling quality */
|
||||
@NonNull
|
||||
public QualityLevel upsampling = QualityLevel.LOW;
|
||||
/**
|
||||
* enables or disables screen-space ambient occlusion
|
||||
*/
|
||||
/** enables or disables screen-space ambient occlusion */
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* enables bent normals computation from AO, and specular AO
|
||||
*/
|
||||
/** enables bent normals computation from AO, and specular AO */
|
||||
public boolean bentNormals = false;
|
||||
/**
|
||||
* min angle in radian to consider. No effect when aoType set to GTAO.
|
||||
*/
|
||||
/** min angle in radian to consider. No effect when aoType set to GTAO. */
|
||||
public float minHorizonAngleRad = 0.0f;
|
||||
/**
|
||||
* Screen Space Cone Tracing (SSCT) options
|
||||
@@ -2006,12 +1930,10 @@ public class View {
|
||||
* @see #setMultiSampleAntiAliasingOptions
|
||||
*/
|
||||
public static class MultiSampleAntiAliasingOptions {
|
||||
/**
|
||||
* enables or disables msaa
|
||||
*/
|
||||
/** enables or disables msaa */
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* sampleCount number of samples to use for multi-sampled anti-aliasing.\n
|
||||
* sampleCount number of samples to use for multi-sampled anti-aliasing.<br>
|
||||
* 0: treated as 1
|
||||
* 1: no anti-aliasing
|
||||
* n: sample count. Effective sample could be different depending on the
|
||||
@@ -2030,106 +1952,75 @@ public class View {
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
* <p><code>feedback</code> of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.</p>
|
||||
*
|
||||
* @see #setTemporalAntiAliasingOptions
|
||||
*/
|
||||
public static class TemporalAntiAliasingOptions {
|
||||
public enum BoxType {
|
||||
/**
|
||||
* use an AABB neighborhood
|
||||
*/
|
||||
/** use an AABB neighborhood */
|
||||
AABB,
|
||||
/**
|
||||
* use the variance of the neighborhood (not recommended)
|
||||
*/
|
||||
VARIANCE,
|
||||
/**
|
||||
* use both AABB and variance
|
||||
*/
|
||||
/** use both AABB and variance */
|
||||
AABB_VARIANCE,
|
||||
}
|
||||
|
||||
public enum BoxClipping {
|
||||
/**
|
||||
* Accurate box clipping
|
||||
*/
|
||||
/** Accurate box clipping */
|
||||
ACCURATE,
|
||||
/**
|
||||
* clamping
|
||||
*/
|
||||
/** clamping */
|
||||
CLAMP,
|
||||
/**
|
||||
* no rejections (use for debugging)
|
||||
*/
|
||||
/** no rejections (use for debugging) */
|
||||
NONE,
|
||||
}
|
||||
|
||||
public enum JitterPattern {
|
||||
/** 4-samples, rotated grid sampling */
|
||||
RGSS_X4,
|
||||
/** 4-samples, uniform grid in helix sequence */
|
||||
UNIFORM_HELIX_X4,
|
||||
/** 8-samples of halton 2,3 */
|
||||
HALTON_23_X8,
|
||||
/** 16-samples of halton 2,3 */
|
||||
HALTON_23_X16,
|
||||
/** 32-samples of halton 2,3 */
|
||||
HALTON_23_X32,
|
||||
}
|
||||
|
||||
/**
|
||||
* reconstruction filter width typically between 1 (sharper) and 2 (smoother)
|
||||
*/
|
||||
/** @deprecated has no effect. */
|
||||
public float filterWidth = 1.0f;
|
||||
/**
|
||||
* history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
*/
|
||||
/** history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA). */
|
||||
public float feedback = 0.12f;
|
||||
/**
|
||||
* texturing lod bias (typically -1 or -2)
|
||||
*/
|
||||
/** texturing lod bias (typically -1 or -2) */
|
||||
public float lodBias = -1.0f;
|
||||
/**
|
||||
* post-TAA sharpen, especially useful when upscaling is true.
|
||||
*/
|
||||
/** post-TAA sharpen, especially useful when upscaling is true. */
|
||||
public float sharpness = 0.0f;
|
||||
/**
|
||||
* enables or disables temporal anti-aliasing
|
||||
*/
|
||||
/** enables or disables temporal anti-aliasing */
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
|
||||
*/
|
||||
public boolean upscaling = false;
|
||||
/**
|
||||
* whether to filter the history buffer
|
||||
*/
|
||||
/** Upscaling factor. Disables Dynamic Resolution. [BETA] */
|
||||
public float upscaling = 1.0f;
|
||||
/** whether to filter the history buffer */
|
||||
public boolean filterHistory = true;
|
||||
/**
|
||||
* whether to apply the reconstruction filter to the input
|
||||
*/
|
||||
/** whether to apply the reconstruction filter to the input */
|
||||
public boolean filterInput = true;
|
||||
/**
|
||||
* whether to use the YcoCg color-space for history rejection
|
||||
*/
|
||||
/** whether to use the YcoCg color-space for history rejection */
|
||||
public boolean useYCoCg = false;
|
||||
/**
|
||||
* type of color gamut box
|
||||
*/
|
||||
/** set to true for HDR content */
|
||||
public boolean hdr = true;
|
||||
/** type of color gamut box */
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.BoxType boxType = TemporalAntiAliasingOptions.BoxType.AABB;
|
||||
/**
|
||||
* clipping algorithm
|
||||
*/
|
||||
/** clipping algorithm */
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.BoxClipping boxClipping = TemporalAntiAliasingOptions.BoxClipping.ACCURATE;
|
||||
/** Jitter Pattern */
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.JitterPattern jitterPattern = TemporalAntiAliasingOptions.JitterPattern.HALTON_23_X16;
|
||||
/** High values increases ghosting artefact, lower values increases jittering, range [0.75, 1.25] */
|
||||
public float varianceGamma = 1.0f;
|
||||
/**
|
||||
* adjust the feedback dynamically to reduce flickering
|
||||
*/
|
||||
/** adjust the feedback dynamically to reduce flickering */
|
||||
public boolean preventFlickering = false;
|
||||
/**
|
||||
* whether to apply history reprojection (debug option)
|
||||
*/
|
||||
/** whether to apply history reprojection (debug option) */
|
||||
public boolean historyReprojection = true;
|
||||
}
|
||||
|
||||
@@ -2138,30 +2029,22 @@ public class View {
|
||||
* @see #setScreenSpaceReflectionsOptions
|
||||
*/
|
||||
public static class ScreenSpaceReflectionsOptions {
|
||||
/**
|
||||
* ray thickness, in world units
|
||||
*/
|
||||
/** ray thickness, in world units */
|
||||
public float thickness = 0.1f;
|
||||
/**
|
||||
* bias, in world units, to prevent self-intersections
|
||||
*/
|
||||
/** bias, in world units, to prevent self-intersections */
|
||||
public float bias = 0.01f;
|
||||
/**
|
||||
* maximum distance, in world units, to raycast
|
||||
*/
|
||||
/** maximum distance, in world units, to raycast */
|
||||
public float maxDistance = 3.0f;
|
||||
/**
|
||||
* stride, in texels, for samples along the ray.
|
||||
*/
|
||||
/** stride, in texels, for samples along the ray. */
|
||||
public float stride = 2.0f;
|
||||
public boolean enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the screen-space guard band.
|
||||
* A guard band can be enabled to avoid some artifacts towards the edge of the screen when
|
||||
* <p>A guard band can be enabled to avoid some artifacts towards the edge of the screen when
|
||||
* using screen-space effects such as SSAO. Enabling the guard band reduces performance slightly.
|
||||
* Currently the guard band can only be enabled or disabled.
|
||||
* Currently the guard band can only be enabled or disabled.</p>
|
||||
*/
|
||||
public static class GuardBandOptions {
|
||||
public boolean enabled = false;
|
||||
@@ -2174,13 +2057,9 @@ public class View {
|
||||
* @see #setSampleCount
|
||||
*/
|
||||
public enum AntiAliasing {
|
||||
/**
|
||||
* no anti aliasing performed as part of post-processing
|
||||
*/
|
||||
/** no anti aliasing performed as part of post-processing */
|
||||
NONE,
|
||||
/**
|
||||
* FXAA is a low-quality but very efficient type of anti-aliasing. (default).
|
||||
*/
|
||||
/** FXAA is a low-quality but very efficient type of anti-aliasing. (default). */
|
||||
FXAA,
|
||||
}
|
||||
|
||||
@@ -2188,13 +2067,9 @@ public class View {
|
||||
* List of available post-processing dithering techniques.
|
||||
*/
|
||||
public enum Dithering {
|
||||
/**
|
||||
* No dithering
|
||||
*/
|
||||
/** No dithering */
|
||||
NONE,
|
||||
/**
|
||||
* Temporal dithering (default)
|
||||
*/
|
||||
/** Temporal dithering (default) */
|
||||
TEMPORAL,
|
||||
}
|
||||
|
||||
@@ -2203,21 +2078,13 @@ public class View {
|
||||
* @see #setShadowType
|
||||
*/
|
||||
public enum ShadowType {
|
||||
/**
|
||||
* percentage-closer filtered shadows (default)
|
||||
*/
|
||||
/** percentage-closer filtered shadows (default) */
|
||||
PCF,
|
||||
/**
|
||||
* variance shadows
|
||||
*/
|
||||
/** variance shadows */
|
||||
VSM,
|
||||
/**
|
||||
* PCF with contact hardening simulation
|
||||
*/
|
||||
/** PCF with contact hardening simulation */
|
||||
DPCF,
|
||||
/**
|
||||
* PCF with soft shadows and contact hardening
|
||||
*/
|
||||
/** PCF with soft shadows and contact hardening */
|
||||
PCSS,
|
||||
PCFd,
|
||||
}
|
||||
@@ -2225,14 +2092,14 @@ public class View {
|
||||
/**
|
||||
* View-level options for VSM Shadowing.
|
||||
* @see #setVsmShadowOptions
|
||||
* @warning This API is still experimental and subject to change.
|
||||
* <b>Warning:</b> This API is still experimental and subject to change.
|
||||
*/
|
||||
public static class VsmShadowOptions {
|
||||
/**
|
||||
* Sets the number of anisotropic samples to use when sampling a VSM shadow map. If greater
|
||||
* than 0, mipmaps will automatically be generated each frame for all lights.
|
||||
*
|
||||
* The number of anisotropic samples = 2 ^ vsmAnisotropy.
|
||||
* <p>The number of anisotropic samples = 2 ^ vsmAnisotropy.</p>
|
||||
*/
|
||||
public int anisotropy = 0;
|
||||
/**
|
||||
@@ -2266,7 +2133,7 @@ public class View {
|
||||
/**
|
||||
* View-level options for DPCF and PCSS Shadowing.
|
||||
* @see #setSoftShadowOptions
|
||||
* @warning This API is still experimental and subject to change.
|
||||
* <b>Warning:</b> This API is still experimental and subject to change.
|
||||
*/
|
||||
public static class SoftShadowOptions {
|
||||
/**
|
||||
|
||||
12
android/filament-tools/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
/.idea/caches
|
||||
/.idea/gradle.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
/.cxx
|
||||
64
android/filament-tools/build.gradle
Normal file
@@ -0,0 +1,64 @@
|
||||
plugins {
|
||||
id "de.undercouch.download" version "5.6.0"
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
|
||||
|
||||
def tools = ['matc', 'cmgen']
|
||||
|
||||
def platforms = [
|
||||
'mac': [classifier: 'osx-aarch_64', archive: "filament-v${VERSION_NAME}-mac.tgz", path: { t -> "filament/bin/${t}" }],
|
||||
'linux': [classifier: 'linux-x86_64', archive: "filament-v${VERSION_NAME}-linux.tgz", path: { t -> "filament/bin/${t}" }],
|
||||
'windows': [classifier: 'windows-x86_64', archive: "filament-v${VERSION_NAME}-windows.tgz", path: { t -> "bin/${t}.exe" }]
|
||||
]
|
||||
|
||||
platforms.each { platform, config ->
|
||||
def platformName = platform.capitalize()
|
||||
def remoteUrl = "https://github.com/google/filament/releases/download/v${VERSION_NAME}/${config.archive}"
|
||||
def downloadFile = file("${buildDir}/downloads/${config.archive}")
|
||||
def extractDir = file("${buildDir}/extracted/filament-v${VERSION_NAME}-${platform}")
|
||||
|
||||
task "downloadRelease${platformName}"(type: Download) {
|
||||
src remoteUrl
|
||||
dest downloadFile
|
||||
overwrite false
|
||||
}
|
||||
|
||||
def extractionTask = task "extractTools${platformName}"(dependsOn: "downloadRelease${platformName}", type: Copy) {
|
||||
group = "setup"
|
||||
from tarTree(resources.gzip(downloadFile))
|
||||
|
||||
// Include specific tools based on platform pattern
|
||||
include tools.collect { tool -> config.path(tool) }
|
||||
|
||||
// Flatten the path so it lands directly in 'into'
|
||||
eachFile { fcd ->
|
||||
fcd.relativePath = new RelativePath(true, fcd.name)
|
||||
}
|
||||
|
||||
into extractDir
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
tools.each { toolName ->
|
||||
create(toolName, MavenPublication) {
|
||||
artifactId = toolName
|
||||
|
||||
platforms.each { platform, config ->
|
||||
def extractDir = file("${buildDir}/extracted/filament-v${VERSION_NAME}-${platform}")
|
||||
def archivePath = config.path(toolName)
|
||||
def exeName = new File(archivePath).name
|
||||
|
||||
artifact(new File(extractDir, exeName)) {
|
||||
classifier = config.classifier
|
||||
extension = "exe"
|
||||
builtBy tasks.named("extractTools${platform.capitalize()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
android/filament-tools/gradle.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
POM_NAME=Filament
|
||||
POM_PACKAGING=exe
|
||||
@@ -22,6 +22,10 @@ add_library(image STATIC IMPORTED)
|
||||
set_target_properties(image PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
|
||||
|
||||
add_library(imageio-lite STATIC IMPORTED)
|
||||
set_target_properties(imageio-lite PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimageio-lite.a)
|
||||
|
||||
add_library(ktxreader STATIC IMPORTED)
|
||||
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
|
||||
@@ -30,6 +34,10 @@ add_library(viewer STATIC IMPORTED)
|
||||
set_target_properties(viewer PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libviewer.a)
|
||||
|
||||
add_library(imagediff STATIC IMPORTED)
|
||||
set_target_properties(imagediff PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimagediff.a)
|
||||
|
||||
add_library(civetweb STATIC IMPORTED)
|
||||
set_target_properties(civetweb PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libcivetweb.a)
|
||||
@@ -57,6 +65,7 @@ add_library(filament-utils-jni SHARED
|
||||
src/main/cpp/IBLPrefilterContext.cpp
|
||||
src/main/cpp/Utils.cpp
|
||||
src/main/cpp/Manipulator.cpp
|
||||
src/main/cpp/ImageDiff.cpp
|
||||
src/main/cpp/RemoteServer.cpp
|
||||
|
||||
${IMAGEIO_DIR}/include/imageio/ImageDecoder.h
|
||||
@@ -74,6 +83,7 @@ target_include_directories(filament-utils-jni PRIVATE
|
||||
${FILAMENT_DIR}/include
|
||||
../../filament/backend/include
|
||||
${IMAGEIO_DIR}/include
|
||||
../../libs/imagediff/include
|
||||
../../libs/utils/include)
|
||||
|
||||
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
||||
@@ -85,10 +95,13 @@ target_link_libraries(filament-utils-jni
|
||||
PRIVATE camutils
|
||||
PRIVATE iblprefilter
|
||||
PRIVATE image
|
||||
PRIVATE imageio-lite
|
||||
PRIVATE filament-jni
|
||||
PRIVATE ktxreader
|
||||
PRIVATE viewer
|
||||
PRIVATE imagediff
|
||||
PRIVATE log
|
||||
PRIVATE utils
|
||||
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
|
||||
PRIVATE jnigraphics # needed for AndroidBitmap_* functions in ImageDiff
|
||||
)
|
||||
|
||||
@@ -159,37 +159,50 @@ extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetViewerOptions(JNIEnv* env, jclass,
|
||||
jlong nativeObject, jobject result) {
|
||||
AutomationEngine* automation = (AutomationEngine*) nativeObject;
|
||||
auto options = automation->getViewerOptions();
|
||||
const auto& settings = automation->getSettings();
|
||||
const auto& options = settings.viewer;
|
||||
|
||||
const jclass klass = env->GetObjectClass(result);
|
||||
|
||||
const jfieldID cameraAperture = env->GetFieldID(klass, "cameraAperture", "F");
|
||||
const jfieldID cameraSpeed = env->GetFieldID(klass, "cameraSpeed", "F");
|
||||
const jfieldID cameraISO = env->GetFieldID(klass, "cameraISO", "F");
|
||||
const jfieldID cameraNear = env->GetFieldID(klass, "cameraNear", "F");
|
||||
const jfieldID cameraFar = env->GetFieldID(klass, "cameraFar", "F");
|
||||
const jfieldID groundShadowStrength = env->GetFieldID(klass, "groundShadowStrength", "F");
|
||||
const jfieldID groundPlaneEnabled = env->GetFieldID(klass, "groundPlaneEnabled", "Z");
|
||||
const jfieldID skyboxEnabled = env->GetFieldID(klass, "skyboxEnabled", "Z");
|
||||
const jfieldID cameraFocalLength = env->GetFieldID(klass, "cameraFocalLength", "F");
|
||||
const jfieldID cameraFocusDistance = env->GetFieldID(klass, "cameraFocusDistance", "F");
|
||||
const jfieldID autoScaleEnabled = env->GetFieldID(klass, "autoScaleEnabled", "Z");
|
||||
const jfieldID autoInstancingEnabled = env->GetFieldID(klass, "autoInstancingEnabled", "Z");
|
||||
|
||||
env->SetFloatField(result, cameraAperture, options.cameraAperture);
|
||||
env->SetFloatField(result, cameraSpeed, options.cameraSpeed);
|
||||
env->SetFloatField(result, cameraISO, options.cameraISO);
|
||||
env->SetFloatField(result, cameraNear, options.cameraNear);
|
||||
env->SetFloatField(result, cameraFar, options.cameraFar);
|
||||
env->SetFloatField(result, groundShadowStrength, options.groundShadowStrength);
|
||||
env->SetBooleanField(result, groundPlaneEnabled, options.groundPlaneEnabled);
|
||||
env->SetBooleanField(result, skyboxEnabled, options.skyboxEnabled);
|
||||
env->SetFloatField(result, cameraFocalLength, options.cameraFocalLength);
|
||||
env->SetFloatField(result, cameraFocusDistance, options.cameraFocusDistance);
|
||||
env->SetBooleanField(result, autoScaleEnabled, options.autoScaleEnabled);
|
||||
env->SetBooleanField(result, autoInstancingEnabled, options.autoInstancingEnabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetCameraSettings(JNIEnv* env, jclass,
|
||||
jlong nativeObject, jobject result) {
|
||||
AutomationEngine* automation = (AutomationEngine*) nativeObject;
|
||||
const auto& settings = automation->getSettings();
|
||||
const auto& camera = settings.camera;
|
||||
|
||||
const jclass klass = env->GetObjectClass(result);
|
||||
|
||||
const jfieldID aperture = env->GetFieldID(klass, "aperture", "F");
|
||||
const jfieldID shutterSpeed = env->GetFieldID(klass, "shutterSpeed", "F");
|
||||
const jfieldID sensitivity = env->GetFieldID(klass, "sensitivity", "F");
|
||||
const jfieldID near = env->GetFieldID(klass, "near", "F");
|
||||
const jfieldID far = env->GetFieldID(klass, "far", "F");
|
||||
const jfieldID focalLength = env->GetFieldID(klass, "focalLength", "F");
|
||||
const jfieldID focusDistance = env->GetFieldID(klass, "focusDistance", "F");
|
||||
|
||||
env->SetFloatField(result, aperture, camera.aperture);
|
||||
env->SetFloatField(result, shutterSpeed, camera.shutterSpeed);
|
||||
env->SetFloatField(result, sensitivity, camera.sensitivity);
|
||||
env->SetFloatField(result, near, camera.near);
|
||||
env->SetFloatField(result, far, camera.far);
|
||||
env->SetFloatField(result, focalLength, camera.focalLength);
|
||||
env->SetFloatField(result, focusDistance, camera.focusDistance);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetColorGrading(JNIEnv*, jclass,
|
||||
jlong nativeObject, jlong nativeEngine) {
|
||||
@@ -215,6 +228,18 @@ Java_com_google_android_filament_utils_AutomationEngine_nShouldClose(JNIEnv*, jc
|
||||
return automation->shouldClose();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetTestCount(JNIEnv*, jclass, jlong native) {
|
||||
AutomationEngine* automation = (AutomationEngine*) native;
|
||||
return (jint) automation->testCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetCurrentTest(JNIEnv*, jclass, jlong native) {
|
||||
AutomationEngine* automation = (AutomationEngine*) native;
|
||||
return (jint) automation->currentTest();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nDestroy(JNIEnv*, jclass, jlong native) {
|
||||
AutomationEngine* automation = (AutomationEngine*) native;
|
||||
|
||||
217
android/filament-utils-android/src/main/cpp/ImageDiff.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/bitmap.h>
|
||||
|
||||
#include <imagediff/ImageDiff.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace imagediff;
|
||||
using namespace utils;
|
||||
|
||||
namespace {
|
||||
|
||||
struct BitmapLock {
|
||||
JNIEnv* env;
|
||||
jobject bitmap;
|
||||
void* pixels;
|
||||
AndroidBitmapInfo info;
|
||||
|
||||
BitmapLock(JNIEnv* env, jobject bitmap) : env(env), bitmap(bitmap), pixels(nullptr) {
|
||||
if (!bitmap) return;
|
||||
if (AndroidBitmap_getInfo(env, bitmap, &info) < 0) {
|
||||
return;
|
||||
}
|
||||
if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) {
|
||||
pixels = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~BitmapLock() {
|
||||
if (pixels) {
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
bool isValid() const { return pixels != nullptr; }
|
||||
|
||||
imagediff::Bitmap toBitmap() const {
|
||||
return {
|
||||
.width = (uint32_t) info.width,
|
||||
.height = (uint32_t) info.height,
|
||||
.stride = (size_t) info.stride,
|
||||
.data = pixels
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
// Helper to convert C++ ImageDiffResult to Java Result
|
||||
jobject createResult(JNIEnv* env, ImageDiffResult const& result, bool generateDiff) {
|
||||
// Create Result class/objects
|
||||
jclass resultClass = env->FindClass("com/google/android/filament/utils/ImageDiff$Result");
|
||||
jmethodID resultCtor = env->GetMethodID(resultClass, "<init>", "()V");
|
||||
jobject resultObj = env->NewObject(resultClass, resultCtor);
|
||||
jfieldID statusField = env->GetFieldID(resultClass, "status", "Lcom/google/android/filament/utils/ImageDiff$Result$Status;");
|
||||
jfieldID failingCountField = env->GetFieldID(resultClass, "failingPixelCount", "J");
|
||||
jfieldID maxDiffField = env->GetFieldID(resultClass, "maxDiffFound", "[F");
|
||||
jfieldID diffImageField = env->GetFieldID(resultClass, "diffImage", "Landroid/graphics/Bitmap;");
|
||||
|
||||
// Map Status enum
|
||||
jclass statusEnum = env->FindClass("com/google/android/filament/utils/ImageDiff$Result$Status");
|
||||
jobject statusObj = nullptr;
|
||||
jfieldID enumField = nullptr;
|
||||
switch (result.status) {
|
||||
case ImageDiffResult::Status::PASSED:
|
||||
enumField = env->GetStaticFieldID(statusEnum, "PASSED", "Lcom/google/android/filament/utils/ImageDiff$Result$Status;");
|
||||
break;
|
||||
case ImageDiffResult::Status::SIZE_MISMATCH:
|
||||
enumField = env->GetStaticFieldID(statusEnum, "SIZE_MISMATCH", "Lcom/google/android/filament/utils/ImageDiff$Result$Status;");
|
||||
break;
|
||||
case ImageDiffResult::Status::PIXEL_DIFFERENCE:
|
||||
enumField = env->GetStaticFieldID(statusEnum, "PIXEL_DIFFERENCE", "Lcom/google/android/filament/utils/ImageDiff$Result$Status;");
|
||||
break;
|
||||
}
|
||||
statusObj = env->GetStaticObjectField(statusEnum, enumField);
|
||||
env->SetObjectField(resultObj, statusField, statusObj);
|
||||
|
||||
env->SetLongField(resultObj, failingCountField, (jlong) result.failingPixelCount);
|
||||
|
||||
jfloatArray maxDiffArray = env->NewFloatArray(4);
|
||||
env->SetFloatArrayRegion(maxDiffArray, 0, 4, result.maxDiffFound);
|
||||
env->SetObjectField(resultObj, maxDiffField, maxDiffArray);
|
||||
|
||||
if (generateDiff && result.diffImage.getWidth() > 0) {
|
||||
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
|
||||
jmethodID createBitmap = env->GetStaticMethodID(bitmapClass, "createBitmap",
|
||||
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
|
||||
|
||||
jclass configClass = env->FindClass("android/graphics/Bitmap$Config");
|
||||
jfieldID argb8888 = env->GetStaticFieldID(configClass, "ARGB_8888", "Landroid/graphics/Bitmap$Config;");
|
||||
jobject configObj = env->GetStaticObjectField(configClass, argb8888);
|
||||
|
||||
uint32_t width = result.diffImage.getWidth();
|
||||
uint32_t height = result.diffImage.getHeight();
|
||||
jobject diffBitmap = env->CallStaticObjectMethod(bitmapClass, createBitmap, (jint)width, (jint)height, configObj);
|
||||
|
||||
if (diffBitmap) {
|
||||
void* diffPixels;
|
||||
if (AndroidBitmap_lockPixels(env, diffBitmap, &diffPixels) == 0) {
|
||||
float const* src = result.diffImage.getPixelRef();
|
||||
uint8_t* dst = (uint8_t*) diffPixels;
|
||||
uint32_t channels = result.diffImage.getChannels(); // usually 4
|
||||
|
||||
for (size_t i = 0; i < width * height; ++i) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
float v = 0.0f;
|
||||
if (c < channels) v = src[i * channels + c];
|
||||
if (c == 3 && channels < 4) v = 1.0f; // Alpha 1.0 if missing
|
||||
dst[i * 4 + c] = (uint8_t) std::min(255.0f, std::max(0.0f, v * 255.0f));
|
||||
}
|
||||
}
|
||||
AndroidBitmap_unlockPixels(env, diffBitmap);
|
||||
env->SetObjectField(resultObj, diffImageField, diffBitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
Java_com_google_android_filament_utils_ImageDiff_nCompareBasic(JNIEnv* env, jclass,
|
||||
jobject refBitmap, jobject candBitmap, jint mode, jint swizzle, jint channelMask,
|
||||
jfloat maxAbsDiff, jfloat maxFailingPixelsFraction, jobject maskBitmap) {
|
||||
|
||||
BitmapLock refArg(env, refBitmap);
|
||||
BitmapLock candArg(env, candBitmap);
|
||||
BitmapLock maskArg(env, maskBitmap);
|
||||
|
||||
if (!refArg.isValid() || !candArg.isValid()) {
|
||||
ImageDiffResult emptyResult;
|
||||
emptyResult.status = ImageDiffResult::Status::SIZE_MISMATCH; // or ERROR
|
||||
return createResult(env, emptyResult, false);
|
||||
}
|
||||
|
||||
ImageDiffConfig config;
|
||||
config.mode = (ImageDiffConfig::Mode) mode;
|
||||
config.swizzle = (ImageDiffConfig::Swizzle) swizzle;
|
||||
config.channelMask = (uint8_t) channelMask;
|
||||
config.maxAbsDiff = maxAbsDiff;
|
||||
config.maxFailingPixelsFraction = maxFailingPixelsFraction;
|
||||
|
||||
imagediff::Bitmap const* maskPtr = nullptr;
|
||||
imagediff::Bitmap maskVal;
|
||||
if (maskBitmap && maskArg.isValid()) {
|
||||
maskVal = maskArg.toBitmap();
|
||||
maskPtr = &maskVal;
|
||||
}
|
||||
|
||||
bool generateDiff = true;
|
||||
ImageDiffResult result = compare(refArg.toBitmap(), candArg.toBitmap(), config, maskPtr, generateDiff);
|
||||
|
||||
return createResult(env, result, generateDiff);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
Java_com_google_android_filament_utils_ImageDiff_nCompareJson(JNIEnv* env, jclass,
|
||||
jobject refBitmap, jobject candBitmap, jstring jsonConfig, jobject maskBitmap) {
|
||||
|
||||
BitmapLock refArg(env, refBitmap);
|
||||
BitmapLock candArg(env, candBitmap);
|
||||
BitmapLock maskArg(env, maskBitmap);
|
||||
|
||||
if (!refArg.isValid() || !candArg.isValid()) {
|
||||
ImageDiffResult emptyResult;
|
||||
emptyResult.status = ImageDiffResult::Status::SIZE_MISMATCH; // or ERROR
|
||||
return createResult(env, emptyResult, false);
|
||||
}
|
||||
|
||||
ImageDiffConfig config;
|
||||
const char* nativeJson = env->GetStringUTFChars(jsonConfig, 0);
|
||||
size_t length = env->GetStringUTFLength(jsonConfig);
|
||||
|
||||
bool parsed = parseConfig(nativeJson, length, &config);
|
||||
env->ReleaseStringUTFChars(jsonConfig, nativeJson);
|
||||
|
||||
if (!parsed) {
|
||||
// Fallback to default or error?
|
||||
// We could log error.
|
||||
utils::slog.e << "ImageDiff JNI: Failed to parse JSON config" << utils::io::endl;
|
||||
ImageDiffResult errResult;
|
||||
errResult.status = ImageDiffResult::Status::PIXEL_DIFFERENCE; // assume fail
|
||||
return createResult(env, errResult, false);
|
||||
}
|
||||
|
||||
imagediff::Bitmap const* maskPtr = nullptr;
|
||||
imagediff::Bitmap maskVal;
|
||||
if (maskBitmap && maskArg.isValid()) {
|
||||
maskVal = maskArg.toBitmap();
|
||||
maskPtr = &maskVal;
|
||||
}
|
||||
|
||||
bool generateDiff = true;
|
||||
ImageDiffResult result = compare(refArg.toBitmap(), candArg.toBitmap(), config, maskPtr, generateDiff);
|
||||
|
||||
return createResult(env, result, generateDiff);
|
||||
}
|
||||
|
||||
@@ -94,20 +94,23 @@ public class AutomationEngine {
|
||||
* Allows remote control for the viewer.
|
||||
*/
|
||||
public static class ViewerOptions {
|
||||
public float cameraAperture = 16.0f;
|
||||
public float cameraSpeed = 125.0f;
|
||||
public float cameraISO = 100.0f;
|
||||
public float cameraNear = 0.1f;
|
||||
public float cameraFar = 100.0f;
|
||||
public float groundShadowStrength = 0.75f;
|
||||
public boolean groundPlaneEnabled = false;
|
||||
public boolean skyboxEnabled = true;
|
||||
public float cameraFocalLength = 28.0f;
|
||||
public float cameraFocusDistance = 0.0f;
|
||||
public boolean autoScaleEnabled = true;
|
||||
public boolean autoInstancingEnabled = false;
|
||||
}
|
||||
|
||||
public static class CameraSettings {
|
||||
public float aperture = 16.0f;
|
||||
public float shutterSpeed = 125.0f;
|
||||
public float sensitivity = 100.0f;
|
||||
public float near = 0.1f;
|
||||
public float far = 100.0f;
|
||||
public float focalLength = 28.0f;
|
||||
public float focusDistance = 10.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an automation engine from a JSON specification.
|
||||
*
|
||||
@@ -229,6 +232,13 @@ public class AutomationEngine {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public CameraSettings getCameraSettings() {
|
||||
CameraSettings result = new CameraSettings();
|
||||
nGetCameraSettings(mNativeObject, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a color grading object that corresponds to the latest settings.
|
||||
*
|
||||
@@ -261,6 +271,9 @@ public class AutomationEngine {
|
||||
*/
|
||||
public boolean shouldClose() { return nShouldClose(mNativeObject); }
|
||||
|
||||
public int getTestCount() { return nGetTestCount(mNativeObject); }
|
||||
public int getCurrentTest() { return nGetCurrentTest(mNativeObject); }
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
nDestroy(mNativeObject);
|
||||
@@ -280,9 +293,12 @@ public class AutomationEngine {
|
||||
long[] materials, long ibl, int sunlight, int[] assetLights, long lightManager,
|
||||
long scene, long renderer);
|
||||
private static native void nGetViewerOptions(long nativeObject, Object result);
|
||||
private static native void nGetCameraSettings(long nativeObject, Object result);
|
||||
private static native long nGetColorGrading(long nativeObject, long nativeEngine);
|
||||
private static native void nSignalBatchMode(long nativeObject);
|
||||
private static native void nStopRunning(long nativeObject);
|
||||
private static native boolean nShouldClose(long nativeObject);
|
||||
private static native int nGetTestCount(long nativeObject);
|
||||
private static native int nGetCurrentTest(long nativeObject);
|
||||
private static native void nDestroy(long nativeObject);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public class ImageDiff {
|
||||
public enum Mode {
|
||||
LEAF, AND, OR
|
||||
}
|
||||
|
||||
public enum Swizzle {
|
||||
RGBA, BGRA
|
||||
}
|
||||
|
||||
public static class Config {
|
||||
@NonNull
|
||||
public Mode mode = Mode.LEAF;
|
||||
@NonNull
|
||||
public Swizzle swizzle = Swizzle.RGBA;
|
||||
public int channelMask = 0xF;
|
||||
public float maxAbsDiff = 0.0f;
|
||||
public float maxFailingPixelsFraction = 0.0f;
|
||||
// Children not supported in this simple wrapper for now, can be added if needed
|
||||
}
|
||||
|
||||
public static class Result {
|
||||
public enum Status {
|
||||
PASSED,
|
||||
SIZE_MISMATCH,
|
||||
PIXEL_DIFFERENCE
|
||||
}
|
||||
|
||||
public Status status;
|
||||
public long failingPixelCount;
|
||||
public float[] maxDiffFound; // [R, G, B, A]
|
||||
public Bitmap diffImage; // Null if not generated
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two bitmaps using a configuration object.
|
||||
*
|
||||
* @param reference Golden image
|
||||
* @param candidate Actual image
|
||||
* @param config Comparison configuration
|
||||
* @param mask Optional mask (grayscale)
|
||||
* @return Result of comparison
|
||||
*/
|
||||
@NonNull
|
||||
public static Result compareBasic(@NonNull Bitmap reference, @NonNull Bitmap candidate,
|
||||
@NonNull Config config, @Nullable Bitmap mask) {
|
||||
return nCompareBasic(reference, candidate, config.mode.ordinal(), config.swizzle.ordinal(),
|
||||
config.channelMask, config.maxAbsDiff, config.maxFailingPixelsFraction, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two bitmaps using a JSON configuration string.
|
||||
*
|
||||
* @param reference Golden image
|
||||
* @param candidate Actual image
|
||||
* @param jsonConfig Comparison configuration in JSON format
|
||||
* @param mask Optional mask (grayscale)
|
||||
* @return Result of comparison
|
||||
*/
|
||||
@NonNull
|
||||
public static Result compare(@NonNull Bitmap reference, @NonNull Bitmap candidate,
|
||||
@NonNull String jsonConfig, @Nullable Bitmap mask) {
|
||||
return nCompareJson(reference, candidate, jsonConfig, mask);
|
||||
}
|
||||
|
||||
private static native Result nCompareBasic(Bitmap reference, Bitmap candidate, int mode, int swizzle,
|
||||
int channelMask, float maxAbsDiff, float maxFailingPixelsFraction, Bitmap mask);
|
||||
|
||||
private static native Result nCompareJson(Bitmap reference, Bitmap candidate, String jsonConfig, Bitmap mask);
|
||||
}
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.google.android.filament.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.MotionEvent
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceView
|
||||
@@ -26,6 +29,7 @@ import com.google.android.filament.android.UiHelper
|
||||
import com.google.android.filament.gltfio.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.nio.Buffer
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
private const val kNearPlane = 0.05f // 5 cm
|
||||
private const val kFarPlane = 1000.0f // 1 km
|
||||
@@ -119,6 +123,8 @@ class ModelViewer(
|
||||
private val target = DoubleArray(3)
|
||||
private val upward = DoubleArray(3)
|
||||
|
||||
private var debugFrameCallback: ((Bitmap) -> Unit)? = null
|
||||
|
||||
init {
|
||||
renderer = engine.createRenderer()
|
||||
scene = engine.createScene()
|
||||
@@ -305,10 +311,39 @@ class ModelViewer(
|
||||
// Render the scene, unless the renderer wants to skip the frame.
|
||||
if (renderer.beginFrame(swapChain!!, frameTimeNanos)) {
|
||||
renderer.render(view)
|
||||
|
||||
debugFrameCallback?.let {
|
||||
val viewport = view.viewport
|
||||
val bitmap = Bitmap.createBitmap(viewport.width, viewport.height,
|
||||
Bitmap.Config.ARGB_8888)
|
||||
val buffer = ByteBuffer.allocateDirect(viewport.width * viewport.height * 4)
|
||||
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
val pixelBufferDescriptor = Texture.PixelBufferDescriptor(buffer,
|
||||
Texture.Format.RGBA, Texture.Type.UBYTE, 1, 0, 0, 0, handler) {
|
||||
buffer.rewind()
|
||||
bitmap.copyPixelsFromBuffer(buffer)
|
||||
it(bitmap)
|
||||
}
|
||||
renderer.readPixels(viewport.left, viewport.bottom, viewport.width,
|
||||
viewport.height, pixelBufferDescriptor)
|
||||
debugFrameCallback = null
|
||||
}
|
||||
|
||||
renderer.endFrame()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a callback that will be invoked with the next rendered frame as a Bitmap. Note that this
|
||||
* is a one-time callback.
|
||||
*
|
||||
* @param callback callback to be invoked with a rendered frame as [Bitmap]
|
||||
*/
|
||||
fun debugGetNextFrameCallback(callback: (Bitmap) -> Unit) {
|
||||
debugFrameCallback = callback
|
||||
}
|
||||
|
||||
private fun populateScene(asset: FilamentAsset) {
|
||||
val rcm = engine.renderableManager
|
||||
var count = 0
|
||||
|
||||
@@ -6,6 +6,7 @@ option(FILAMENT_ENABLE_FGVIEWER "Enables Frame Graph Viewer" OFF)
|
||||
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
|
||||
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
|
||||
option(FILAMENT_SUPPORTS_WEBGPU "Enables WebGPU on Android" OFF)
|
||||
option(FILAMENT_SUPPORTS_WEBP_TEXTURES "Enable webp texture support on Android" OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
@@ -30,6 +31,12 @@ add_library(stb STATIC IMPORTED)
|
||||
set_target_properties(stb PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libstb.a)
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
add_library(webpdecoder STATIC IMPORTED)
|
||||
set_target_properties(webpdecoder PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libwebpdecoder.a)
|
||||
endif()
|
||||
|
||||
add_library(basis_transcoder STATIC IMPORTED)
|
||||
set_target_properties(basis_transcoder PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbasis_transcoder.a)
|
||||
@@ -81,6 +88,10 @@ set(GLTFIO_INCLUDE_DIRS
|
||||
../../libs/ktxreader/include
|
||||
)
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
list(APPEND GLTFIO_INCLUDE_DIRS ../../third_party/libwebp/src)
|
||||
endif()
|
||||
|
||||
add_library(gltfio-jni SHARED ${GLTFIO_SRCS})
|
||||
|
||||
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_DRACO_SUPPORTED=1)
|
||||
@@ -107,3 +118,6 @@ target_link_libraries(gltfio-jni
|
||||
PRIVATE perfetto # needed only when FILAMENT_ENABLE_PERFETTO is defined
|
||||
PRIVATE log # needed only when perfetto above is used
|
||||
)
|
||||
if (FILAMENT_SUPPORTS_WEBP_TEXTURES)
|
||||
target_link_libraries(gltfio-jni PRIVATE webpdecoder)
|
||||
endif()
|
||||
|
||||
@@ -128,6 +128,18 @@ Java_com_google_android_filament_gltfio_ResourceLoader_nCreateKtx2Provider(JNIEn
|
||||
return (jlong) createKtx2Provider(engine);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nIsWebpSupported(JNIEnv*, jclass) {
|
||||
return (jboolean) isWebpSupported();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateWebpProvider(JNIEnv*, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) createWebpProvider(engine);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nDestroyTextureProvider(JNIEnv*, jclass,
|
||||
jlong nativeProvider) {
|
||||
|
||||
@@ -37,6 +37,7 @@ public class ResourceLoader {
|
||||
private final long mNativeObject;
|
||||
private final long mNativeStbProvider;
|
||||
private final long mNativeKtx2Provider;
|
||||
private final long mNativeWebpProvider;
|
||||
|
||||
/**
|
||||
* Constructs a resource loader tied to the given Filament engine.
|
||||
@@ -50,9 +51,17 @@ public class ResourceLoader {
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, false);
|
||||
mNativeStbProvider = nCreateStbProvider(nativeEngine);
|
||||
mNativeKtx2Provider = nCreateKtx2Provider(nativeEngine);
|
||||
|
||||
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeStbProvider);
|
||||
nAddTextureProvider(mNativeObject, "image/png", mNativeStbProvider);
|
||||
nAddTextureProvider(mNativeObject, "image/ktx2", mNativeKtx2Provider);
|
||||
if (nIsWebpSupported()) {
|
||||
mNativeWebpProvider = nCreateWebpProvider(nativeEngine);
|
||||
nAddTextureProvider(mNativeObject, "image/webp", mNativeWebpProvider);
|
||||
}
|
||||
else {
|
||||
mNativeWebpProvider = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,9 +77,17 @@ public class ResourceLoader {
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, normalizeSkinningWeights);
|
||||
mNativeStbProvider = nCreateStbProvider(nativeEngine);
|
||||
mNativeKtx2Provider = nCreateKtx2Provider(nativeEngine);
|
||||
|
||||
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeStbProvider);
|
||||
nAddTextureProvider(mNativeObject, "image/png", mNativeStbProvider);
|
||||
nAddTextureProvider(mNativeObject, "image/ktx2", mNativeKtx2Provider);
|
||||
if (nIsWebpSupported()) {
|
||||
mNativeWebpProvider = nCreateWebpProvider(nativeEngine);
|
||||
nAddTextureProvider(mNativeObject, "image/webp", mNativeWebpProvider);
|
||||
}
|
||||
else {
|
||||
mNativeWebpProvider = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,6 +97,9 @@ public class ResourceLoader {
|
||||
nDestroyResourceLoader(mNativeObject);
|
||||
nDestroyTextureProvider(mNativeStbProvider);
|
||||
nDestroyTextureProvider(mNativeKtx2Provider);
|
||||
if (nIsWebpSupported()) {
|
||||
nDestroyTextureProvider(mNativeWebpProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,6 +211,9 @@ public class ResourceLoader {
|
||||
|
||||
private static native long nCreateStbProvider(long nativeEngine);
|
||||
private static native long nCreateKtx2Provider(long nativeEngine);
|
||||
private static native boolean nIsWebpSupported();
|
||||
private static native long nCreateWebpProvider(long nativeEngine);
|
||||
|
||||
private static native void nAddTextureProvider(long nativeLoader, String url, long nativeProvider);
|
||||
private static native void nDestroyTextureProvider(long nativeProvider);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.67.0
|
||||
VERSION_NAME=1.69.2
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -80,54 +80,12 @@ frame and the external texture are perfectly synchronized.
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
## Building Samples
|
||||
|
||||
Before you start, make sure to read [Filament's README](../../README.md). You need to be able to
|
||||
compile Filament's native library and Filament's AAR for this project. The easiest way to proceed
|
||||
is to install all the required dependencies and to run the following commands at the root of the
|
||||
source tree:
|
||||
source tree.
|
||||
|
||||
```shell
|
||||
./build.sh -p desktop -i release
|
||||
./build.sh -p android release
|
||||
```
|
||||
To build the samples, please follow the steps described in [BUILDING.md](../../BUILDING.md#android)
|
||||
|
||||
This will build all the native components and the AAR required by this sample application.
|
||||
|
||||
If you do not use the build script, you must set the `filament_tools_dir` property when invoking
|
||||
Gradle, either from the command line or from `local.properties`. This property must point to the
|
||||
distribution/install directory for desktop (produced by make/ninja install). This directory must
|
||||
contain `bin/matc` and `bin/cmgen`.
|
||||
|
||||
Example:
|
||||
```shell
|
||||
./gradlew -Pfilament_tools_dir=../../dist-release assembleDebug
|
||||
```
|
||||
|
||||
## Important: SDK location
|
||||
|
||||
Either ensure your `ANDROID_HOME` environment variable is set or make sure the root project
|
||||
contains a `local.properties` file with the `sdk.dir` property pointing to your installation of
|
||||
the Android SDK.
|
||||
|
||||
## Compiling
|
||||
|
||||
### Android Studio
|
||||
|
||||
You must use the latest stable release of Android Studio. To open the project, point Studio to the
|
||||
`android` folder. After opening the project and syncing to gradle, select the sample of your choice
|
||||
using the drop-down widget in the toolbar.
|
||||
|
||||
To compile and run each sample make sure you have selected the appropriate build variant
|
||||
(arm7, arm8, x86 or x86_64). If you are not sure you can simply select the "universal"
|
||||
variant which includes all the other ones.
|
||||
|
||||
### Command Line
|
||||
|
||||
From the `android` directory in the project root:
|
||||
|
||||
```shell
|
||||
./gradlew :samples:sample-hello-triangle:installDebug
|
||||
```
|
||||
|
||||
Replace `sample-hello-triangle` with your preferred project.
|
||||
|
||||
@@ -389,9 +389,9 @@ class MainActivity : Activity() {
|
||||
viewerContent.assetLights = modelViewer.asset?.lightEntities
|
||||
automation.applySettings(modelViewer.engine, json, viewerContent)
|
||||
modelViewer.view.colorGrading = automation.getColorGrading(modelViewer.engine)
|
||||
modelViewer.cameraFocalLength = automation.viewerOptions.cameraFocalLength
|
||||
modelViewer.cameraNear = automation.viewerOptions.cameraNear
|
||||
modelViewer.cameraFar = automation.viewerOptions.cameraFar
|
||||
modelViewer.cameraFocalLength = automation.cameraSettings.focalLength
|
||||
modelViewer.cameraNear = automation.cameraSettings.near
|
||||
modelViewer.cameraFar = automation.cameraSettings.far
|
||||
updateRootTransform()
|
||||
}
|
||||
|
||||
|
||||
35
android/samples/sample-render-validation/build.gradle
Normal file
@@ -0,0 +1,35 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(versions.jdk)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.google.android.filament.validation'
|
||||
|
||||
compileSdkVersion versions.compileSdk
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.validation"
|
||||
minSdkVersion versions.minSdk
|
||||
targetSdkVersion versions.targetSdk
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility versions.jdk
|
||||
targetCompatibility versions.jdk
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation deps.kotlin
|
||||
implementation deps.coroutines.core
|
||||
implementation project(':filament-android')
|
||||
implementation project(':gltfio-android')
|
||||
implementation project(':filament-utils-android')
|
||||
implementation project(':filament-utils-android')
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:label="Filament Validation"
|
||||
android:supportsRtl="true"
|
||||
android:largeHeap="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:theme="@android:style/Theme.NoTitleBar">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
||||
android:screenOrientation="fullSensor">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.validation
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Choreographer
|
||||
import android.view.SurfaceView
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.google.android.filament.utils.ModelViewer
|
||||
import com.google.android.filament.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
class MainActivity : Activity(), ValidationRunner.Callback {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
Utils.init()
|
||||
System.loadLibrary("filament-utils-jni")
|
||||
}
|
||||
private const val TAG = "FilamentValidation"
|
||||
}
|
||||
|
||||
private lateinit var surfaceView: SurfaceView
|
||||
private lateinit var choreographer: Choreographer
|
||||
private lateinit var modelViewer: ModelViewer
|
||||
private lateinit var statusTextView: TextView
|
||||
private var validationRunner: ValidationRunner? = null
|
||||
|
||||
// Frame callback
|
||||
private val frameScheduler = object : Choreographer.FrameCallback {
|
||||
override fun doFrame(frameTimeNanos: Long) {
|
||||
choreographer.postFrameCallback(this)
|
||||
modelViewer.render(frameTimeNanos)
|
||||
validationRunner?.onFrame(frameTimeNanos)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Simple layout
|
||||
val layout = android.widget.FrameLayout(this)
|
||||
surfaceView = SurfaceView(this)
|
||||
layout.addView(surfaceView)
|
||||
|
||||
statusTextView = TextView(this)
|
||||
statusTextView.setTextColor(0xFFFFFFFF.toInt())
|
||||
statusTextView.textSize = 16f
|
||||
statusTextView.setPadding(20, 20, 20, 20)
|
||||
statusTextView.text = "Initializing..."
|
||||
layout.addView(statusTextView)
|
||||
|
||||
setContentView(layout)
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
||||
choreographer = Choreographer.getInstance()
|
||||
modelViewer = ModelViewer(surfaceView)
|
||||
|
||||
// Check permissions?
|
||||
// We assume 'adb install -g' or permissions granted.
|
||||
// But for scoped storage we might not need PERMISSION if reading from app-specific dirs,
|
||||
// but user mentioned /sdcard/ so we need MANAGE_EXTERNAL_STORAGE or READ_EXTERNAL_STORAGE.
|
||||
// For waiting/simplicity, we just try.
|
||||
|
||||
handleIntent()
|
||||
}
|
||||
|
||||
private fun handleIntent() {
|
||||
val intent = intent
|
||||
val testConfigPath = intent.getStringExtra("test_config")
|
||||
|
||||
if (testConfigPath != null) {
|
||||
startValidation(testConfigPath)
|
||||
} else {
|
||||
statusTextView.text = "No test_config provided via Intent.\nUse -e test_config <path>"
|
||||
Log.w(TAG, "No test config provided")
|
||||
}
|
||||
}
|
||||
|
||||
private fun startValidation(configPath: String) {
|
||||
try {
|
||||
Log.i(TAG, "Parsing config from $configPath")
|
||||
val config = ConfigParser.parseFromPath(configPath)
|
||||
|
||||
val outputDir = File(getExternalFilesDir(null), "validation_results")
|
||||
Log.i(TAG, "Output dir: ${outputDir.absolutePath}")
|
||||
|
||||
validationRunner = ValidationRunner(this, modelViewer, config, outputDir)
|
||||
validationRunner?.callback = this
|
||||
validationRunner?.start()
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to start validation", e)
|
||||
statusTextView.text = "Error: ${e.message}"
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
choreographer.postFrameCallback(frameScheduler)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
}
|
||||
|
||||
override fun onTestFinished(result: ValidationRunner.TestResult) {
|
||||
runOnUiThread {
|
||||
val status = "Test ${result.name} finished: ${if(result.passed) "PASS" else "FAIL"}"
|
||||
statusTextView.text = status
|
||||
Log.i(TAG, status)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAllTestsFinished() {
|
||||
runOnUiThread {
|
||||
statusTextView.text = "All tests finished!"
|
||||
Log.i(TAG, "All tests finished")
|
||||
// Optional: Auto-close activity?
|
||||
// finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStatusChanged(status: String) {
|
||||
runOnUiThread {
|
||||
statusTextView.text = status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.validation
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
data class RenderTestConfig(
|
||||
val name: String,
|
||||
val backends: List<String>,
|
||||
val models: Map<String, String>, // name -> path
|
||||
val tests: List<TestConfig>
|
||||
)
|
||||
|
||||
data class TestConfig(
|
||||
val name: String,
|
||||
val description: String?,
|
||||
val backends: List<String>,
|
||||
val models: Set<String>,
|
||||
val rendering: JSONObject,
|
||||
val tolerance: JSONObject?
|
||||
)
|
||||
|
||||
|
||||
// See test/renderdiff/FORMAT.md for the full specification matched by this parser.
|
||||
class ConfigParser {
|
||||
companion object {
|
||||
fun parseFromPath(path: String): RenderTestConfig {
|
||||
val file = File(path)
|
||||
val jsonTxt = removeComments(file.readText())
|
||||
val json = JSONObject(jsonTxt)
|
||||
return parseRenderTestConfig(json, file.parentFile)
|
||||
}
|
||||
|
||||
private fun removeComments(json: String): String {
|
||||
return json.lines().joinToString("\n") { it.substringBefore("//") }
|
||||
}
|
||||
|
||||
private fun parseRenderTestConfig(json: JSONObject, baseDir: File?): RenderTestConfig {
|
||||
val name = json.getString("name")
|
||||
val backends = json.getJSONArray("backends").toList<String>()
|
||||
|
||||
val modelSearchPaths = json.optJSONArray("model_search_paths")?.toList<String>() ?: emptyList()
|
||||
val models = mutableMapOf<String, String>()
|
||||
|
||||
baseDir?.let { dir ->
|
||||
modelSearchPaths.forEach { searchPath ->
|
||||
val searchDir = File(dir, searchPath)
|
||||
if (searchDir.exists()) {
|
||||
searchDir.walkTopDown().filter { it.isFile && (it.extension == "glb" || it.extension == "gltf") }.forEach { file ->
|
||||
models[file.nameWithoutExtension] = file.absolutePath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val presetsJson = json.optJSONArray("presets")
|
||||
val presets = mutableMapOf<String, PresetConfig>()
|
||||
if (presetsJson != null) {
|
||||
for (i in 0 until presetsJson.length()) {
|
||||
val p = parsePreset(presetsJson.getJSONObject(i), models.keys)
|
||||
presets[p.name] = p
|
||||
}
|
||||
}
|
||||
|
||||
val testsJson = json.getJSONArray("tests")
|
||||
val tests = mutableListOf<TestConfig>()
|
||||
for (i in 0 until testsJson.length()) {
|
||||
tests.add(parseTestConfig(testsJson.getJSONObject(i), models.keys, presets, backends))
|
||||
}
|
||||
|
||||
return RenderTestConfig(name, backends, models, tests)
|
||||
}
|
||||
|
||||
private fun parsePreset(json: JSONObject, existingModels: Set<String>): PresetConfig {
|
||||
val name = json.getString("name")
|
||||
val rendering = json.getJSONObject("rendering")
|
||||
val models = json.optJSONArray("models")?.toList<String>() ?: emptyList()
|
||||
|
||||
// Validate models
|
||||
models.forEach { if (!existingModels.contains(it)) throw IllegalArgumentException("Model $it not found") }
|
||||
|
||||
val tolerance = json.optJSONObject("tolerance")
|
||||
return PresetConfig(name, rendering, models, tolerance)
|
||||
}
|
||||
|
||||
private fun parseTestConfig(
|
||||
json: JSONObject,
|
||||
existingModels: Set<String>,
|
||||
presets: Map<String, PresetConfig>,
|
||||
defaultBackends: List<String>
|
||||
): TestConfig {
|
||||
val name = json.getString("name")
|
||||
val description = json.optString("description")
|
||||
val backends = json.optJSONArray("backends")?.toList<String>() ?: defaultBackends
|
||||
|
||||
val applyPresets = json.optJSONArray("apply_presets")?.toList<String>() ?: emptyList()
|
||||
|
||||
val rendering = JSONObject()
|
||||
val combinedModels = mutableSetOf<String>()
|
||||
var lastTolerance: JSONObject? = null
|
||||
|
||||
applyPresets.forEach { presetName ->
|
||||
val preset = presets[presetName] ?: throw IllegalArgumentException("Unknown preset $presetName")
|
||||
// Merge rendering (flat copy)
|
||||
val keys = preset.rendering.keys()
|
||||
while(keys.hasNext()) {
|
||||
val k = keys.next()
|
||||
rendering.put(k, preset.rendering.get(k))
|
||||
}
|
||||
combinedModels.addAll(preset.models)
|
||||
if (preset.tolerance != null) lastTolerance = preset.tolerance
|
||||
}
|
||||
|
||||
val testRendering = json.optJSONObject("rendering")
|
||||
if (testRendering != null) {
|
||||
val keys = testRendering.keys()
|
||||
while(keys.hasNext()) {
|
||||
val k = keys.next()
|
||||
rendering.put(k, testRendering.get(k))
|
||||
}
|
||||
}
|
||||
|
||||
val testModels = json.optJSONArray("models")?.toList<String>() ?: emptyList()
|
||||
combinedModels.addAll(testModels)
|
||||
|
||||
// Validate models
|
||||
combinedModels.forEach { if (!existingModels.contains(it)) throw IllegalArgumentException("Model $it not found") }
|
||||
|
||||
val tolerance = json.optJSONObject("tolerance") ?: lastTolerance
|
||||
|
||||
return TestConfig(name, description, backends, combinedModels, rendering, tolerance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class PresetConfig(
|
||||
val name: String,
|
||||
val rendering: JSONObject,
|
||||
val models: List<String>,
|
||||
val tolerance: JSONObject?
|
||||
)
|
||||
|
||||
private inline fun <reified T> JSONArray.toList(): List<T> {
|
||||
val list = mutableListOf<T>()
|
||||
for (i in 0 until length()) {
|
||||
list.add(get(i) as T)
|
||||
}
|
||||
return list
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.validation
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.util.Log
|
||||
import com.google.android.filament.Engine
|
||||
import com.google.android.filament.Renderer
|
||||
import com.google.android.filament.View
|
||||
import com.google.android.filament.utils.AutomationEngine
|
||||
import com.google.android.filament.utils.ImageDiff
|
||||
import com.google.android.filament.utils.ModelViewer
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
class ValidationRunner(
|
||||
private val context: Context,
|
||||
private val modelViewer: ModelViewer,
|
||||
private val config: RenderTestConfig,
|
||||
private val outputDir: File
|
||||
) {
|
||||
|
||||
private var currentState = State.IDLE
|
||||
private var currentTestIndex = 0
|
||||
private var currentModelIndex = 0
|
||||
private var currentEngine: AutomationEngine? = null
|
||||
private var currentTestConfig: TestConfig? = null
|
||||
private var currentModelName: String? = null
|
||||
|
||||
private var loadStartFence: com.google.android.filament.Fence? = null
|
||||
private var loadStartTime = 0L
|
||||
|
||||
enum class State {
|
||||
IDLE,
|
||||
LOADING_MODEL,
|
||||
WAITING_FOR_FENCE,
|
||||
RUNNING_TEST,
|
||||
COMPARING
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun onTestFinished(result: TestResult)
|
||||
fun onAllTestsFinished()
|
||||
fun onStatusChanged(status: String)
|
||||
}
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
fun start() {
|
||||
if (config.tests.isEmpty()) {
|
||||
callback?.onAllTestsFinished()
|
||||
return
|
||||
}
|
||||
currentTestIndex = 0
|
||||
currentModelIndex = 0
|
||||
startTest(config.tests[0])
|
||||
}
|
||||
|
||||
private fun startTest(test: TestConfig) {
|
||||
currentTestConfig = test
|
||||
if (test.models.isEmpty()) {
|
||||
nextTest()
|
||||
return
|
||||
}
|
||||
currentModelIndex = 0
|
||||
startModel(test.models.elementAt(0))
|
||||
}
|
||||
|
||||
private fun startModel(modelName: String) {
|
||||
currentModelName = modelName
|
||||
val modelPath = config.models[modelName]
|
||||
if (modelPath == null) {
|
||||
Log.e("ValidationRunner", "Model $modelName not found")
|
||||
nextModel()
|
||||
return
|
||||
}
|
||||
|
||||
currentState = State.LOADING_MODEL
|
||||
callback?.onStatusChanged("Loading $modelName for ${currentTestConfig?.name}")
|
||||
|
||||
// Load model on main thread (required by ModelViewer)
|
||||
// We assume this is called from main thread or we dispatch
|
||||
loadModel(modelPath)
|
||||
}
|
||||
|
||||
private fun loadModel(path: String) {
|
||||
// Assume called on Main Thread
|
||||
modelViewer.destroyModel()
|
||||
try {
|
||||
val bytes = File(path).readBytes()
|
||||
val buffer = ByteBuffer.wrap(bytes)
|
||||
modelViewer.loadModelGlb(buffer)
|
||||
modelViewer.transformToUnitCube()
|
||||
loadStartFence = modelViewer.engine.createFence()
|
||||
loadStartTime = System.nanoTime()
|
||||
currentState = State.WAITING_FOR_FENCE
|
||||
} catch (e: Exception) {
|
||||
Log.e("ValidationRunner", "Failed to load $path", e)
|
||||
nextModel()
|
||||
}
|
||||
}
|
||||
|
||||
fun onFrame(frameTimeNanos: Long) {
|
||||
when (currentState) {
|
||||
State.IDLE -> {}
|
||||
State.WAITING_FOR_FENCE -> {
|
||||
loadStartFence?.let { fence ->
|
||||
if (fence.wait(com.google.android.filament.Fence.Mode.FLUSH, 0) == com.google.android.filament.Fence.FenceStatus.CONDITION_SATISFIED) {
|
||||
modelViewer.engine.destroyFence(fence)
|
||||
loadStartFence = null
|
||||
|
||||
// Compile materials (simplified)
|
||||
modelViewer.scene.forEach { entity ->
|
||||
// ... existing material compilation logic ...
|
||||
}
|
||||
|
||||
startAutomation()
|
||||
}
|
||||
}
|
||||
}
|
||||
State.RUNNING_TEST -> {
|
||||
currentEngine?.let { engine ->
|
||||
val content = AutomationEngine.ViewerContent()
|
||||
content.view = modelViewer.view
|
||||
content.renderer = modelViewer.renderer
|
||||
content.scene = modelViewer.scene
|
||||
content.lightManager = modelViewer.engine.lightManager
|
||||
|
||||
// Tick
|
||||
// Delta time?
|
||||
val deltaTime = 1.0f / 60.0f // Fixed step for consistency?
|
||||
engine.tick(modelViewer.engine, content, deltaTime)
|
||||
|
||||
if (!engine.isRunning) {
|
||||
// Test finished (for this spec)
|
||||
currentState = State.COMPARING
|
||||
captureAndCompare()
|
||||
}
|
||||
}
|
||||
}
|
||||
State.COMPARING -> {} // Busy
|
||||
State.LOADING_MODEL -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startAutomation() {
|
||||
val test = currentTestConfig!!
|
||||
val specJson = JSONObject()
|
||||
specJson.put("name", test.name)
|
||||
specJson.put("base", test.rendering)
|
||||
val fullSpec = "[${specJson.toString()}]"
|
||||
|
||||
currentEngine = AutomationEngine(fullSpec)
|
||||
val options = AutomationEngine.Options()
|
||||
options.sleepDuration = 0.0f // Minimal sleep, let frames drive it
|
||||
options.minFrameCount = 5 // Ensure some frames pass
|
||||
currentEngine?.setOptions(options)
|
||||
currentEngine?.startRunning()
|
||||
currentState = State.RUNNING_TEST
|
||||
}
|
||||
|
||||
|
||||
private fun captureAndCompare() {
|
||||
callback?.onStatusChanged("Comparing ${currentTestConfig?.name}...")
|
||||
val view = modelViewer.view
|
||||
val renderer = modelViewer.renderer
|
||||
val width = view.viewport.width
|
||||
val height = view.viewport.height
|
||||
|
||||
val buffer = ByteBuffer.allocateDirect(width * height * 4)
|
||||
|
||||
val pbd = com.google.android.filament.Texture.PixelBufferDescriptor(
|
||||
buffer,
|
||||
com.google.android.filament.Texture.Format.RGBA,
|
||||
com.google.android.filament.Texture.Type.UBYTE,
|
||||
1, 0, 0, 0, 0, // alignment, left, top, stride (0=default)
|
||||
null // handler (null = current thread? no, handler is for callback)
|
||||
) {
|
||||
// Callback when readPixels is done
|
||||
// Dispatch to background thread for comparison to avoid blocking UI?
|
||||
// "it" is undefined here? The callback interface is Runnable?
|
||||
// Kotlin lambda for Runnable.
|
||||
compareCapturedImage(buffer, width, height)
|
||||
}
|
||||
renderer.readPixels(0, 0, width, height, pbd)
|
||||
}
|
||||
|
||||
private fun compareCapturedImage(buffer: java.nio.Buffer, width: Int, height: Int) {
|
||||
// This runs on... which thread? Filament driver thread possibly.
|
||||
// We should use a helper to process.
|
||||
|
||||
val testName = currentTestConfig!!.name
|
||||
val modelName = currentModelName!!
|
||||
val backend = "opengl" // Hardcoded for now, or get from View/Engine?
|
||||
val testFullName = "${testName}.${backend}.${modelName}"
|
||||
|
||||
// Golden path
|
||||
// We expect a golden directory.
|
||||
val goldenFile = File(config.models.get(modelName)!!).parentFile.parentFile.resolve("golden/${testFullName}.png")
|
||||
// Strategy: models are in .../models/model.glb
|
||||
// Goldens are in .../golden/
|
||||
|
||||
Thread {
|
||||
try {
|
||||
// Convert buffer to Bitmap
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
bitmap.copyPixelsFromBuffer(buffer)
|
||||
|
||||
// Flip Y? ReadPixels is typically bottom-up?
|
||||
// Filament readPixels is bottom-left? YES.
|
||||
// Bitmap is top-left.
|
||||
// We need to flip.
|
||||
val matrix = android.graphics.Matrix()
|
||||
matrix.postScale(1f, -1f)
|
||||
val flipped = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)
|
||||
|
||||
var passed = false
|
||||
if (goldenFile.exists()) {
|
||||
val golden = android.graphics.BitmapFactory.decodeFile(goldenFile.absolutePath)
|
||||
if (golden != null) {
|
||||
// Populate tolerance from config
|
||||
val tol = currentTestConfig?.tolerance ?: org.json.JSONObject()
|
||||
val tolJson = tol.toString()
|
||||
|
||||
val result = ImageDiff.compare(golden, flipped, tolJson, null)
|
||||
passed = (result.status == ImageDiff.Result.Status.PASSED)
|
||||
|
||||
// Save diff if failed?
|
||||
if (!passed) {
|
||||
val diffFile = File(outputDir, "${testFullName}_diff.png")
|
||||
if (result.diffImage != null) {
|
||||
FileOutputStream(diffFile).use { out ->
|
||||
result.diffImage.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e("ValidationRunner", "Failed to load golden: ${goldenFile.absolutePath}")
|
||||
}
|
||||
} else {
|
||||
Log.w("ValidationRunner", "Golden not found: ${goldenFile.absolutePath}")
|
||||
}
|
||||
|
||||
// Save output
|
||||
val outFile = File(outputDir, "${testFullName}.png")
|
||||
FileOutputStream(outFile).use { out ->
|
||||
flipped.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
}
|
||||
|
||||
callback?.onTestFinished(TestResult(testFullName, passed))
|
||||
|
||||
// Schedule next model on main thread
|
||||
// Use Handler or View.post
|
||||
modelViewer.view.viewport
|
||||
// dispatch nextModel()
|
||||
android.os.Handler(android.os.Looper.getMainLooper()).post {
|
||||
nextModel()
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("ValidationRunner", "Comparison failed", e)
|
||||
android.os.Handler(android.os.Looper.getMainLooper()).post { nextModel() }
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun nextModel() {
|
||||
currentModelIndex++
|
||||
if (currentTestConfig != null && currentModelIndex < currentTestConfig!!.models.size) {
|
||||
startModel(currentTestConfig!!.models.elementAt(currentModelIndex))
|
||||
} else {
|
||||
nextTest()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun nextTest() {
|
||||
currentTestIndex++
|
||||
if (currentTestIndex < config.tests.size) {
|
||||
startTest(config.tests[currentTestIndex])
|
||||
} else {
|
||||
currentState = State.IDLE
|
||||
zipResults()
|
||||
callback?.onAllTestsFinished()
|
||||
}
|
||||
}
|
||||
|
||||
private fun zipResults() {
|
||||
callback?.onStatusChanged("Zipping results...")
|
||||
val zipFile = File(outputDir, "results.zip")
|
||||
try {
|
||||
java.util.zip.ZipOutputStream(java.io.FileOutputStream(zipFile)).use { zos ->
|
||||
outputDir.walkTopDown().filter { it.isFile && it.name != "results.zip" }.forEach { file ->
|
||||
val entryName = file.relativeTo(outputDir).path
|
||||
zos.putNextEntry(java.util.zip.ZipEntry(entryName))
|
||||
file.inputStream().use { it.copyTo(zos) }
|
||||
zos.closeEntry()
|
||||
}
|
||||
}
|
||||
Log.i("ValidationRunner", "Zipped results to ${zipFile.absolutePath}")
|
||||
} catch (e: Exception) {
|
||||
Log.e("ValidationRunner", "Failed to zip results", e)
|
||||
}
|
||||
}
|
||||
|
||||
data class TestResult(val name: String, val passed: Boolean)
|
||||
|
||||
12
android/samples/sample-texture-target/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
/.idea/caches
|
||||
/.idea/gradle.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
/src/main/assets
|
||||
.externalNativeBuild
|
||||
53
android/samples/sample-texture-target/build.gradle
Normal file
@@ -0,0 +1,53 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(versions.jdk)
|
||||
}
|
||||
|
||||
filamentTools {
|
||||
materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
|
||||
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
|
||||
}
|
||||
|
||||
clean.doFirst {
|
||||
delete "src/main/assets"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.google.android.filament.texturetarget'
|
||||
|
||||
compileSdkVersion versions.compileSdk
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.texturetarget"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion versions.targetSdk
|
||||
}
|
||||
|
||||
// NOTE: This is a workaround required because the AGP task collectReleaseDependencies
|
||||
// is not configuration-cache friendly yet; this is only useful for Play publication
|
||||
dependenciesInfo {
|
||||
includeInApk = false
|
||||
}
|
||||
|
||||
// We use the .filamat extension for materials compiled with matc
|
||||
// Telling aapt to not compress them allows to load them efficiently
|
||||
aaptOptions {
|
||||
noCompress 'filamat', 'ktx'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility versions.jdk
|
||||
targetCompatibility versions.jdk
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation deps.kotlin
|
||||
implementation project(':filament-android')
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.texturetarget
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.hardware.HardwareBuffer
|
||||
import android.opengl.Matrix
|
||||
import android.os.Bundle
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceView
|
||||
import android.view.animation.LinearInterpolator
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.RenderableManager.PrimitiveType
|
||||
import com.google.android.filament.VertexBuffer.AttributeType
|
||||
import com.google.android.filament.VertexBuffer.VertexAttribute
|
||||
import com.google.android.filament.android.DisplayHelper
|
||||
import com.google.android.filament.android.FilamentHelper
|
||||
import com.google.android.filament.android.UiHelper
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.channels.Channels
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class MainActivity : Activity() {
|
||||
companion object {
|
||||
init {
|
||||
Filament.init()
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var surfaceView: SurfaceView
|
||||
private lateinit var uiHelper: UiHelper
|
||||
private lateinit var displayHelper: DisplayHelper
|
||||
private lateinit var choreographer: Choreographer
|
||||
|
||||
private lateinit var engine: Engine
|
||||
private lateinit var renderer: Renderer
|
||||
private lateinit var scene: Scene
|
||||
private lateinit var view: View
|
||||
private lateinit var camera: Camera
|
||||
|
||||
private lateinit var triangleMaterial: Material
|
||||
private lateinit var texturedMaterial: Material
|
||||
private lateinit var triangleVertexBuffer: VertexBuffer
|
||||
private lateinit var triangleIndexBuffer: IndexBuffer
|
||||
private lateinit var quadVertexBuffer: VertexBuffer
|
||||
private lateinit var quadIndexBuffer: IndexBuffer
|
||||
|
||||
@Entity private var triangleRenderable = 0
|
||||
@Entity private var quadRenderable = 0
|
||||
|
||||
private var swapChain: SwapChain? = null
|
||||
|
||||
private val frameScheduler = FrameCallback()
|
||||
private val animator = ValueAnimator.ofFloat(0.0f, 360.0f)
|
||||
|
||||
private var hardwareBuffer: HardwareBuffer? = null
|
||||
private var texture: Texture? = null
|
||||
private var renderTarget: RenderTarget? = null
|
||||
|
||||
private var useExternalTexture = true
|
||||
|
||||
private lateinit var offscreenView: View
|
||||
private lateinit var offscreenCamera: Camera
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// To use set this flag with adb, run
|
||||
// adb shell am start -n com.google.android.filament.texturetarget/.MainActivity --ez useExternalTexture false
|
||||
useExternalTexture = intent.getBooleanExtra("useExternalTexture", true)
|
||||
surfaceView = SurfaceView(this)
|
||||
setContentView(surfaceView)
|
||||
choreographer = Choreographer.getInstance()
|
||||
displayHelper = DisplayHelper(this)
|
||||
setupSurfaceView()
|
||||
setupFilament()
|
||||
setupView()
|
||||
setupScene()
|
||||
}
|
||||
|
||||
private fun setupSurfaceView() {
|
||||
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
|
||||
uiHelper.renderCallback = SurfaceCallback()
|
||||
uiHelper.attachTo(surfaceView)
|
||||
}
|
||||
|
||||
private fun setupFilament() {
|
||||
engine = Engine.create()
|
||||
renderer = engine.createRenderer()
|
||||
scene = engine.createScene()
|
||||
view = engine.createView()
|
||||
camera = engine.createCamera(engine.entityManager.create())
|
||||
offscreenView = engine.createView()
|
||||
offscreenCamera = engine.createCamera(engine.entityManager.create())
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
scene.skybox = Skybox.Builder()
|
||||
.priority(0)
|
||||
.color(0.0f, 0.0f, 1.0f, 1.0f).build(engine)
|
||||
|
||||
// This is the view that will be drawn on screen.
|
||||
view.camera = camera
|
||||
view.scene = scene
|
||||
view.isPostProcessingEnabled = false
|
||||
|
||||
// This is the view that will be rendered off-screen.
|
||||
offscreenView.camera = offscreenCamera
|
||||
offscreenView.scene = scene
|
||||
offscreenView.isPostProcessingEnabled = false
|
||||
}
|
||||
|
||||
private fun setupScene() {
|
||||
loadMaterials()
|
||||
createTriangleMesh()
|
||||
createQuadMesh()
|
||||
|
||||
// layer 1: skybox
|
||||
// layer 2: triangle
|
||||
// layer 3: quad
|
||||
|
||||
triangleMaterial.defaultInstance.cullingMode = Material.CullingMode.NONE;
|
||||
texturedMaterial.defaultInstance.cullingMode = Material.CullingMode.NONE;
|
||||
|
||||
// The triangle is a regular renderable.
|
||||
triangleRenderable = EntityManager.get().create()
|
||||
RenderableManager.Builder(1)
|
||||
.geometry(0, PrimitiveType.TRIANGLES, triangleVertexBuffer, triangleIndexBuffer, 0, 3)
|
||||
.material(0, triangleMaterial.defaultInstance)
|
||||
.culling(false)
|
||||
.castShadows(false)
|
||||
.receiveShadows(false)
|
||||
.layerMask(7, 2)
|
||||
.build(engine, triangleRenderable)
|
||||
|
||||
// The quad is a regular renderable.
|
||||
quadRenderable = EntityManager.get().create()
|
||||
RenderableManager.Builder(1)
|
||||
.geometry(0, PrimitiveType.TRIANGLES, quadVertexBuffer, quadIndexBuffer, 0, 6)
|
||||
.material(0, texturedMaterial.defaultInstance)
|
||||
.culling(false)
|
||||
.castShadows(false)
|
||||
.receiveShadows(false)
|
||||
.layerMask(7, 4)
|
||||
.build(engine, quadRenderable)
|
||||
|
||||
// We only want to render the triangle in the offscreen view.
|
||||
offscreenView.setVisibleLayers(7, 3) // render skybox + triangle
|
||||
|
||||
// We only want to render the quad in the on-screen view.
|
||||
view.setVisibleLayers(7, 4) // render quad only
|
||||
|
||||
scene.addEntity(triangleRenderable)
|
||||
scene.addEntity(quadRenderable)
|
||||
|
||||
startAnimation()
|
||||
}
|
||||
|
||||
private fun loadMaterials() {
|
||||
readUncompressedAsset("materials/baked_color.filamat").let {
|
||||
triangleMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
|
||||
}
|
||||
|
||||
if (useExternalTexture) {
|
||||
readUncompressedAsset("materials/texturedExternal.filamat").let {
|
||||
texturedMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
|
||||
}
|
||||
} else {
|
||||
readUncompressedAsset("materials/textured.filamat").let {
|
||||
texturedMaterial = Material.Builder().payload(it, it.remaining()).build(engine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTriangleMesh() {
|
||||
val intSize = 4
|
||||
val floatSize = 4
|
||||
val shortSize = 2
|
||||
val vertexSize = 3 * floatSize + intSize
|
||||
|
||||
data class Vertex(val x: Float, val y: Float, val z: Float, val color: Int)
|
||||
fun ByteBuffer.put(v: Vertex): ByteBuffer {
|
||||
putFloat(v.x)
|
||||
putFloat(v.y)
|
||||
putFloat(v.z)
|
||||
putInt(v.color)
|
||||
return this
|
||||
}
|
||||
|
||||
val vertexCount = 3
|
||||
val a1 = PI * 2.0 / 3.0
|
||||
val a2 = PI * 4.0 / 3.0
|
||||
|
||||
val vertexData = ByteBuffer.allocate(vertexCount * vertexSize)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.put(Vertex(1.0f, 0.0f, 0.0f, 0xffff0000.toInt()))
|
||||
.put(Vertex(cos(a1).toFloat(), sin(a1).toFloat(), 0.0f, 0xff00ff00.toInt()))
|
||||
.put(Vertex(cos(a2).toFloat(), sin(a2).toFloat(), 0.0f, 0xff0000ff.toInt()))
|
||||
.flip()
|
||||
|
||||
triangleVertexBuffer = VertexBuffer.Builder()
|
||||
.bufferCount(1)
|
||||
.vertexCount(vertexCount)
|
||||
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT3, 0, vertexSize)
|
||||
.attribute(VertexAttribute.COLOR, 0, AttributeType.UBYTE4, 3 * floatSize, vertexSize)
|
||||
.normalized(VertexAttribute.COLOR)
|
||||
.build(engine)
|
||||
triangleVertexBuffer.setBufferAt(engine, 0, vertexData)
|
||||
|
||||
val indexData = ByteBuffer.allocate(vertexCount * shortSize)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.putShort(0)
|
||||
.putShort(1)
|
||||
.putShort(2)
|
||||
.flip()
|
||||
|
||||
triangleIndexBuffer = IndexBuffer.Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
|
||||
.build(engine)
|
||||
triangleIndexBuffer.setBuffer(engine, indexData)
|
||||
}
|
||||
|
||||
private fun createQuadMesh() {
|
||||
val floatSize = 4
|
||||
val shortSize = 2
|
||||
val vertexSize = (2 * floatSize) + (2 * floatSize) // position + UV
|
||||
|
||||
data class Vertex(val x: Float, val y: Float, val u: Float, val v: Float)
|
||||
fun ByteBuffer.put(v: Vertex): ByteBuffer {
|
||||
putFloat(v.x)
|
||||
putFloat(v.y)
|
||||
putFloat(v.u)
|
||||
putFloat(v.v)
|
||||
return this
|
||||
}
|
||||
|
||||
val vertexCount = 4
|
||||
val vertexData = ByteBuffer.allocate(vertexCount * vertexSize)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.put(Vertex(-1.0f, -1.0f, 0.0f, 0.0f))
|
||||
.put(Vertex( 1.0f, -1.0f, 1.0f, 0.0f))
|
||||
.put(Vertex( 1.0f, 1.0f, 1.0f, 1.0f))
|
||||
.put(Vertex(-1.0f, 1.0f, 0.0f, 1.0f))
|
||||
.flip()
|
||||
|
||||
quadVertexBuffer = VertexBuffer.Builder()
|
||||
.bufferCount(1)
|
||||
.vertexCount(vertexCount)
|
||||
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, vertexSize)
|
||||
.attribute(VertexAttribute.UV0, 0, AttributeType.FLOAT2, 2 * floatSize, vertexSize)
|
||||
.build(engine)
|
||||
quadVertexBuffer.setBufferAt(engine, 0, vertexData)
|
||||
|
||||
val indexData = ByteBuffer.allocate(6 * shortSize)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.putShort(0).putShort(1).putShort(2)
|
||||
.putShort(0).putShort(2).putShort(3)
|
||||
.flip()
|
||||
|
||||
quadIndexBuffer = IndexBuffer.Builder()
|
||||
.indexCount(6)
|
||||
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
|
||||
.build(engine)
|
||||
quadIndexBuffer.setBuffer(engine, indexData)
|
||||
}
|
||||
|
||||
private fun startAnimation() {
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.duration = 4000
|
||||
animator.repeatMode = ValueAnimator.RESTART
|
||||
animator.repeatCount = ValueAnimator.INFINITE
|
||||
animator.addUpdateListener { a ->
|
||||
val transformMatrix = FloatArray(16)
|
||||
Matrix.setRotateM(transformMatrix, 0, -(a.animatedValue as Float), 0.0f, 0.0f, 1.0f)
|
||||
val tcm = engine.transformManager
|
||||
tcm.setTransform(tcm.getInstance(triangleRenderable), transformMatrix)
|
||||
}
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
choreographer.postFrameCallback(frameScheduler)
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
animator.cancel()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
animator.cancel()
|
||||
uiHelper.detach()
|
||||
|
||||
// Destroy all renderables.
|
||||
scene.remove(triangleRenderable)
|
||||
scene.remove(quadRenderable)
|
||||
|
||||
// Destroy all resources.
|
||||
engine.destroyEntity(triangleRenderable)
|
||||
engine.destroyEntity(quadRenderable)
|
||||
engine.destroyRenderer(renderer)
|
||||
engine.destroyVertexBuffer(triangleVertexBuffer)
|
||||
engine.destroyIndexBuffer(triangleIndexBuffer)
|
||||
engine.destroyVertexBuffer(quadVertexBuffer)
|
||||
engine.destroyIndexBuffer(quadIndexBuffer)
|
||||
engine.destroyMaterial(triangleMaterial)
|
||||
engine.destroyMaterial(texturedMaterial)
|
||||
engine.destroyView(view)
|
||||
engine.destroyView(offscreenView)
|
||||
engine.destroyScene(scene)
|
||||
engine.destroyCameraComponent(camera.entity)
|
||||
engine.destroyCameraComponent(offscreenCamera.entity)
|
||||
renderTarget?.let { engine.destroyRenderTarget(it) }
|
||||
texture?.let { engine.destroyTexture(it) }
|
||||
hardwareBuffer?.close()
|
||||
|
||||
val entityManager = EntityManager.get()
|
||||
entityManager.destroy(triangleRenderable)
|
||||
entityManager.destroy(quadRenderable)
|
||||
entityManager.destroy(camera.entity)
|
||||
entityManager.destroy(offscreenCamera.entity)
|
||||
|
||||
engine.destroy()
|
||||
}
|
||||
|
||||
inner class FrameCallback : Choreographer.FrameCallback {
|
||||
override fun doFrame(frameTimeNanos: Long) {
|
||||
choreographer.postFrameCallback(this)
|
||||
if (uiHelper.isReadyToRender) {
|
||||
if (renderer.beginFrame(swapChain!!, frameTimeNanos)) {
|
||||
// Render the triangle to the texture.
|
||||
renderer.render(offscreenView)
|
||||
// Render the quad to the screen.
|
||||
renderer.render(view)
|
||||
renderer.endFrame()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class SurfaceCallback : UiHelper.RendererCallback {
|
||||
override fun onNativeWindowChanged(surface: Surface) {
|
||||
swapChain?.let { engine.destroySwapChain(it) }
|
||||
swapChain = engine.createSwapChain(surface, uiHelper.swapChainFlags)
|
||||
displayHelper.attach(renderer, surfaceView.display)
|
||||
}
|
||||
|
||||
override fun onDetachedFromSurface() {
|
||||
displayHelper.detach()
|
||||
swapChain?.let {
|
||||
engine.destroySwapChain(it)
|
||||
engine.flushAndWait()
|
||||
swapChain = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResized(width: Int, height: Int) {
|
||||
// On-screen camera
|
||||
val zoom = 1.0
|
||||
val aspect = width.toDouble() / height.toDouble()
|
||||
camera.setProjection(Camera.Projection.ORTHO, -aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0)
|
||||
view.viewport = Viewport(0, 0, width, height)
|
||||
|
||||
// Off-screen camera
|
||||
val offscreenZoom = 1.5
|
||||
offscreenCamera.setProjection(Camera.Projection.ORTHO,
|
||||
-aspect * offscreenZoom, aspect * offscreenZoom,
|
||||
-offscreenZoom, offscreenZoom, 0.0, 10.0)
|
||||
offscreenView.viewport = Viewport(0, 0, width, height)
|
||||
|
||||
// If we have a render target, destroy it.
|
||||
renderTarget?.let { engine.destroyRenderTarget(it) }
|
||||
texture?.let { engine.destroyTexture(it) }
|
||||
hardwareBuffer?.close()
|
||||
|
||||
if (useExternalTexture) {
|
||||
// Create a new render target.
|
||||
hardwareBuffer = HardwareBuffer.create(width, height,
|
||||
HardwareBuffer.RGBA_8888, 1,
|
||||
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT)
|
||||
|
||||
texture = Texture.Builder()
|
||||
.width(width)
|
||||
.height(height)
|
||||
.usage(Texture.Usage.COLOR_ATTACHMENT or Texture.Usage.SAMPLEABLE)
|
||||
.sampler(Texture.Sampler.SAMPLER_EXTERNAL)
|
||||
.format(Texture.InternalFormat.RGBA8)
|
||||
.external()
|
||||
.build(engine)
|
||||
|
||||
texture!!.setExternalImage(engine, hardwareBuffer!!)
|
||||
} else {
|
||||
texture = Texture.Builder()
|
||||
.width(width)
|
||||
.height(height)
|
||||
.levels(1)
|
||||
.usage(Texture.Usage.COLOR_ATTACHMENT or Texture.Usage.SAMPLEABLE)
|
||||
.format(Texture.InternalFormat.RGBA8)
|
||||
.build(engine)
|
||||
}
|
||||
|
||||
renderTarget = RenderTarget.Builder()
|
||||
.texture(RenderTarget.AttachmentPoint.COLOR, texture!!)
|
||||
.build(engine)
|
||||
|
||||
offscreenView.renderTarget = renderTarget
|
||||
// Set the texture on the quad material.
|
||||
texturedMaterial.defaultInstance.setParameter("texture", texture!!,
|
||||
TextureSampler(TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR,
|
||||
TextureSampler.WrapMode.CLAMP_TO_EDGE))
|
||||
FilamentHelper.synchronizePendingFrames(engine)
|
||||
}
|
||||
}
|
||||
|
||||
private fun readUncompressedAsset(assetName: String): ByteBuffer {
|
||||
assets.openFd(assetName).use { fd ->
|
||||
val input = fd.createInputStream()
|
||||
val dst = ByteBuffer.allocate(fd.length.toInt())
|
||||
val src = Channels.newChannel(input)
|
||||
src.read(dst)
|
||||
src.close()
|
||||
return dst.apply { rewind() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
material {
|
||||
name : baked_color,
|
||||
shadingModel : unlit,
|
||||
requires : [
|
||||
color
|
||||
]
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
// You must always call the prepareMaterial() function
|
||||
prepareMaterial(material);
|
||||
|
||||
// We set the material's color to the color interpolated from
|
||||
// the model's vertices
|
||||
material.baseColor = getColor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
material {
|
||||
name : textured,
|
||||
shadingModel : unlit,
|
||||
parameters : [
|
||||
{
|
||||
type : sampler2d,
|
||||
name : texture
|
||||
}
|
||||
],
|
||||
requires: [
|
||||
uv0
|
||||
]
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor = texture(materialParams_texture, uvToRenderTargetUV(getUV0()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
material {
|
||||
name : textured,
|
||||
shadingModel : unlit,
|
||||
parameters : [
|
||||
{
|
||||
type : samplerExternal,
|
||||
name : texture
|
||||
}
|
||||
],
|
||||
requires: [
|
||||
uv0
|
||||
]
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor = texture(materialParams_texture, uvToRenderTargetUV(getUV0()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Texture Target</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -3,6 +3,7 @@ include ':filament-android'
|
||||
include ':filamat-android'
|
||||
include ':gltfio-android'
|
||||
include ':filament-utils-android'
|
||||
include ':filament-tools'
|
||||
|
||||
// Samples
|
||||
include ':samples:sample-gltf-viewer'
|
||||
@@ -17,7 +18,9 @@ include ':samples:sample-multi-view'
|
||||
include ':samples:sample-page-curl'
|
||||
include ':samples:sample-stream-test'
|
||||
include ':samples:sample-texture-view'
|
||||
include ':samples:sample-texture-target'
|
||||
include ':samples:sample-textured-object'
|
||||
include ':samples:sample-transparent-view'
|
||||
include ':samples:sample-render-validation'
|
||||
|
||||
rootProject.name = 'filament'
|
||||
|
||||
29
build.sh
@@ -158,7 +158,7 @@ function print_fgviewer_help {
|
||||
}
|
||||
|
||||
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g | cut -f 1 -d ".")}
|
||||
FILAMENT_NDK_VERSION=$(cat `dirname $0`/build/common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g | cut -f 1 -d ".")
|
||||
|
||||
# Internal variables
|
||||
ISSUE_CLEAN=false
|
||||
@@ -214,8 +214,6 @@ ENABLE_PERFETTO=""
|
||||
|
||||
BACKEND_DEBUG_FLAG_OPTION=""
|
||||
|
||||
STEREOSCOPIC_OPTION=""
|
||||
|
||||
OSMESA_OPTION=""
|
||||
|
||||
IOS_BUILD_SIMULATOR=false
|
||||
@@ -316,7 +314,6 @@ function build_desktop_target {
|
||||
${ASAN_UBSAN_OPTION} \
|
||||
${COVERAGE_OPTION} \
|
||||
${BACKEND_DEBUG_FLAG_OPTION} \
|
||||
${STEREOSCOPIC_OPTION} \
|
||||
${OSMESA_OPTION} \
|
||||
${architectures} \
|
||||
../..
|
||||
@@ -455,7 +452,6 @@ function build_android_target {
|
||||
${VULKAN_ANDROID_OPTION} \
|
||||
${WEBGPU_OPTION} \
|
||||
${BACKEND_DEBUG_FLAG_OPTION} \
|
||||
${STEREOSCOPIC_OPTION} \
|
||||
${ENABLE_PERFETTO} \
|
||||
../..
|
||||
ln -sf "out/cmake-android-${lc_target}-${arch}/compile_commands.json" \
|
||||
@@ -556,11 +552,14 @@ function build_android {
|
||||
archive_android "Release"
|
||||
fi
|
||||
|
||||
local root_dir=$(pwd)
|
||||
|
||||
pushd android > /dev/null
|
||||
|
||||
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.tools-dir=${root_dir}/out/debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${VULKAN_ANDROID_GRADLE_OPTION} \
|
||||
${WEBGPU_ANDROID_GRADLE_OPTION} \
|
||||
@@ -573,6 +572,7 @@ function build_android {
|
||||
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.tools-dir=${root_dir}/out/debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${WEBGPU_ANDROID_GRADLE_OPTION} \
|
||||
:filamat-android:assembleDebug
|
||||
@@ -581,6 +581,7 @@ function build_android {
|
||||
for sample in ${ANDROID_SAMPLES}; do
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.tools-dir=${root_dir}/out/debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${MATOPT_GRADLE_OPTION} \
|
||||
:samples:${sample}:assembleDebug
|
||||
@@ -613,6 +614,7 @@ function build_android {
|
||||
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.tools-dir=${root_dir}/out/release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${VULKAN_ANDROID_GRADLE_OPTION} \
|
||||
${WEBGPU_ANDROID_GRADLE_OPTION} \
|
||||
@@ -625,6 +627,7 @@ function build_android {
|
||||
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.tools-dir=${root_dir}/out/release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${WEBGPU_ANDROID_GRADLE_OPTION} \
|
||||
:filamat-android:assembleRelease
|
||||
@@ -633,6 +636,7 @@ function build_android {
|
||||
for sample in ${ANDROID_SAMPLES}; do
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.tools-dir=${root_dir}/out/release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${MATOPT_GRADLE_OPTION} \
|
||||
:samples:${sample}:assembleRelease
|
||||
@@ -689,7 +693,6 @@ function build_ios_target {
|
||||
${WEBGPU_OPTION} \
|
||||
${MATDBG_OPTION} \
|
||||
${MATOPT_OPTION} \
|
||||
${STEREOSCOPIC_OPTION} \
|
||||
../..
|
||||
ln -sf "out/cmake-ios-${lc_target}-${arch}/compile_commands.json" \
|
||||
../../compile_commands.json
|
||||
@@ -1003,20 +1006,6 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:Py:" opt; do
|
||||
;;
|
||||
x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}"
|
||||
;;
|
||||
S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in
|
||||
instanced)
|
||||
STEREOSCOPIC_OPTION="-DFILAMENT_SAMPLES_STEREO_TYPE=instanced"
|
||||
;;
|
||||
multiview)
|
||||
STEREOSCOPIC_OPTION="-DFILAMENT_SAMPLES_STEREO_TYPE=multiview"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown stereoscopic type ${OPTARG}"
|
||||
echo "Type must be one of [instanced|multiview]"
|
||||
echo ""
|
||||
exit 1
|
||||
esac
|
||||
;;
|
||||
X) OSMESA_OPTION="-DFILAMENT_OSMESA_PATH=${OPTARG}"
|
||||
;;
|
||||
y)
|
||||
|
||||
@@ -18,8 +18,8 @@ if [[ "$GITHUB_WORKFLOW" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Unless explicitly specified, NDK version will be set to match exactly the required one
|
||||
FILAMENT_NDK_VERSION=${GITHUB_NDK_VERSION:-27.0.11718014}
|
||||
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
|
||||
FILAMENT_NDK_VERSION=$(cat `dirname $0`/../common/versions | grep GITHUB_NDK_VERSION | sed s/GITHUB_NDK_VERSION=//g)
|
||||
|
||||
(! grep "${FILAMENT_NDK_VERSION}" `dirname $0`/../../android/build.gradle > /dev/null) &&
|
||||
echo "Mismatch of NDK versions: want ${FILAMENT_NDK_VERSION} and not found in android/build.gradle" &&
|
||||
|
||||
@@ -34,6 +34,11 @@ if [[ "$TARGET" == "presubmit" ]]; then
|
||||
BUILD_RELEASE=release
|
||||
fi
|
||||
|
||||
if [[ "$TARGET" == "presubmit-with-test" ]]; then
|
||||
BUILD_RELEASE=release
|
||||
RUN_TESTS=-u
|
||||
fi
|
||||
|
||||
if [[ "$TARGET" == "debug" ]]; then
|
||||
BUILD_DEBUG=debug
|
||||
GENERATE_ARCHIVES=-a
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
libs/viewer/test_settings
|
||||
filament/test/test_filament --gtest_filter=-FilamentTest.FroxelData:FilamentExposureWithEngineTest.SetExposure:FilamentExposureWithEngineTest.ComputeEV100:RenderingTest.*
|
||||
filament/test/test_material_parser
|
||||
libs/math/test_math
|
||||
libs/image/test_image compare libs/image/tests/reference/
|
||||
libs/utils/test_utils
|
||||
|
||||
@@ -3,7 +3,7 @@ GITHUB_CMAKE_VERSION=3.22.1
|
||||
GITHUB_NINJA_VERSION=1.10.2
|
||||
GITHUB_MESA_VERSION=24.2.1
|
||||
GITHUB_LLVM_VERSION=16
|
||||
GITHUB_NDK_VERSION=27.0.11718014
|
||||
GITHUB_NDK_VERSION=29.0.14206865
|
||||
GITHUB_EMSDK_VERSION=3.1.60
|
||||
GITHUB_VULKANSDK_VERSION=1.4.321.0
|
||||
GITHUB_GLTF_SAMPLE_ASSETS_COMMIT=d441dfdb87413ff412c620849a649d61789a470f
|
||||
GITHUB_GLTF_SAMPLE_ASSETS_COMMIT=d441dfdb87413ff412c620849a649d61789a470f
|
||||
|
||||
@@ -75,7 +75,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
# C_FLAGS += -Wl,-pie
|
||||
# CXX_FLAGS += -lstdc++
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -mcpu=cortex-a57" CACHE STRING "Toolchain CFLAGS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -march=armv8-a -mtune=cortex-a78" CACHE STRING "Toolchain CFLAGS")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING "Toolchain CXXFLAGS")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie -static-libstdc++" CACHE STRING "Toolchain LDFLAGS")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++" CACHE STRING "Toolchain LDFLAGS")
|
||||
|
||||
@@ -87,7 +87,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
# for hardfp: CFLAGS must have -mhard-float
|
||||
# LDFLAGS must have -Wl,--no-warn-mismatch
|
||||
#
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb -march=armv7-a -mcpu=cortex-a15 -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE" CACHE STRING "Toolchain CFLAGS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon-vfpv4 -fPIE" CACHE STRING "Toolchain CFLAGS")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING "Toolchain CXXFLAGS")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -march=armv7-a -Wl,--no-warn-mismatch -L${TOOLCHAIN}/arm-linux-androideabi/lib/armv7-a -static-libstdc++ -fPIE -pie" CACHE STRING "Toolchain LDFLAGS")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -march=armv7-a -Wl,--no-warn-mismatch -L${TOOLCHAIN}/arm-linux-androideabi/lib/armv7-a -static-libstdc++" CACHE STRING "Toolchain LDFLAGS")
|
||||
|
||||
@@ -97,6 +97,7 @@ in table [standardProperties].
|
||||
**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
|
||||
**ior** | Index of refraction, either for refractive objects or as an alternative to reflectance
|
||||
**microThickness** | Thickness of the thin layer of refractive objects
|
||||
**dispersion** | Strength of the dispersion effect for refractive objects, specified as 20/Abbe number
|
||||
**bentNormal** | A normal pointing in the average unoccluded direction. Can be used to improve indirect lighting quality
|
||||
**shadowStrength** | Strength factor between 0 and 1 for all shadows received by this material
|
||||
[Table [standardProperties]: Properties of the standard model]
|
||||
@@ -126,6 +127,7 @@ The type and range of each property is described in table [standardPropertiesTyp
|
||||
**absorption** | float3 | [0..n] |
|
||||
**microThickness** | float | [0..n] |
|
||||
**thickness** | float | [0..n] |
|
||||
**dispersion** | float | [0..n] | Realistic values are between [0, 1], with the exception of Rutile, which has a value of 2.04
|
||||
[Table [standardPropertiesTypes]: Range and type of the standard model's properties]
|
||||
|
||||
|
||||
@@ -153,13 +155,14 @@ The type and range of each property is described in table [standardPropertiesTyp
|
||||
as-is, which can lead to physically impossible materials, however, this might be desirable
|
||||
for artistic reasons.
|
||||
|
||||
!!! Note: About `thickness` and `microThickness` for refraction
|
||||
!!! Note: About `thickness`, `microThickness` and `dispersion` for refraction
|
||||
`thickness` represents the thickness of solid objects in the direction of the normal, for
|
||||
satisfactory results, this should be provided per fragment (e.g.: as a texture) or at least per
|
||||
vertex. `microThickness` represent the thickness of the thin layer of an object, and can
|
||||
generally be provided as a constant value. For example, a 1mm thin hollow sphere of radius 1m,
|
||||
would have a `thickness` of 1 and a `microThickness` of 0.001. Currently `thickness` is not
|
||||
used when `refractionType` is set to `thin`.
|
||||
would have a `thickness` of 1 and a `microThickness` of 0.001. Dispersion controls the angular
|
||||
separation of colors transmitting through a volume, and can be set by a constant value.
|
||||
Currently `thickness` and `dispersion` are not used when `refractionType` is set to `thin`.
|
||||
|
||||
### Base color
|
||||
|
||||
@@ -651,6 +654,26 @@ the `refractionType` is set to `solid` and `absorption` coefficients are set.
|
||||
![Figure [varyingThickness]: `thickness` varying from 0.0 at the top of the prism to 3.0 at the
|
||||
bottom of the prism](images/material_thickness.png)
|
||||
|
||||
### Dispersion
|
||||
|
||||
The dispersion property controls the angular separation of colors transmitting through a relatively
|
||||
clear volume. It can only be used when `refractionType` is set to `volume`.
|
||||
Its value is specified as 20/Abbe number. When the value is zero, no dispersion is used.
|
||||
|
||||
Table [commonMatDispersion] describes acceptable dispersion values for various types of materials.
|
||||
|
||||
Material | Abbe Number (V) | Dispersion (20/V)
|
||||
--------------------------:|:------------------:|:-----------------
|
||||
Rutile | 9.8 | 2.04
|
||||
Polycarbonate | 32 | 0.625
|
||||
Diamond | 55 | 0.36
|
||||
Water | 55 | 0.36
|
||||
Crown Glass | 59 | 0.33
|
||||
[Table [commonMatDispersion]: Dispersion of common materials]
|
||||
|
||||
![Figure [dispersionProperty]: `dispersion` varying from 0.0
|
||||
(left) to 5.0 (right)](images/materials/dispersion.png)
|
||||
|
||||
## Subsurface model
|
||||
|
||||
### Thickness
|
||||
@@ -2276,6 +2299,7 @@ struct MaterialInputs {
|
||||
float3 absorption; // default float3(0.0, 0.0, 0.0)
|
||||
float ior; // default: 1.5
|
||||
float microThickness; // default: 0.0, not available with refractionType "solid"
|
||||
float dispersion; // default: 0.0, not available with refractionType "thin"
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -2456,9 +2480,9 @@ type aliases:
|
||||
**uint2** | uvec2 | A vector of 2 unsigned integers
|
||||
**uint3** | uvec3 | A vector of 3 unsigned integers
|
||||
**uint4** | uvec4 | A vector of 4 unsigned integers
|
||||
**float2** | float2 | A vector of 2 floats
|
||||
**float3** | float3 | A vector of 3 floats
|
||||
**float4** | float4 | A vector of 4 floats
|
||||
**float2** | vec2 | A vector of 2 floats
|
||||
**float3** | vec3 | A vector of 3 floats
|
||||
**float4** | vec4 | A vector of 4 floats
|
||||
**float4x4** | mat4 | A 4x4 float matrix
|
||||
**float3x3** | mat3 | A 3x3 float matrix
|
||||
|
||||
|
||||
6
docs/build/windows_android.html
vendored
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>Build for Android on Windows - Filament</title>
|
||||
<title>Android on Windows - Filament</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
@@ -273,7 +273,7 @@ copy filament-android\build\outputs\aar\filament-android-release.aar ..\..\out\
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../build/maven_release.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../dup/contributing.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
@@ -287,7 +287,7 @@ copy filament-android\build\outputs\aar\filament-android-release.aar ..\..\out\
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../build/maven_release.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../dup/contributing.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
255
docs/dup/backend_test.html
Normal file
@@ -0,0 +1,255 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>backend - Filament</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link rel="shortcut icon" href="../favicon.png">
|
||||
<link rel="stylesheet" href="../css/variables.css">
|
||||
<link rel="stylesheet" href="../css/general.css">
|
||||
<link rel="stylesheet" href="../css/chrome.css">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
||||
<link rel="stylesheet" href="../fonts/fonts.css">
|
||||
|
||||
<!-- Highlight.js Stylesheets -->
|
||||
<link rel="stylesheet" href="../highlight.css">
|
||||
<link rel="stylesheet" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
|
||||
<!-- MathJax -->
|
||||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
|
||||
<!-- Provide site root to javascript -->
|
||||
<script>
|
||||
var path_to_root = "../";
|
||||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
var theme = localStorage.getItem('mdbook-theme');
|
||||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||||
|
||||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||||
}
|
||||
|
||||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
|
||||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||||
<script>
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
var sidebar = null;
|
||||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<div style="display:flex;align-items:center;justify-content:center">
|
||||
<img class="flogo" src="../images/filament_logo_small.png"></img>
|
||||
</div>
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper" class="page-wrapper">
|
||||
|
||||
<div class="page">
|
||||
<div id="menu-bar-hover-placeholder"></div>
|
||||
<div id="menu-bar" class="menu-bar sticky">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<!-- Filament: disable themes because the markdeep part does not look good for dark themes -->
|
||||
<!--
|
||||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</button>
|
||||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||||
</ul>
|
||||
-->
|
||||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h1 class="menu-title">Filament</h1>
|
||||
|
||||
<div class="right-buttons">
|
||||
<a href="https://github.com/google/filament" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="search-wrapper" class="hidden">
|
||||
<form id="searchbar-outer" class="searchbar-outer">
|
||||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||||
</form>
|
||||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||||
<div id="searchresults-header" class="searchresults-header"></div>
|
||||
<ul id="searchresults">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||||
<script>
|
||||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<h1 id="backend-unit-tests"><a class="header" href="#backend-unit-tests">Backend Unit Tests</a></h1>
|
||||
<p>These are tests that ensure the Filament backend is working properly on various operating systems
|
||||
and graphics backends.</p>
|
||||
<p>The majority of these tests generate images that are then compared against a known golden image.</p>
|
||||
<h2 id="running-with-a-specific-graphics-library"><a class="header" href="#running-with-a-specific-graphics-library">Running with a specific graphics library</a></h2>
|
||||
<p>Run with <code>-a<backend></code> to run with a specific backend, such as <code>-avulkan</code> for vulkan or <code>-ametal</code>
|
||||
for metal.</p>
|
||||
<h2 id="image-comparisons"><a class="header" href="#image-comparisons">Image comparisons</a></h2>
|
||||
<p>The expected images are stored as PNG files in the <code>expected_images</code> subdirectory of the test source
|
||||
code. When cmake is run it will copy this directory to the build output creating
|
||||
<code>images/expected_images</code> inside the same directory as the unit test binary.</p>
|
||||
<p>The unit tests will then write their resulting images into <code>images/actual_images</code> in order to make
|
||||
the tests easier to debug.</p>
|
||||
<p>If an image comparison test fails, it writes a diff image to <code>images/diff_images</code> where each pixel of the diff is white (255,255,255) if the comparison for the corresponding pixel succeeds and black (0,0,0) of the comparison for the corresponding pixel fails.</p>
|
||||
<h3 id="python-utility-for-updating-golden-images-and-comparing-results"><a class="header" href="#python-utility-for-updating-golden-images-and-comparing-results">Python utility for updating golden images and comparing results</a></h3>
|
||||
<p>Inside the unit test source code directory there is a python script called
|
||||
<code>move_actual_images_to_expected.py</code>.
|
||||
It will display the actual and expected images side-by-side and copy the actual image into the
|
||||
source tree's <code>expected_images</code> directory if the user approves the change.</p>
|
||||
<h4 id="directories"><a class="header" href="#directories">Directories</a></h4>
|
||||
<p>The <code>-r</code> flag is required and should be the directory where the test binary is.</p>
|
||||
<p>If not running the script from the directory it's in, <code>-s</code> should be the source code's
|
||||
<code>expected_images</code> directory.</p>
|
||||
<h4 id="configuring-comparemove-behavior"><a class="header" href="#configuring-comparemove-behavior">Configuring compare/move behavior</a></h4>
|
||||
<p>The <code>-c</code> flag has the tool display the actual and expected images side-by-side. By default it
|
||||
does this by opening both with the OS's default behavior. <code>-p</code> can be used to specify a different
|
||||
terminal program.</p>
|
||||
<p>The <code>-m</code> flag has the tool move the actual image to overwrite the expected image in the source
|
||||
tree. If the images are also being compared then the move will only happen if the user approves the
|
||||
change.</p>
|
||||
<p>After updating the expected images, cmake will need to be run again to copy them to the binary's
|
||||
directory. Also, currently some platforms can't load images to compare and so have the hash
|
||||
hardcoded into the test source code, so for now those need to be updated by running the test and
|
||||
copying the value manually.</p>
|
||||
<h4 id="picking-which-tests-to-compare"><a class="header" href="#picking-which-tests-to-compare">Picking which tests to compare</a></h4>
|
||||
<p>The <code>-x</code> flag causes the tool to check the <code>test_detail.xml</code> file and only process the images who
|
||||
failed a comparison. <code>--gtest_output=xml</code> needs to be passed to the test binary to generate this
|
||||
file.</p>
|
||||
<p>The <code>-t</code> argument takes a list of images to compare, provided as the file name without the <code>.png</code>
|
||||
suffix.</p>
|
||||
<h2 id="unsupported-tests"><a class="header" href="#unsupported-tests">Unsupported tests</a></h2>
|
||||
<p>If a test depends on a feature that is unsupported by the current environment, it will start with
|
||||
the <code>SKIP_IF</code> macro. This will cause the test to not be run.</p>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../notes/tests.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/test_ci_backend.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../notes/tests.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/test_ci_backend.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -158,7 +158,8 @@
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<h2 id="updating-vulkan-headers"><a class="header" href="#updating-vulkan-headers">Updating Vulkan headers</a></h2>
|
||||
<h1 id="bluevk"><a class="header" href="#bluevk">bluevk</a></h1>
|
||||
<h2 id="updating-vulkan-headers"><a class="header" href="#updating-vulkan-headers">Updating Vulkan headers</a></h2>
|
||||
<p>To update the Vulkan headers, perform the following steps.</p>
|
||||
<p>First, find the latest version of the Vulkan headers here:
|
||||
https://github.com/KhronosGroup/Vulkan-Headers/tags</p>
|
||||
|
||||
@@ -158,8 +158,8 @@
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<h2 id="building-filament"><a class="header" href="#building-filament">Building Filament</a></h2>
|
||||
<h3 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h3>
|
||||
<h1 id="building-filament"><a class="header" href="#building-filament">Building Filament</a></h1>
|
||||
<h2 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h2>
|
||||
<p>To build Filament, you must first install the following tools:</p>
|
||||
<ul>
|
||||
<li>CMake 3.22.1 (or more recent)</li>
|
||||
@@ -175,14 +175,14 @@ section below.</p>
|
||||
<li>Android NDK 25.1 or higher</li>
|
||||
<li>Java 17</li>
|
||||
</ul>
|
||||
<h3 id="environment-variables"><a class="header" href="#environment-variables">Environment variables</a></h3>
|
||||
<h2 id="environment-variables"><a class="header" href="#environment-variables">Environment variables</a></h2>
|
||||
<p>To build Filament for Android, make sure the environment variable <code>ANDROID_HOME</code> points to the
|
||||
location of your Android SDK.</p>
|
||||
<p>When building for WebGL, you'll also need to set <code>EMSDK</code>. See <a href="#webassembly">WebAssembly</a>.</p>
|
||||
<h3 id="ide"><a class="header" href="#ide">IDE</a></h3>
|
||||
<p>We recommend using CLion to develop for Filament. Simply open the root directory's CMakeLists.txt
|
||||
in CLion to obtain a usable project.</p>
|
||||
<h3 id="easy-build"><a class="header" href="#easy-build">Easy build</a></h3>
|
||||
<h2 id="easy-build"><a class="header" href="#easy-build">Easy build</a></h2>
|
||||
<p>Once the required OS specific dependencies listed below are installed, you can use the script
|
||||
located in <code>build.sh</code> to build Filament easily on macOS and Linux.</p>
|
||||
<p>This script can be invoked from anywhere and will produce build artifacts in the <code>out/</code> directory
|
||||
@@ -206,7 +206,7 @@ The script offers more features described by executing <code>build.sh -h</code>.
|
||||
<li><code>-t</code>: <a href="https://google.github.io/filament/dup/fgviewer.html"><code>fgviewer</code></a></li>
|
||||
<li><code>-b</code> and <code>-y</code>: <a href="https://google.github.io/filament/notes/asan_ubsan.html">ASAN/UBSAN builds</a></li>
|
||||
</ul>
|
||||
<h3 id="filament-specific-cmake-options"><a class="header" href="#filament-specific-cmake-options">Filament-specific CMake Options</a></h3>
|
||||
<h2 id="filament-specific-cmake-options"><a class="header" href="#filament-specific-cmake-options">Filament-specific CMake Options</a></h2>
|
||||
<p>The following CMake options are boolean options specific to Filament:</p>
|
||||
<ul>
|
||||
<li><code>FILAMENT_ENABLE_LTO</code>: Enable link-time optimizations if supported by the compiler</li>
|
||||
@@ -223,7 +223,7 @@ The script offers more features described by executing <code>build.sh -h</code>.
|
||||
cmake . -DOPTION=ON # Replace OPTION with the option name, set to ON / OFF
|
||||
</code></pre>
|
||||
<p>Options can also be set with the CMake GUI.</p>
|
||||
<h3 id="linux"><a class="header" href="#linux">Linux</a></h3>
|
||||
<h2 id="linux"><a class="header" href="#linux">Linux</a></h2>
|
||||
<p>Make sure you've installed the following dependencies:</p>
|
||||
<ul>
|
||||
<li><code>clang-16</code> or higher</li>
|
||||
@@ -265,7 +265,7 @@ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
|
||||
<pre><code class="language-shell">ninja
|
||||
</code></pre>
|
||||
<p>This will build Filament, its tests and samples, and various host tools.</p>
|
||||
<h3 id="macos"><a class="header" href="#macos">macOS</a></h3>
|
||||
<h2 id="macos"><a class="header" href="#macos">macOS</a></h2>
|
||||
<p>To compile Filament you must have the most recent version of Xcode installed and you need to
|
||||
make sure the command line tools are setup by running:</p>
|
||||
<pre><code class="language-shell">xcode-select --install
|
||||
@@ -278,14 +278,14 @@ cd out/cmake-release
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
|
||||
ninja
|
||||
</code></pre>
|
||||
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
|
||||
<h2 id="ios"><a class="header" href="#ios">iOS</a></h2>
|
||||
<p>The easiest way to build Filament for iOS is to use <code>build.sh</code> and the
|
||||
<code>-p ios</code> flag. For instance to build the debug target:</p>
|
||||
<pre><code class="language-shell">./build.sh -p ios debug
|
||||
</code></pre>
|
||||
<p>See <a href="./ios/samples/README.html">ios/samples/README.md</a> for more information.</p>
|
||||
<h3 id="windows"><a class="header" href="#windows">Windows</a></h3>
|
||||
<h4 id="building-on-windows-with-visual-studio-2019-or-later"><a class="header" href="#building-on-windows-with-visual-studio-2019-or-later">Building on Windows with Visual Studio 2019 or later</a></h4>
|
||||
<h2 id="windows"><a class="header" href="#windows">Windows</a></h2>
|
||||
<h3 id="building-on-windows-with-visual-studio-2019-or-later"><a class="header" href="#building-on-windows-with-visual-studio-2019-or-later">Building on Windows with Visual Studio 2019 or later</a></h3>
|
||||
<p>Install the following components:</p>
|
||||
<ul>
|
||||
<li><a href="https://www.visualstudio.com/downloads">Visual Studio 2019 or later</a></li>
|
||||
@@ -314,7 +314,7 @@ target in the <em>Solution Explorer</em> and choose <em>Build</em> to build a sp
|
||||
<code>out</code> folder run the following command.</p>
|
||||
<pre><code class="language-bat">cmake --build . --target gltf_viewer --config Release
|
||||
</code></pre>
|
||||
<h3 id="android"><a class="header" href="#android">Android</a></h3>
|
||||
<h2 id="android"><a class="header" href="#android">Android</a></h2>
|
||||
<p>Before building Filament for Android, make sure to build Filament for your host. Some of the
|
||||
host tools are required to successfully build for Android.</p>
|
||||
<p>Filament can be built for the following architectures:</p>
|
||||
@@ -327,13 +327,42 @@ host tools are required to successfully build for Android.</p>
|
||||
<p>Note that the main target is the ARM 64-bit target. Our implementation is optimized first and
|
||||
foremost for <code>arm64-v8a</code>.</p>
|
||||
<p>To build Android on Windows machines, see <a href="android/Windows.html">android/Windows.md</a>.</p>
|
||||
<h4 id="easy-android-build"><a class="header" href="#easy-android-build">Easy Android build</a></h4>
|
||||
<h3 id="important-sdk-location"><a class="header" href="#important-sdk-location">Important: SDK location</a></h3>
|
||||
<p>Either ensure your <code>ANDROID_HOME</code> environment variable is set or make sure the root project
|
||||
contains a <code>local.properties</code> file with the <code>sdk.dir</code> property pointing to your installation of
|
||||
the Android SDK.</p>
|
||||
<h3 id="easy-android-build"><a class="header" href="#easy-android-build">Easy Android build</a></h3>
|
||||
<p>The easiest way to build Filament for Android is to use <code>build.sh</code> and the
|
||||
<code>-p android</code> flag. For instance to build the release target:</p>
|
||||
<pre><code class="language-shell">./build.sh -p android release
|
||||
</code></pre>
|
||||
<p>To build a sample (such as <code>android/samples/sample-hello-triangle</code>) for an ARM 64-bit phone, you would run</p>
|
||||
<pre><code class="language-shell">./build.sh -p android -q arm64-v8a -k sample-hello-triangle release
|
||||
</code></pre>
|
||||
<p>The output APK can be found in <code>android/samples/sample-hello-triangle/build/outputs/apk/release/sample-hello-triangle-release-unsigned.apk</code></p>
|
||||
<p>Run <code>build.sh -h</code> for more information.</p>
|
||||
<h4 id="manual-builds"><a class="header" href="#manual-builds">Manual builds</a></h4>
|
||||
<h3 id="android-studio"><a class="header" href="#android-studio">Android Studio</a></h3>
|
||||
<p>You must use the latest stable release of Android Studio.</p>
|
||||
<p>The Android build of filament is separated into java/kotlin client APIs, a layer of jni bindings
|
||||
that bridges java/kotlin with native code, and Filament and other component code that have been compiled
|
||||
into architecture-specific libraries. Our default Android Studio gradle setup can compile java/kotlin and
|
||||
the jni bindings for you, but it will treat the filament libraries as already compiled and present on
|
||||
the system.</p>
|
||||
<p>Therefore, before compiling the sample app or any other targets, you must
|
||||
make sure that the native filament libraries have been compiled and are located at a prescribed location
|
||||
so that the jni bindings can link against them. You can do so by using the easy build script</p>
|
||||
<pre><code class="language-shell">./build.sh -p android release -q arm64-v8a
|
||||
</code></pre>
|
||||
<p>Note that the above step will also install host machine tools into prescribed locations. These tools are
|
||||
required for compiling Filament assets such as materials and environment maps.</p>
|
||||
<p>Now we are ready to compile the apps. To open the project, point Studio to the <code>android</code> folder.
|
||||
After opening the project and syncing with Gradle, select the sample of your choice
|
||||
using the drop-down widget in the toolbar. Additionally, you will need to select a deployment target.
|
||||
By doing so, Android Studio will automatically try to compile the app only for that specific
|
||||
device's architecture. So if you are targeting a new Pixel phone, make sure that the step above
|
||||
(compiling the library) is targeting ARM 64-bit (<code>-q arm64-v8a</code> ), and if you are running the app on
|
||||
an emulator on a Linux machine with an x86 64-bit chipset, you would indicate (<code>-q x86_64</code>) in the above step.</p>
|
||||
<h3 id="manual-builds"><a class="header" href="#manual-builds">Manual builds</a></h3>
|
||||
<p>Invoke CMake in a build directory of your choice, inside of filament's directory. The commands
|
||||
below show how to build Filament for ARM 64-bit (<code>aarch64</code>).</p>
|
||||
<pre><code class="language-shell">mkdir out/android-build-release-aarch64
|
||||
@@ -350,7 +379,7 @@ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-aarch64-linux-androi
|
||||
<p>This will generate Filament's Android binaries in <code>out/android-release</code>. This location is important
|
||||
to build the Android Studio projects located in <code>filament/android</code>. After install, the library
|
||||
binaries should be found in <code>out/android-release/filament/lib/arm64-v8a</code>.</p>
|
||||
<h4 id="aar"><a class="header" href="#aar">AAR</a></h4>
|
||||
<h3 id="aar"><a class="header" href="#aar">AAR</a></h3>
|
||||
<p>Before you attempt to build the AAR, make sure you've compiled and installed the native libraries
|
||||
as explained in the sections above. You must have the following ABIs built in
|
||||
<code>out/android-release/filament/lib/</code>:</p>
|
||||
@@ -376,7 +405,7 @@ AAR.</p>
|
||||
</code></pre>
|
||||
<p>The <code>-Pcom.google.android.filament.dist-dir</code> can be used to specify a different installation
|
||||
directory (it must match the CMake install prefix used in the previous steps).</p>
|
||||
<h4 id="using-filaments-aar"><a class="header" href="#using-filaments-aar">Using Filament's AAR</a></h4>
|
||||
<h3 id="using-filaments-aar"><a class="header" href="#using-filaments-aar">Using Filament's AAR</a></h3>
|
||||
<p>Create a new module in your project and select <em>Import .JAR or .AAR Package</em> when prompted. Make
|
||||
sure to add the newly created module as a dependency to your application.</p>
|
||||
<p>If you do not wish to include all supported ABIs, make sure to create the appropriate flavors in
|
||||
@@ -412,7 +441,7 @@ productFlavors {
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="webassembly"><a class="header" href="#webassembly">WebAssembly</a></h3>
|
||||
<h2 id="webassembly"><a class="header" href="#webassembly">WebAssembly</a></h2>
|
||||
<p>The core Filament library can be cross-compiled to WebAssembly from either macOS or Linux. To get
|
||||
started, follow the instructions for building Filament on your platform (<a href="#macos">macOS</a> or
|
||||
<a href="#linux">linux</a>), which will ensure you have the proper dependencies installed.</p>
|
||||
|
||||
@@ -209,7 +209,7 @@ as possible. The current external dependencies of the runtime library include:</
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../build/maven_release.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../build/windows_android.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
@@ -223,7 +223,7 @@ as possible. The current external dependencies of the runtime library include:</
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../build/maven_release.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../build/windows_android.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ tree into <code>docs_src/src_mdbook/src/dup</code>. Moreover, to restore valid l
|
||||
to perform a number of URL replacements in addition to the copy. These replacements are
|
||||
described in <a href="https://github.com/google/filament/blob/main/docs_src/build/duplicates.json"><code>docs_src/build/duplicates.json</code></a>.</p>
|
||||
<h3 id="core-concept-docs"><a class="header" href="#core-concept-docs">Core concept docs</a></h3>
|
||||
<p>The primary design of Filament as a phyiscally-based renderer and details of its materials
|
||||
<p>The primary design of Filament as a physically-based renderer and details of its materials
|
||||
system are described in <code>Filament.md.html</code> and <code>Materials.md.html</code>, respectively. These two
|
||||
documents are written in <a href="https://casual-effects.com/markdeep/"><code>markdeep</code></a>. To embed them into our book, we</p>
|
||||
<ol>
|
||||
@@ -253,7 +253,7 @@ add a link in <code>SUMMARY.md</code>, and perform the steps outlined in
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../notes/release_guide.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../release/branching.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
@@ -267,7 +267,7 @@ add a link in <code>SUMMARY.md</code>, and perform the steps outlined in
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../notes/release_guide.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../release/branching.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||