Compare commits
264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f222f1b925 | ||
|
|
2839c352b8 | ||
|
|
6a01cbc312 | ||
|
|
6193156556 | ||
|
|
fe23aa917d | ||
|
|
eb8a29a332 | ||
|
|
6eec2cde81 | ||
|
|
98ae61ffe5 | ||
|
|
adb489c77a | ||
|
|
eeccfed8e4 | ||
|
|
893ed861e9 | ||
|
|
411ae23512 | ||
|
|
8f05984551 | ||
|
|
4567b01c1d | ||
|
|
29315f9a1b | ||
|
|
0626902530 | ||
|
|
d4a2d30a1c | ||
|
|
cec5f3e988 | ||
|
|
02501c6e60 | ||
|
|
4d8da14c1f | ||
|
|
4fae917fb5 | ||
|
|
c84036c8c4 | ||
|
|
34429f5490 | ||
|
|
59c2d5bef3 | ||
|
|
a3412c4f45 | ||
|
|
564d846be5 | ||
|
|
41186340c9 | ||
|
|
96bba71739 | ||
|
|
5ab7a9e3ab | ||
|
|
4c30067dac | ||
|
|
243ba77025 | ||
|
|
229f1f6d95 | ||
|
|
bc2eae2ecd | ||
|
|
e468ec91b7 | ||
|
|
ca2829461a | ||
|
|
7805687f7a | ||
|
|
af82aaa0fc | ||
|
|
410ecfd014 | ||
|
|
0df1f9fcce | ||
|
|
45f7e07832 | ||
|
|
1aefe741b2 | ||
|
|
d1842919cf | ||
|
|
6473771f1e | ||
|
|
2d57a82b49 | ||
|
|
dc2d55c409 | ||
|
|
c0b8e98a93 | ||
|
|
8252bbe512 | ||
|
|
a4817f3e2a | ||
|
|
fa879b4bd0 | ||
|
|
005e4ba2ec | ||
|
|
d2299c4502 | ||
|
|
5c666c254e | ||
|
|
a09c17bd4f | ||
|
|
57df4481e9 | ||
|
|
47af85aed1 | ||
|
|
44fc295913 | ||
|
|
6878b0be36 | ||
|
|
6c222bf4e3 | ||
|
|
042bfe2597 | ||
|
|
97133f3591 | ||
|
|
d06cc4390e | ||
|
|
6047d3235f | ||
|
|
2cda6e35bd | ||
|
|
8f8d51e17b | ||
|
|
6919e3b274 | ||
|
|
10bf944410 | ||
|
|
eb70fd5dee | ||
|
|
986a3869cc | ||
|
|
9ad3d88d74 | ||
|
|
a3bfdb89fa | ||
|
|
2895530e09 | ||
|
|
f8069aa99f | ||
|
|
b70eea9556 | ||
|
|
44a8da6a8e | ||
|
|
3bd066f993 | ||
|
|
1b10afa9e6 | ||
|
|
024910ba8e | ||
|
|
f2e3a132db | ||
|
|
87abd1f8bc | ||
|
|
57662c52f2 | ||
|
|
a50cd1f8c8 | ||
|
|
fe907398d4 | ||
|
|
8b6ddfe97a | ||
|
|
3226b20ece | ||
|
|
61d473887f | ||
|
|
b3d7819e78 | ||
|
|
de6220594d | ||
|
|
d9dfe69a81 | ||
|
|
22d4e63787 | ||
|
|
f033799a43 | ||
|
|
30e150c016 | ||
|
|
f5f27749a4 | ||
|
|
b5f95213db | ||
|
|
9a2f6fdb53 | ||
|
|
d42865373d | ||
|
|
761977d385 | ||
|
|
f83eb114bc | ||
|
|
9c20294e4b | ||
|
|
40e7a86f5f | ||
|
|
21248f15b5 | ||
|
|
34707431f7 | ||
|
|
4f32817f6d | ||
|
|
cc9e05e711 | ||
|
|
5e585496b2 | ||
|
|
1e501eb00b | ||
|
|
419d68d4db | ||
|
|
fdc28801a2 | ||
|
|
c008109335 | ||
|
|
8450232448 | ||
|
|
99c5fc7388 | ||
|
|
90c156ebef | ||
|
|
2df02d81d3 | ||
|
|
8019b11589 | ||
|
|
cc51726590 | ||
|
|
16454e0de6 | ||
|
|
318e22af51 | ||
|
|
3bf934f5d7 | ||
|
|
68ac87dc24 | ||
|
|
b4a6d0a83e | ||
|
|
a09037cec0 | ||
|
|
50a61984ec | ||
|
|
6486eba7e2 | ||
|
|
acb8f00075 | ||
|
|
06d9183aaa | ||
|
|
c92d13c0c9 | ||
|
|
bd9aba35f6 | ||
|
|
75af25419d | ||
|
|
f6b90d2a31 | ||
|
|
7fbd00e59b | ||
|
|
f814138f83 | ||
|
|
96d3f2f16b | ||
|
|
89694168a6 | ||
|
|
63d5698a78 | ||
|
|
24ca2bf181 | ||
|
|
f37a3e9497 | ||
|
|
90ad9b457a | ||
|
|
30f5a97ea1 | ||
|
|
964a1bd7f2 | ||
|
|
a3822f4af0 | ||
|
|
e9c9e45ac9 | ||
|
|
fb831dec0a | ||
|
|
bcdad769ff | ||
|
|
dc1c5529c0 | ||
|
|
8b8d563b0f | ||
|
|
be4fb4fdbb | ||
|
|
dcca236f60 | ||
|
|
70dba2398e | ||
|
|
47521d70a1 | ||
|
|
468992f4cd | ||
|
|
0db7057983 | ||
|
|
8a63834607 | ||
|
|
4e4d4f9ee3 | ||
|
|
6abef94d95 | ||
|
|
4b1c557bb1 | ||
|
|
94a1eb27b4 | ||
|
|
a9754273b0 | ||
|
|
2fe4f6cbe7 | ||
|
|
1159435d47 | ||
|
|
a6f364e0f3 | ||
|
|
c6942a52e6 | ||
|
|
c65dc99771 | ||
|
|
65394f6301 | ||
|
|
b0beee03bc | ||
|
|
6971b3b6b0 | ||
|
|
4270384661 | ||
|
|
fe1de41b8e | ||
|
|
82cb13936c | ||
|
|
212b64ea5f | ||
|
|
2849dc6a2a | ||
|
|
d84bb82e44 | ||
|
|
5746532b7c | ||
|
|
2e10fe6680 | ||
|
|
f55c9ee437 | ||
|
|
06e639ae91 | ||
|
|
8de19cb582 | ||
|
|
47b1ece804 | ||
|
|
d47189536f | ||
|
|
4533a42a6f | ||
|
|
853247f32f | ||
|
|
5f6cbc779a | ||
|
|
548b28c6e2 | ||
|
|
239246e221 | ||
|
|
75c4f36f96 | ||
|
|
7260bab7b3 | ||
|
|
e7250571e7 | ||
|
|
c68d0a4e46 | ||
|
|
a37b431e87 | ||
|
|
98107016b9 | ||
|
|
37d080dfd1 | ||
|
|
de75b9d125 | ||
|
|
8bccfc2863 | ||
|
|
07fd883f9a | ||
|
|
5ceb9fc5d5 | ||
|
|
d14ba856a7 | ||
|
|
7eec70276e | ||
|
|
4f58a7e5fb | ||
|
|
30565a5afc | ||
|
|
62d06592d3 | ||
|
|
e74e583b97 | ||
|
|
f54a0a3452 | ||
|
|
6778ab0624 | ||
|
|
37768ed9e1 | ||
|
|
20abfec7d3 | ||
|
|
269d636785 | ||
|
|
39862c91ce | ||
|
|
03df97d0e3 | ||
|
|
40e10817dd | ||
|
|
523f4026b4 | ||
|
|
b82dca4fac | ||
|
|
5ebc6bce04 | ||
|
|
a6bf162431 | ||
|
|
bd625e42e9 | ||
|
|
7471237178 | ||
|
|
52698aab14 | ||
|
|
3d121eb873 | ||
|
|
1dd7b06e6f | ||
|
|
d2ca1c79d2 | ||
|
|
52913e685e | ||
|
|
f30332b12b | ||
|
|
f31eb09ca0 | ||
|
|
0bec65701a | ||
|
|
59ef044ce0 | ||
|
|
76f1e91fd2 | ||
|
|
d72d3533e6 | ||
|
|
9ce2c319a9 | ||
|
|
4fe5832333 | ||
|
|
79f1744823 | ||
|
|
e352542e24 | ||
|
|
5938242d61 | ||
|
|
cfddd5b273 | ||
|
|
8a865e531e | ||
|
|
d05fb52ebf | ||
|
|
fd142b9b84 | ||
|
|
6658283617 | ||
|
|
8b3caeffb9 | ||
|
|
5fae33bde5 | ||
|
|
43cc5f9906 | ||
|
|
902eb32e3c | ||
|
|
08f7973d0c | ||
|
|
a736b8b018 | ||
|
|
094e7169cc | ||
|
|
44d4694c29 | ||
|
|
42862ddcde | ||
|
|
236ed9680c | ||
|
|
229fdc9be5 | ||
|
|
4af0cdfd4d | ||
|
|
451fac7d7b | ||
|
|
617dc932bb | ||
|
|
583c1c07cf | ||
|
|
9e01348dd5 | ||
|
|
ec2579bad5 | ||
|
|
e5a9a259de | ||
|
|
6472f645fc | ||
|
|
e9ace4e5fb | ||
|
|
c119f9bdca | ||
|
|
7997e4aa21 | ||
|
|
cdb0f20c6c | ||
|
|
4da58ecb29 | ||
|
|
075486724f | ||
|
|
530f41c29c | ||
|
|
5cbd80136c | ||
|
|
bfd1de809a | ||
|
|
0f2993aec7 | ||
|
|
e8bb895c58 |
4
.gitignore
vendored
@@ -12,3 +12,7 @@ filament/docs/html/**
|
||||
*tmp*.png
|
||||
civetweb.txt
|
||||
/TAGS
|
||||
settings.json
|
||||
test*.png
|
||||
test*.json
|
||||
results
|
||||
|
||||
52
BRANCHING.md
@@ -27,55 +27,3 @@ Bugs are defined as one of the following _introduced since the prior release_:
|
||||
- unintentional public API changes
|
||||
|
||||
For example, a long-standing crash just recently discovered would not necessitate a bug fix PR.
|
||||
|
||||
## Creating a GitHub Release
|
||||
|
||||
Be sure to choose the *release* branch when drafting a GitHub release.
|
||||
|
||||
## Git Commands
|
||||
|
||||
These commands assume a release candidate branch called *rc/1.9.0*.
|
||||
|
||||
### Creating a Release Candidate Branch
|
||||
|
||||
```
|
||||
$ git checkout main
|
||||
$ git pull
|
||||
$ git branch rc/1.9.0
|
||||
$ git push origin rc/1.9.0
|
||||
```
|
||||
|
||||
### Merging the Release Candidate Branch Into Release
|
||||
|
||||
There may be temporary hotfixes in the release branch that should be overriden by the new release
|
||||
candidate. To accomplish this, we first merge release into rc using the _ours_ strategy. Then we
|
||||
merge rc into release.
|
||||
|
||||
```
|
||||
$ git checkout rc/1.9.0
|
||||
$ git pull
|
||||
$ git fetch origin release:release
|
||||
$ git merge -s ours release
|
||||
$ git checkout release
|
||||
$ git merge --no-ff rc/1.9.0
|
||||
$ git push origin release
|
||||
```
|
||||
|
||||
### Deleting the Release Candidate Branch
|
||||
|
||||
```
|
||||
$ git branch -d rc/1.9.0
|
||||
$ git push origin --delete rc/1.9.0
|
||||
```
|
||||
|
||||
### See a History of the Release Branch
|
||||
|
||||
```
|
||||
$ git log --oneline --first-parent
|
||||
|
||||
442b061 (HEAD -> release) Merge branch 'rc/1.9.2' into release
|
||||
ac50d21 Hotfix
|
||||
94dc2f7 Hotfix
|
||||
b34ed5b Merge branch 'rc/1.9.1' into release
|
||||
aeef498 Merge branch 'rc/1.9.0' into release
|
||||
```
|
||||
|
||||
22
BUILDING.md
@@ -17,9 +17,9 @@ section below.
|
||||
|
||||
To build Filament for Android you must also install the following:
|
||||
|
||||
- Android Studio 4.0.1 or more recent
|
||||
- Android Studio 4.1.0 or more recent
|
||||
- Android SDK
|
||||
- Android NDK "side-by-side" 21.3 or higher
|
||||
- Android NDK "side-by-side" 22.0 or higher
|
||||
|
||||
### Environment variables
|
||||
|
||||
@@ -375,7 +375,7 @@ same version that our continuous builds use.
|
||||
|
||||
```
|
||||
cd <your chosen parent folder for the emscripten SDK>
|
||||
curl -L https://github.com/emscripten-core/emsdk/archive/1.39.19.zip > emsdk.zip
|
||||
curl -L https://github.com/emscripten-core/emsdk/archive/2.0.12.zip > emsdk.zip
|
||||
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
|
||||
python ./emsdk.py install latest
|
||||
python ./emsdk.py activate latest
|
||||
@@ -468,3 +468,19 @@ export SWIFTSHADER_LD_LIBRARY_PATH=`pwd`
|
||||
```
|
||||
|
||||
Next, go to your Filament repo and use the [easy build](#easy-build) script with `-t`.
|
||||
|
||||
## SwiftShader for CI
|
||||
|
||||
Continuous testing turnaround can be quite slow if you need to build SwiftShader from scratch, so we
|
||||
provide an Ubuntu-based Docker image that has it already built. The Docker image also includes
|
||||
everything necessary for building Filament. You can fetch and run the image as follows:
|
||||
|
||||
```
|
||||
docker pull ghcr.io/filament-assets/swiftshader
|
||||
docker run -it ghcr.io/filament-assets/swiftshader
|
||||
```
|
||||
|
||||
To do more with the container, see the helper script at `build/swiftshader/test.sh`.
|
||||
|
||||
If you are a team member, you can update the public image to the latest SwiftShader by
|
||||
following the instructions at the top of `build/swiftshader/Dockerfile`.
|
||||
|
||||
@@ -21,6 +21,10 @@ option(FILAMENT_ENABLE_LTO "Enable link-time optimizations if supported by the c
|
||||
|
||||
option(FILAMENT_SKIP_SAMPLES "Don't build samples" OFF)
|
||||
|
||||
option(FILAMENT_SUPPORTS_XCB "Include XCB support in Linux builds" ON)
|
||||
|
||||
option(FILAMENT_SUPPORTS_XLIB "Include XLIB support in Linux builds" ON)
|
||||
|
||||
set(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB "2" CACHE STRING
|
||||
"Per render pass arena size. Must be roughly 1 MB larger than FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, default 2."
|
||||
)
|
||||
@@ -83,6 +87,16 @@ if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL)
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
if (FILAMENT_SUPPORTS_XCB)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_XCB)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_XLIB)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_XLIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ANDROID OR WEBGL OR IOS)
|
||||
set(IS_MOBILE_TARGET TRUE)
|
||||
endif()
|
||||
@@ -248,7 +262,10 @@ if (LINUX)
|
||||
# /usr/bin/ld: ../bluegl/libbluegl.a(BlueGL.cpp.o): relocation R_X86_64_32S
|
||||
# against `.bss' can not be used when making a shared object; recompile with -fPIC
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
endif()
|
||||
|
||||
if (ANDROID)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
endif()
|
||||
|
||||
if (CYGWIN)
|
||||
@@ -418,7 +435,18 @@ set(MATC_BASE_FLAGS ${MATC_API_FLAGS} -p ${MATC_TARGET} ${MATC_OPT_FLAGS})
|
||||
# ==================================================================================================
|
||||
# choose where to put the objects in the dist folder
|
||||
if (NOT DIST_ARCH)
|
||||
set(DIST_ARCH x86_64)
|
||||
# On Apple silicon, the value of CMAKE_HOST_SYSTEM_PROCESSOR varies based on the CMake process's
|
||||
# own architecture. Because of this, running a x86_64 CMake binary on Apple silicon will cause
|
||||
# DIST_ARCH to be set incorrectly.
|
||||
set(DIST_ARCH "${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
|
||||
if (CMAKE_OSX_ARCHITECTURES MATCHES ".*;.*")
|
||||
set(DIST_ARCH "universal")
|
||||
else()
|
||||
if (NOT CMAKE_OSX_ARCHITECTURES STREQUAL "")
|
||||
set(DIST_ARCH "${CMAKE_OSX_ARCHITECTURES}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if (NOT DIST_DIR)
|
||||
set(DIST_DIR "${DIST_ARCH}")
|
||||
@@ -593,7 +621,6 @@ set(FILAMENT_SAMPLES_BINARY_DIR ${PROJECT_BINARY_DIR}/samples)
|
||||
if (WEBGL)
|
||||
add_subdirectory(web/filament-js)
|
||||
add_subdirectory(web/samples)
|
||||
add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
endif()
|
||||
|
||||
if (IS_HOST_PLATFORM)
|
||||
@@ -601,6 +628,7 @@ if (IS_HOST_PLATFORM)
|
||||
add_subdirectory(${LIBRARIES}/filamentapp)
|
||||
add_subdirectory(${LIBRARIES}/filagui)
|
||||
add_subdirectory(${LIBRARIES}/imageio)
|
||||
add_subdirectory(${LIBRARIES}/viewer)
|
||||
|
||||
add_subdirectory(${FILAMENT}/java/filamat)
|
||||
add_subdirectory(${FILAMENT}/java/filament)
|
||||
@@ -611,6 +639,7 @@ if (IS_HOST_PLATFORM)
|
||||
add_subdirectory(${EXTERNAL}/astcenc/tnt)
|
||||
add_subdirectory(${EXTERNAL}/etc2comp)
|
||||
add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
add_subdirectory(${EXTERNAL}/jsmn/tnt)
|
||||
add_subdirectory(${EXTERNAL}/libassimp/tnt)
|
||||
add_subdirectory(${EXTERNAL}/libpng/tnt)
|
||||
add_subdirectory(${EXTERNAL}/libsdl2/tnt)
|
||||
|
||||
41
README.md
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.9.3'
|
||||
implementation 'com.google.android.filament:filament-android:1.9.11'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -63,7 +63,7 @@ A much smaller alternative to `filamat-android` that can only generate OpenGL sh
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```
|
||||
pod 'Filament', '~> 1.9.3'
|
||||
pod 'Filament', '~> 1.9.11'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
@@ -136,7 +136,7 @@ Here are a few screenshots of applications that use Filament in production:
|
||||
- Clear coat
|
||||
- Anisotropic lighting
|
||||
- Approximated translucent (subsurface) materials
|
||||
- Cloth shading
|
||||
- Cloth/fabric/sheen shading
|
||||
- Normal mapping & ambient occlusion mapping
|
||||
- Image-based lighting
|
||||
- Physically-based camera (shutter speed, sensitivity and aperture)
|
||||
@@ -157,6 +157,41 @@ Here are a few screenshots of applications that use Filament in production:
|
||||
- TAA, FXAA, MSAA and specular anti-aliasing
|
||||
- Dynamic resolution
|
||||
|
||||
### glTF 2.0
|
||||
|
||||
- Encodings
|
||||
- [x] Embeded
|
||||
- [x] Binary
|
||||
|
||||
- Primitive Types
|
||||
- [x] Points
|
||||
- [x] Lines
|
||||
- [ ] Line Loop
|
||||
- [ ] Line Strip
|
||||
- [x] Triangles
|
||||
- [ ] Triangle Strip
|
||||
- [ ] Triangle Fan
|
||||
|
||||
- Animation
|
||||
- [x] Transform animation
|
||||
- [x] Linear interpolation
|
||||
- [x] Morph animation
|
||||
- [x] Sparse accessor
|
||||
- [x] Skin animation
|
||||
- [x] Joint animation
|
||||
|
||||
- Extensions
|
||||
- [x] KHR_draco_mesh_compression
|
||||
- [x] KHR_lights_punctual
|
||||
- [x] KHR_materials_clearcoat
|
||||
- [x] KHR_materials_pbrSpecularGlossiness
|
||||
- [x] KHR_materials_sheen
|
||||
- [x] KHR_materials_transmission
|
||||
- [x] KHR_materials_unlit
|
||||
- [x] KHR_mesh_quantization
|
||||
- [x] KHR_texture_transform
|
||||
|
||||
|
||||
## Rendering with Filament
|
||||
|
||||
### Native Linux, macOS and Windows
|
||||
|
||||
138
RELEASE_GUIDE.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Filament Release Guide
|
||||
|
||||
This guide makes use of some "environment variables":
|
||||
- $RELEASE = the new version of Filament we are releasing today. (e.g., 1.9.3)
|
||||
- $NEXT_RELEASE = the version we plan to release next week (e.g., 1.9.4)
|
||||
|
||||
Before starting, ensure that each of these branches is up-to-date with origin:
|
||||
- release
|
||||
- rc/$RELEASE
|
||||
- main
|
||||
|
||||
## 0. Make sure the rc/$RELEASE branch has the correct version.
|
||||
|
||||
It should have the version corresponding to its name, $RELEASE.
|
||||
|
||||
## 1. Update RELEASE_NOTES.md on the rc branch.
|
||||
|
||||
Checkout the rc/$RELEASE branch. In RELEASE_NOTES.md, locate the header corresponding to $RELEASE
|
||||
and write release notes. To see which commits make up the release, run:
|
||||
|
||||
```
|
||||
build/common/release.sh -c rc/$RELEASE
|
||||
```
|
||||
|
||||
Commit the changes to rc/$RELEASE with the title:
|
||||
|
||||
```
|
||||
Update RELEASE_NOTES for $RELEASE
|
||||
```
|
||||
|
||||
## 2. Bump versions on main to $RELEASE.
|
||||
|
||||
Checkout main and run the following command to bump Filament's version to $RELEASE:
|
||||
|
||||
```
|
||||
build/common/bump-version.sh $RELEASE
|
||||
```
|
||||
|
||||
Commit changes to main with the title:
|
||||
|
||||
```
|
||||
Bump version to $RELEASE
|
||||
```
|
||||
|
||||
Do not push to origin yet.
|
||||
|
||||
## 3. Cherry-pick RELEASE_NOTES change from rc branch to main.
|
||||
|
||||
```
|
||||
git cherry-pick rc/$RELEASE
|
||||
```
|
||||
|
||||
Update the headers. The "Next release" header becomes a header for $NEXT_RELEASE, and a new "Next
|
||||
release" header is added.
|
||||
|
||||
For example, this:
|
||||
|
||||
```
|
||||
## Next release (main branch)
|
||||
- foo
|
||||
- bar
|
||||
|
||||
## v1.9.3
|
||||
- baz
|
||||
- bat
|
||||
```
|
||||
|
||||
becomes:
|
||||
|
||||
```
|
||||
## Next release (main branch)
|
||||
|
||||
## v1.9.4
|
||||
- foo
|
||||
- bar
|
||||
|
||||
## v1.9.3
|
||||
- baz
|
||||
- bat
|
||||
```
|
||||
|
||||
Ammend these changes to the cherry-picked change.
|
||||
|
||||
```
|
||||
git add -u
|
||||
git commit --amend --no-edit
|
||||
```
|
||||
|
||||
## 4. Run release script.
|
||||
|
||||
```
|
||||
build/common/release.sh rc/$RELEASE rc/$NEXT_RELEASE
|
||||
```
|
||||
|
||||
This script will merge rc/$RELEASE into release, delete the rc branch, and create a new rc
|
||||
branch called rc/$NEXT_RELEASE. Verify that everything looks okay locally.
|
||||
|
||||
## 5. Push the release branch.
|
||||
|
||||
```
|
||||
git push origin release
|
||||
```
|
||||
|
||||
## 6. Create the GitHub release.
|
||||
|
||||
Use the GitHub UI to create a GitHub release corresponding to $RELEASE version.
|
||||
Make sure the target is set to the release branch.
|
||||
|
||||
## 7. Delete the old rc branch.
|
||||
|
||||
```
|
||||
git push origin --delete rc/$RELEASE
|
||||
```
|
||||
|
||||
## 8. Bump the version on the new rc branch to $NEXT_RELEASE.
|
||||
|
||||
```
|
||||
git checkout rc/$NEXT_RELEASE
|
||||
build/common/bump-version.sh $NEXT_RELEASE
|
||||
```
|
||||
|
||||
Commit the changes to rc/$NEXT_RELEASE with the title:
|
||||
|
||||
```
|
||||
Bump version to $NEXT_RELEASE
|
||||
```
|
||||
|
||||
## 9. Push main.
|
||||
|
||||
```
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## 10. Push the new rc branch.
|
||||
|
||||
```
|
||||
git push origin rc/$NEXT_RELEASE
|
||||
```
|
||||
110
RELEASE_NOTES.md
@@ -3,7 +3,115 @@
|
||||
This file contains one line summaries of commits that are worthy of mentioning in release notes.
|
||||
A new header is inserted each time a *tag* is created.
|
||||
|
||||
## Next release (v1.9.4)
|
||||
## Next release (main branch)
|
||||
|
||||
## v1.9.11
|
||||
|
||||
- Added support for Apple silicon Macs. build.sh can now be used to build on either Apple silicon or
|
||||
Intel-based Macs. Pass the `-l` flag to build universal binaries.
|
||||
- Added `sheenColor` and `sheenRoughness` properties to materials to create cloth/fabric.
|
||||
- Materials generation using `libfilamat` is now multi-threaded.
|
||||
- `MaterialBuilder::build()` now expects a reference to a `JobSystem` to multi-thread shaders
|
||||
generation. A `JobSystem` can be obtained with `Engine::getJobSystem()` when using Filament,
|
||||
or created directly otherwise. (⚠️ **API change**)
|
||||
- Add planar reflection RenderTarget demo.
|
||||
- Metal: honor inverseFrontFaces RasterState.
|
||||
- Metal: Fix crash when switching between views with shadowing enabled.
|
||||
- Metal: Fix crash when calling Texture::setImage() on SAMPLER_2D_ARRAY texture.
|
||||
- gltfio: added support for `KHR_materials_sheen`.
|
||||
- gltfio: shader optimizations are now disabled by default, unless opting in or using ubershaders.
|
||||
- gltfio: Fix "_maskThreshold not found" error.
|
||||
- gltfio on Java: fix potential memory leak in AssetLoader#destroy.
|
||||
- gltfio: fix crash during async texture decode.
|
||||
- gltfio: support animation in dynamically-added instances.
|
||||
- gltfio: Improve robustness when decoding textures.
|
||||
- gltfio: Fix animator crash for orphaned nodes.
|
||||
- gltfio: fix tangents with morphing.
|
||||
- gltf_viewer: fix very sporadic crash when exiting.
|
||||
- gltf_viewer: fix crash when rapidly switching between glTF models.
|
||||
- WebGL: Fix samples erroring on Windows with Chrome.
|
||||
- WebGL: Support `highlight` for setBloomOptions in JavaScript.
|
||||
- WebGL: Include TypeScript bindings in releases.
|
||||
- engine: Fix, punctual lights get clipped at certain angles.
|
||||
- engine: Fix memory leak when calling `View::setViewport` frequently.
|
||||
- engine: Fix, materials not working on some Qualcomm devices.
|
||||
- engine: Modulate emissive by alpha on blended objects.
|
||||
- engine: Fix, RenderTarget cleared multiple times.
|
||||
- Java: Fix JNI bindings for color grading.
|
||||
- Android: reduced binary size.
|
||||
|
||||
## v1.9.10
|
||||
|
||||
- Introduce `libibl_lite` library.
|
||||
- engine: Fix `EXC_BAD_INSTRUCTION` seen when using headless SwapChains on macOS with OpenGL.
|
||||
- engine: Add new callback API to `SwapChain`.
|
||||
- engine: Fix SwiftShader crash when using an IBL without a reflections texture.
|
||||
- filamat: Shrink internal `Skybox` material size.
|
||||
- filamat: improvements to generated material size.
|
||||
- filamat: silence spirv-opt warnings in release builds.
|
||||
- matc: Add fog variant filter.
|
||||
- matc: Fix crash when building mobile materials.
|
||||
- math: reduce template bloat for matrices.
|
||||
|
||||
## v1.9.9
|
||||
|
||||
- Vulkan: internal robustness improvements
|
||||
- Metal: Support CVPixelBuffer SwapChains
|
||||
- Metal: Support copyFrame
|
||||
- Fix clear behavior with RenderTarget API.
|
||||
- Fix GetRefractionMode JNI binding
|
||||
- Additional fixes for Fence bug
|
||||
|
||||
## v1.9.8
|
||||
|
||||
- Fix a few Fence-related bugs
|
||||
- gltfio: add createInstance() to AssetLoader.
|
||||
- gltfio: fix ASAN issue when consuming invalid animation.
|
||||
- gltfio: do not segfault on invalid primitives.
|
||||
- gltfio: add safety checks to getAnimator.
|
||||
- gltfio: fix segfault when consuming invalid file.
|
||||
- Vulkan: various internal refactoring and improvements
|
||||
- mathio: add ostream operator for quaternions.
|
||||
- Fix color grading not applied when dithering is off.
|
||||
|
||||
## v1.9.7
|
||||
|
||||
- Vulkan: improvements to the ReadPixels implementation.
|
||||
- Vulkan: warn instead of panic for sampler overflow.
|
||||
- Vulkan: fix leak with headless swap chain.
|
||||
- PlatformVkLinux now supports all combos of XLIB and XCB.
|
||||
- Fix TypeScript binding for TextureUsage.
|
||||
|
||||
## v1.9.6
|
||||
|
||||
- Added View::setVsmShadowOptions (experimental)
|
||||
- Add anisotropic shadow map sampling with VSM (experimental)
|
||||
- matc: fixed bug where some compilation failures still exited with code 0
|
||||
- Vulkan + Android: fix build break
|
||||
- Add optional XCB support to PlatformVkLinux
|
||||
- Fix Vulkan black screen on Windows with NVIDIA hardware
|
||||
|
||||
## v1.9.5
|
||||
|
||||
- Added a new Live Wallpaper Android sample
|
||||
- `UiHelper` now supports managing a `SurfaceHolder`
|
||||
- Fix: an internal texture resource was never destroyed
|
||||
- Fix: hang on 2-CPU machines
|
||||
- Fix: Vulkan crash when using shadow cascades
|
||||
- Linux fixes for headless SwiftShader
|
||||
- Fix null pointer dereference in `FIndirectLight`
|
||||
- Fix Windows build by avoiding nested initializers
|
||||
- Vulkan: support readPixels and headless swap chains
|
||||
- VSM improvements
|
||||
|
||||
## v1.9.4
|
||||
|
||||
- Add screen space cone tracing (SSCT)
|
||||
- Improvements to VSM shadow quality
|
||||
- New `ShadowOptions` control to render Variance Shadow Maps (VSM) with MSAA (experimental)
|
||||
- Improvements and fixes to screen-space ambient occlusion
|
||||
- gltf_viewer: add --headless option
|
||||
- gltf_viewer: Add new automation UI and functionality
|
||||
|
||||
## v1.9.3
|
||||
|
||||
|
||||
@@ -6,11 +6,29 @@ In addition to the requirements for [building Filament on Windows](../BUILDING.m
|
||||
need the Android SDK and NDK. See [Getting Started with the
|
||||
NDK](https://developer.android.com/ndk/guides/) for detailed installation instructions.
|
||||
|
||||
You'll also need [Ninja 1.8](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) (or
|
||||
more recent) and [Git for Windows](https://git-scm.com/download/win) to clone the repository and run
|
||||
Bash scripts.
|
||||
|
||||
Ensure the `%ANDROID_HOME%` environment variable is set to your Android SDK installation location.
|
||||
|
||||
On Windows, we require VS2019 for building the host tools. All of the following commands should be
|
||||
executed in a *Visual Studio x64 Native Tools Command Prompt for VS 2019*.
|
||||
|
||||
### A Note About Python 3
|
||||
|
||||
Python 3 is required. If CMake errors because it cannot find Python 3:
|
||||
|
||||
```
|
||||
Could NOT find PythonInterp: Found unsuitable version "1.4", but required is at least "3"
|
||||
```
|
||||
|
||||
then add the following flag to the CMake invocations:
|
||||
|
||||
```
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=\path\to\python3
|
||||
```
|
||||
|
||||
## Desktop Tools
|
||||
|
||||
First, a few Filament tools need to be compiled for desktop.
|
||||
|
||||
@@ -62,11 +62,11 @@ buildscript {
|
||||
// Our minSdkVersion is 19.
|
||||
ext.versions = [
|
||||
'minSdk': 19,
|
||||
'targetSdk': 29,
|
||||
'compileSdk': 29,
|
||||
'kotlin': '1.4.10',
|
||||
'buildTools': '30.0.1',
|
||||
'ndk': '21.3.6528147'
|
||||
'targetSdk': 30,
|
||||
'compileSdk': 30,
|
||||
'kotlin': '1.4.21',
|
||||
'buildTools': '30.0.3',
|
||||
'ndk': '22.0.7026061'
|
||||
]
|
||||
|
||||
ext.deps = [
|
||||
@@ -78,7 +78,7 @@ buildscript {
|
||||
]
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
}
|
||||
|
||||
|
||||
@@ -95,3 +95,25 @@ void JniImageCallback::invoke(void*, void* user) {
|
||||
JniImageCallback* data = reinterpret_cast<JniImageCallback*>(user);
|
||||
delete data;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
JniCallback* JniCallback::make(JNIEnv* env, jobject handler, jobject callback) {
|
||||
return new JniCallback(env, handler, callback);
|
||||
}
|
||||
|
||||
JniCallback::JniCallback(JNIEnv* env, jobject handler, jobject callback)
|
||||
: mEnv(env)
|
||||
, mHandler(env->NewGlobalRef(handler))
|
||||
, mCallback(env->NewGlobalRef(callback)) {
|
||||
acquireCallbackJni(env, mCallbackUtils);
|
||||
}
|
||||
|
||||
JniCallback::~JniCallback() {
|
||||
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
|
||||
}
|
||||
|
||||
void JniCallback::invoke(void* user) {
|
||||
JniCallback* data = reinterpret_cast<JniCallback*>(user);
|
||||
delete data;
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ struct JniImageCallback {
|
||||
|
||||
private:
|
||||
JniImageCallback(JNIEnv* env, jobject handler, jobject runnable, long image);
|
||||
JniImageCallback(JniBufferCallback const &) = delete;
|
||||
JniImageCallback(JniBufferCallback&&) = delete;
|
||||
JniImageCallback(JniImageCallback const &) = delete;
|
||||
JniImageCallback(JniImageCallback&&) = delete;
|
||||
~JniImageCallback();
|
||||
|
||||
JNIEnv* mEnv;
|
||||
@@ -72,3 +72,20 @@ private:
|
||||
long mImage;
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
struct JniCallback {
|
||||
static JniCallback* make(JNIEnv* env, jobject handler, jobject runnable);
|
||||
|
||||
static void invoke(void* user);
|
||||
|
||||
private:
|
||||
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
|
||||
JniCallback(JniCallback const &) = delete;
|
||||
JniCallback(JniCallback&&) = delete;
|
||||
~JniCallback();
|
||||
|
||||
JNIEnv* mEnv;
|
||||
jobject mHandler;
|
||||
jobject mCallback;
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
@@ -33,13 +33,16 @@ add_library(shaders STATIC IMPORTED)
|
||||
set_target_properties(shaders PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libshaders.a)
|
||||
|
||||
set(FILAMAT_INCLUDE_DIRS
|
||||
../../libs/utils/include
|
||||
)
|
||||
|
||||
include_directories(${FILAMENT_DIR}/include)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libfilamat-jni.map")
|
||||
|
||||
add_library(filamat-jni SHARED
|
||||
src/main/cpp/MaterialBuilder.cpp
|
||||
)
|
||||
add_library(filamat-jni SHARED src/main/cpp/MaterialBuilder.cpp)
|
||||
target_include_directories(filamat-jni PRIVATE ${FILAMAT_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(filamat-jni
|
||||
${FILAMAT_FLAVOR}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
|
||||
#include <utils/JobSystem.h>
|
||||
|
||||
using namespace filament;
|
||||
using namespace filamat;
|
||||
|
||||
@@ -45,9 +47,23 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nDestroyMaterialBuilder
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nBuilderBuild(JNIEnv*, jclass,
|
||||
jlong nativeBuilder) {
|
||||
jlong nativeBuilder, jlong nativeJobSystem) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
return (jlong) new Package(builder->build());
|
||||
auto jobSystem = (utils::JobSystem*) nativeJobSystem;
|
||||
|
||||
if (nativeJobSystem == 0) {
|
||||
jobSystem = new utils::JobSystem;
|
||||
jobSystem->adopt();
|
||||
}
|
||||
|
||||
jlong result = (jlong) new Package(builder->build(*jobSystem));
|
||||
|
||||
if (nativeJobSystem == 0) {
|
||||
jobSystem->emancipate();
|
||||
delete jobSystem;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jbyteArray JNICALL
|
||||
|
||||
@@ -17,17 +17,29 @@
|
||||
package com.google.android.filament.filamat;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MaterialBuilder {
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
|
||||
// Keep to finalize native resources
|
||||
private final BuilderFinalizer mFinalizer;
|
||||
private final long mNativeObject;
|
||||
|
||||
private static Class<?> sEngineClass = null;
|
||||
private static Method sGetNativeJobSystemMethod = null;
|
||||
|
||||
static {
|
||||
System.loadLibrary("filamat-jni");
|
||||
try {
|
||||
sEngineClass = Class.forName("com.google.android.filament.Engine");
|
||||
sGetNativeJobSystemMethod = sEngineClass.getDeclaredMethod("getNativeJobSystem");
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
// It's okay if we don't find it, this is to avoid creating dependencies
|
||||
}
|
||||
}
|
||||
|
||||
public enum Shading {
|
||||
@@ -421,9 +433,55 @@ public class MaterialBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates, builds, and returns the compiled material. While this method never
|
||||
* returns null, the returned {@link MaterialPackage} may be invalid. Call
|
||||
* {@link MaterialPackage#isValid()} before using it.
|
||||
*
|
||||
* Calling this method is equivalent to calling {@link #build(Object)} and passing
|
||||
* <code>null</code> as the job system provider.
|
||||
*
|
||||
* @see #build(Object)
|
||||
*/
|
||||
@NonNull
|
||||
public MaterialPackage build() {
|
||||
long nativePackage = nBuilderBuild(mNativeObject);
|
||||
return build(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates, builds, and returns the compiled material. While this method never
|
||||
* returns null, the returned {@link MaterialPackage} may be invalid. Call
|
||||
* {@link MaterialPackage#isValid()} before using it.
|
||||
*
|
||||
* You can pass a job system provider to this method, or null. When passing null
|
||||
* or an invalid job system provider, a temporary job system will be created which
|
||||
* is less efficient than reusing an existing job system.
|
||||
*
|
||||
* Currently the only valid type of job system provider is an <code>Engine</code>
|
||||
* instance from the main Filament library (<code>com.google.android.filament.Engine</code>).
|
||||
*
|
||||
* If you are using Filament and the filamat library together you <em>must</em> pass an
|
||||
* <code>Engine</code> as the job system provider, <em>or</em> invoke
|
||||
* <code>MaterialBuilder</code> from a thread other than the thread used to invoke Filament
|
||||
* APIs.
|
||||
*
|
||||
* @param jobSystemProvider An <code>Engine</code> instance or null
|
||||
*/
|
||||
@NonNull
|
||||
public MaterialPackage build(@Nullable Object jobSystemProvider) {
|
||||
long nativeJobSystem = 0;
|
||||
if (jobSystemProvider != null && sEngineClass != null) {
|
||||
if (sEngineClass.isInstance(jobSystemProvider) && sGetNativeJobSystemMethod != null) {
|
||||
try {
|
||||
//noinspection ConstantConditions
|
||||
nativeJobSystem = (Long) sGetNativeJobSystemMethod.invoke(jobSystemProvider);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long nativePackage = nBuilderBuild(mNativeObject, nativeJobSystem);
|
||||
byte[] data = nGetPackageBytes(nativePackage);
|
||||
MaterialPackage result =
|
||||
new MaterialPackage(ByteBuffer.wrap(data), nGetPackageIsValid(nativePackage));
|
||||
@@ -455,7 +513,7 @@ public class MaterialBuilder {
|
||||
private static native long nCreateMaterialBuilder();
|
||||
private static native void nDestroyMaterialBuilder(long nativeBuilder);
|
||||
|
||||
private static native long nBuilderBuild(long nativeBuilder);
|
||||
private static native long nBuilderBuild(long nativeBuilder, long nativeJobSystem);
|
||||
private static native byte[] nGetPackageBytes(long nativePackage);
|
||||
private static native boolean nGetPackageIsValid(long nativePackage);
|
||||
private static native void nDestroyPackage(long nativePackage);
|
||||
|
||||
@@ -17,9 +17,9 @@ add_library(utils STATIC IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
|
||||
add_library(ibl STATIC IMPORTED)
|
||||
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
|
||||
add_library(ibl-lite STATIC IMPORTED)
|
||||
set_target_properties(ibl-lite PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl-lite.a)
|
||||
|
||||
add_library(filaflat STATIC IMPORTED)
|
||||
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
|
||||
@@ -70,6 +70,7 @@ add_library(filament-jni SHARED
|
||||
src/main/cpp/SkyBox.cpp
|
||||
src/main/cpp/Stream.cpp
|
||||
src/main/cpp/SurfaceOrientation.cpp
|
||||
src/main/cpp/SwapChain.cpp
|
||||
src/main/cpp/Texture.cpp
|
||||
src/main/cpp/TextureSampler.cpp
|
||||
src/main/cpp/TransformManager.cpp
|
||||
@@ -91,7 +92,7 @@ target_link_libraries(filament-jni
|
||||
PRIVATE filaflat
|
||||
PRIVATE filabridge
|
||||
PRIVATE geometry
|
||||
PRIVATE ibl
|
||||
PRIVATE ibl-lite
|
||||
PRIVATE log
|
||||
PRIVATE GLESv3
|
||||
PRIVATE EGL
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
LIBFILAMENT {
|
||||
global: *filament*; JNI*;
|
||||
global:
|
||||
Java_com_google_android_filament_*;
|
||||
JNI*;
|
||||
*filament*Camera*;
|
||||
*filament*Skybox*;
|
||||
*filament*Engine*;
|
||||
*filament*RenderableManager*;
|
||||
*filament*Aabb*;
|
||||
*filament*IndirectLight*;
|
||||
*filament*LightManager*;
|
||||
*filament*Transform*;
|
||||
*filament*Material*;
|
||||
*filament*IndexBuffer*;
|
||||
*filament*VertexBuffer*;
|
||||
*filament*Texture*;
|
||||
*filament*geometry*;
|
||||
|
||||
local: *;
|
||||
};
|
||||
@@ -306,3 +306,9 @@ Java_com_google_android_filament_Engine_nGetRenderableManager(JNIEnv*, jclass,
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) &engine->getRenderableManager();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Engine_nGetJobSystem(JNIEnv*, jclass, jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) &engine->getJobSystem();
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
|
||||
jlong nativeBuilder, jint mapSize, jint cascades, jfloatArray splitPositions,
|
||||
jfloat constantBias, jfloat normalBias, jfloat shadowFar, jfloat shadowNearHint,
|
||||
jfloat shadowFarHint, jboolean stable, jboolean screenSpaceContactShadows, jint stepCount,
|
||||
jfloat maxShadowDistance) {
|
||||
jfloat maxShadowDistance, jint vsmMsaaSamples) {
|
||||
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
|
||||
LightManager::ShadowOptions shadowOptions {
|
||||
.mapSize = (uint32_t)mapSize,
|
||||
@@ -90,7 +90,10 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
|
||||
.stable = (bool)stable,
|
||||
.screenSpaceContactShadows = (bool)screenSpaceContactShadows,
|
||||
.stepCount = uint8_t(stepCount),
|
||||
.maxShadowDistance = maxShadowDistance
|
||||
.maxShadowDistance = maxShadowDistance,
|
||||
.vsm = {
|
||||
.msaaSamples = (uint8_t) vsmMsaaSamples
|
||||
}
|
||||
};
|
||||
jfloat *nativeSplits = env->GetFloatArrayElements(splitPositions, NULL);
|
||||
const jsize splitCount = std::min((jsize) 3, env->GetArrayLength(splitPositions));
|
||||
|
||||
@@ -91,7 +91,7 @@ Java_com_google_android_filament_Material_nGetBlendingMode(JNIEnv*, jclass,
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Material_nGetRefraction(JNIEnv*, jclass,
|
||||
Java_com_google_android_filament_Material_nGetRefractionMode(JNIEnv*, jclass,
|
||||
jlong nativeMaterial) {
|
||||
Material* material = (Material*) nativeMaterial;
|
||||
return (jint)material->getRefractionMode();
|
||||
@@ -204,9 +204,20 @@ Java_com_google_android_filament_Material_nGetParameters(JNIEnv* env, jclass,
|
||||
jfieldID parameterSamplerOffset = env->GetStaticFieldID(parameterClass,
|
||||
"SAMPLER_OFFSET", "I");
|
||||
|
||||
jfieldID parameterSubpassOffset = env->GetStaticFieldID(parameterClass,
|
||||
"SUBPASS_OFFSET", "I");
|
||||
|
||||
jint offset = env->GetStaticIntField(parameterClass, parameterSamplerOffset);
|
||||
jint subpassOffset = env->GetStaticIntField(parameterClass, parameterSubpassOffset);
|
||||
for (size_t i = 0; i < received; i++) {
|
||||
jint type = info[i].isSampler ? (jint) info[i].samplerType + offset : (jint) info[i].type;
|
||||
jint type;
|
||||
if (info[i].isSampler) {
|
||||
type = (jint) info[i].samplerType + offset;
|
||||
} else if (info[i].isSubpass) {
|
||||
type = subpassOffset;
|
||||
} else {
|
||||
type = (jint) info[i].type;
|
||||
}
|
||||
|
||||
env->CallStaticVoidMethod(
|
||||
parameterClass, parameterAdd,
|
||||
|
||||
31
android/filament-android/src/main/cpp/SwapChain.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 <filament/SwapChain.h>
|
||||
|
||||
#include "common/CallbackUtils.h"
|
||||
|
||||
using namespace filament;
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* env, jclass,
|
||||
jlong nativeSwapChain, jobject handler, jobject runnable) {
|
||||
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
|
||||
auto *callback = JniCallback::make(env, handler, runnable);
|
||||
swapChain->setFrameCompletedCallback(&JniCallback::invoke, callback);
|
||||
}
|
||||
@@ -130,6 +130,21 @@ Java_com_google_android_filament_View_nSetDynamicResolutionOptions(JNIEnv*, jcla
|
||||
view->setDynamicResolutionOptions(options);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetShadowType(JNIEnv*, jclass, jlong nativeView, jint type) {
|
||||
View* view = (View*) nativeView;
|
||||
view->setShadowType((View::ShadowType) type);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetVsmShadowOptions(JNIEnv*, jclass, jlong nativeView,
|
||||
jint anisotropy) {
|
||||
View* view = (View*) nativeView;
|
||||
View::VsmShadowOptions options;
|
||||
options.anisotropy = (uint8_t) anisotropy;
|
||||
view->setVsmShadowOptions(options);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetRenderQuality(JNIEnv*, jclass,
|
||||
@@ -196,19 +211,41 @@ Java_com_google_android_filament_View_nGetAmbientOcclusion(JNIEnv*, jclass, jlon
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetAmbientOcclusionOptions(JNIEnv*, jclass,
|
||||
jlong nativeView, jfloat radius, jfloat bias, jfloat power, jfloat resolution, jfloat intensity,
|
||||
jint quality, jint upsampling, jboolean enabled, jfloat minHorizonAngleRad) {
|
||||
jint quality, jint lowPassFilter, jint upsampling, jboolean enabled, jfloat minHorizonAngleRad) {
|
||||
View* view = (View*) nativeView;
|
||||
View::AmbientOcclusionOptions options = {
|
||||
.radius = radius,
|
||||
.power = power,
|
||||
.bias = bias,
|
||||
.resolution = resolution,
|
||||
.intensity = intensity,
|
||||
.quality = (View::QualityLevel)quality,
|
||||
.upsampling = (View::QualityLevel)upsampling,
|
||||
.enabled = (bool)enabled,
|
||||
.minHorizonAngleRad = minHorizonAngleRad
|
||||
};
|
||||
View::AmbientOcclusionOptions options = view->getAmbientOcclusionOptions();
|
||||
options.radius = radius;
|
||||
options.power = power;
|
||||
options.bias = bias;
|
||||
options.resolution = resolution;
|
||||
options.intensity = intensity;
|
||||
options.quality = (View::QualityLevel)quality;
|
||||
options.lowPassFilter = (View::QualityLevel)lowPassFilter;
|
||||
options.upsampling = (View::QualityLevel)upsampling;
|
||||
options.enabled = (bool)enabled;
|
||||
options.minHorizonAngleRad = minHorizonAngleRad;
|
||||
view->setAmbientOcclusionOptions(options);
|
||||
}
|
||||
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetSSCTOptions(JNIEnv *, jclass, jlong nativeView,
|
||||
jfloat ssctLightConeRad, jfloat ssctStartTraceDistance, jfloat ssctContactDistanceMax,
|
||||
jfloat ssctIntensity, jfloat ssctLightDirX, jfloat ssctLightDirY, jfloat ssctLightDirZ,
|
||||
jfloat ssctDepthBias, jfloat ssctDepthSlopeBias, jint ssctSampleCount,
|
||||
jint ssctRayCount, jboolean ssctEnabled) {
|
||||
View* view = (View*) nativeView;
|
||||
View::AmbientOcclusionOptions options = view->getAmbientOcclusionOptions();
|
||||
options.ssct.lightConeRad = ssctLightConeRad;
|
||||
options.ssct.shadowDistance = ssctStartTraceDistance;
|
||||
options.ssct.contactDistanceMax = ssctContactDistanceMax;
|
||||
options.ssct.intensity = ssctIntensity;
|
||||
options.ssct.lightDirection = math::float3{ ssctLightDirX, ssctLightDirY, ssctLightDirZ };
|
||||
options.ssct.depthBias = ssctDepthBias;
|
||||
options.ssct.depthSlopeBias = ssctDepthSlopeBias;
|
||||
options.ssct.sampleCount = (uint8_t)ssctSampleCount;
|
||||
options.ssct.rayCount = (uint8_t)ssctRayCount;
|
||||
options.ssct.enabled = (bool)ssctEnabled;
|
||||
view->setAmbientOcclusionOptions(options);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,14 @@ bool acquireDrawingSurface(JNIEnv* env, jobject surface,
|
||||
jboolean foundJawt = JNI_FALSE;
|
||||
for (int jawtVersion : jawtVersions) {
|
||||
awt.version = jawtVersion;
|
||||
#if defined(__APPLE__) && defined(__aarch64__)
|
||||
// FIXME: enable Apple Silicon build. The problem here is that we attempt to link an x86 jdk and that fails
|
||||
// so JAWT_GetAWT doesn't exist at link time.
|
||||
#warning "FIXME: JAWT_GetAWT() not supported"
|
||||
foundJawt = {};
|
||||
#else
|
||||
foundJawt = JAWT_GetAWT(env, &awt);
|
||||
#endif
|
||||
if (foundJawt == JNI_TRUE) {
|
||||
#ifndef NDEBUG
|
||||
printf("Found valid AWT v%08x.\n", jawtVersion);
|
||||
|
||||
@@ -270,7 +270,7 @@ public class ColorGrading {
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder shadowsMidtonesHighlights(
|
||||
public Builder shadowsMidtonesHighlights(
|
||||
@NonNull @Size(min = 4) float[] shadows,
|
||||
@NonNull @Size(min = 4) float[] midtones,
|
||||
@NonNull @Size(min = 4) float[] highlights,
|
||||
@@ -309,7 +309,7 @@ public class ColorGrading {
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder slopeOffsetPower(
|
||||
public Builder slopeOffsetPower(
|
||||
@NonNull @Size(min = 3) float[] slope,
|
||||
@NonNull @Size(min = 3) float[] offset,
|
||||
@NonNull @Size(min = 3) float[] power) {
|
||||
@@ -360,7 +360,7 @@ public class ColorGrading {
|
||||
*
|
||||
* @return This Builder, for chaining calls
|
||||
*/
|
||||
Builder vibrance(float vibrance) {
|
||||
public Builder vibrance(float vibrance) {
|
||||
nBuilderVibrance(mNativeBuilder, vibrance);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -568,7 +568,7 @@ public class Engine {
|
||||
* Destroys a {@link ColorGrading} and frees all its associated resources.
|
||||
* @param colorGrading the {@link ColorGrading} to destroy
|
||||
*/
|
||||
public void destroySkybox(@NonNull ColorGrading colorGrading) {
|
||||
public void destroyColorGrading(@NonNull ColorGrading colorGrading) {
|
||||
assertDestroy(nDestroyColorGrading(getNativeObject(), colorGrading.getNativeObject()));
|
||||
colorGrading.clearNativeObject();
|
||||
}
|
||||
@@ -654,13 +654,21 @@ public class Engine {
|
||||
return mNativeObject;
|
||||
}
|
||||
|
||||
@UsedByReflection("MaterialBuilder.java")
|
||||
public long getNativeJobSystem() {
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Calling method on destroyed Engine");
|
||||
}
|
||||
return nGetJobSystem(getNativeObject());
|
||||
}
|
||||
|
||||
private void clearNativeObject() {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static void assertDestroy(boolean success) {
|
||||
if (!success) {
|
||||
throw new IllegalStateException("Object couldn't be destoyed (double destroy()?)");
|
||||
throw new IllegalStateException("Object couldn't be destroyed (double destroy()?)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,4 +706,5 @@ public class Engine {
|
||||
private static native long nGetTransformManager(long nativeEngine);
|
||||
private static native long nGetLightManager(long nativeEngine);
|
||||
private static native long nGetRenderableManager(long nativeEngine);
|
||||
private static native long nGetJobSystem(long nativeEngine);
|
||||
}
|
||||
|
||||
@@ -305,6 +305,25 @@ public class LightManager {
|
||||
*</p>
|
||||
*/
|
||||
public float maxShadowDistance = 0.3f;
|
||||
|
||||
/*
|
||||
* Options prefixed with 'vsm' are available when the View's ShadowType is set to VSM.
|
||||
*
|
||||
* @see View#setShadowType
|
||||
*/
|
||||
|
||||
/**
|
||||
* The number of MSAA samples to use when rendering VSM shadow maps.
|
||||
* Must be a power-of-two and greater than or equal to 1. A value of 1 effectively turns
|
||||
* off MSAA.
|
||||
* Higher values may not be available depending on the underlying hardware.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Warning: This API is still experimental and subject to change.</strong>
|
||||
* </p>
|
||||
*/
|
||||
@IntRange(from = 1)
|
||||
public int vsmMsaaSamples = 1;
|
||||
}
|
||||
|
||||
public static class ShadowCascades {
|
||||
@@ -433,7 +452,7 @@ public class LightManager {
|
||||
options.mapSize, options.shadowCascades, options.cascadeSplitPositions,
|
||||
options.constantBias, options.normalBias, options.shadowFar, options.shadowNearHint,
|
||||
options.shadowFarHint, options.stable, options.screenSpaceContactShadows,
|
||||
options.stepCount, options.maxShadowDistance);
|
||||
options.stepCount, options.maxShadowDistance, options.vsmMsaaSamples);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1059,7 +1078,7 @@ public class LightManager {
|
||||
private static native void nDestroyBuilder(long nativeBuilder);
|
||||
private static native boolean nBuilderBuild(long nativeBuilder, long nativeEngine, int entity);
|
||||
private static native void nBuilderCastShadows(long nativeBuilder, boolean enable);
|
||||
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, int cascades, float[] splitPositions, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable, boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance);
|
||||
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, int cascades, float[] splitPositions, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable, boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance, int vsmMsaaSamples);
|
||||
private static native void nBuilderCastLight(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderPosition(long nativeBuilder, float x, float y, float z);
|
||||
private static native void nBuilderDirection(long nativeBuilder, float x, float y, float z);
|
||||
|
||||
@@ -233,7 +233,8 @@ public class Material {
|
||||
SAMPLER_2D_ARRAY,
|
||||
SAMPLER_CUBEMAP,
|
||||
SAMPLER_EXTERNAL,
|
||||
SAMPLER_3D
|
||||
SAMPLER_3D,
|
||||
SUBPASS_INPUT
|
||||
}
|
||||
|
||||
public enum Precision {
|
||||
@@ -247,6 +248,10 @@ public class Material {
|
||||
@UsedByNative("Material.cpp")
|
||||
private static final int SAMPLER_OFFSET = Type.MAT4.ordinal() + 1;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@UsedByNative("Material.cpp")
|
||||
private static final int SUBPASS_OFFSET = Type.SAMPLER_3D.ordinal() + 1;
|
||||
|
||||
@NonNull
|
||||
public final String name;
|
||||
@NonNull
|
||||
|
||||
@@ -131,7 +131,7 @@ public class RenderableManager {
|
||||
* @param type specifies the topology of the primitive (e.g., PrimitiveType.TRIANGLES)
|
||||
* @param vertices specifies the vertex buffer, which in turn specifies a set of attributes
|
||||
* @param indices specifies the index buffer (either u16 or u32)
|
||||
* @param offset specifies where in the index buffer to start reading (expressed as a number of bytes)
|
||||
* @param offset specifies where in the index buffer to start reading (expressed as a number of indices)
|
||||
* @param minIndex specifies the minimum index contained in the index buffer
|
||||
* @param maxIndex specifies the maximum index contained in the index buffer
|
||||
* @param count number of indices to read (for triangles, this should be a multiple of 3)
|
||||
@@ -268,6 +268,14 @@ public class RenderableManager {
|
||||
|
||||
/**
|
||||
* Controls if this renderable casts shadows, false by default.
|
||||
*
|
||||
* If the View's shadow type is set to {@link View.ShadowType#VSM}, castShadows should only
|
||||
* be disabled if either is true:
|
||||
* <ul>
|
||||
* <li>{@link RenderableManager#setReceiveShadows} is also disabled</li>
|
||||
* <li>the object is guaranteed to not cast shadows on itself or other objects (for
|
||||
* example, a ground plane)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@NonNull
|
||||
public Builder castShadows(boolean enabled) {
|
||||
|
||||
@@ -85,6 +85,12 @@ public class SwapChain {
|
||||
*/
|
||||
public static final long CONFIG_READABLE = 0x2;
|
||||
|
||||
/**
|
||||
* Indicates that the native X11 window is an XCB window rather than an XLIB window.
|
||||
* This is ignored on non-Linux platforms and in builds that support only one X11 API.
|
||||
*/
|
||||
public static final long CONFIG_ENABLE_XCB = 0x4;
|
||||
|
||||
SwapChain(long nativeSwapChain, Object surface) {
|
||||
mNativeObject = nativeSwapChain;
|
||||
mSurface = surface;
|
||||
@@ -98,6 +104,31 @@ public class SwapChain {
|
||||
return mSurface;
|
||||
}
|
||||
|
||||
/**
|
||||
* FrameCompletedCallback is a callback function that notifies an application when a frame's
|
||||
* contents have completed rendering on the GPU.
|
||||
*
|
||||
* <p>
|
||||
* Use setFrameCompletedCallback to set a callback on an individual SwapChain. Each time a frame
|
||||
* completes GPU rendering, the callback will be called.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The FrameCompletedCallback is guaranteed to be called on the main Filament thread.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Warning: Only Filament's Metal backend supports frame callbacks. Other backends ignore the
|
||||
* callback (which will never be called) and proceed normally.
|
||||
* </p>
|
||||
*
|
||||
* @param handler A {@link java.util.concurrent.Executor Executor}.
|
||||
* @param callback The Runnable callback to invoke.
|
||||
*/
|
||||
public void setFrameCompletedCallback(@NonNull Object handler, @NonNull Runnable callback) {
|
||||
nSetFrameCompletedCallback(getNativeObject(), handler, callback);
|
||||
}
|
||||
|
||||
public long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Calling method on destroyed SwapChain");
|
||||
@@ -108,4 +139,6 @@ public class SwapChain {
|
||||
void clearNativeObject() {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static native void nSetFrameCompletedCallback(long nativeSwapChain, Object handler, Runnable callback);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class View {
|
||||
private VignetteOptions mVignetteOptions;
|
||||
private ColorGrading mColorGrading;
|
||||
private TemporalAntiAliasingOptions mTemporalAntiAliasingOptions;
|
||||
private VsmShadowOptions mVsmShadowOptions;
|
||||
|
||||
/**
|
||||
* Generic quality level.
|
||||
@@ -176,6 +177,14 @@ public class View {
|
||||
@NonNull
|
||||
public QualityLevel quality = QualityLevel.LOW;
|
||||
|
||||
/**
|
||||
* The lowPassFilter setting controls the quality of the low pass filter applied to
|
||||
* AO estimation. The default is QualityLevel.MEDIUM which is sufficient for most mobile
|
||||
* applications. QualityLevel.LOW disables the filter entirely.
|
||||
*/
|
||||
@NonNull
|
||||
public QualityLevel lowPassFilter = QualityLevel.MEDIUM;
|
||||
|
||||
/**
|
||||
* The upsampling setting controls the quality of the ambient occlusion buffer upsampling.
|
||||
* The default is QualityLevel.LOW and uses bilinear filtering, a value of
|
||||
@@ -195,6 +204,64 @@ public class View {
|
||||
* For e.g. a good values to try could be around 0.2.
|
||||
*/
|
||||
public float minHorizonAngleRad = 0.0f;
|
||||
|
||||
|
||||
/**
|
||||
* Full cone angle in radian, between 0 and pi/2. This affects the softness of the shadows,
|
||||
* as well as how far they are cast. A smaller angle yields to sharper and shorter shadows.
|
||||
* The default angle is about 60 degrees.
|
||||
*/
|
||||
public float ssctLightConeRad = 1.0f;
|
||||
|
||||
/**
|
||||
* Distance from where tracing starts.
|
||||
* This affects how far shadows are cast.
|
||||
*/
|
||||
public float ssctStartTraceDistance = 0.01f;
|
||||
|
||||
/**
|
||||
* Maximum contact distance with the cone. Intersections between the traced cone and
|
||||
* geometry samller than this distance are ignored.
|
||||
*/
|
||||
public float ssctContactDistanceMax = 1.0f;
|
||||
|
||||
/**
|
||||
* Intensity of the shadows.
|
||||
*/
|
||||
public float ssctIntensity = 0.8f;
|
||||
|
||||
/**
|
||||
* Light direction.
|
||||
*/
|
||||
@NonNull @Size(min = 3)
|
||||
public float[] ssctLightDirection = { 0, -1, 0 };
|
||||
|
||||
/**
|
||||
* Depth bias in world units (mitigate self shadowing)
|
||||
*/
|
||||
public float ssctDepthBias = 0.01f;
|
||||
|
||||
/**
|
||||
* Depth slope bias (mitigate self shadowing)
|
||||
*/
|
||||
public float ssctDepthSlopeBias = 0.01f;
|
||||
|
||||
/**
|
||||
* Tracing sample count, between 1 and 255. This affects the quality as well as the
|
||||
* distance of the shadows.
|
||||
*/
|
||||
public int ssctSampleCount = 4;
|
||||
|
||||
/**
|
||||
* Numbers of rays to trace, between 1 and 255. This affects the noise of the shadows.
|
||||
* Performance degrades quickly with this value.
|
||||
*/
|
||||
public int ssctRayCount = 1;
|
||||
|
||||
/**
|
||||
* Enables or disables SSCT.
|
||||
*/
|
||||
public boolean ssctEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,6 +566,42 @@ public class View {
|
||||
TEMPORAL
|
||||
}
|
||||
|
||||
/**
|
||||
* List of available shadow mapping techniques.
|
||||
*
|
||||
* @see #setShadowType
|
||||
*/
|
||||
public enum ShadowType {
|
||||
/**
|
||||
* Percentage-closer filtered shadows (default).
|
||||
*/
|
||||
PCF,
|
||||
|
||||
/**
|
||||
* Variance shadows.
|
||||
*/
|
||||
VSM
|
||||
}
|
||||
|
||||
/**
|
||||
* View-level options for VSM shadowing.
|
||||
*
|
||||
* @see View#setVsmShadowOptions
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* <p>
|
||||
* The number of anisotropic samples = 2 ^ vsmAnisotropy.
|
||||
* </p>
|
||||
*
|
||||
* <strong>Warning: This API is still experimental and subject to change.</strong>
|
||||
*/
|
||||
public int anisotropy = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to select buffers.
|
||||
*/
|
||||
@@ -1080,6 +1183,56 @@ public class View {
|
||||
nSetDynamicLightingOptions(getNativeObject(), zLightNear, zLightFar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the shadow mapping technique this View uses.
|
||||
*
|
||||
* The ShadowType affects all the shadows seen within the View.
|
||||
*
|
||||
* <p>
|
||||
* {@link ShadowType#VSM} imposes a restriction on marking renderables as only shadow receivers
|
||||
* (but not casters). To ensure correct shadowing with VSM, all shadow participant renderables
|
||||
* should be marked as both receivers and casters. Objects that are guaranteed to not cast
|
||||
* shadows on themselves or other objects (such as flat ground planes) can be set to not cast
|
||||
* shadows, which might improve shadow quality.
|
||||
* </p>
|
||||
*
|
||||
* <strong>Warning: This API is still experimental and subject to change.</strong>
|
||||
*/
|
||||
public void setShadowType(ShadowType type) {
|
||||
nSetShadowType(getNativeObject(), type.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets VSM shadowing options that apply across the entire View.
|
||||
*
|
||||
* Additional light-specific VSM options can be set with
|
||||
* {@link LightManager.Builder#shadowOptions}.
|
||||
*
|
||||
* Only applicable when shadow type is set to ShadowType::VSM.
|
||||
*
|
||||
* <strong>Warning: This API is still experimental and subject to change.</strong>
|
||||
*
|
||||
* @param options Options for shadowing.
|
||||
* @see #setShadowType
|
||||
*/
|
||||
public void setVsmShadowOptions(@NonNull VsmShadowOptions options) {
|
||||
mVsmShadowOptions = options;
|
||||
nSetVsmShadowOptions(getNativeObject(), options.anisotropy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the VSM shadowing options.
|
||||
* @see #setVsmShadowOptions
|
||||
* @return VSM shadow options currently set.
|
||||
*/
|
||||
@NonNull
|
||||
public VsmShadowOptions getVsmShadowOptions() {
|
||||
if (mVsmShadowOptions == null) {
|
||||
mVsmShadowOptions = new VsmShadowOptions();
|
||||
}
|
||||
return mVsmShadowOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates or deactivates ambient occlusion.
|
||||
* @see #setAmbientOcclusionOptions
|
||||
@@ -1109,8 +1262,12 @@ public class View {
|
||||
public void setAmbientOcclusionOptions(@NonNull AmbientOcclusionOptions options) {
|
||||
mAmbientOcclusionOptions = options;
|
||||
nSetAmbientOcclusionOptions(getNativeObject(), options.radius, options.bias, options.power,
|
||||
options.resolution, options.intensity, options.quality.ordinal(), options.upsampling.ordinal(),
|
||||
options.resolution, options.intensity, options.quality.ordinal(), options.lowPassFilter.ordinal(), options.upsampling.ordinal(),
|
||||
options.enabled, options.minHorizonAngleRad);
|
||||
nSetSSCTOptions(getNativeObject(), options.ssctLightConeRad, options.ssctStartTraceDistance, options.ssctContactDistanceMax, options.ssctIntensity,
|
||||
options.ssctLightDirection[0], options.ssctLightDirection[1], options.ssctLightDirection[2],
|
||||
options.ssctDepthBias, options.ssctDepthSlopeBias, options.ssctSampleCount,
|
||||
options.ssctRayCount, options.ssctEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1267,6 +1424,8 @@ public class View {
|
||||
private static native void nSetDynamicResolutionOptions(long nativeView, boolean enabled, boolean homogeneousScaling, float minScale, float maxScale, int quality);
|
||||
private static native void nSetRenderQuality(long nativeView, int hdrColorBufferQuality);
|
||||
private static native void nSetDynamicLightingOptions(long nativeView, float zLightNear, float zLightFar);
|
||||
private static native void nSetShadowType(long nativeView, int type);
|
||||
private static native void nSetVsmShadowOptions(long nativeView, int anisotropy);
|
||||
private static native void nSetColorGrading(long nativeView, long nativeColorGrading);
|
||||
private static native void nSetPostProcessingEnabled(long nativeView, boolean enabled);
|
||||
private static native boolean nIsPostProcessingEnabled(long nativeView);
|
||||
@@ -1274,7 +1433,8 @@ public class View {
|
||||
private static native boolean nIsFrontFaceWindingInverted(long nativeView);
|
||||
private static native void nSetAmbientOcclusion(long nativeView, int ordinal);
|
||||
private static native int nGetAmbientOcclusion(long nativeView);
|
||||
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution, float intensity, int quality, int upsampling, boolean enabled, float minHorizonAngleRad);
|
||||
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution, float intensity, int quality, int lowPassFilter, int upsampling, boolean enabled, float minHorizonAngleRad);
|
||||
private static native void nSetSSCTOptions(long nativeView, float ssctLightConeRad, float ssctStartTraceDistance, float ssctContactDistanceMax, float ssctIntensity, float v, float v1, float v2, float ssctDepthBias, float ssctDepthSlopeBias, int ssctSampleCount, int ssctRayCount, boolean ssctEnabled);
|
||||
private static native void nSetBloomOptions(long nativeView, long dirtNativeObject, float dirtStrength, float strength, int resolution, float anamorphism, int levels, int blendMode, boolean threshold, boolean enabled, float highlight);
|
||||
private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, boolean enabled);
|
||||
private static native void nSetBlendMode(long nativeView, int blendMode);
|
||||
|
||||
@@ -30,8 +30,8 @@ import android.view.TextureView;
|
||||
import com.google.android.filament.SwapChain;
|
||||
|
||||
/**
|
||||
* UiHelper is a simple class that can manage either a SurfaceView or a TextureView so it can
|
||||
* be used to render into with Filament.
|
||||
* UiHelper is a simple class that can manage either a SurfaceView, TextureView, or a SurfaceHolder
|
||||
* so it can be used to render into with Filament.
|
||||
*
|
||||
* Here is a simple example with a SurfaceView. The code would be exactly the same with a
|
||||
* TextureView:
|
||||
@@ -191,6 +191,23 @@ public class UiHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static class SurfaceHolderHandler implements RenderSurface {
|
||||
private SurfaceHolder mSurfaceHolder;
|
||||
|
||||
SurfaceHolderHandler(SurfaceHolder surface) {
|
||||
mSurfaceHolder = surface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
mSurfaceHolder.setFixedSize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
}
|
||||
}
|
||||
|
||||
private class TextureViewHandler implements RenderSurface {
|
||||
private TextureView mTextureView;
|
||||
private Surface mSurface;
|
||||
@@ -258,8 +275,8 @@ public class UiHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources associated to the native window specified in {@link #attachTo(SurfaceView)}
|
||||
* or {@link #attachTo(TextureView)}.
|
||||
* Free resources associated to the native window specified in {@link #attachTo(SurfaceView)},
|
||||
* {@link #attachTo(TextureView)}, or {@link #attachTo(SurfaceHolder)}.
|
||||
*/
|
||||
public void detach() {
|
||||
destroySwapChain();
|
||||
@@ -315,8 +332,8 @@ public class UiHelper {
|
||||
* Controls whether the render target (SurfaceView or TextureView) is opaque or not.
|
||||
* The render target is considered opaque by default.
|
||||
*
|
||||
* Must be called before calling {@link #attachTo(SurfaceView)}
|
||||
* or {@link #attachTo(TextureView)}.
|
||||
* Must be called before calling {@link #attachTo(SurfaceView)}, {@link #attachTo(TextureView)},
|
||||
* or {@link #attachTo(SurfaceHolder)}.
|
||||
*
|
||||
* @param opaque Indicates whether the render target should be opaque. True by default.
|
||||
*/
|
||||
@@ -341,6 +358,8 @@ public class UiHelper {
|
||||
* Must be called before calling {@link #attachTo(SurfaceView)}
|
||||
* or {@link #attachTo(TextureView)}.
|
||||
*
|
||||
* Has no effect when using {@link #attachTo(SurfaceHolder)}.
|
||||
*
|
||||
* @param overlay Indicates whether the render target should be rendered below the activity's
|
||||
* surface when transparent.
|
||||
*/
|
||||
@@ -403,7 +422,9 @@ public class UiHelper {
|
||||
|
||||
SurfaceHolder holder = view.getHolder();
|
||||
holder.addCallback(callback);
|
||||
holder.setFixedSize(mDesiredWidth, mDesiredHeight);
|
||||
if (mDesiredWidth > 0 && mDesiredHeight > 0) {
|
||||
holder.setFixedSize(mDesiredWidth, mDesiredHeight);
|
||||
}
|
||||
|
||||
// in case the SurfaceView's surface already existed
|
||||
final Surface surface = holder.getSurface();
|
||||
@@ -483,6 +504,55 @@ public class UiHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate UiHelper with a SurfaceHolder.
|
||||
*
|
||||
* As soon as a Surface is created, we'll create the
|
||||
* EGL resources needed, and call user callbacks if needed.
|
||||
*/
|
||||
public void attachTo(@NonNull SurfaceHolder holder) {
|
||||
if (attach(holder)) {
|
||||
int format = isOpaque() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
|
||||
holder.setFormat(format);
|
||||
|
||||
mRenderSurface = new SurfaceHolderHandler(holder);
|
||||
|
||||
final SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||
if (LOGGING) Log.d(LOG_TAG, "surfaceCreated()");
|
||||
createSwapChain(holder.getSurface());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
// Note: this is always called at least once after surfaceCreated()
|
||||
if (LOGGING) Log.d(LOG_TAG, "surfaceChanged(" + width + ", " + height + ")");
|
||||
mRenderCallback.onResized(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
if (LOGGING) Log.d(LOG_TAG, "surfaceDestroyed()");
|
||||
destroySwapChain();
|
||||
}
|
||||
};
|
||||
|
||||
holder.addCallback(callback);
|
||||
if (mDesiredWidth > 0 && mDesiredHeight > 0) {
|
||||
holder.setFixedSize(mDesiredWidth, mDesiredHeight);
|
||||
}
|
||||
|
||||
// in case the SurfaceHolder's surface already existed
|
||||
final Surface surface = holder.getSurface();
|
||||
if (surface != null && surface.isValid()) {
|
||||
callback.surfaceCreated(holder);
|
||||
callback.surfaceChanged(holder, format,
|
||||
holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean attach(@NonNull Object nativeWindow) {
|
||||
if (mNativeWindow != null) {
|
||||
// we are already attached to a native window
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
flavorDimensions "functionality"
|
||||
|
||||
@@ -29,7 +29,6 @@ set(GLTFIO_SRCS
|
||||
${GLTFIO_DIR}/include/gltfio/AssetLoader.h
|
||||
${GLTFIO_DIR}/include/gltfio/MaterialProvider.h
|
||||
${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
|
||||
${GLTFIO_DIR}/include/gltfio/SimpleViewer.h
|
||||
${GLTFIO_DIR}/include/gltfio/FilamentAsset.h
|
||||
${GLTFIO_DIR}/include/gltfio/FilamentInstance.h
|
||||
|
||||
|
||||
@@ -34,3 +34,10 @@ Java_com_google_android_filament_gltfio_MaterialProvider_nDestroyMaterialProvide
|
||||
auto provider = (MaterialProvider*) nativeProvider;
|
||||
delete provider;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_MaterialProvider_nDestroyMaterials(JNIEnv*, jclass,
|
||||
jlong nativeProvider) {
|
||||
auto provider = (MaterialProvider*) nativeProvider;
|
||||
provider->destroyMaterials();
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ import java.nio.Buffer;
|
||||
public class AssetLoader {
|
||||
private long mNativeObject;
|
||||
private Engine mEngine;
|
||||
private MaterialProvider mMaterialCache;
|
||||
|
||||
/**
|
||||
* Constructs an <code>AssetLoader </code>that can be used to create and destroy instances of
|
||||
* Constructs an <code>AssetLoader</code> that can be used to create and destroy instances of
|
||||
* {@link FilamentAsset}.
|
||||
*
|
||||
* @param engine the engine that the loader should pass to builder objects
|
||||
@@ -100,6 +101,7 @@ public class AssetLoader {
|
||||
}
|
||||
|
||||
mEngine = engine;
|
||||
mMaterialCache = generator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +109,7 @@ public class AssetLoader {
|
||||
*/
|
||||
public void destroy() {
|
||||
nDestroyAssetLoader(mNativeObject);
|
||||
mMaterialCache.destroyMaterials();
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
@@ -152,6 +155,32 @@ public class AssetLoader {
|
||||
return new FilamentAsset(mEngine, nativeAsset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new instance to an instanced asset.
|
||||
*
|
||||
* Use this with caution. It is more efficient to pre-allocate a max number of instances, and
|
||||
* gradually add them to the scene as needed. Instances can also be "recycled" by removing and
|
||||
* re-adding them to the scene.
|
||||
*
|
||||
* NOTE: destroyInstance() does not exist because gltfio favors flat arrays for storage of
|
||||
* entity lists and instance lists, which would be slow to shift. We also wish to discourage
|
||||
* create/destroy churn, as noted above.
|
||||
*
|
||||
* This cannot be called after FilamentAsset#releaseSourceData().
|
||||
* This cannot be called on a non-instanced asset.
|
||||
* Animation is not supported in new instances.
|
||||
* See also AssetLoader#createInstancedAsset().
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings("unused")
|
||||
public FilamentInstance createInstance(@NonNull FilamentAsset asset) {
|
||||
long nativeInstance = nCreateInstance(mNativeObject, asset.getNativeObject());
|
||||
if (nativeInstance == 0) {
|
||||
return null;
|
||||
}
|
||||
return new FilamentInstance(nativeInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows clients to enable diagnostic shading on newly-loaded assets.
|
||||
*/
|
||||
@@ -175,6 +204,7 @@ public class AssetLoader {
|
||||
private static native long nCreateAssetFromJson(long nativeLoader, Buffer buffer, int remaining);
|
||||
private static native long nCreateInstancedAsset(long nativeLoader, Buffer buffer, int remaining,
|
||||
long[] nativeInstances);
|
||||
private static native long nCreateInstance(long nativeLoader, long nativeAsset);
|
||||
private static native void nEnableDiagnostics(long nativeLoader, boolean enable);
|
||||
private static native void nDestroyAsset(long nativeLoader, long nativeAsset);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,11 @@ public class FilamentAsset {
|
||||
if (mAnimator != null) {
|
||||
return mAnimator;
|
||||
}
|
||||
mAnimator = new Animator(nGetAnimator(getNativeObject()));
|
||||
long nativeAnimator = nGetAnimator(getNativeObject());
|
||||
if (nativeAnimator == 0) {
|
||||
throw new IllegalStateException("Unable to create animator");
|
||||
}
|
||||
mAnimator = new Animator(nativeAnimator);
|
||||
return mAnimator;
|
||||
}
|
||||
|
||||
@@ -215,6 +219,7 @@ public class FilamentAsset {
|
||||
*
|
||||
* This should only be called after ResourceLoader#loadResources().
|
||||
* If using Animator, this should be called after getAnimator().
|
||||
* If this is an instanced asset, this prevents creation of new instances.
|
||||
*/
|
||||
public void releaseSourceData() {
|
||||
nReleaseSourceData(mNativeObject);
|
||||
|
||||
@@ -47,10 +47,21 @@ public class MaterialProvider {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys all cached materials.
|
||||
*
|
||||
* This is not called automatically when MaterialProvider is destroyed, which allows
|
||||
* clients to take ownership of the cache if desired.
|
||||
*/
|
||||
public void destroyMaterials() {
|
||||
nDestroyMaterials(mNativeObject);
|
||||
}
|
||||
|
||||
long getNativeObject() {
|
||||
return mNativeObject;
|
||||
}
|
||||
|
||||
private static native long nCreateMaterialProvider(long nativeEngine);
|
||||
private static native void nDestroyMaterialProvider(long nativeProvider);
|
||||
private static native void nDestroyMaterials(long nativeProvider);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.9.3
|
||||
VERSION_NAME=1.9.11
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Fri Jan 10 16:04:09 PST 2020
|
||||
#Thu Nov 05 09:33:02 PST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
|
||||
@@ -15,6 +15,12 @@ Demonstrates how to create a light and a mesh with the attributes required for l
|
||||
|
||||

|
||||
|
||||
### `live-wallpaper`
|
||||
|
||||
Demonstrates how to use Filament as renderer for an Android Live Wallpaper.
|
||||
|
||||

|
||||
|
||||
### `image-based-lighting`
|
||||
|
||||
Demonstrates how to create image-based lights and load complex meshes:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
12
android/samples/sample-live-wallpaper/.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
|
||||
18
android/samples/sample-live-wallpaper/build.gradle
Normal file
@@ -0,0 +1,18 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
android {
|
||||
compileSdkVersion versions.compileSdk
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.livewallpaper"
|
||||
minSdkVersion versions.minSdk
|
||||
targetSdkVersion versions.targetSdk
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation deps.kotlin
|
||||
implementation project(':filament-android')
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.livewallpaper">
|
||||
|
||||
<uses-feature android:name="android.software.live_wallpaper" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/wallpaper_label"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<service
|
||||
android:name=".FilamentLiveWallpaper"
|
||||
android:label="@string/wallpaper_label"
|
||||
android:permission="android.permission.BIND_WALLPAPER">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.wallpaper.WallpaperService" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.service.wallpaper" android:resource="@xml/wallpaper" />
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.livewallpaper
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Service
|
||||
import android.graphics.Color
|
||||
import android.graphics.PixelFormat
|
||||
import android.service.wallpaper.WallpaperService
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.LinearInterpolator
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.android.DisplayHelper
|
||||
import com.google.android.filament.android.UiHelper
|
||||
|
||||
|
||||
class FilamentLiveWallpaper : WallpaperService() {
|
||||
// Make sure to initialize Filament first
|
||||
// This loads the JNI library needed by most API calls
|
||||
companion object {
|
||||
init {
|
||||
Filament.init()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateEngine(): Engine {
|
||||
return FilamentWallpaperEngine()
|
||||
}
|
||||
|
||||
private inner class FilamentWallpaperEngine : Engine() {
|
||||
|
||||
// UiHelper is provided by Filament to manage SurfaceHolder
|
||||
private lateinit var uiHelper: UiHelper
|
||||
// DisplayHelper is provided by Filament to manage the display
|
||||
private lateinit var displayHelper: DisplayHelper
|
||||
// Choreographer is used to schedule new frames
|
||||
private lateinit var choreographer: Choreographer
|
||||
|
||||
// Engine creates and destroys Filament resources
|
||||
// Each engine must be accessed from a single thread of your choosing
|
||||
// Resources cannot be shared across engines
|
||||
private lateinit var engine: com.google.android.filament.Engine
|
||||
// A renderer instance is tied to a single surface (SurfaceView, TextureView, etc.)
|
||||
private lateinit var renderer: Renderer
|
||||
// A scene holds all the renderable, lights, etc. to be drawn
|
||||
private lateinit var scene: Scene
|
||||
// A view defines a viewport, a scene and a camera for rendering
|
||||
private lateinit var view: View
|
||||
// Should be pretty obvious :)
|
||||
private lateinit var camera: Camera
|
||||
|
||||
// A swap chain is Filament's representation of a surface
|
||||
private var swapChain: SwapChain? = null
|
||||
|
||||
// Performs the rendering and schedules new frames
|
||||
private val frameScheduler = FrameCallback()
|
||||
|
||||
// We'll use this ValueAnimator to smoothly cycle the background between hues.
|
||||
private val animator = ValueAnimator.ofFloat(0.0f, 360.0f)
|
||||
|
||||
override fun onCreate(surfaceHolder: SurfaceHolder) {
|
||||
super.onCreate(surfaceHolder)
|
||||
surfaceHolder.setSizeFromLayout()
|
||||
surfaceHolder.setFormat(PixelFormat.RGBA_8888)
|
||||
|
||||
choreographer = Choreographer.getInstance()
|
||||
|
||||
displayHelper = DisplayHelper(this@FilamentLiveWallpaper)
|
||||
|
||||
setupUiHelper()
|
||||
setupFilament()
|
||||
setupView()
|
||||
setupScene()
|
||||
}
|
||||
|
||||
private fun setupUiHelper() {
|
||||
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
|
||||
uiHelper.renderCallback = SurfaceCallback()
|
||||
uiHelper.attachTo(surfaceHolder)
|
||||
}
|
||||
|
||||
private fun setupFilament() {
|
||||
engine = com.google.android.filament.Engine.create()
|
||||
renderer = engine.createRenderer()
|
||||
scene = engine.createScene()
|
||||
view = engine.createView()
|
||||
camera = engine.createCamera()
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
scene.skybox = Skybox.Builder().build(engine)
|
||||
|
||||
// NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference
|
||||
// view.isPostProcessingEnabled = false
|
||||
|
||||
// Tell the view which camera we want to use
|
||||
view.camera = camera
|
||||
|
||||
// Tell the view which scene we want to render
|
||||
view.scene = scene
|
||||
}
|
||||
|
||||
private fun setupScene() {
|
||||
// Set the exposure on the camera, this exposure follows the sunny f/16 rule
|
||||
camera.setExposure(16.0f, 1.0f / 125.0f, 100.0f)
|
||||
|
||||
startAnimation()
|
||||
}
|
||||
|
||||
private fun startAnimation() {
|
||||
// Animate the color of the Skybox.
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.duration = 10000
|
||||
animator.repeatMode = ValueAnimator.RESTART
|
||||
animator.repeatCount = ValueAnimator.INFINITE
|
||||
animator.addUpdateListener { a ->
|
||||
val hue = a.animatedValue as Float
|
||||
val color = Color.HSVToColor(floatArrayOf(hue, 1.0f, 1.0f))
|
||||
scene.skybox?.setColor(floatArrayOf(
|
||||
Color.red(color) / 255.0f,
|
||||
Color.green(color) / 255.0f,
|
||||
Color.blue(color) / 255.0f,
|
||||
1.0f))
|
||||
}
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onVisibilityChanged(visible: Boolean) {
|
||||
super.onVisibilityChanged(visible)
|
||||
if (visible) {
|
||||
choreographer.postFrameCallback(frameScheduler)
|
||||
animator.start()
|
||||
} else {
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
animator.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
// Stop the animation and any pending frame
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
animator.cancel()
|
||||
|
||||
// Always detach the surface before destroying the engine
|
||||
uiHelper.detach()
|
||||
|
||||
// Cleanup all resources
|
||||
engine.destroyRenderer(renderer)
|
||||
engine.destroyView(view)
|
||||
engine.destroyScene(scene)
|
||||
engine.destroyCamera(camera)
|
||||
|
||||
// Destroying the engine will free up any resource you may have forgotten
|
||||
// to destroy, but it's recommended to do the cleanup properly
|
||||
engine.destroy()
|
||||
}
|
||||
|
||||
inner class FrameCallback : Choreographer.FrameCallback {
|
||||
override fun doFrame(frameTimeNanos: Long) {
|
||||
// Schedule the next frame
|
||||
choreographer.postFrameCallback(this)
|
||||
|
||||
// This check guarantees that we have a swap chain
|
||||
if (uiHelper.isReadyToRender) {
|
||||
// If beginFrame() returns false you should skip the frame
|
||||
// This means you are sending frames too quickly to the GPU
|
||||
if (renderer.beginFrame(swapChain!!, frameTimeNanos)) {
|
||||
renderer.render(view)
|
||||
renderer.endFrame()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class SurfaceCallback : UiHelper.RendererCallback {
|
||||
override fun onNativeWindowChanged(surface: Surface) {
|
||||
swapChain?.let { engine.destroySwapChain(it) }
|
||||
swapChain = engine.createSwapChain(surface)
|
||||
val display =
|
||||
(application.getSystemService(Service.WINDOW_SERVICE) as WindowManager)
|
||||
.defaultDisplay
|
||||
displayHelper.attach(renderer, display)
|
||||
}
|
||||
|
||||
override fun onDetachedFromSurface() {
|
||||
displayHelper.detach()
|
||||
swapChain?.let {
|
||||
engine.destroySwapChain(it)
|
||||
// Required to ensure we don't return before Filament is done executing the
|
||||
// destroySwapChain command, otherwise Android might destroy the Surface
|
||||
// too early
|
||||
engine.flushAndWait()
|
||||
swapChain = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResized(width: Int, height: Int) {
|
||||
val aspect = width.toDouble() / height.toDouble()
|
||||
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
|
||||
|
||||
view.viewport = Viewport(0, 0, width, height)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -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,4 @@
|
||||
<resources>
|
||||
<string name="wallpaper_label">Filament Sample Live Wallpaper</string>
|
||||
<string name="wallpaper_author">Google</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>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:author="@string/wallpaper_author"
|
||||
android:thumbnail="@drawable/wallpaper_thumb" />
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -216,7 +216,9 @@ class MainActivity : Activity() {
|
||||
// variant of the filamat library.
|
||||
.optimization(MaterialBuilder.Optimization.NONE)
|
||||
|
||||
.build()
|
||||
// When compiling more than one material variant, it is more efficient to pass an Engine
|
||||
// instance to reuse the Engine's job system
|
||||
.build(engine)
|
||||
|
||||
if (matPackage.isValid) {
|
||||
val buffer = matPackage.buffer
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -10,6 +10,7 @@ include ':samples:sample-hello-camera'
|
||||
include ':samples:sample-hello-triangle'
|
||||
include ':samples:sample-image-based-lighting'
|
||||
include ':samples:sample-lit-cube'
|
||||
include ':samples:sample-live-wallpaper'
|
||||
include ':samples:sample-material-builder'
|
||||
include ':samples:sample-multi-view'
|
||||
include ':samples:sample-page-curl'
|
||||
|
||||
32
build.sh
@@ -41,7 +41,9 @@ function print_help {
|
||||
echo " -t"
|
||||
echo " Enable SwiftShader support for Vulkan in desktop builds."
|
||||
echo " -l"
|
||||
echo " Combine iOS arm64 and x86_64 into universal libraries (implies -s)."
|
||||
echo " Build arm64/x86_64 universal libraries."
|
||||
echo " For iOS, this builds universal binaries for devices and the simulator (implies -s)."
|
||||
echo " For macOS, this builds universal binaries for both Apple silicon and Intel-based Macs."
|
||||
echo " -w"
|
||||
echo " Build Web documents (compiles .md.html files to .html)."
|
||||
echo ""
|
||||
@@ -121,7 +123,7 @@ VULKAN_ANDROID_GRADLE_OPTION=""
|
||||
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=OFF"
|
||||
|
||||
IOS_BUILD_SIMULATOR=false
|
||||
IOS_CREATE_UNIVERSAL_LIBRARIES=false
|
||||
BUILD_UNIVERSAL_LIBRARIES=false
|
||||
|
||||
BUILD_GENERATOR=Ninja
|
||||
BUILD_COMMAND=ninja
|
||||
@@ -158,6 +160,10 @@ function build_desktop_target {
|
||||
local lc_name=$(echo "${UNAME}" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "${lc_name}" == "darwin" ]]; then
|
||||
local deployment_target="-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14"
|
||||
|
||||
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
|
||||
local architectures="-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
|
||||
@@ -169,6 +175,7 @@ function build_desktop_target {
|
||||
-DFILAMENT_ENABLE_JAVA="${FILAMENT_ENABLE_JAVA}" \
|
||||
${SWIFTSHADER_OPTION} \
|
||||
${deployment_target} \
|
||||
${architectures} \
|
||||
../..
|
||||
fi
|
||||
${BUILD_COMMAND} ${build_targets}
|
||||
@@ -241,14 +248,10 @@ function build_webgl_with_target {
|
||||
|
||||
if [[ "${ISSUE_ARCHIVES}" == "true" ]]; then
|
||||
echo "Generating out/filament-${lc_target}-web.tgz..."
|
||||
# The web archive has the following subfolders:
|
||||
# dist...core WASM module and accompanying JS file.
|
||||
# docs...HTML tutorials for the JS API, accompanying demos, and a reference page.
|
||||
cd web
|
||||
tar -cvf "../../filament-${lc_target}-web.tar" -s /^filament-js/dist/ \
|
||||
filament-js/filament.js
|
||||
tar -rvf "../../filament-${lc_target}-web.tar" -s /^filament-js/dist/ \
|
||||
filament-js/filament.wasm
|
||||
cd web/filament-js
|
||||
tar -cvf "../../../filament-${lc_target}-web.tar" filament.js
|
||||
tar -rvf "../../../filament-${lc_target}-web.tar" filament.wasm
|
||||
tar -rvf "../../../filament-${lc_target}-web.tar" filament.d.ts
|
||||
cd -
|
||||
gzip -c "../filament-${lc_target}-web.tar" > "../filament-${lc_target}-web.tgz"
|
||||
rm "../filament-${lc_target}-web.tar"
|
||||
@@ -525,7 +528,7 @@ function build_ios {
|
||||
build_ios_target "Debug" "x86_64" "iphonesimulator"
|
||||
fi
|
||||
|
||||
if [[ "${IOS_CREATE_UNIVERSAL_LIBRARIES}" == "true" ]]; then
|
||||
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
|
||||
build/ios/create-universal-libs.sh \
|
||||
-o out/ios-debug/filament/lib/universal \
|
||||
out/ios-debug/filament/lib/arm64 \
|
||||
@@ -543,7 +546,7 @@ function build_ios {
|
||||
build_ios_target "Release" "x86_64" "iphonesimulator"
|
||||
fi
|
||||
|
||||
if [[ "${IOS_CREATE_UNIVERSAL_LIBRARIES}" == "true" ]]; then
|
||||
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
|
||||
build/ios/create-universal-libs.sh \
|
||||
-o out/ios-release/filament/lib/universal \
|
||||
out/ios-release/filament/lib/arm64 \
|
||||
@@ -756,9 +759,8 @@ while getopts ":hacfijmp:q:uvslwt" opt; do
|
||||
;;
|
||||
l)
|
||||
IOS_BUILD_SIMULATOR=true
|
||||
IOS_CREATE_UNIVERSAL_LIBRARIES=true
|
||||
echo "iOS simulator support enabled."
|
||||
echo "Creating iOS universal libraries."
|
||||
BUILD_UNIVERSAL_LIBRARIES=true
|
||||
echo "Building universal libraries."
|
||||
;;
|
||||
w)
|
||||
ISSUE_WEB_DOCS=true
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#
|
||||
# The default is release
|
||||
|
||||
NDK_VERSION="ndk;21.3.6528147"
|
||||
ANDROID_NDK_VERSION=21
|
||||
NDK_VERSION="ndk;22.0.7026061"
|
||||
ANDROID_NDK_VERSION=22
|
||||
|
||||
# Exclude Vulkan from CI builds for Android. (It is enabled for other platforms.)
|
||||
EXCLUDE_VULKAN=-v
|
||||
|
||||
75
build/common/bump-version.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
function print_help {
|
||||
local SELF_NAME
|
||||
SELF_NAME=$(basename "$0")
|
||||
echo "$SELF_NAME. Update the Filament version number."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $SELF_NAME <new version>"
|
||||
echo ""
|
||||
echo "<new version> should be a 3 part semantic version, such as 1.9.3"
|
||||
echo ""
|
||||
echo "This script does not interface with git. It is up to the user to commit the change."
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h"
|
||||
echo " Print this help message and exit."
|
||||
}
|
||||
|
||||
while getopts "h" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ "$#" -ne 1 ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION_REGEX="[[:digit:]]+.[[:digit:]]+.[[:digit:]]+"
|
||||
NEW_VERSION="$1"
|
||||
|
||||
function replace {
|
||||
FIND_STR="${1//\{\{VERSION\}\}/${VERSION_REGEX}}"
|
||||
REPLACE_STR="${1//\{\{VERSION\}\}/${NEW_VERSION}}"
|
||||
local FILE_NAME="$2"
|
||||
sed -i '' -E "s/${FIND_STR}/${REPLACE_STR}/" "${FILE_NAME}"
|
||||
}
|
||||
|
||||
# The following are the canonical locations where the Filament version number is referenced.
|
||||
|
||||
replace \
|
||||
"implementation 'com.google.android.filament:filament-android:{{VERSION}}'" \
|
||||
README.md
|
||||
|
||||
replace \
|
||||
"pod 'Filament', '~> {{VERSION}}'" \
|
||||
README.md
|
||||
|
||||
replace \
|
||||
"VERSION_NAME={{VERSION}}" \
|
||||
android/gradle.properties
|
||||
|
||||
replace \
|
||||
"spec.version = \"{{VERSION}}\"" \
|
||||
ios/CocoaPods/Filament.podspec
|
||||
|
||||
replace \
|
||||
":http => \"https:\/\/github.com\/google\/filament\/releases\/download\/v{{VERSION}}\/filament-v{{VERSION}}-ios.tgz\" }" \
|
||||
ios/CocoaPods/Filament.podspec
|
||||
|
||||
replace \
|
||||
"\"version\": \"{{VERSION}}\"" \
|
||||
web/filament-js/package.json
|
||||
175
build/common/release.sh
Executable file
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
function print_help {
|
||||
local SELF_NAME
|
||||
SELF_NAME=$(basename "$0")
|
||||
echo "$SELF_NAME. Merge the release candidate (rc) branch into release and cut a new rc branch."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $SELF_NAME [options] <current rc branch new> <new rc branch name>"
|
||||
echo " $SELF_NAME -c <current rc branch new>"
|
||||
echo ""
|
||||
echo "current rc branch name should be the name of an existing rc/* branch"
|
||||
echo "new rc branch name should be the new rc branch name and should not exist"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $SELF_NAME rc/1.9.3 rc/1.9.4"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -c"
|
||||
echo " List the commits that make up a release and exit."
|
||||
echo " -h"
|
||||
echo " Print this help message and exit."
|
||||
echo " -p"
|
||||
echo " Automatically push changes to origin (dangerous)."
|
||||
}
|
||||
|
||||
function list_commits {
|
||||
git log --oneline release.."$1"
|
||||
}
|
||||
|
||||
PUSH_CHANGES=false
|
||||
LIST_COMMITS=false
|
||||
while getopts "hpc" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
p)
|
||||
PUSH_CHANGES=true
|
||||
;;
|
||||
c)
|
||||
LIST_COMMITS=true
|
||||
;;
|
||||
*)
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ "${LIST_COMMITS}" == "true" ]]; then
|
||||
if [[ "$#" -ne 1 ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RC_BRANCH=$1
|
||||
|
||||
list_commits "${RC_BRANCH}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$#" -ne 2 ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RC_BRANCH=$1
|
||||
NEW_RC_BRANCH=$2
|
||||
|
||||
####################################################################################################
|
||||
# Preamble
|
||||
####################################################################################################
|
||||
|
||||
# Check that the RC_BRANCH is a real branch.
|
||||
git show-branch "${RC_BRANCH}" >/dev/null 2>&1 || {
|
||||
echo "Branch ${RC_BRANCH} does not exist (try running git fetch first)."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Ensure no staged or working changes
|
||||
if [ ! -z "$(git status --untracked-files=no --porcelain)" ]; then
|
||||
echo "You have uncommited changes. Please stash or commit before running."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure release, main, and the release candidate branch are up-to-date.
|
||||
git checkout main
|
||||
git pull origin main --rebase
|
||||
|
||||
git checkout "${RC_BRANCH}"
|
||||
git pull origin "${RC_BRANCH}" --rebase
|
||||
|
||||
git checkout release
|
||||
git pull origin release --rebase
|
||||
|
||||
####################################################################################################
|
||||
# Merge rc branch into release
|
||||
####################################################################################################
|
||||
|
||||
# We need to merge rc into release in a somewhat roundabout way because we want the merge to always
|
||||
# favor the changes on the rc branch. Any commits *only* on the release branch should be lost. These
|
||||
# abandonded commits should only ever be temporary hotfixes.
|
||||
# See the last part of https://stackoverflow.com/a/27338013/2671441 for more details.
|
||||
# The benefit of this strategy is that we'll never get any merge conflicts. All of these commands
|
||||
# can run without human intervention.
|
||||
|
||||
git checkout release
|
||||
|
||||
# Do a merge commit. The content of this commit does not matter, so we use a strategy that never
|
||||
# fails. This advances release.
|
||||
git merge --no-edit -s ours "${RC_BRANCH}"
|
||||
|
||||
# Change working tree and index to desired content.
|
||||
# --detach ensures rc branch will not move when doing the reset in the next step.
|
||||
git checkout --detach "${RC_BRANCH}"
|
||||
|
||||
# Move HEAD to release without changing contents of working tree and index.
|
||||
git reset --soft release
|
||||
|
||||
# 'attach' HEAD to release.
|
||||
# This ensures release will move when doing 'commit --amend'.
|
||||
git checkout release
|
||||
|
||||
# Change content of merge commit to current index (i.e. content of rc branch).
|
||||
git commit --amend -C HEAD
|
||||
|
||||
####################################################################################################
|
||||
# Cut a new release candidate branch
|
||||
####################################################################################################
|
||||
|
||||
git checkout main
|
||||
git branch --track "${NEW_RC_BRANCH}"
|
||||
|
||||
####################################################################################################
|
||||
# Delete the old release candidate branch
|
||||
####################################################################################################
|
||||
|
||||
git branch -D "${RC_BRANCH}"
|
||||
|
||||
####################################################################################################
|
||||
# Push changes
|
||||
####################################################################################################
|
||||
|
||||
if [[ "${PUSH_CHANGES}" == "true" ]]; then
|
||||
# Push the release branch
|
||||
git push origin release
|
||||
|
||||
# Delete the old rc branch remotely
|
||||
git push origin --delete "${RC_BRANCH}"
|
||||
|
||||
# Push the new rc branch
|
||||
git push origin "${NEW_RC_BRANCH}"
|
||||
else
|
||||
echo ""
|
||||
echo "Done."
|
||||
echo ""
|
||||
echo "Changes have not been pushed."
|
||||
echo "If everything looks good locally, run the following:"
|
||||
echo "---------------------------------------------------------"
|
||||
echo "git push origin release"
|
||||
echo "git push origin --delete ${RC_BRANCH}"
|
||||
echo "git push origin ${NEW_RC_BRANCH}"
|
||||
echo "---------------------------------------------------------"
|
||||
echo "Or, to undo everything:"
|
||||
echo "---------------------------------------------------------"
|
||||
echo "git checkout release && git reset --hard origin/release"
|
||||
echo "git branch -D ${NEW_RC_BRANCH}"
|
||||
echo "git checkout --track origin/rc/${RC_BRANCH}"
|
||||
echo "---------------------------------------------------------"
|
||||
fi
|
||||
@@ -1,3 +1,4 @@
|
||||
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
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
SELF_NAME=$(basename "$0")
|
||||
|
||||
function print_help {
|
||||
local SELF_NAME=`basename $0`
|
||||
echo "$SELF_NAME. Combine multiple static libraries using an archiver tool."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
@@ -10,7 +11,9 @@ function print_help {
|
||||
echo ""
|
||||
echo "Notes:"
|
||||
echo " <archives> must be a list of absolute paths to static library archives."
|
||||
echo " This script creates a temporary working directory inside the current directory."
|
||||
echo " Mach-O universal binaries are supported, but all archives must be homogeneous: either"
|
||||
echo " all universal, or none."
|
||||
echo " This script creates temporary working directories inside the current directory."
|
||||
}
|
||||
|
||||
if [[ "$#" -lt 3 ]]; then
|
||||
@@ -22,43 +25,118 @@ AR_TOOL="$1"
|
||||
shift
|
||||
OUTPUT_PATH="$1"
|
||||
shift
|
||||
ARCHIVES="$@"
|
||||
ARCHIVES=("$@")
|
||||
|
||||
# Create a temporary working directory named after the destination library.
|
||||
TEMP_DIR="${OUTPUT_PATH##*/}" # remove leading path, if any
|
||||
TEMP_DIR="_${TEMP_DIR%.a}" # remove '.a' extension
|
||||
mkdir -p "${TEMP_DIR}"
|
||||
function combine_static_libs {
|
||||
local output_path="$1"
|
||||
shift
|
||||
local archives=("$@")
|
||||
|
||||
pushd "${TEMP_DIR}" >/dev/null
|
||||
# Create a temporary working directory named after the destination library.
|
||||
local temp_dir="${output_path##*/}" # remove leading path, if any
|
||||
temp_dir="_${temp_dir%.a}" # remove '.a' extension
|
||||
mkdir -p "${temp_dir}"
|
||||
|
||||
for a in ${ARCHIVES}; do
|
||||
# Create a separate directory for each archive to combine. This is necessary to avoid overriding
|
||||
# object files from seprate archives that have the same name.
|
||||
DIR_NAME="${a##*/}" # remove leading path, if any
|
||||
DIR_NAME="${DIR_NAME%.a}" # remove '.a' extension
|
||||
mkdir -p "${DIR_NAME}"
|
||||
pushd "${temp_dir}" >/dev/null
|
||||
|
||||
pushd "${DIR_NAME}" >/dev/null
|
||||
for a in "${archives[@]}"; do
|
||||
# Create a separate directory for each archive to combine. This is necessary to avoid
|
||||
# overriding object files from seprate archives that have the same name.
|
||||
dir_name="${a##*/}" # remove leading path, if any
|
||||
dir_name="${dir_name%.a}" # remove '.a' extension
|
||||
mkdir -p "${dir_name}"
|
||||
|
||||
# Extract object files from each archive.
|
||||
"${AR_TOOL}" -x "$a"
|
||||
pushd "${dir_name}" >/dev/null
|
||||
|
||||
# Prepend the library name to the object file to ensure each object file has a unique name.
|
||||
for o in *.o; do
|
||||
mv "$o" "${DIR_NAME}_${o}"
|
||||
# Extract object files from each archive.
|
||||
"${AR_TOOL}" -x "$a"
|
||||
|
||||
# Prepend the library name to the object file to ensure each object file has a unique name.
|
||||
for o in *.o; do
|
||||
mv "$o" "${dir_name}_${o}"
|
||||
done
|
||||
|
||||
popd >/dev/null
|
||||
done
|
||||
|
||||
popd >/dev/null
|
||||
|
||||
# Combine the library files into a single static library archive.
|
||||
rm -f "${output_path}"
|
||||
"${AR_TOOL}" -qc "${output_path}" $(find "${temp_dir}" -iname '*.o')
|
||||
|
||||
# Clean up. Delete objects in the temporary working directory. In theory we could leave the
|
||||
# directory as a "cache" of extracted object files, but it complicates the logic to handle cases
|
||||
# where object files are removed from a library.
|
||||
find "${temp_dir}" -iname "*.o" -delete
|
||||
}
|
||||
|
||||
function universal_error {
|
||||
echo "Error: archives passed to $SELF_NAME must be either all universal, or all non-universal."
|
||||
echo "Archives: ${ARCHIVES[*]}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Determine if the archives are Mach-O universal binaries.
|
||||
has_universal=""
|
||||
for a in "${ARCHIVES[@]}"; do
|
||||
if file "$a" | grep -q 'Mach-O universal'; then
|
||||
if [[ "${has_universal}" == "false" ]]; then
|
||||
universal_error
|
||||
fi
|
||||
has_universal=true
|
||||
else
|
||||
if [[ "${has_universal}" == "true" ]]; then
|
||||
universal_error
|
||||
fi
|
||||
has_universal=false
|
||||
fi
|
||||
done
|
||||
|
||||
popd >/dev/null
|
||||
if [[ "${has_universal}" == "true" ]]; then
|
||||
# If the archives are universal libraries, we have to do some extra work:
|
||||
# - "thin" each archive into its individual architectures
|
||||
# - for each architecture, combine the single-architecture static libraries
|
||||
# - create a final universal binary from the static libraries
|
||||
|
||||
# Combine the library files into a single static library archive.
|
||||
rm -f "${OUTPUT_PATH}"
|
||||
"${AR_TOOL}" -qc "${OUTPUT_PATH}" $(find "${TEMP_DIR}" -iname '*.o')
|
||||
archs_temp_dir="${OUTPUT_PATH##*/}" # remove leading path, if any
|
||||
archs_temp_dir="_${archs_temp_dir%.a}_archs" # remove '.a' extension
|
||||
|
||||
# Clean up. Delete objects in the temporary working directory. In theory we could leave the
|
||||
# directory as a "cache" of extracted object files, but it complicates the logic to handle cases
|
||||
# where object files are removed from a library.
|
||||
find "${TEMP_DIR}" -iname "*.o" -delete
|
||||
mkdir -p "${archs_temp_dir}"
|
||||
pushd "${archs_temp_dir}" >/dev/null
|
||||
|
||||
# Thin each archive into its architectures.
|
||||
for a in "${ARCHIVES[@]}"; do
|
||||
# Determine which architectures are present in the archive.
|
||||
archs=$(lipo -archs "${a}")
|
||||
|
||||
for arch in ${archs}; do
|
||||
mkdir -p "${arch}"
|
||||
lipo -thin "${arch}" -output "${arch}/${a##*/}" "$a"
|
||||
done
|
||||
done
|
||||
|
||||
popd >/dev/null
|
||||
|
||||
# Combine each set of single-architecture archives.
|
||||
arch_outputs=()
|
||||
for arch_dir in "${archs_temp_dir}"/*/ ; do
|
||||
arch=$(basename "$arch_dir")
|
||||
|
||||
arch_output="${OUTPUT_PATH%.a}_${arch}.a"
|
||||
arch_outputs+=("$arch_output")
|
||||
combine_static_libs "$arch_output" $(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a')
|
||||
done
|
||||
|
||||
# Finally, combine the single-architecture archives into a universal binary.
|
||||
lipo -create "${arch_outputs[@]}" -output "${OUTPUT_PATH}"
|
||||
|
||||
# Clean up.
|
||||
rm "${arch_outputs[@]}"
|
||||
find "${archs_temp_dir}" -iname "*.a" -delete
|
||||
|
||||
else
|
||||
|
||||
combine_static_libs "${OUTPUT_PATH}" "${ARCHIVES[@]}"
|
||||
|
||||
fi
|
||||
|
||||
53
build/swiftshader/Dockerfile
Normal file
@@ -0,0 +1,53 @@
|
||||
# Build the image:
|
||||
# docker build --no-cache --tag ssfilament -f build/swiftshader/Dockerfile .
|
||||
# docker tag ssfilament ghcr.io/filament-assets/swiftshader
|
||||
#
|
||||
# Publish the image:
|
||||
# docker login ghcr.io --username <user> --password <token>
|
||||
# docker push ghcr.io/filament-assets/swiftshader
|
||||
#
|
||||
# Run the image and mount the current directory:
|
||||
# docker run -it -v `pwd`:/trees/filament -t ssfilament
|
||||
|
||||
FROM ubuntu:focal
|
||||
WORKDIR /trees
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV SWIFTSHADER_LD_LIBRARY_PATH=/trees/swiftshader/build
|
||||
ENV CXXFLAGS='-fno-builtin -Wno-pass-failed'
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get --no-install-recommends install -y \
|
||||
apt-transport-https \
|
||||
apt-utils \
|
||||
build-essential \
|
||||
cmake \
|
||||
ca-certificates \
|
||||
git \
|
||||
ninja-build \
|
||||
python \
|
||||
python3 \
|
||||
xorg-dev \
|
||||
clang-7 \
|
||||
libc++-7-dev \
|
||||
libc++abi-7-dev \
|
||||
lldb
|
||||
|
||||
# Ensure that clang is used instead of gcc.
|
||||
RUN set -eux ;\
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100 ;\
|
||||
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100 ;\
|
||||
update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 ;\
|
||||
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
|
||||
|
||||
# Get patch files from the local Filament tree.
|
||||
COPY build/swiftshader/*.diff .
|
||||
|
||||
# Clone SwiftShader, apply patches, and build it.
|
||||
RUN set -eux ;\
|
||||
git clone https://swiftshader.googlesource.com/SwiftShader swiftshader ;\
|
||||
cd swiftshader ;\
|
||||
git checkout 139f5c3 ;\
|
||||
git apply /trees/*.diff ;\
|
||||
cd build ;\
|
||||
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release ;\
|
||||
ninja
|
||||
56
build/swiftshader/gallery.py
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
spath = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
path = Path(spath)
|
||||
|
||||
folder = "../../results/"
|
||||
|
||||
images = list(path.glob(folder + '*.png'))
|
||||
|
||||
images.sort()
|
||||
|
||||
gallery = open(path.absolute().joinpath(folder + 'index.html'), 'w')
|
||||
|
||||
gallery.write("""<html>
|
||||
<head>
|
||||
<script type="module" src="https://unpkg.com/img-comparison-slider@latest/dist/component/component.esm.js"></script>
|
||||
<script nomodule="" src="https://unpkg.com/img-comparison-slider@latest/dist/component/component.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/img-comparison-slider@latest/dist/collection/styles/initial.css"/>
|
||||
<style>
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
margin-top: 150px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
color: blue;
|
||||
}
|
||||
a:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
""")
|
||||
|
||||
tag = ''
|
||||
|
||||
for image in images:
|
||||
group = image.stem.rstrip('0123456789')
|
||||
before = f'https://filament-assets.github.io/golden/{group}/{image.name}'
|
||||
after = image.name
|
||||
gallery.write('\n')
|
||||
gallery.write(f'<h2><a href="{image.stem}.json">{image.stem}.json</a></h2>\n')
|
||||
gallery.write('<img-comparison-slider>\n')
|
||||
gallery.write(f'<img slot="before" src="{before}" /> <img slot="after" src="{after}" />\n')
|
||||
gallery.write('</img-comparison-slider>\n')
|
||||
|
||||
gallery.write("""</body>
|
||||
</html>
|
||||
""")
|
||||
62
build/swiftshader/patch_00.diff
Normal file
@@ -0,0 +1,62 @@
|
||||
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
|
||||
index 86913ec72..3b35345af 100644
|
||||
--- a/src/Vulkan/VkPipeline.cpp
|
||||
+++ b/src/Vulkan/VkPipeline.cpp
|
||||
@@ -71,7 +71,56 @@ std::vector<uint32_t> preprocessSpirv(
|
||||
if(optimize)
|
||||
{
|
||||
// Full optimization list taken from spirv-opt.
|
||||
- opt.RegisterPerformancePasses();
|
||||
+
|
||||
+ // We have removed CreateRedundancyEliminationPass because it segfaults when encountering:
|
||||
+ // %389 = OpCompositeConstruct %7 %386 %387 %388 %86
|
||||
+ // When inserting an entry into instruction_to_value_ (which is an unordered_map)
|
||||
+ // This could perhaps be investigated further with help from asan.
|
||||
+
|
||||
+ using namespace spvtools;
|
||||
+ opt.RegisterPass(CreateWrapOpKillPass())
|
||||
+ .RegisterPass(CreateDeadBranchElimPass())
|
||||
+ .RegisterPass(CreateMergeReturnPass())
|
||||
+ .RegisterPass(CreateInlineExhaustivePass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreatePrivateToLocalPass())
|
||||
+ .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
||||
+ .RegisterPass(CreateLocalSingleStoreElimPass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateScalarReplacementPass())
|
||||
+ .RegisterPass(CreateLocalAccessChainConvertPass())
|
||||
+ .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
||||
+ .RegisterPass(CreateLocalSingleStoreElimPass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateLocalMultiStoreElimPass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateCCPPass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateLoopUnrollPass(true))
|
||||
+ .RegisterPass(CreateDeadBranchElimPass())
|
||||
+ .RegisterPass(CreateRedundancyEliminationPass()) // workaround for SEGFAULT
|
||||
+ .RegisterPass(CreateCombineAccessChainsPass())
|
||||
+ .RegisterPass(CreateSimplificationPass())
|
||||
+ .RegisterPass(CreateScalarReplacementPass())
|
||||
+ .RegisterPass(CreateLocalAccessChainConvertPass())
|
||||
+ .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
||||
+ .RegisterPass(CreateLocalSingleStoreElimPass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateSSARewritePass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateVectorDCEPass())
|
||||
+ .RegisterPass(CreateDeadInsertElimPass())
|
||||
+ .RegisterPass(CreateDeadBranchElimPass())
|
||||
+ .RegisterPass(CreateSimplificationPass())
|
||||
+ .RegisterPass(CreateIfConversionPass())
|
||||
+ .RegisterPass(CreateCopyPropagateArraysPass())
|
||||
+ .RegisterPass(CreateReduceLoadSizePass())
|
||||
+ .RegisterPass(CreateAggressiveDCEPass())
|
||||
+ .RegisterPass(CreateBlockMergePass())
|
||||
+ .RegisterPass(CreateRedundancyEliminationPass()) // workaround for SEGFAULT
|
||||
+ .RegisterPass(CreateDeadBranchElimPass())
|
||||
+ .RegisterPass(CreateBlockMergePass())
|
||||
+ .RegisterPass(CreateSimplificationPass());
|
||||
}
|
||||
|
||||
std::vector<uint32_t> optimized;
|
||||
127
build/swiftshader/test.sh
Executable file
@@ -0,0 +1,127 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
function print_help {
|
||||
local self_name=$(basename "$0")
|
||||
echo "This script issues docker commands for testing Filament with SwiftShader."
|
||||
echo "The usual sequence of commands is: fetch, start, build filament release, and run."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $self_name [command]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " build filament [debug | release]"
|
||||
echo " Use the container to build Filament."
|
||||
echo " build swiftshader [debug | release]"
|
||||
echo " Use the container to do a clean rebuild of SwiftShader."
|
||||
echo " (Note that the container already has SwiftShader built.)"
|
||||
echo " fetch"
|
||||
echo " Download the docker image from the central repository."
|
||||
echo " help"
|
||||
echo " Print this help message."
|
||||
echo " logs"
|
||||
echo " Print messages from the container's kernel ring buffer."
|
||||
echo " This is useful for diagnosing OOM issues."
|
||||
echo " run [lldb]"
|
||||
echo " Launch a test inside the container, optionally via lldb."
|
||||
echo " shell"
|
||||
echo " Interact with a bash prompt in the container."
|
||||
echo " start"
|
||||
echo " Start a container from the image."
|
||||
echo " stop"
|
||||
echo " Stop the container."
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Change the current working directory to the Filament root.
|
||||
pushd "$(dirname "$0")/../.." > /dev/null
|
||||
|
||||
if [[ "$1" == "build" ]] && [[ "$2" == "filament" ]]; then
|
||||
docker exec runner filament/build.sh -t $3 gltf_viewer
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "build" ]] && [[ "$2" == "swiftshader" ]]; then
|
||||
BUILD_TYPE="$3"
|
||||
BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}"
|
||||
docker exec --workdir /trees/swiftshader runner rm -rf build
|
||||
docker exec --workdir /trees/swiftshader runner mkdir build
|
||||
docker exec --workdir /trees/swiftshader/build runner cmake -GNinja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" ..
|
||||
docker exec --workdir /trees/swiftshader/build runner ninja
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "fetch" ]]; then
|
||||
docker pull ghcr.io/filament-assets/swiftshader:latest
|
||||
docker tag ghcr.io/filament-assets/swiftshader:latest ssfilament
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "help" ]]; then
|
||||
print_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$1" == "logs" ]]; then
|
||||
docker exec runner dmesg --human --read-clear
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "run" ]] && [[ "$2" == "lldb" ]]; then
|
||||
docker exec -i --workdir /trees/filament/results runner \
|
||||
lldb --batch -o run -o bt -- \
|
||||
../out/cmake-release/samples/gltf_viewer \
|
||||
--headless \
|
||||
--batch ../libs/viewer/tests/basic.json \
|
||||
--api vulkan
|
||||
docker exec runner /trees/filament/build/swiftshader/gallery.py
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "run" ]]; then
|
||||
docker exec --tty --workdir /trees/filament/results runner \
|
||||
/usr/bin/catchsegv \
|
||||
../out/cmake-release/samples/gltf_viewer \
|
||||
--headless \
|
||||
--batch ../libs/viewer/tests/basic.json \
|
||||
--api vulkan
|
||||
docker exec runner /trees/filament/build/swiftshader/gallery.py
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "shell" ]]; then
|
||||
docker exec --interactive --tty runner /bin/bash
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Notes on options being passed to docker's run command:
|
||||
#
|
||||
# - The memory constraint seems to prevent an OOM signal in GitHub Actions.
|
||||
# - The cap / security args allow use of lldb and creation of core dumps.
|
||||
# - The privileged arg allows use of dmesg for examining OOM logs.
|
||||
#
|
||||
# Currently, a GitHub Actions VM has 2 CPUs, 7 GB RAM, and 14 GB of SSD disk space.
|
||||
#
|
||||
# Please be aware that Docker Desktop might impose additional resource constraints, and that those
|
||||
# settings can only be controlled with its GUI. We recommend at least 7 GB of memory and 2 GB swap.
|
||||
if [[ "$1" == "start" ]]; then
|
||||
mkdir -p results
|
||||
docker run --tty --rm --detach --privileged \
|
||||
--memory 6.5g \
|
||||
--name runner \
|
||||
--cap-add=SYS_PTRACE \
|
||||
--security-opt seccomp=unconfined \
|
||||
--security-opt apparmor=unconfined \
|
||||
--volume `pwd`:/trees/filament \
|
||||
--workdir /trees \
|
||||
ssfilament
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "$1" == "stop" ]]; then
|
||||
docker container rm runner --force
|
||||
exit $?
|
||||
fi
|
||||
|
||||
print_help
|
||||
exit 1
|
||||
@@ -42,20 +42,22 @@ counter-increment: h6;margin-right:10px}</style><style>.hljs{display:block;overf
|
||||
    <a href="#materialmodels/litmodel/metals" class="level3"><span class="tocNumber">3.1.5  </span>Metals</a><br>
|
||||
    <a href="#materialmodels/litmodel/refraction" class="level3"><span class="tocNumber">3.1.6  </span>Refraction</a><br>
|
||||
    <a href="#materialmodels/litmodel/reflectance" class="level3"><span class="tocNumber">3.1.7  </span>Reflectance</a><br>
|
||||
    <a href="#materialmodels/litmodel/clearcoat" class="level3"><span class="tocNumber">3.1.8  </span>Clear coat</a><br>
|
||||
    <a href="#materialmodels/litmodel/clearcoatroughness" class="level3"><span class="tocNumber">3.1.9  </span>Clear coat roughness</a><br>
|
||||
    <a href="#materialmodels/litmodel/anisotropy" class="level3"><span class="tocNumber">3.1.10  </span>Anisotropy</a><br>
|
||||
    <a href="#materialmodels/litmodel/anisotropydirection" class="level3"><span class="tocNumber">3.1.11  </span>Anisotropy direction</a><br>
|
||||
    <a href="#materialmodels/litmodel/ambientocclusion" class="level3"><span class="tocNumber">3.1.12  </span>Ambient occlusion</a><br>
|
||||
    <a href="#materialmodels/litmodel/normal" class="level3"><span class="tocNumber">3.1.13  </span>Normal</a><br>
|
||||
    <a href="#materialmodels/litmodel/bentnormal" class="level3"><span class="tocNumber">3.1.14  </span>Bent normal</a><br>
|
||||
    <a href="#materialmodels/litmodel/clearcoatnormal" class="level3"><span class="tocNumber">3.1.15  </span>Clear coat normal</a><br>
|
||||
    <a href="#materialmodels/litmodel/emissive" class="level3"><span class="tocNumber">3.1.16  </span>Emissive</a><br>
|
||||
    <a href="#materialmodels/litmodel/post-lightingcolor" class="level3"><span class="tocNumber">3.1.17  </span>Post-lighting color</a><br>
|
||||
    <a href="#materialmodels/litmodel/indexofrefraction" class="level3"><span class="tocNumber">3.1.18  </span>Index of refraction</a><br>
|
||||
    <a href="#materialmodels/litmodel/transmission" class="level3"><span class="tocNumber">3.1.19  </span>Transmission</a><br>
|
||||
    <a href="#materialmodels/litmodel/absorption" class="level3"><span class="tocNumber">3.1.20  </span>Absorption</a><br>
|
||||
    <a href="#materialmodels/litmodel/micro-thicknessandthickness" class="level3"><span class="tocNumber">3.1.21  </span>Micro-thickness and thickness</a><br>
|
||||
    <a href="#materialmodels/litmodel/sheencolor" class="level3"><span class="tocNumber">3.1.8  </span>Sheen color</a><br>
|
||||
    <a href="#materialmodels/litmodel/sheenroughness" class="level3"><span class="tocNumber">3.1.9  </span>Sheen roughness</a><br>
|
||||
    <a href="#materialmodels/litmodel/clearcoat" class="level3"><span class="tocNumber">3.1.10  </span>Clear coat</a><br>
|
||||
    <a href="#materialmodels/litmodel/clearcoatroughness" class="level3"><span class="tocNumber">3.1.11  </span>Clear coat roughness</a><br>
|
||||
    <a href="#materialmodels/litmodel/anisotropy" class="level3"><span class="tocNumber">3.1.12  </span>Anisotropy</a><br>
|
||||
    <a href="#materialmodels/litmodel/anisotropydirection" class="level3"><span class="tocNumber">3.1.13  </span>Anisotropy direction</a><br>
|
||||
    <a href="#materialmodels/litmodel/ambientocclusion" class="level3"><span class="tocNumber">3.1.14  </span>Ambient occlusion</a><br>
|
||||
    <a href="#materialmodels/litmodel/normal" class="level3"><span class="tocNumber">3.1.15  </span>Normal</a><br>
|
||||
    <a href="#materialmodels/litmodel/bentnormal" class="level3"><span class="tocNumber">3.1.16  </span>Bent normal</a><br>
|
||||
    <a href="#materialmodels/litmodel/clearcoatnormal" class="level3"><span class="tocNumber">3.1.17  </span>Clear coat normal</a><br>
|
||||
    <a href="#materialmodels/litmodel/emissive" class="level3"><span class="tocNumber">3.1.18  </span>Emissive</a><br>
|
||||
    <a href="#materialmodels/litmodel/post-lightingcolor" class="level3"><span class="tocNumber">3.1.19  </span>Post-lighting color</a><br>
|
||||
    <a href="#materialmodels/litmodel/indexofrefraction" class="level3"><span class="tocNumber">3.1.20  </span>Index of refraction</a><br>
|
||||
    <a href="#materialmodels/litmodel/transmission" class="level3"><span class="tocNumber">3.1.21  </span>Transmission</a><br>
|
||||
    <a href="#materialmodels/litmodel/absorption" class="level3"><span class="tocNumber">3.1.22  </span>Absorption</a><br>
|
||||
    <a href="#materialmodels/litmodel/micro-thicknessandthickness" class="level3"><span class="tocNumber">3.1.23  </span>Micro-thickness and thickness</a><br>
|
||||
  <a href="#materialmodels/subsurfacemodel" class="level2"><span class="tocNumber">3.2  </span>Subsurface model</a><br>
|
||||
    <a href="#materialmodels/subsurfacemodel/thickness" class="level3"><span class="tocNumber">3.2.1  </span>Thickness</a><br>
|
||||
    <a href="#materialmodels/subsurfacemodel/subsurfacecolor" class="level3"><span class="tocNumber">3.2.2  </span>Subsurface color</a><br>
|
||||
@@ -135,7 +137,7 @@ This document is part of the <a href="https://github.com/google/filament">Filame
|
||||
</p><ul>
|
||||
<li class="minus"><a href="https://github.com/romainguy">Romain Guy</a>, <a href="https://twitter.com/romainguy">@romainguy</a>
|
||||
</li>
|
||||
<li class="minus"><a href="https://github.com/pixelflinger">Mathias Agopian</a>, <a href="https://twitter.com/darthmoosious">@romainguy</a></li></ul>
|
||||
<li class="minus"><a href="https://github.com/pixelflinger">Mathias Agopian</a>, <a href="https://twitter.com/darthmoosious">@darthmoosious</a></li></ul>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="overview"> </a><a class="target" name="overview"> </a><a class="target" name="toc2"> </a><h1>Overview</h1>
|
||||
@@ -231,6 +233,8 @@ in <a href="#table_standardproperties">table 1</a>.
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">metallic</strong> </td><td style="text-align:left"> Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1) </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">roughness</strong> </td><td style="text-align:left"> Perceived smoothness (1.0) or roughness (0.0) of a surface. Smooth surfaces exhibit sharp reflections </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">reflectance</strong> </td><td style="text-align:left"> Fresnel reflectance at normal incidence for dielectric surfaces. This directly controls the strength of the reflections </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">sheenColor</strong> </td><td style="text-align:left"> Strength of the sheen layer </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">sheenRoughness</strong> </td><td style="text-align:left"> Perceived smoothness or roughness of the sheen layer </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">clearCoat</strong> </td><td style="text-align:left"> Strength of the clear coat layer </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">clearCoatRoughness</strong> </td><td style="text-align:left"> Perceived smoothness or roughness of the clear coat layer </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">anisotropy</strong> </td><td style="text-align:left"> Amount of anisotropy in either the tangent or bitangent direction </td></tr>
|
||||
@@ -257,6 +261,8 @@ The type and range of each property is described in <a href="#table_standardprop
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">metallic</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [0..1] </td><td style="text-align:left"> Should be 0 or 1 </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">roughness</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [0..1] </td><td style="text-align:left">   </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">reflectance</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [0..1] </td><td style="text-align:left"> Prefer values > 0.35 </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">sheenColor</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:center"> [0..1] </td><td style="text-align:left"> Linear RGB </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">sheenRoughness</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [0..1] </td><td style="text-align:left">   </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">clearCoat</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [0..1] </td><td style="text-align:left"> Should be 0 or 1 </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">clearCoatRoughness</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [0..1] </td><td style="text-align:left">   </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">anisotropy</strong> </td><td style="text-align:center"> float </td><td style="text-align:center"> [−1..1] </td><td style="text-align:left"> Anisotropy is in the tangent direction when this value is positive </td></tr>
|
||||
@@ -517,11 +523,59 @@ it easy to define from a texture.
|
||||
|
||||
</p><p>
|
||||
|
||||
See the Index of <a href="#refraction">refraction</a> section for more information about the <code>ior</code> property and refractive
|
||||
See section <a href="#toc3.1.20">3.1.20</a> for more information about the <code>ior</code> property and refractive
|
||||
indices.
|
||||
|
||||
</p>
|
||||
<a class="target" name="clearcoat"> </a><a class="target" name="materialmodels/litmodel/clearcoat"> </a><a class="target" name="toc3.1.8"> </a><h3>Clear coat</h3>
|
||||
<a class="target" name="sheencolor"> </a><a class="target" name="materialmodels/litmodel/sheencolor"> </a><a class="target" name="toc3.1.8"> </a><h3>Sheen color</h3>
|
||||
<p>
|
||||
|
||||
|
||||
The sheen color controls the color appearance and strength of an optional sheen layer on top of the
|
||||
base layer described by the properties above. The sheen layer always sits below the clear coat layer
|
||||
if such a layer is present.
|
||||
|
||||
</p><p>
|
||||
|
||||
The sheen layer can be used to represent cloth and fabric materials. Please refer to
|
||||
section <a href="#toc3.3">3.3</a> for more information about cloth and fabric materials.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>sheenColor</code> is shown in <a href="#figure_materialsheencolor">figure 7</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_sheen_color.png" target="_blank"><img class="markdeep" src="images/screenshot_sheen_color.png"></a><div class="imagecaption"><a class="target" name="figure_materialsheencolor"> </a><b style="font-style:normal;">Figure 7:</b> Different sheen colors</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
</p><div class="admonition note">If you do not need the other properties offered by the standard lit material model but want to
|
||||
create a cloth-like or fabric-like appearance, it is more efficient to use the dedicated cloth
|
||||
model described in section <a href="#toc3.3">3.3</a>.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="sheenroughness"> </a><a class="target" name="materialmodels/litmodel/sheenroughness"> </a><a class="target" name="toc3.1.9"> </a><h3>Sheen roughness</h3>
|
||||
<p>
|
||||
|
||||
|
||||
The <code>sheenRoughness</code> property is similar to the <code>roughness</code> property but applies only to the
|
||||
sheen layer.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>sheenRoughness</code> on a rough metal is shown in <a href="#figure_sheenroughnessproperty">figure 8</a>
|
||||
(click on the image to see a larger version). In this picture, the base layer is a dark blue, with
|
||||
<code>metallic</code> set to <code>0.0</code> and <code>roughness</code> set to <code>1.0</code>.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/sheen_roughness.png" target="_blank"><img class="markdeep" src="images/materials/sheen_roughness.png"></a><div class="imagecaption"><a class="target" name="figure_sheenroughnessproperty"> </a><b style="font-style:normal;">Figure 8:</b> <code>sheenRoughness</code> varying from 0.0
|
||||
(left) to 1.0 (right)</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="clearcoat"> </a><a class="target" name="materialmodels/litmodel/clearcoat"> </a><a class="target" name="toc3.1.10"> </a><h3>Clear coat</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -536,7 +590,7 @@ will always be isotropic and dielectric.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/material_carbon_fiber.png" target="_blank"><img class="markdeep" src="images/material_carbon_fiber.png"></a><div class="imagecaption"><a class="target" name="figure_clearcoat"> </a><b style="font-style:normal;">Figure 7:</b> Comparison of a carbon-fiber material under the standard material model
|
||||
</p><center><div class="image" style><a href="images/material_carbon_fiber.png" target="_blank"><img class="markdeep" src="images/material_carbon_fiber.png"></a><div class="imagecaption"><a class="target" name="figure_clearcoat"> </a><b style="font-style:normal;">Figure 9:</b> Comparison of a carbon-fiber material under the standard material model
|
||||
(left) and the clear coat model (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -547,12 +601,12 @@ parts of the surface that have a clear coat layers and parts that don't.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>clearCoat</code> on a rough metal is shown in <a href="#figure_clearcoatproperty">figure 8</a>
|
||||
The effect of <code>clearCoat</code> on a rough metal is shown in <a href="#figure_clearcoatproperty">figure 10</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/clear_coat.png" target="_blank"><img class="markdeep" src="images/materials/clear_coat.png"></a><div class="imagecaption"><a class="target" name="figure_clearcoatproperty"> </a><b style="font-style:normal;">Figure 8:</b> <code>clearCoat</code> varying from 0.0
|
||||
</p><center><div class="image" style><a href="images/materials/clear_coat.png" target="_blank"><img class="markdeep" src="images/materials/clear_coat.png"></a><div class="imagecaption"><a class="target" name="figure_clearcoatproperty"> </a><b style="font-style:normal;">Figure 10:</b> <code>clearCoat</code> varying from 0.0
|
||||
(left) to 1.0 (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -560,8 +614,12 @@ The effect of <code>clearCoat</code> on a rough metal is shown in <a href="#figu
|
||||
</p><div class="admonition warning">The clear coat layer effectively doubles the cost of specular computations. Do not assign a
|
||||
value, even 0.0, to the clear coat property if you don't need this second layer.</div>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
</p><div class="admonition note">The clear coat layer is added on top of the sheen layer if present.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="clearcoatroughness"> </a><a class="target" name="materialmodels/litmodel/clearcoatroughness"> </a><a class="target" name="toc3.1.9"> </a><h3>Clear coat roughness</h3>
|
||||
<a class="target" name="clearcoatroughness"> </a><a class="target" name="materialmodels/litmodel/clearcoatroughness"> </a><a class="target" name="toc3.1.11"> </a><h3>Clear coat roughness</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -570,16 +628,16 @@ clear coat layer.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>clearCoatRoughness</code> on a rough metal is shown in <a href="#figure_clearcoatroughnessproperty">figure 9</a>
|
||||
The effect of <code>clearCoatRoughness</code> on a rough metal is shown in <a href="#figure_clearcoatroughnessproperty">figure 11</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/clear_coat_roughness.png" target="_blank"><img class="markdeep" src="images/materials/clear_coat_roughness.png"></a><div class="imagecaption"><a class="target" name="figure_clearcoatroughnessproperty"> </a><b style="font-style:normal;">Figure 9:</b> <code>clearCoatRoughness</code> varying from 0.0
|
||||
</p><center><div class="image" style><a href="images/materials/clear_coat_roughness.png" target="_blank"><img class="markdeep" src="images/materials/clear_coat_roughness.png"></a><div class="imagecaption"><a class="target" name="figure_clearcoatroughnessproperty"> </a><b style="font-style:normal;">Figure 11:</b> <code>clearCoatRoughness</code> varying from 0.0
|
||||
(left) to 1.0 (right)</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="anisotropy"> </a><a class="target" name="materialmodels/litmodel/anisotropy"> </a><a class="target" name="toc3.1.10"> </a><h3>Anisotropy</h3>
|
||||
<a class="target" name="anisotropy"> </a><a class="target" name="materialmodels/litmodel/anisotropy"> </a><a class="target" name="toc3.1.12"> </a><h3>Anisotropy</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -589,28 +647,28 @@ model by using the <code>anisotropy</code> property.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/material_anisotropic.png" target="_blank"><img class="markdeep" src="images/material_anisotropic.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropic"> </a><b style="font-style:normal;">Figure 10:</b> Comparison of isotropic material
|
||||
</p><center><div class="image" style><a href="images/material_anisotropic.png" target="_blank"><img class="markdeep" src="images/material_anisotropic.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropic"> </a><b style="font-style:normal;">Figure 12:</b> Comparison of isotropic material
|
||||
(left) and anistropic material (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
The effect of <code>anisotropy</code> on a rough metal is shown in <a href="#figure_anisotropyproperty">figure 11</a>
|
||||
The effect of <code>anisotropy</code> on a rough metal is shown in <a href="#figure_anisotropyproperty">figure 13</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/anisotropy.png" target="_blank"><img class="markdeep" src="images/materials/anisotropy.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropyproperty"> </a><b style="font-style:normal;">Figure 11:</b> <code>anisotropy</code> varying from 0.0
|
||||
</p><center><div class="image" style><a href="images/materials/anisotropy.png" target="_blank"><img class="markdeep" src="images/materials/anisotropy.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropyproperty"> </a><b style="font-style:normal;">Figure 13:</b> <code>anisotropy</code> varying from 0.0
|
||||
(left) to 1.0 (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
The <a href="#figure_anisotropydir">figure 12</a> below shows how the direction of the anisotropic highlights can be
|
||||
The <a href="#figure_anisotropydir">figure 14</a> below shows how the direction of the anisotropic highlights can be
|
||||
controlled by using either positive or negative values: positive values define anisotropy in the
|
||||
tangent direction and negative values in the bitangent direction.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_anisotropy_direction.png" target="_blank"><img class="markdeep" src="images/screenshot_anisotropy_direction.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropydir"> </a><b style="font-style:normal;">Figure 12:</b> Positive (left) vs negative
|
||||
</p><center><div class="image" style><a href="images/screenshot_anisotropy_direction.png" target="_blank"><img class="markdeep" src="images/screenshot_anisotropy_direction.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropydir"> </a><b style="font-style:normal;">Figure 14:</b> Positive (left) vs negative
|
||||
(right) <code>anisotropy</code> values</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -619,7 +677,7 @@ tangent direction and negative values in the bitangent direction.
|
||||
not assign a value (even 0.0) to the <code>anisotropy</code> property if you don't need anisotropy.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="anisotropydirection"> </a><a class="target" name="materialmodels/litmodel/anisotropydirection"> </a><a class="target" name="toc3.1.11"> </a><h3>Anisotropy direction</h3>
|
||||
<a class="target" name="anisotropydirection"> </a><a class="target" name="materialmodels/litmodel/anisotropydirection"> </a><a class="target" name="toc3.1.13"> </a><h3>Anisotropy direction</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -629,25 +687,25 @@ come from a texture, encoding the directions local to the surface.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>anisotropyDirection</code> on a metal is shown in <a href="#figure_anisotropydirectionproperty">figure 14</a>
|
||||
The effect of <code>anisotropyDirection</code> on a metal is shown in <a href="#figure_anisotropydirectionproperty">figure 16</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_anisotropy.png" target="_blank"><img class="markdeep" src="images/screenshot_anisotropy.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropydirectionproperty"> </a><b style="font-style:normal;">Figure 13:</b> Anisotropic metal rendered
|
||||
</p><center><div class="image" style><a href="images/screenshot_anisotropy.png" target="_blank"><img class="markdeep" src="images/screenshot_anisotropy.png"></a><div class="imagecaption"><a class="target" name="figure_anisotropydirectionproperty"> </a><b style="font-style:normal;">Figure 15:</b> Anisotropic metal rendered
|
||||
with a direction map</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
The result shown in <a href="#figure_anisotropydirectionproperty">figure 14</a> was obtained using the direction map shown
|
||||
in <a href="#figure_anisotropydirectionproperty">figure 14</a>.
|
||||
The result shown in <a href="#figure_anisotropydirectionproperty">figure 16</a> was obtained using the direction map shown
|
||||
in <a href="#figure_anisotropydirectionproperty">figure 16</a>.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_anisotropy_map.jpg" target="_blank"><img class="markdeep" src="images/screenshot_anisotropy_map.jpg"></a><div class="imagecaption"><a class="target" name="figure_anisotropydirectionproperty"> </a><b style="font-style:normal;">Figure 14:</b> Example of a direction map</div></div></center>
|
||||
</p><center><div class="image" style><a href="images/screenshot_anisotropy_map.jpg" target="_blank"><img class="markdeep" src="images/screenshot_anisotropy_map.jpg"></a><div class="imagecaption"><a class="target" name="figure_anisotropydirectionproperty"> </a><b style="font-style:normal;">Figure 16:</b> Example of a direction map</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="ambientocclusion"> </a><a class="target" name="materialmodels/litmodel/ambientocclusion"> </a><a class="target" name="toc3.1.12"> </a><h3>Ambient occlusion</h3>
|
||||
<a class="target" name="ambientocclusion"> </a><a class="target" name="materialmodels/litmodel/ambientocclusion"> </a><a class="target" name="toc3.1.14"> </a><h3>Ambient occlusion</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -658,11 +716,11 @@ directional, point and spot lights, nor specular lighting.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_ao.jpg" target="_blank"><img class="markdeep" src="images/screenshot_ao.jpg"></a><div class="imagecaption"><a class="target" name="figure_aoexample"> </a><b style="font-style:normal;">Figure 15:</b> Comparison of materials without diffuse ambient occlusion
|
||||
</p><center><div class="image" style><a href="images/screenshot_ao.jpg" target="_blank"><img class="markdeep" src="images/screenshot_ao.jpg"></a><div class="imagecaption"><a class="target" name="figure_aoexample"> </a><b style="font-style:normal;">Figure 17:</b> Comparison of materials without diffuse ambient occlusion
|
||||
(left) and with (right)</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="normal"> </a><a class="target" name="materialmodels/litmodel/normal"> </a><a class="target" name="toc3.1.13"> </a><h3>Normal</h3>
|
||||
<a class="target" name="normal"> </a><a class="target" name="materialmodels/litmodel/normal"> </a><a class="target" name="toc3.1.15"> </a><h3>Normal</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -675,7 +733,7 @@ space, which means that +Z points outside of the surface.
|
||||
For example, let's imagine that we want to render a piece of furniture covered in tufted leather.
|
||||
Modeling the geometry to accurately represent the tufted pattern would require too many triangles
|
||||
so we instead bake a high-poly mesh into a normal map. Once the base map is applied to a simplified
|
||||
mesh, we get the result in <a href="#figure_normalmapped">figure 16</a>.
|
||||
mesh, we get the result in <a href="#figure_normalmapped">figure 18</a>.
|
||||
|
||||
</p><p>
|
||||
|
||||
@@ -683,7 +741,7 @@ Note that the <code>normal</code> property affects the <em class="underscore">ba
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_normal_mapping.jpg" target="_blank"><img class="markdeep" src="images/screenshot_normal_mapping.jpg"></a><div class="imagecaption"><a class="target" name="figure_normalmapped"> </a><b style="font-style:normal;">Figure 16:</b> Low-poly mesh without normal mapping (left)
|
||||
</p><center><div class="image" style><a href="images/screenshot_normal_mapping.jpg" target="_blank"><img class="markdeep" src="images/screenshot_normal_mapping.jpg"></a><div class="imagecaption"><a class="target" name="figure_normalmapped"> </a><b style="font-style:normal;">Figure 18:</b> Low-poly mesh without normal mapping (left)
|
||||
and with (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -691,7 +749,7 @@ and with (right)</div></div></center>
|
||||
</p><div class="admonition warning">Using a normal map increases the runtime cost of the material model.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="bentnormal"> </a><a class="target" name="materialmodels/litmodel/bentnormal"> </a><a class="target" name="toc3.1.14"> </a><h3>Bent normal</h3>
|
||||
<a class="target" name="bentnormal"> </a><a class="target" name="materialmodels/litmodel/bentnormal"> </a><a class="target" name="toc3.1.16"> </a><h3>Bent normal</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -703,16 +761,16 @@ specular ambient occlusion (see section <a href="#toc4.2.24">4.2.24</a> about
|
||||
</p><p>
|
||||
|
||||
Bent normals can greatly increase the visual fidelity of an asset with various cavities and concave
|
||||
areas, as shown in <a href="#figure_bentnormalmapped">figure 17</a>. See the areas of the ears, nostrils and eyes for
|
||||
areas, as shown in <a href="#figure_bentnormalmapped">figure 19</a>. See the areas of the ears, nostrils and eyes for
|
||||
instance.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/material_bent_normal.gif" target="_blank"><img class="markdeep" src="images/material_bent_normal.gif"></a><div class="imagecaption"><a class="target" name="figure_bentnormalmapped"> </a><b style="font-style:normal;">Figure 17:</b> Example of a model rendered with and without a bent normal map. Both
|
||||
</p><center><div class="image" style><a href="images/material_bent_normal.gif" target="_blank"><img class="markdeep" src="images/material_bent_normal.gif"></a><div class="imagecaption"><a class="target" name="figure_bentnormalmapped"> </a><b style="font-style:normal;">Figure 19:</b> Example of a model rendered with and without a bent normal map. Both
|
||||
versions use the same ambient occlusion map.</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="clearcoatnormal"> </a><a class="target" name="materialmodels/litmodel/clearcoatnormal"> </a><a class="target" name="toc3.1.15"> </a><h3>Clear coat normal</h3>
|
||||
<a class="target" name="clearcoatnormal"> </a><a class="target" name="materialmodels/litmodel/clearcoatnormal"> </a><a class="target" name="toc3.1.17"> </a><h3>Clear coat normal</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -721,7 +779,7 @@ behaves otherwise like the <code>normal</code> property.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_clear_coat_normal.jpg" target="_blank"><img class="markdeep" src="images/screenshot_clear_coat_normal.jpg"></a><div class="imagecaption"><a class="target" name="figure_clearcoatnormalmapped"> </a><b style="font-style:normal;">Figure 18:</b> A material with a clear coat normal
|
||||
</p><center><div class="image" style><a href="images/screenshot_clear_coat_normal.jpg" target="_blank"><img class="markdeep" src="images/screenshot_clear_coat_normal.jpg"></a><div class="imagecaption"><a class="target" name="figure_clearcoatnormalmapped"> </a><b style="font-style:normal;">Figure 20:</b> A material with a clear coat normal
|
||||
map and a surface normal map</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -729,7 +787,7 @@ map and a surface normal map</div></div></center>
|
||||
</p><div class="admonition warning">Using a clear coat normal map increases the runtime cost of the material model.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="emissive"> </a><a class="target" name="materialmodels/litmodel/emissive"> </a><a class="target" name="toc3.1.16"> </a><h3>Emissive</h3>
|
||||
<a class="target" name="emissive"> </a><a class="target" name="materialmodels/litmodel/emissive"> </a><a class="target" name="toc3.1.18"> </a><h3>Emissive</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -757,7 +815,7 @@ not affected by the camera exposure. When the weight is set to 1, the intensity
|
||||
the camera exposure like with any regular light.
|
||||
|
||||
</p>
|
||||
<a class="target" name="post-lightingcolor"> </a><a class="target" name="materialmodels/litmodel/post-lightingcolor"> </a><a class="target" name="toc3.1.17"> </a><h3>Post-lighting color</h3>
|
||||
<a class="target" name="post-lightingcolor"> </a><a class="target" name="materialmodels/litmodel/post-lightingcolor"> </a><a class="target" name="toc3.1.19"> </a><h3>Post-lighting color</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -778,7 +836,7 @@ this option for more information.
|
||||
<code>postLightingBlending</code> to <code>add</code> and by providing an RGB color with alpha set to <code>0.0</code>.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="indexofrefraction"> </a><a class="target" name="materialmodels/litmodel/indexofrefraction"> </a><a class="target" name="toc3.1.18"> </a><h3>Index of refraction</h3>
|
||||
<a class="target" name="indexofrefraction"> </a><a class="target" name="materialmodels/litmodel/indexofrefraction"> </a><a class="target" name="toc3.1.20"> </a><h3>Index of refraction</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -811,27 +869,28 @@ light to bend further away from the initial path.
|
||||
<p></p><p>
|
||||
|
||||
The appearance of a refractive material will greatly depend on the <code>refractionType</code> and
|
||||
<code>refractionMode</code> settings of the material. Refer to the <a href="#blendingandtransparency:refractiontype">Blending and transparency: refractionType</a> section and the <a href="#blendingandtransparency:refractionmode">Blending and transparency: refractionMode</a> section for more information.
|
||||
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.15">4.2.15</a> and section <a href="#toc4.2.14">4.2.14</a>
|
||||
for more information.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>ior</code> when <code>refractionMode</code> is set to <code>cubemap</code> and <code>refractionType</code> is set to <code>solid</code>
|
||||
can be seen in <a href="#figure_iorproperty2">figure 19</a> (click on the image to see a larger version).
|
||||
can be seen in <a href="#figure_iorproperty2">figure 21</a> (click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/ior.png" target="_blank"><img class="markdeep" src="images/materials/ior.png"></a><div class="imagecaption"><a class="target" name="figure_iorproperty2"> </a><b style="font-style:normal;">Figure 19:</b> <code>transmission</code> varying from 1.0
|
||||
</p><center><div class="image" style><a href="images/materials/ior.png" target="_blank"><img class="markdeep" src="images/materials/ior.png"></a><div class="imagecaption"><a class="target" name="figure_iorproperty2"> </a><b style="font-style:normal;">Figure 21:</b> <code>transmission</code> varying from 1.0
|
||||
(left) to 1.5 (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
<a href="#figure_iorproperty">Figure 20</a> shows the comparison of a sphere of <code>ior</code> 1.0 with a sphere of <code>ior</code> 1.33, with
|
||||
<a href="#figure_iorproperty">Figure 22</a> shows the comparison of a sphere of <code>ior</code> 1.0 with a sphere of <code>ior</code> 1.33, with
|
||||
the <code>refractionMode</code> set to <code>screenspace</code> and the <code>refractionType</code> set to <code>solid</code>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/material_ior.png" target="_blank"><img class="markdeep" src="images/material_ior.png"></a><div class="imagecaption"><a class="target" name="figure_iorproperty"> </a><b style="font-style:normal;">Figure 20:</b> <code>ior</code> of 1.0 (left) and 1.33 (right)</div></div></center>
|
||||
</p><center><div class="image" style><a href="images/material_ior.png" target="_blank"><img class="markdeep" src="images/material_ior.png"></a><div class="imagecaption"><a class="target" name="figure_iorproperty"> </a><b style="font-style:normal;">Figure 22:</b> <code>ior</code> of 1.0 (left) and 1.33 (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
@@ -852,7 +911,7 @@ See the <a href="#reflectance">Reflectance</a> section for more information on t
|
||||
glass, certain plastics, etc.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="transmission"> </a><a class="target" name="materialmodels/litmodel/transmission"> </a><a class="target" name="toc3.1.19"> </a><h3>Transmission</h3>
|
||||
<a class="target" name="transmission"> </a><a class="target" name="materialmodels/litmodel/transmission"> </a><a class="target" name="toc3.1.21"> </a><h3>Transmission</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -869,12 +928,12 @@ diffuse component is not visible anymore, only the specular component is.
|
||||
</p><p>
|
||||
|
||||
The effect of <code>transmission</code> on a glossy dielectric (<code>ior</code> of 1.5, <code>refractionMode</code> set to
|
||||
<code>cubemap</code>, <code>refractionType</code> set to <code>solid</code>) is shown in <a href="#figure_transmissionproperty">figure 21</a>
|
||||
<code>cubemap</code>, <code>refractionType</code> set to <code>solid</code>) is shown in <a href="#figure_transmissionproperty">figure 23</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/transmission.png" target="_blank"><img class="markdeep" src="images/materials/transmission.png"></a><div class="imagecaption"><a class="target" name="figure_transmissionproperty"> </a><b style="font-style:normal;">Figure 21:</b> <code>transmission</code> varying from 0.0
|
||||
</p><center><div class="image" style><a href="images/materials/transmission.png" target="_blank"><img class="markdeep" src="images/materials/transmission.png"></a><div class="imagecaption"><a class="target" name="figure_transmissionproperty"> </a><b style="font-style:normal;">Figure 23:</b> <code>transmission</code> varying from 0.0
|
||||
(left) to 1.0 (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -883,17 +942,17 @@ The effect of <code>transmission</code> on a glossy dielectric (<code>ior</code>
|
||||
materials.</div>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="absorption"> </a><a class="target" name="materialmodels/litmodel/absorption"> </a><a class="target" name="toc3.1.20"> </a><h3>Absorption</h3>
|
||||
<a class="target" name="absorption"> </a><a class="target" name="materialmodels/litmodel/absorption"> </a><a class="target" name="toc3.1.22"> </a><h3>Absorption</h3>
|
||||
<p>
|
||||
|
||||
|
||||
The <code>absorption</code> property defines the absorption coefficients of light transmitted through the
|
||||
material. <a href="#figure_absorptionexample">Figure 22</a> shows the effect of <code>absorption</code> on a refracting object with
|
||||
material. <a href="#figure_absorptionexample">Figure 24</a> shows the effect of <code>absorption</code> on a refracting object with
|
||||
an index of refraction of 1.5 and a base color set to white.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/material_absorption.png" target="_blank"><img class="markdeep" src="images/material_absorption.png"></a><div class="imagecaption"><a class="target" name="figure_absorptionexample"> </a><b style="font-style:normal;">Figure 22:</b> Refracting object without (left)
|
||||
</p><center><div class="image" style><a href="images/material_absorption.png" target="_blank"><img class="markdeep" src="images/material_absorption.png"></a><div class="imagecaption"><a class="target" name="figure_absorptionexample"> </a><b style="font-style:normal;">Figure 24:</b> Refracting object without (left)
|
||||
and with (right) absorption</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -917,13 +976,13 @@ $$color \cdot (1 - absorption)$$
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of varying the <code>absorption</code> coefficients is shown in <a href="#figure_absorptionproperty">figure 23</a>
|
||||
The effect of varying the <code>absorption</code> coefficients is shown in <a href="#figure_absorptionproperty">figure 25</a>
|
||||
(click on the image to see a larger version). In this picture, the object has a fixed <code>thickness</code>
|
||||
of 4.5 and an index of refraction set to 1.3.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/absorption.png" target="_blank"><img class="markdeep" src="images/materials/absorption.png"></a><div class="imagecaption"><a class="target" name="figure_absorptionproperty"> </a><b style="font-style:normal;">Figure 23:</b> <code>absorption</code> varying from (0.0, 0.02, 0.14)
|
||||
</p><center><div class="image" style><a href="images/materials/absorption.png" target="_blank"><img class="markdeep" src="images/materials/absorption.png"></a><div class="imagecaption"><a class="target" name="figure_absorptionproperty"> </a><b style="font-style:normal;">Figure 25:</b> <code>absorption</code> varying from (0.0, 0.02, 0.14)
|
||||
(left) to (0.0, 0.36, 2.3) (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -943,7 +1002,7 @@ While this computation can be done in the material itself we recommend doing it
|
||||
possible. Filament provides an API for this purpose, <code>Color::absorptionAtDistance()</code>.
|
||||
|
||||
</p>
|
||||
<a class="target" name="micro-thicknessandthickness"> </a><a class="target" name="materialmodels/litmodel/micro-thicknessandthickness"> </a><a class="target" name="toc3.1.21"> </a><h3>Micro-thickness and thickness</h3>
|
||||
<a class="target" name="micro-thicknessandthickness"> </a><a class="target" name="materialmodels/litmodel/micro-thicknessandthickness"> </a><a class="target" name="toc3.1.23"> </a><h3>Micro-thickness and thickness</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -973,23 +1032,23 @@ rays are refracted.
|
||||
</p><p>
|
||||
|
||||
The effect <code>thickness</code> in a solid volume with <code>refractionMode</code> set to <code>screenSpace</code> is shown in
|
||||
<a href="#figure_thicknessproperty">figure 24</a> (click on the image to see a larger version). Note how the <code>thickness</code>
|
||||
<a href="#figure_thicknessproperty">figure 26</a> (click on the image to see a larger version). Note how the <code>thickness</code>
|
||||
value not only changes the effect of <code>absorption</code> but also modifies the direction of the refracted
|
||||
light.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/materials/thickness.png" target="_blank"><img class="markdeep" src="images/materials/thickness.png"></a><div class="imagecaption"><a class="target" name="figure_thicknessproperty"> </a><b style="font-style:normal;">Figure 24:</b> <code>thickness</code> varying from 0.0
|
||||
</p><center><div class="image" style><a href="images/materials/thickness.png" target="_blank"><img class="markdeep" src="images/materials/thickness.png"></a><div class="imagecaption"><a class="target" name="figure_thicknessproperty"> </a><b style="font-style:normal;">Figure 26:</b> <code>thickness</code> varying from 0.0
|
||||
(left) to 2.0 (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
<a href="#figure_varyingthickness">Figure 25</a> shows what a prism with spatially varying <code>thickness</code> looks like when
|
||||
<a href="#figure_varyingthickness">Figure 27</a> shows what a prism with spatially varying <code>thickness</code> looks like when
|
||||
the <code>refractionType</code> is set to <code>solid</code> and <code>absorption</code> coefficients are set.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/material_thickness.png" target="_blank"><img class="markdeep" src="images/material_thickness.png"></a><div class="imagecaption"><a class="target" name="figure_varyingthickness"> </a><b style="font-style:normal;">Figure 25:</b> <code>thickness</code> varying from 0.0 at the top of the prism to 3.0 at the
|
||||
</p><center><div class="image" style><a href="images/material_thickness.png" target="_blank"><img class="markdeep" src="images/material_thickness.png"></a><div class="imagecaption"><a class="target" name="figure_varyingthickness"> </a><b style="font-style:normal;">Figure 27:</b> <code>thickness</code> varying from 0.0 at the top of the prism to 3.0 at the
|
||||
bottom of the prism</div></div></center>
|
||||
|
||||
<p></p>
|
||||
@@ -1014,19 +1073,19 @@ forward/backward scattering. Some fabrics also exhibit two-tone specular colors
|
||||
|
||||
</p><p>
|
||||
|
||||
<a href="#figure_materialcloth">Figure 26</a> shows how the standard material model fails to capture the appearance of a
|
||||
<a href="#figure_materialcloth">Figure 28</a> shows how the standard material model fails to capture the appearance of a
|
||||
sample of denim fabric. The surface appears rigid (almost plastic-like), more similar to a tarp
|
||||
than a piece of clothing. This figure also shows how important the softer specular lobe caused by
|
||||
absorption and scattering is to the faithful recreation of the fabric.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth.png"></a><div class="imagecaption"><a class="target" name="figure_materialcloth"> </a><b style="font-style:normal;">Figure 26:</b> Comparison of denim fabric rendered using the standard model
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth.png"></a><div class="imagecaption"><a class="target" name="figure_materialcloth"> </a><b style="font-style:normal;">Figure 28:</b> Comparison of denim fabric rendered using the standard model
|
||||
(left) and the cloth model (right)</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
Velvet is an interesting use case for a cloth material model. As shown in <a href="#figure_materialvelvet">figure 27</a>
|
||||
Velvet is an interesting use case for a cloth material model. As shown in <a href="#figure_materialvelvet">figure 29</a>
|
||||
this type of fabric exhibits strong rim lighting due to forward and backward scattering. These
|
||||
scattering events are caused by fibers standing straight at the surface of the fabric. When the
|
||||
incident light comes from the direction opposite to the view direction, the fibers will forward
|
||||
@@ -1035,7 +1094,7 @@ direction, the fibers will scatter the light backward.
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth_velvet.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth_velvet.png"></a><div class="imagecaption"><a class="target" name="figure_materialvelvet"> </a><b style="font-style:normal;">Figure 27:</b> Velvet fabric showcasing forward and
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth_velvet.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth_velvet.png"></a><div class="imagecaption"><a class="target" name="figure_materialvelvet"> </a><b style="font-style:normal;">Figure 29:</b> Velvet fabric showcasing forward and
|
||||
backward scattering</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
@@ -1097,12 +1156,12 @@ two-tone specular materials.
|
||||
|
||||
</p><p>
|
||||
|
||||
The effect of <code>sheenColor</code> is shown in <a href="#figure_materialclothsheen">figure 28</a>
|
||||
The effect of <code>sheenColor</code> is shown in <a href="#figure_materialclothsheen">figure 30</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth_sheen.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth_sheen.png"></a><div class="imagecaption"><a class="target" name="figure_materialclothsheen"> </a><b style="font-style:normal;">Figure 28:</b> Blue fabric without (left) and with (right) sheen</div></div></center>
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth_sheen.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth_sheen.png"></a><div class="imagecaption"><a class="target" name="figure_materialclothsheen"> </a><b style="font-style:normal;">Figure 30:</b> Blue fabric without (left) and with (right) sheen</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="subsurfacecolor"> </a><a class="target" name="materialmodels/clothmodel/subsurfacecolor"> </a><a class="target" name="toc3.3.2"> </a><h3>Subsurface color</h3>
|
||||
@@ -1119,12 +1178,12 @@ useful to create softer fabrics.
|
||||
|
||||
<p></p><p>
|
||||
|
||||
The effect of <code>subsurfaceColor</code> is shown in <a href="#figure_materialclothsubsurface">figure 29</a>
|
||||
The effect of <code>subsurfaceColor</code> is shown in <a href="#figure_materialclothsubsurface">figure 31</a>
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth_subsurface.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth_subsurface.png"></a><div class="imagecaption"><a class="target" name="figure_materialclothsubsurface"> </a><b style="font-style:normal;">Figure 29:</b> White cloth (left column) vs white cloth with
|
||||
</p><center><div class="image" style><a href="images/screenshot_cloth_subsurface.png" target="_blank"><img class="markdeep" src="images/screenshot_cloth_subsurface.png"></a><div class="imagecaption"><a class="target" name="figure_materialclothsubsurface"> </a><b style="font-style:normal;">Figure 31:</b> White cloth (left column) vs white cloth with
|
||||
brown subsurface scatting (right)</div></div></center>
|
||||
|
||||
<p></p>
|
||||
@@ -1160,12 +1219,12 @@ the blending mode specified by the <code>postLightingBlending</code> material op
|
||||
|
||||
</p><p>
|
||||
|
||||
<a href="#figure_materialunlit">Figure 30</a> shows an example of the unlit material model
|
||||
<a href="#figure_materialunlit">Figure 32</a> shows an example of the unlit material model
|
||||
(click on the image to see a larger version).
|
||||
|
||||
</p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_unlit.jpg" target="_blank"><img class="markdeep" src="images/screenshot_unlit.jpg"></a><div class="imagecaption"><a class="target" name="figure_materialunlit"> </a><b style="font-style:normal;">Figure 30:</b> The unlit model is used to render debug information</div></div></center>
|
||||
</p><center><div class="image" style><a href="images/screenshot_unlit.jpg" target="_blank"><img class="markdeep" src="images/screenshot_unlit.jpg"></a><div class="imagecaption"><a class="target" name="figure_materialunlit"> </a><b style="font-style:normal;">Figure 32:</b> The unlit model is used to render debug information</div></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="specularglossiness"> </a><a class="target" name="materialmodels/specularglossiness"> </a><a class="target" name="toc3.5"> </a><h2>Specular glossiness</h2>
|
||||
@@ -1241,7 +1300,7 @@ the JSON object notation:
|
||||
<span class="line"> // fragment shader</span>
|
||||
<span class="line">}</span></code></pre><p>
|
||||
|
||||
A minimum viable material definition must contain a <code>material</code> section and a <code>fragment</code> block. The
|
||||
A minimum viable material definition must contain a <code>material</code> preamble and a <code>fragment</code> block. The
|
||||
<code>vertex</code> block is optional.
|
||||
|
||||
</p>
|
||||
@@ -1713,33 +1772,33 @@ non-shader data.
|
||||
<p></p><p>
|
||||
|
||||
</p><ul>
|
||||
<li class="minus"><code>default</code>: the transparent object is rendered normally (as seen in <a href="#figure_transparencydefault">figure 31</a>),
|
||||
<li class="minus"><code>default</code>: the transparent object is rendered normally (as seen in <a href="#figure_transparencydefault">figure 33</a>),
|
||||
honoring the <code>culling</code> mode, etc.
|
||||
</li>
|
||||
<li class="minus"><code>twoPassesOneSide</code>: the transparent object is first rendered in the depth buffer, then again in
|
||||
the color buffer, honoring the <code>culling</code> mode. This effectively renders only half of the
|
||||
transparent object as shown in <a href="#figure_transparencytwopassesoneside">figure 32</a>.
|
||||
transparent object as shown in <a href="#figure_transparencytwopassesoneside">figure 34</a>.
|
||||
</li>
|
||||
<li class="minus"><code>twoPassesTwoSides</code>: the transparent object is rendered twice in the color buffer: first with its
|
||||
back faces, then with its front faces. This mode lets you render both set of faces while reducing
|
||||
or eliminating sorting issues, as shown in <a href="#figure_transparencytwopassestwosides">figure 33</a>.
|
||||
or eliminating sorting issues, as shown in <a href="#figure_transparencytwopassestwosides">figure 35</a>.
|
||||
<code>twoPassesTwoSides</code> can be combined with <code>doubleSided</code> for better effect.</li></ul>
|
||||
|
||||
<p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> transparency : twoPassesOneSide</span>
|
||||
<span class="line">}</span></code></pre><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_transparency_default.png" target="_blank"><img class="markdeep" src="images/screenshot_transparency_default.png"></a><div class="imagecaption"><a class="target" name="figure_transparencydefault"> </a><b style="font-style:normal;">Figure 31:</b> This double sided model shows the type of sorting issues transparent
|
||||
</p><center><div class="image" style><a href="images/screenshot_transparency_default.png" target="_blank"><img class="markdeep" src="images/screenshot_transparency_default.png"></a><div class="imagecaption"><a class="target" name="figure_transparencydefault"> </a><b style="font-style:normal;">Figure 33:</b> This double sided model shows the type of sorting issues transparent
|
||||
objects can be subject to in <code>default</code> mode</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_twopasses_oneside.png" target="_blank"><img class="markdeep" src="images/screenshot_twopasses_oneside.png"></a><div class="imagecaption"><a class="target" name="figure_transparencytwopassesoneside"> </a><b style="font-style:normal;">Figure 32:</b> In <code>twoPassesOneSide</code> mode, only one set of faces is visible
|
||||
</p><center><div class="image" style><a href="images/screenshot_twopasses_oneside.png" target="_blank"><img class="markdeep" src="images/screenshot_twopasses_oneside.png"></a><div class="imagecaption"><a class="target" name="figure_transparencytwopassesoneside"> </a><b style="font-style:normal;">Figure 34:</b> In <code>twoPassesOneSide</code> mode, only one set of faces is visible
|
||||
and correctly sorted</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_twopasses_twosides.png" target="_blank"><img class="markdeep" src="images/screenshot_twopasses_twosides.png"></a><div class="imagecaption"><a class="target" name="figure_transparencytwopassestwosides"> </a><b style="font-style:normal;">Figure 33:</b> In <code>twoPassesTwoSides</code> mode, both set of faces are visible
|
||||
</p><center><div class="image" style><a href="images/screenshot_twopasses_twosides.png" target="_blank"><img class="markdeep" src="images/screenshot_twopasses_twosides.png"></a><div class="imagecaption"><a class="target" name="figure_transparencytwopassestwosides"> </a><b style="font-style:normal;">Figure 35:</b> In <code>twoPassesTwoSides</code> mode, both set of faces are visible
|
||||
and sorting issues are minimized or eliminated</div></div></center>
|
||||
|
||||
<p></p>
|
||||
@@ -1905,14 +1964,14 @@ and sorting issues are minimized or eliminated</div></div></center>
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> When adding a clear coat layer, the change in index of refraction (IoR) is taken into account
|
||||
to modify the specular color of the base layer. This appears to darken <code>baseColor</code>. When this
|
||||
effect is disabled, <code>baseColor</code> is left unmodified. See <a href="#figure_clearcoatiorchange">figure 34</a> for an
|
||||
effect is disabled, <code>baseColor</code> is left unmodified. See <a href="#figure_clearcoatiorchange">figure 36</a> for an
|
||||
example of how this property can affect a red metallic base layer.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> clearCoatIorChange : false</span>
|
||||
<span class="line">}</span></code></pre><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_clear_coat_ior_change.jpg" target="_blank"><img class="markdeep" src="images/screenshot_clear_coat_ior_change.jpg"></a><div class="imagecaption"><a class="target" name="figure_clearcoatiorchange"> </a><b style="font-style:normal;">Figure 34:</b> The same rough metallic ball with a clear coat layer rendered
|
||||
</p><center><div class="image" style><a href="images/screenshot_clear_coat_ior_change.jpg" target="_blank"><img class="markdeep" src="images/screenshot_clear_coat_ior_change.jpg"></a><div class="imagecaption"><a class="target" name="figure_clearcoatiorchange"> </a><b style="font-style:normal;">Figure 36:</b> The same rough metallic ball with a clear coat layer rendered
|
||||
with <code>clearCoatIorChange</code> enabled (left) and disabled
|
||||
(right).</div></div></center>
|
||||
|
||||
@@ -1928,21 +1987,21 @@ with <code>clearCoatIorChange</code> enabled (left) and disabled
|
||||
</p></dd><dt>Description</dt><dd><p> Multi-bounce ambient occlusion takes into account interreflections when applying ambient
|
||||
occlusion to image-based lighting. Turning this feature on avoids over-darkening occluded
|
||||
areas. It also takes the surface color into account to generate colored ambient occlusion.
|
||||
<a href="#figure_multibounceao">Figure 35</a> compares the ambient occlusion term of a surface with and without
|
||||
<a href="#figure_multibounceao">Figure 37</a> compares the ambient occlusion term of a surface with and without
|
||||
multi-bounce ambient occlusion. Notice how multi-bounce ambient occlusion introduces color
|
||||
in the occluded areas. <a href="#figure_multibounceaoanimated">Figure 36</a> toggles between multi-bounce ambient
|
||||
in the occluded areas. <a href="#figure_multibounceaoanimated">Figure 38</a> toggles between multi-bounce ambient
|
||||
occlusion on and off on a lit brick material to highlight the effects of this property.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> multiBounceAmbientOcclusion : true</span>
|
||||
<span class="line">}</span></code></pre><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_multi_bounce_ao.jpg" target="_blank"><img class="markdeep" src="images/screenshot_multi_bounce_ao.jpg"></a><div class="imagecaption"><a class="target" name="figure_multibounceao"> </a><b style="font-style:normal;">Figure 35:</b> Brick texture amient occlusion map rendered with multi-bounce ambient
|
||||
</p><center><div class="image" style><a href="images/screenshot_multi_bounce_ao.jpg" target="_blank"><img class="markdeep" src="images/screenshot_multi_bounce_ao.jpg"></a><div class="imagecaption"><a class="target" name="figure_multibounceao"> </a><b style="font-style:normal;">Figure 37:</b> Brick texture amient occlusion map rendered with multi-bounce ambient
|
||||
occclusion enabled (left) and disabled (right).</div></div></center>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_multi_bounce_ao.gif" target="_blank"><img class="markdeep" src="images/screenshot_multi_bounce_ao.gif"></a><div class="imagecaption"><a class="target" name="figure_multibounceaoanimated"> </a><b style="font-style:normal;">Figure 36:</b> Brick texture rendered with multi-bounce ambient
|
||||
</p><center><div class="image" style><a href="images/screenshot_multi_bounce_ao.gif" target="_blank"><img class="markdeep" src="images/screenshot_multi_bounce_ao.gif"></a><div class="imagecaption"><a class="target" name="figure_multibounceaoanimated"> </a><b style="font-style:normal;">Figure 38:</b> Brick texture rendered with multi-bounce ambient
|
||||
occclusion enabled and disabled.</div></div></center>
|
||||
|
||||
<p></p>
|
||||
@@ -1959,7 +2018,7 @@ occclusion enabled and disabled.</div></div></center>
|
||||
</p></dd><dt>Description</dt><dd><p> Static ambient occlusion maps and dynamic ambient occlusion (SSAO, etc.) apply to diffuse
|
||||
indirect lighting. When setting this property to other than <code>none</code>, a new ambient occlusion
|
||||
term is derived from the surface roughness and applied to specular indirect lighting.
|
||||
This effect helps remove unwanted specular reflections as shown in <a href="#figure_specularao">figure 37</a>.
|
||||
This effect helps remove unwanted specular reflections as shown in <a href="#figure_specularao">figure 39</a>.
|
||||
When this value is set to <code>simple</code>, Filament uses a cheap but approximate method of computing
|
||||
the specular ambient occlusion term. If this value is set to <code>bentNormals</code>, Filament will use
|
||||
a much more accurate but much more expensive method. <code>bentNormals</code> only works if the material
|
||||
@@ -1970,7 +2029,7 @@ occclusion enabled and disabled.</div></div></center>
|
||||
<span class="line"> specularAmbientOcclusion : simple</span>
|
||||
<span class="line">}</span></code></pre><p>
|
||||
|
||||
</p><center><div class="image" style><a href="images/screenshot_specular_ao.gif" target="_blank"><img class="markdeep" src="images/screenshot_specular_ao.gif"></a><div class="imagecaption"><a class="target" name="figure_specularao"> </a><b style="font-style:normal;">Figure 37:</b> Comparison of specular ambient occlusion on and off. The effect is
|
||||
</p><center><div class="image" style><a href="images/screenshot_specular_ao.gif" target="_blank"><img class="markdeep" src="images/screenshot_specular_ao.gif"></a><div class="imagecaption"><a class="target" name="figure_specularao"> </a><b style="font-style:normal;">Figure 39:</b> Comparison of specular ambient occlusion on and off. The effect is
|
||||
particularly visible under the hose.</div></div></center>
|
||||
|
||||
<p></p>
|
||||
@@ -2179,6 +2238,8 @@ plastic with bump mapping:
|
||||
<span class="line"> <span class="hljs-type">float</span> ambientOcclusion; <span class="hljs-comment">// default: 0.0</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"> <span class="hljs-comment">// not available when the shading model is subsurface or cloth</span></span>
|
||||
<span class="line"> float3 sheenColor; <span class="hljs-comment">// default: float3(0.0)</span></span>
|
||||
<span class="line"> <span class="hljs-type">float</span> sheenRoughness; <span class="hljs-comment">// default: 0.0</span></span>
|
||||
<span class="line"> <span class="hljs-type">float</span> clearCoat; <span class="hljs-comment">// default: 1.0</span></span>
|
||||
<span class="line"> <span class="hljs-type">float</span> clearCoatRoughness; <span class="hljs-comment">// default: 0.0</span></span>
|
||||
<span class="line"> float3 clearCoatNormal; <span class="hljs-comment">// default: float3(0.0, 0.0, 1.0)</span></span>
|
||||
@@ -2313,7 +2374,7 @@ The following APIs are only available from the fragment block:
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getWorldNormalVector()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Normalized normal in world space, after bump mapping (must be used after <code>prepareMaterial()</code>) </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getWorldGeometricNormalVector()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Normalized normal in world space, before bump mapping (can be used before <code>prepareMaterial()</code>) </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getWorldReflectedVector()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Reflection of the view vector about the normal (must be used after <code>prepareMaterial()</code>) </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getNormalizedViewportCoord(float2)</strong> </td><td style="text-align:center"> float2 </td><td style="text-align:left"> Normalized viewport position (i.e. clip-space position normalized to [0, 1], can be used before <code>prepareMaterial()</code>) </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getNormalizedViewportCoord()</strong> </td><td style="text-align:center"> float2 </td><td style="text-align:left"> Normalized viewport position (i.e. clip-space position normalized to [0, 1], can be used before <code>prepareMaterial()</code>) </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getNdotV()</strong> </td><td style="text-align:center"> float </td><td style="text-align:left"> The result of <code>dot(normal, view)</code>, always strictly greater than 0 (must be used after <code>prepareMaterial()</code>) </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getColor()</strong> </td><td style="text-align:center"> float4 </td><td style="text-align:left"> Interpolated color of the fragment, if the color attribute is required </td></tr>
|
||||
<tr><td style="text-align:left"> <strong class="asterisk">getUV0()</strong> </td><td style="text-align:center"> float2 </td><td style="text-align:left"> First interpolated set of UV coordinates, only available if the uv0 attribute is required </td></tr>
|
||||
|
||||
@@ -13,7 +13,7 @@ This document is part of the [Filament project](https://github.com/google/filame
|
||||
## Authors
|
||||
|
||||
- [Romain Guy](https://github.com/romainguy), [@romainguy](https://twitter.com/romainguy)
|
||||
- [Mathias Agopian](https://github.com/pixelflinger), [@romainguy](https://twitter.com/darthmoosious)
|
||||
- [Mathias Agopian](https://github.com/pixelflinger), [@darthmoosious](https://twitter.com/darthmoosious)
|
||||
|
||||
# Overview
|
||||
|
||||
@@ -81,6 +81,8 @@ in table [standardProperties].
|
||||
**metallic** | Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1)
|
||||
**roughness** | Perceived smoothness (1.0) or roughness (0.0) of a surface. Smooth surfaces exhibit sharp reflections
|
||||
**reflectance** | Fresnel reflectance at normal incidence for dielectric surfaces. This directly controls the strength of the reflections
|
||||
**sheenColor** | Strength of the sheen layer
|
||||
**sheenRoughness** | Perceived smoothness or roughness of the sheen layer
|
||||
**clearCoat** | Strength of the clear coat layer
|
||||
**clearCoatRoughness** | Perceived smoothness or roughness of the clear coat layer
|
||||
**anisotropy** | Amount of anisotropy in either the tangent or bitangent direction
|
||||
@@ -106,6 +108,8 @@ The type and range of each property is described in table [standardPropertiesTyp
|
||||
**metallic** | float | [0..1] | Should be 0 or 1
|
||||
**roughness** | float | [0..1] |
|
||||
**reflectance** | float | [0..1] | Prefer values > 0.35
|
||||
**sheenColor** | float3 | [0..1] | Linear RGB
|
||||
**sheenRoughness** | float | [0..1] |
|
||||
**clearCoat** | float | [0..1] | Should be 0 or 1
|
||||
**clearCoatRoughness** | float | [0..1] |
|
||||
**anisotropy** | float | [-1..1] | Anisotropy is in the tangent direction when this value is positive
|
||||
@@ -293,9 +297,40 @@ impossible materials, however, this might be desirable for artistic reasons.
|
||||
The `reflectance` property is designed as a normalized property in the range 0..1 which makes
|
||||
it easy to define from a texture.
|
||||
|
||||
See the Index of refraction section for more information about the `ior` property and refractive
|
||||
See section [Index of refraction] for more information about the `ior` property and refractive
|
||||
indices.
|
||||
|
||||
### Sheen color
|
||||
|
||||
The sheen color controls the color appearance and strength of an optional sheen layer on top of the
|
||||
base layer described by the properties above. The sheen layer always sits below the clear coat layer
|
||||
if such a layer is present.
|
||||
|
||||
The sheen layer can be used to represent cloth and fabric materials. Please refer to
|
||||
section [Cloth model] for more information about cloth and fabric materials.
|
||||
|
||||
The effect of `sheenColor` is shown in figure [materialSheenColor]
|
||||
(click on the image to see a larger version).
|
||||
|
||||
![Figure [materialSheenColor]: Different sheen colors](images/screenshot_sheen_color.png)
|
||||
|
||||
!!! Note
|
||||
If you do not need the other properties offered by the standard lit material model but want to
|
||||
create a cloth-like or fabric-like appearance, it is more efficient to use the dedicated cloth
|
||||
model described in section [Cloth model].
|
||||
|
||||
### Sheen roughness
|
||||
|
||||
The `sheenRoughness` property is similar to the `roughness` property but applies only to the
|
||||
sheen layer.
|
||||
|
||||
The effect of `sheenRoughness` on a rough metal is shown in figure [sheenRoughnessProperty]
|
||||
(click on the image to see a larger version). In this picture, the base layer is a dark blue, with
|
||||
`metallic` set to `0.0` and `roughness` set to `1.0`.
|
||||
|
||||
![Figure [sheenRoughnessProperty]: `sheenRoughness` varying from 0.0
|
||||
(left) to 1.0 (right)](images/materials/sheen_roughness.png)
|
||||
|
||||
### Clear coat
|
||||
|
||||
Multi-layer materials are fairly common, particularly materials with a thin translucent
|
||||
@@ -322,6 +357,9 @@ The effect of `clearCoat` on a rough metal is shown in figure [clearCoatProperty
|
||||
The clear coat layer effectively doubles the cost of specular computations. Do not assign a
|
||||
value, even 0.0, to the clear coat property if you don't need this second layer.
|
||||
|
||||
!!! Note
|
||||
The clear coat layer is added on top of the sheen layer if present.
|
||||
|
||||
### Clear coat roughness
|
||||
|
||||
The `clearCoatRoughness` property is similar to the `roughness` property but applies only to the
|
||||
@@ -490,8 +528,9 @@ Other dielectric materials | 1.33 to 1.58
|
||||
[Table [commonMatIOR]: Index of refraction of common materials]
|
||||
|
||||
The appearance of a refractive material will greatly depend on the `refractionType` and
|
||||
`refractionMode` settings of the material. Refer to the Blending and transparency: refractionType
|
||||
section and the Blending and transparency: refractionMode section for more information.
|
||||
`refractionMode` settings of the material. Refer to section
|
||||
[Blending and transparency: refractionType] and section [Blending and transparency: refractionMode]
|
||||
for more information.
|
||||
|
||||
The effect of `ior` when `refractionMode` is set to `cubemap` and `refractionType` is set to `solid`
|
||||
can be seen in figure [iorProperty2] (click on the image to see a larger version).
|
||||
@@ -795,7 +834,7 @@ fragment {
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A minimum viable material definition must contain a `material` section and a `fragment` block. The
|
||||
A minimum viable material definition must contain a `material` preamble and a `fragment` block. The
|
||||
`vertex` block is optional.
|
||||
|
||||
### Differences with JSON
|
||||
@@ -1771,6 +1810,8 @@ struct MaterialInputs {
|
||||
float ambientOcclusion; // default: 0.0
|
||||
|
||||
// not available when the shading model is subsurface or cloth
|
||||
float3 sheenColor; // default: float3(0.0)
|
||||
float sheenRoughness; // default: 0.0
|
||||
float clearCoat; // default: 1.0
|
||||
float clearCoatRoughness; // default: 0.0
|
||||
float3 clearCoatNormal; // default: float3(0.0, 0.0, 1.0)
|
||||
|
||||
BIN
docs/images/materials/sheen_roughness.png
Normal file
|
After Width: | Height: | Size: 557 KiB |
BIN
docs/images/samples/example_live_wallpaper.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/images/screenshot_sheen_color.png
Normal file
|
After Width: | Height: | Size: 3.6 MiB |
@@ -170,6 +170,7 @@ set(MATERIAL_SRCS
|
||||
src/materials/separableGaussianBlur.mat
|
||||
src/materials/antiAliasing/fxaa.mat
|
||||
src/materials/antiAliasing/taa.mat
|
||||
src/materials/vsmMipmap.mat
|
||||
)
|
||||
|
||||
# Embed the binary resource blob for materials.
|
||||
@@ -290,6 +291,18 @@ add_custom_command(
|
||||
APPEND
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${MATERIAL_DIR}/sao.filamat"
|
||||
DEPENDS src/materials/ssao/ssaoUtils.fs
|
||||
APPEND
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${MATERIAL_DIR}/sao.filamat"
|
||||
DEPENDS src/materials/ssao/ssct.fs
|
||||
APPEND
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${RESGEN_OUTPUTS}
|
||||
COMMAND resgen ${RESGEN_FLAGS} ${MATERIAL_BINS}
|
||||
@@ -337,7 +350,7 @@ target_link_libraries(${TARGET} PUBLIC utils)
|
||||
target_link_libraries(${TARGET} PUBLIC geometry) # TODO: remove this dependency after deprecating VertexBuffer::populateTangentQuaternions
|
||||
target_link_libraries(${TARGET} PUBLIC filaflat)
|
||||
target_link_libraries(${TARGET} PUBLIC filabridge)
|
||||
target_link_libraries(${TARGET} PUBLIC ibl)
|
||||
target_link_libraries(${TARGET} PUBLIC ibl-lite)
|
||||
|
||||
if (FILAMENT_ENABLE_MATDBG)
|
||||
target_link_libraries(${TARGET} PUBLIC matdbg)
|
||||
@@ -377,7 +390,6 @@ set(LINUX_LINKER_OPTIMIZATION_FLAGS
|
||||
)
|
||||
|
||||
set(LINUX_COMPILER_FLAGS
|
||||
-fPIC
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
|
||||
@@ -297,10 +297,12 @@ if (APPLE)
|
||||
test/ShaderGenerator.cpp
|
||||
test/TrianglePrimitive.cpp
|
||||
test/Arguments.cpp
|
||||
test/test_FeedbackLoops.cpp
|
||||
test/test_MissingRequiredAttributes.cpp
|
||||
test/test_ReadPixels.cpp
|
||||
test/test_BufferUpdates.cpp
|
||||
test/test_MRT.cpp)
|
||||
test/test_MRT.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(backend_test PRIVATE
|
||||
backend
|
||||
@@ -326,6 +328,11 @@ if (APPLE)
|
||||
spirv-cross-msl
|
||||
)
|
||||
|
||||
if (NOT IOS)
|
||||
target_link_libraries(backend_test PRIVATE image imageio)
|
||||
list(APPEND BACKEND_TEST_DEPS image imageio)
|
||||
endif()
|
||||
|
||||
set(BACKEND_TEST_COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libbackendtest_combined.a")
|
||||
combine_static_libs(backend_test "${BACKEND_TEST_COMBINED_OUTPUT}" "${BACKEND_TEST_DEPS}")
|
||||
|
||||
@@ -337,7 +344,7 @@ if (APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE AND NOT IOS AND NOT FILAMENT_USE_SWIFTSHADER)
|
||||
if (APPLE AND NOT IOS)
|
||||
add_executable(backend_test_mac test/mac_runner.mm)
|
||||
target_link_libraries(backend_test_mac PRIVATE "-framework Metal -framework AppKit -framework QuartzCore")
|
||||
# Because each test case is a separate file, the -force_load flag is necessary to prevent the
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/unwindows.h> // Because we define ERROR in the FenceStatus enum.
|
||||
|
||||
#include <backend/PresentCallable.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <array> // FIXME: STL headers are not allowed in public headers
|
||||
@@ -41,6 +43,8 @@ namespace backend {
|
||||
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = 0x8;
|
||||
|
||||
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_SAMPLER_COUNT = 16; // Matches the Adreno Vulkan driver.
|
||||
@@ -215,6 +219,11 @@ enum class SamplerType : uint8_t {
|
||||
SAMPLER_3D, //!< 3D texture
|
||||
};
|
||||
|
||||
//! Subpass type
|
||||
enum class SubpassType : uint8_t {
|
||||
SUBPASS_INPUT
|
||||
};
|
||||
|
||||
//! Texture sampler format
|
||||
enum class SamplerFormat : uint8_t {
|
||||
INT = 0, //!< signed integer sampler
|
||||
@@ -878,6 +887,11 @@ struct PolygonOffset {
|
||||
};
|
||||
|
||||
|
||||
using FrameScheduledCallback = void(*)(backend::PresentCallable callable, void* user);
|
||||
|
||||
using FrameCompletedCallback = void(*)(void* user);
|
||||
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace backend {
|
||||
* within a CATransation:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* void myFrameFinishedCallback(PresentCallable presentCallable, void* user) {
|
||||
* void myFrameScheduledCallback(PresentCallable presentCallable, void* user) {
|
||||
* [CATransaction begin];
|
||||
* // Update other UI elements...
|
||||
* presentCallable();
|
||||
@@ -44,11 +44,13 @@ namespace backend {
|
||||
* }
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* To obtain a PresentCallable, pass a backend::FrameFinishedCallback to the beginFrame() function.
|
||||
* The callback is called with a PresentCallable object and optional user data:
|
||||
* To obtain a PresentCallable, set a SwapChain::FrameScheduledCallback on a SwapChain with the
|
||||
* SwapChain::setFrameScheduledCallback method. The callback is called with a PresentCallable object
|
||||
* and optional user data:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* if (renderer->beginFrame(swapChain, myFrameFinishedCallback, nullptr)) {
|
||||
* swapChain->setFrameScheduledCallback(myFrameScheduledCallback, nullptr);
|
||||
* if (renderer->beginFrame(swapChain)) {
|
||||
* renderer->render(view);
|
||||
* renderer->endFrame();
|
||||
* }
|
||||
@@ -57,14 +59,14 @@ namespace backend {
|
||||
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
|
||||
* backends ignore the callback (which will never be called) and proceed normally.
|
||||
*
|
||||
* @remark The backend::FrameFinishedCallback is called on an arbitrary thread.
|
||||
* @remark The SwapChain::FrameScheduledCallback is called on an arbitrary thread.
|
||||
*
|
||||
* Applications *must* call each PresentCallable they receive. Each PresentCallable represents a
|
||||
* frame that is waiting to be presented. If an application fails to call a PresentCallable, a
|
||||
* memory leak could occur. To "cancel" the presentation of a frame, pass false to the
|
||||
* PresentCallable, which will cancel the presentation of the frame and release associated memory.
|
||||
*
|
||||
* @see Renderer, SwapChain, Renderer.beginFrame
|
||||
* @see Renderer, SwapChain::setFrameScheduledCallback
|
||||
*/
|
||||
class UTILS_PUBLIC PresentCallable {
|
||||
public:
|
||||
@@ -92,18 +94,9 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* FrameFinishedCallback is a callback function that notifies an application when Filament has
|
||||
* finished processing a frame and that frame is ready to be scheduled for presentation.
|
||||
*
|
||||
* beginFrame() takes an optional FrameFinishedCallback. If the callback is provided, then that
|
||||
* frame will *not* automatically be scheduled for presentation. Instead, the application must call
|
||||
* the given PresentCallable.
|
||||
*
|
||||
* @remark The backend::FrameFinishedCallback is called on an arbitrary thread.
|
||||
*
|
||||
* @see PresentCallable, beginFrame()
|
||||
* @deprecated, FrameFinishedCallback has been renamed to SwapChain::FrameScheduledCallback.
|
||||
*/
|
||||
using FrameFinishedCallback = void(*)(PresentCallable callable, void* user);
|
||||
using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable, void* user);
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -133,8 +133,16 @@ DECL_DRIVER_API_0(tick)
|
||||
|
||||
DECL_DRIVER_API_N(beginFrame,
|
||||
int64_t, monotonic_clock_ns,
|
||||
uint32_t, frameId,
|
||||
backend::FrameFinishedCallback, callback,
|
||||
uint32_t, frameId)
|
||||
|
||||
DECL_DRIVER_API_N(setFrameScheduledCallback,
|
||||
backend::SwapChainHandle, sch,
|
||||
backend::FrameScheduledCallback, callback,
|
||||
void*, user)
|
||||
|
||||
DECL_DRIVER_API_N(setFrameCompletedCallback,
|
||||
backend::SwapChainHandle, sch,
|
||||
backend::FrameCompletedCallback, callback,
|
||||
void*, user)
|
||||
|
||||
DECL_DRIVER_API_N(setPresentationTime,
|
||||
@@ -283,6 +291,7 @@ DECL_DRIVER_API_SYNCHRONOUS_N(bool, isTextureFormatMipmappable, backend::Texture
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isRenderTargetFormatSupported, backend::TextureFormat, format)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameTimeSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, areFeedbackLoopsSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, canGenerateMipmaps)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
|
||||
|
||||
@@ -43,7 +43,8 @@ public:
|
||||
|
||||
struct Sampler {
|
||||
utils::CString name = {}; // name of the sampler in the shader
|
||||
size_t binding = 0; // binding point of the sampler in the shader
|
||||
uint16_t binding = 0; // binding point of the sampler in the shader
|
||||
bool strict = false; // if true, this sampler must always have a bound texture
|
||||
};
|
||||
|
||||
using SamplerGroupInfo = std::array<std::vector<Sampler>, SAMPLER_BINDING_COUNT>;
|
||||
|
||||
@@ -19,33 +19,148 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <math/scalar.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
// This little utility adds padding to multi-channel interleaved data by inserting dummy values.
|
||||
// This is very useful for platforms that only accept 4-component data, since users often wish to
|
||||
// submit 3-component data.
|
||||
// Provides an alpha value when expanding 3-channel images to 4-channel.
|
||||
// Also used as a normalization scale when converting between numeric types.
|
||||
template<typename componentType> inline componentType getMaxValue();
|
||||
|
||||
class DataReshaper {
|
||||
public:
|
||||
template<typename componentType, int numSrcChannels, int numDstChannels,
|
||||
componentType maxValue = std::numeric_limits<componentType>::max()>
|
||||
|
||||
// Adds padding to multi-channel interleaved data by inserting dummy values, or discards
|
||||
// trailing channels. This is useful for platforms that only accept 4-component data, since
|
||||
// users often wish to submit (or receive) 3-component data.
|
||||
template<typename componentType, size_t srcChannelCount, size_t dstChannelCount>
|
||||
static void reshape(void* dest, const void* src, size_t numSrcBytes) {
|
||||
const componentType maxValue = getMaxValue<componentType>();
|
||||
const componentType* in = (const componentType*) src;
|
||||
componentType* out = (componentType*) dest;
|
||||
const size_t numWords = (numSrcBytes / sizeof(componentType)) / numSrcChannels;
|
||||
for (size_t word = 0; word < numWords; ++word) {
|
||||
for (size_t component = 0; component < numSrcChannels; ++component) {
|
||||
out[component] = in[component];
|
||||
const size_t width = (numSrcBytes / sizeof(componentType)) / srcChannelCount;
|
||||
const int minChannelCount = filament::math::min(srcChannelCount, dstChannelCount);
|
||||
for (size_t column = 0; column < width; ++column) {
|
||||
for (size_t channel = 0; channel < minChannelCount; ++channel) {
|
||||
out[channel] = in[channel];
|
||||
}
|
||||
for (size_t component = (size_t)numSrcChannels; component < numDstChannels; ++component) {
|
||||
out[component] = maxValue;
|
||||
for (size_t channel = srcChannelCount; channel < dstChannelCount; ++channel) {
|
||||
out[channel] = maxValue;
|
||||
}
|
||||
in += numSrcChannels;
|
||||
out += numDstChannels;
|
||||
in += srcChannelCount;
|
||||
out += dstChannelCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a 4-channel image of UBYTE, INT, UINT, or FLOAT to a different type.
|
||||
template<typename dstComponentType, typename srcComponentType>
|
||||
static void reshapeImage(uint8_t* dest, const uint8_t* src, size_t srcBytesPerRow,
|
||||
size_t dstBytesPerRow, size_t dstChannelCount, size_t height, bool swizzle, bool flip) {
|
||||
const size_t srcChannelCount = 4;
|
||||
const dstComponentType dstMaxValue = getMaxValue<dstComponentType>();
|
||||
const srcComponentType srcMaxValue = getMaxValue<srcComponentType>();
|
||||
const size_t width = (srcBytesPerRow / sizeof(srcComponentType)) / srcChannelCount;
|
||||
const size_t minChannelCount = filament::math::min(srcChannelCount, dstChannelCount);
|
||||
assert(minChannelCount <= 4);
|
||||
const int inds[4] = {swizzle ? 2 : 0, 1, swizzle ? 0 : 2, 3};
|
||||
|
||||
int srcStride;
|
||||
if (flip) {
|
||||
src += srcBytesPerRow * (height - 1);
|
||||
srcStride = -srcBytesPerRow;
|
||||
} else {
|
||||
srcStride = srcBytesPerRow;
|
||||
}
|
||||
|
||||
for (size_t row = 0; row < height; ++row) {
|
||||
const srcComponentType* in = (const srcComponentType*) src;
|
||||
dstComponentType* out = (dstComponentType*) dest;
|
||||
for (size_t column = 0; column < width; ++column) {
|
||||
for (size_t channel = 0; channel < minChannelCount; ++channel) {
|
||||
out[channel] = in[inds[channel]] * dstMaxValue / srcMaxValue;
|
||||
}
|
||||
for (size_t channel = srcChannelCount; channel < dstChannelCount; ++channel) {
|
||||
out[channel] = dstMaxValue;
|
||||
}
|
||||
in += srcChannelCount;
|
||||
out += dstChannelCount;
|
||||
}
|
||||
src += srcStride;
|
||||
dest += dstBytesPerRow;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a 4-channel image of UBYTE, INT, UINT, or FLOAT to a different type.
|
||||
static bool reshapeImage(PixelBufferDescriptor* dst, PixelDataType srcType,
|
||||
const uint8_t* srcBytes, int srcBytesPerRow, int width, int height, bool swizzle,
|
||||
bool flip) {
|
||||
size_t dstChannelCount;
|
||||
switch (dst->format) {
|
||||
case PixelDataFormat::RGB: dstChannelCount = 3; break;
|
||||
case PixelDataFormat::RGBA: dstChannelCount = 4; break;
|
||||
default: return false;
|
||||
}
|
||||
void (*reshaper)(uint8_t*, const uint8_t*, size_t, size_t, size_t, size_t, bool, bool)
|
||||
= nullptr;
|
||||
constexpr auto UBYTE = PixelDataType::UBYTE, FLOAT = PixelDataType::FLOAT,
|
||||
UINT = PixelDataType::UINT, INT = PixelDataType::INT;
|
||||
switch (dst->type) {
|
||||
case UBYTE:
|
||||
switch (srcType) {
|
||||
case UBYTE: reshaper = reshapeImage<uint8_t, uint8_t>; break;
|
||||
case FLOAT: reshaper = reshapeImage<uint8_t, float>; break;
|
||||
case INT: reshaper = reshapeImage<uint8_t, int32_t>; break;
|
||||
case UINT: reshaper = reshapeImage<uint8_t, uint32_t>; break;
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
case FLOAT:
|
||||
switch (srcType) {
|
||||
case UBYTE: reshaper = reshapeImage<float, uint8_t>; break;
|
||||
case FLOAT: reshaper = reshapeImage<float, float>; break;
|
||||
case INT: reshaper = reshapeImage<float, int32_t>; break;
|
||||
case UINT: reshaper = reshapeImage<float, uint32_t>; break;
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
case INT:
|
||||
switch (srcType) {
|
||||
case UBYTE: reshaper = reshapeImage<int32_t, uint8_t>; break;
|
||||
case FLOAT: reshaper = reshapeImage<int32_t, float>; break;
|
||||
case INT: reshaper = reshapeImage<int32_t, int32_t>; break;
|
||||
case UINT: reshaper = reshapeImage<int32_t, uint32_t>; break;
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
case UINT:
|
||||
switch (srcType) {
|
||||
case UBYTE: reshaper = reshapeImage<uint32_t, uint8_t>; break;
|
||||
case FLOAT: reshaper = reshapeImage<uint32_t, float>; break;
|
||||
case INT: reshaper = reshapeImage<uint32_t, int32_t>; break;
|
||||
case UINT: reshaper = reshapeImage<uint32_t, uint32_t>; break;
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
uint8_t* dstBytes = (uint8_t*) dst->buffer;
|
||||
const int dstBytesPerRow = PixelBufferDescriptor::computeDataSize(dst->format, dst->type,
|
||||
dst->stride ? dst->stride : width, 1, dst->alignment);
|
||||
reshaper(dstBytes, srcBytes, srcBytesPerRow, dstBytesPerRow, dstChannelCount, height,
|
||||
swizzle, flip);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<> inline float getMaxValue() { return 1.0f; }
|
||||
template<> inline int32_t getMaxValue() { return 0x7fffffff; }
|
||||
template<> inline uint32_t getMaxValue() { return 0xffffffff; }
|
||||
template<> inline uint16_t getMaxValue() { return 0x3c00; } // 0x3c00 is 1.0 in half-float.
|
||||
template<> inline uint8_t getMaxValue() { return 0xff; }
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ TextureReshaper::TextureReshaper(TextureFormat requestedFormat) noexcept {
|
||||
const size_t reshapedSize = p.size / 6 * 8; // reshaping from 6 to 8 bytes per pixel
|
||||
void* reshapeBuffer = malloc(reshapedSize);
|
||||
ASSERT_POSTCONDITION(reshapeBuffer, "Could not allocate memory to reshape pixels.");
|
||||
// 0x3c00 is 1.0 in 16 bit floating point.
|
||||
DataReshaper::reshape<uint16_t, 3, 4, 0x3c00>(reshapeBuffer, p.buffer, p.size);
|
||||
DataReshaper::reshape<uint16_t, 3, 4>(reshapeBuffer, p.buffer, p.size);
|
||||
|
||||
PixelBufferDescriptor reshaped(reshapeBuffer, reshapedSize,
|
||||
PixelBufferDescriptor::PixelDataFormat::RGBA,
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
#include <Metal/Metal.h>
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
#include <tsl/robin_set.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
class MetalDriver;
|
||||
class MetalBlitter;
|
||||
class MetalBufferPool;
|
||||
class MetalRenderTarget;
|
||||
@@ -39,21 +42,13 @@ struct MetalSamplerGroup;
|
||||
struct MetalVertexBuffer;
|
||||
|
||||
struct MetalContext {
|
||||
MetalDriver* driver;
|
||||
id<MTLDevice> device = nullptr;
|
||||
id<MTLCommandQueue> commandQueue = nullptr;
|
||||
|
||||
id<MTLCommandBuffer> pendingCommandBuffer = nullptr;
|
||||
id<MTLRenderCommandEncoder> currentRenderPassEncoder = nullptr;
|
||||
|
||||
// These two fields store a callback and user data to notify the client that a frame is ready
|
||||
// for presentation.
|
||||
// If frameFinishedCallback is nullptr, then the Metal backend automatically calls
|
||||
// presentDrawable when the frame is commited.
|
||||
// Otherwise, the Metal backend will not automatically present the frame. Instead, clients bear
|
||||
// the responsibility of presenting the frame by calling the PresentCallable object.
|
||||
backend::FrameFinishedCallback frameFinishedCallback = nullptr;
|
||||
void* frameFinishedUserData = nullptr;
|
||||
|
||||
// Tracks resources used by command buffers.
|
||||
MetalResourceTracker resourceTracker;
|
||||
|
||||
@@ -65,6 +60,7 @@ struct MetalContext {
|
||||
DepthStencilStateTracker depthStencilState;
|
||||
UniformBufferState uniformState[VERTEX_BUFFER_START];
|
||||
CullModeStateTracker cullModeState;
|
||||
WindingStateTracker windingState;
|
||||
|
||||
// State caches.
|
||||
DepthStencilStateCache depthStencilStateCache;
|
||||
@@ -73,13 +69,13 @@ struct MetalContext {
|
||||
|
||||
MetalSamplerGroup* samplerBindings[SAMPLER_BINDING_COUNT] = {};
|
||||
|
||||
// Keeps track of all alive sampler groups.
|
||||
tsl::robin_set<MetalSamplerGroup*> samplerGroups;
|
||||
|
||||
MetalBufferPool* bufferPool;
|
||||
|
||||
// Surface-related properties.
|
||||
MetalSwapChain* currentSurface = nullptr;
|
||||
id<CAMetalDrawable> currentDrawable = nil;
|
||||
id<MTLTexture> currentDepthTexture = nil;
|
||||
id<MTLTexture> headlessDrawable = nil;
|
||||
MetalSwapChain* currentDrawSwapChain = nil;
|
||||
MetalSwapChain* currentReadSwapChain = nil;
|
||||
|
||||
// External textures.
|
||||
CVMetalTextureCacheRef textureCache = nullptr;
|
||||
@@ -98,14 +94,6 @@ struct MetalContext {
|
||||
TimerQueryInterface* timerQueryImpl;
|
||||
};
|
||||
|
||||
// Acquire the current surface's CAMetalDrawable for the current frame if it has not already been
|
||||
// acquired. This method stores it in the context's currentDrawable field and returns the
|
||||
// drawable's texture.
|
||||
// For headless swapchains a new texture is created.
|
||||
id<MTLTexture> acquireDrawable(MetalContext* context);
|
||||
|
||||
id<MTLTexture> acquireDepthTexture(MetalContext* context);
|
||||
|
||||
id<MTLCommandBuffer> getPendingCommandBuffer(MetalContext* context);
|
||||
|
||||
void submitPendingCommands(MetalContext* context);
|
||||
|
||||
@@ -24,94 +24,6 @@ namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
void presentDrawable(bool presentFrame, void* user) {
|
||||
// CFBridgingRelease here is used to balance the CFBridgingRetain inside of acquireDrawable.
|
||||
id<CAMetalDrawable> drawable = (id<CAMetalDrawable>) CFBridgingRelease(user);
|
||||
if (presentFrame) {
|
||||
[drawable present];
|
||||
}
|
||||
// The drawable will be released here when the "drawable" variable goes out of scope.
|
||||
}
|
||||
|
||||
id<MTLTexture> acquireDrawable(MetalContext* context) {
|
||||
if (context->currentDrawable) {
|
||||
return context->currentDrawable.texture;
|
||||
}
|
||||
if (context->currentSurface->isHeadless()) {
|
||||
if (context->headlessDrawable) {
|
||||
return context->headlessDrawable;
|
||||
}
|
||||
// For headless surfaces we construct a "fake" drawable, which is simply a renderable
|
||||
// texture.
|
||||
MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor new];
|
||||
textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
textureDescriptor.width = context->currentSurface->getSurfaceWidth();
|
||||
textureDescriptor.height = context->currentSurface->getSurfaceHeight();
|
||||
// Specify MTLTextureUsageShaderRead so the headless surface can be blitted from.
|
||||
textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
||||
#if defined(IOS)
|
||||
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||
#else
|
||||
textureDescriptor.storageMode = MTLStorageModeManaged;
|
||||
#endif
|
||||
context->headlessDrawable = [context->device newTextureWithDescriptor:textureDescriptor];
|
||||
return context->headlessDrawable;
|
||||
}
|
||||
|
||||
context->currentDrawable = [context->currentSurface->getLayer() nextDrawable];
|
||||
|
||||
if (context->frameFinishedCallback) {
|
||||
id<CAMetalDrawable> drawable = context->currentDrawable;
|
||||
backend::FrameFinishedCallback callback = context->frameFinishedCallback;
|
||||
void* userData = context->frameFinishedUserData;
|
||||
// This block strongly captures drawable to keep it alive until the handler executes.
|
||||
[getPendingCommandBuffer(context) addScheduledHandler:^(id<MTLCommandBuffer> cb) {
|
||||
// CFBridgingRetain is used here to give the drawable a +1 retain count before
|
||||
// casting it to a void*.
|
||||
PresentCallable callable(presentDrawable, (void*) CFBridgingRetain(drawable));
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
callback(callable, userData);
|
||||
});
|
||||
}];
|
||||
}
|
||||
ASSERT_POSTCONDITION(context->currentDrawable != nil, "Could not obtain drawable.");
|
||||
return context->currentDrawable.texture;
|
||||
}
|
||||
|
||||
id<MTLTexture> acquireDepthTexture(MetalContext* context) {
|
||||
if (context->currentDepthTexture) {
|
||||
// If the surface size has changed, we'll need to allocate a new depth texture.
|
||||
if (context->currentDepthTexture.width != context->currentSurface->getSurfaceWidth() ||
|
||||
context->currentDepthTexture.height != context->currentSurface->getSurfaceHeight()) {
|
||||
context->currentDepthTexture = nil;
|
||||
} else {
|
||||
return context->currentDepthTexture;
|
||||
}
|
||||
}
|
||||
|
||||
const MTLPixelFormat depthFormat =
|
||||
#if defined(IOS)
|
||||
MTLPixelFormatDepth32Float;
|
||||
#else
|
||||
context->device.depth24Stencil8PixelFormatSupported ?
|
||||
MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float;
|
||||
#endif
|
||||
|
||||
const NSUInteger width = context->currentSurface->getSurfaceWidth();
|
||||
const NSUInteger height = context->currentSurface->getSurfaceHeight();
|
||||
MTLTextureDescriptor* descriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:depthFormat
|
||||
width:width
|
||||
height:height
|
||||
mipmapped:NO];
|
||||
descriptor.usage = MTLTextureUsageRenderTarget;
|
||||
descriptor.resourceOptions = MTLResourceStorageModePrivate;
|
||||
|
||||
context->currentDepthTexture = [context->device newTextureWithDescriptor:descriptor];
|
||||
|
||||
return context->currentDepthTexture;
|
||||
}
|
||||
|
||||
id<MTLCommandBuffer> getPendingCommandBuffer(MetalContext* context) {
|
||||
if (context->pendingCommandBuffer) {
|
||||
return context->pendingCommandBuffer;
|
||||
|
||||