Compare commits
104 Commits
sceneform-
...
sceneform-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae6ab66af4 | ||
|
|
7be3994c96 | ||
|
|
836b641bff | ||
|
|
44bfac85e9 | ||
|
|
a141abd212 | ||
|
|
12aba0f1b7 | ||
|
|
40666bdd23 | ||
|
|
66d71be300 | ||
|
|
614a832be0 | ||
|
|
92de93bfb8 | ||
|
|
c1b7f2ac27 | ||
|
|
6110809d23 | ||
|
|
81a52411ed | ||
|
|
6956154d62 | ||
|
|
9940a68165 | ||
|
|
c3d957671d | ||
|
|
fbb7e1f2ef | ||
|
|
6e90d73e24 | ||
|
|
07c1dbb5f4 | ||
|
|
4e0749f0ae | ||
|
|
f5bd28b7df | ||
|
|
ad4c4148f4 | ||
|
|
a35762bdf2 | ||
|
|
1ca2b1b642 | ||
|
|
373e519292 | ||
|
|
acea32aae8 | ||
|
|
150fd321bc | ||
|
|
1bbe203a15 | ||
|
|
37201e742f | ||
|
|
ba8adc2d49 | ||
|
|
d3efbd810e | ||
|
|
91c946cfbd | ||
|
|
98d39b7e7e | ||
|
|
e7169cb889 | ||
|
|
8f70f8f879 | ||
|
|
8c6ac11c2d | ||
|
|
d9bebaa8e7 | ||
|
|
5baa699c7c | ||
|
|
8c8cfb6528 | ||
|
|
f1c6acafff | ||
|
|
03161226f2 | ||
|
|
4d0859b266 | ||
|
|
896c85c324 | ||
|
|
49f1464016 | ||
|
|
c8b3544a36 | ||
|
|
321845d04a | ||
|
|
a31928600e | ||
|
|
f3752a42c8 | ||
|
|
2f35f26148 | ||
|
|
d47e6f9456 | ||
|
|
6bb385f354 | ||
|
|
dd7af66516 | ||
|
|
04f3268961 | ||
|
|
a3c939894c | ||
|
|
b460d2f547 | ||
|
|
9ea81bc2fd | ||
|
|
cebc83e8fa | ||
|
|
b3cd6a7f59 | ||
|
|
c8f5190099 | ||
|
|
28ab087f79 | ||
|
|
e66aeb0c94 | ||
|
|
749817b64b | ||
|
|
1b18724b6b | ||
|
|
ff5a2a7a99 | ||
|
|
125f79e5e0 | ||
|
|
fac084dfdf | ||
|
|
f8ebc047e0 | ||
|
|
00f6fa24f7 | ||
|
|
0394aeb23b | ||
|
|
c4989da047 | ||
|
|
60363e518d | ||
|
|
2a74397101 | ||
|
|
0cccbda9b9 | ||
|
|
0c1fdc88ec | ||
|
|
8228deb209 | ||
|
|
8029ad5cc3 | ||
|
|
045274bbdb | ||
|
|
206512add0 | ||
|
|
f876171239 | ||
|
|
f96501215b | ||
|
|
0158e7e858 | ||
|
|
c6444fb502 | ||
|
|
60d304a83b | ||
|
|
422bf8631b | ||
|
|
013d735242 | ||
|
|
3be10d816a | ||
|
|
9ce88e6e23 | ||
|
|
83c40e6664 | ||
|
|
28f2806beb | ||
|
|
d37e21f4ea | ||
|
|
d113af8afb | ||
|
|
f676d3d3ea | ||
|
|
cd2786a2ef | ||
|
|
5ea35ab87e | ||
|
|
c21d11e20f | ||
|
|
8fe11a067d | ||
|
|
67ffa91843 | ||
|
|
55fbb300ca | ||
|
|
4901f6f72a | ||
|
|
cfb9c03226 | ||
|
|
d6de2bf426 | ||
|
|
b5eb00bdb1 | ||
|
|
ede9f7fdbb | ||
|
|
eaf790aaa7 |
@@ -169,7 +169,10 @@ endif()
|
||||
# -fsanitize=undefined causes extremely long link times
|
||||
# -fsanitize=address causes a crash with assimp, which we can't explain for now
|
||||
#set(EXTRA_SANITIZE_OPTIONS "-fsanitize=undefined -fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
|
||||
# clang-cl.exe on Windows does not support -fstack-protector.
|
||||
if (NOT CLANG_CL)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
|
||||
|
||||
# ==================================================================================================
|
||||
@@ -223,6 +226,24 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
add_definitions(-DFILAMENT_DRIVER_SUPPORTS_VULKAN)
|
||||
endif()
|
||||
|
||||
# Build with Metal support on non-WebGL Apple platforms.
|
||||
if (APPLE AND NOT WEBGL)
|
||||
option(FILAMENT_SUPPORTS_METAL "Include the Metal backend" ON)
|
||||
else()
|
||||
option(FILAMENT_SUPPORTS_METAL "Include the Metal backend" OFF)
|
||||
endif()
|
||||
if (FILAMENT_SUPPORTS_METAL)
|
||||
add_definitions(-DFILAMENT_SUPPORTS_METAL)
|
||||
endif()
|
||||
|
||||
# Building filamat increases build times and isn't required for non-desktop platforms, so turn it
|
||||
# off by default.
|
||||
if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
|
||||
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" ON)
|
||||
else()
|
||||
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" OFF)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Distribution
|
||||
# ==================================================================================================
|
||||
@@ -288,19 +309,18 @@ function(get_resgen_vars ARCHIVE_DIR ARCHIVE_NAME)
|
||||
${ARCHIVE_DIR}/${ARCHIVE_NAME}.apple.S
|
||||
${ARCHIVE_DIR}/${ARCHIVE_NAME}.h
|
||||
)
|
||||
if (NOT WIN32)
|
||||
set(ASM_ARCH_FLAG "-arch ${DIST_ARCH}")
|
||||
endif()
|
||||
set(ASM_ARCH_FLAG "-arch ${DIST_ARCH}")
|
||||
if (APPLE)
|
||||
set(ASM_SUFFIX ".apple")
|
||||
endif()
|
||||
if (WEBGL)
|
||||
set(RESGEN_HEADER "${ARCHIVE_DIR}/${ARCHIVE_NAME}.h" PARENT_SCOPE)
|
||||
set(RESGEN_HEADER "${ARCHIVE_DIR}/${ARCHIVE_NAME}.h" PARENT_SCOPE)
|
||||
# Visual Studio makes it difficult to use assembly without using MASM. MASM doesn't support
|
||||
# the equivalent of .incbin, so on Windows we'll just tell resgen to output a C file.
|
||||
if (WEBGL OR WIN32)
|
||||
set(RESGEN_OUTPUTS "${OUTPUTS};${ARCHIVE_DIR}/${ARCHIVE_NAME}.c" PARENT_SCOPE)
|
||||
set(RESGEN_FLAGS -cx ${ARCHIVE_DIR} -p ${ARCHIVE_NAME} PARENT_SCOPE)
|
||||
set(RESGEN_SOURCE "${ARCHIVE_DIR}/${ARCHIVE_NAME}.c" PARENT_SCOPE)
|
||||
else()
|
||||
set(RESGEN_HEADER "${ARCHIVE_DIR}/${ARCHIVE_NAME}.h" PARENT_SCOPE)
|
||||
set(RESGEN_OUTPUTS "${OUTPUTS}" PARENT_SCOPE)
|
||||
set(RESGEN_FLAGS -x ${ARCHIVE_DIR} -p ${ARCHIVE_NAME} PARENT_SCOPE)
|
||||
set(RESGEN_SOURCE "${ARCHIVE_DIR}/${ARCHIVE_NAME}${ASM_SUFFIX}.S" PARENT_SCOPE)
|
||||
@@ -311,17 +331,11 @@ endfunction()
|
||||
# ==================================================================================================
|
||||
# Sub-projects
|
||||
# ==================================================================================================
|
||||
# spirv-tools must come before filamat, as filamat relies on the presence of the
|
||||
# spirv-tools_SOURCE_DIR variable.
|
||||
add_subdirectory(${EXTERNAL}/spirv-tools)
|
||||
add_subdirectory(${EXTERNAL}/glslang/tnt)
|
||||
add_subdirectory(${EXTERNAL}/spirv-cross/tnt)
|
||||
|
||||
# Common to all platforms
|
||||
add_subdirectory(${EXTERNAL}/libgtest/tnt)
|
||||
add_subdirectory(${LIBRARIES}/filabridge)
|
||||
add_subdirectory(${LIBRARIES}/filaflat)
|
||||
add_subdirectory(${LIBRARIES}/filamat)
|
||||
add_subdirectory(${LIBRARIES}/filameshio)
|
||||
add_subdirectory(${LIBRARIES}/image)
|
||||
add_subdirectory(${LIBRARIES}/math)
|
||||
@@ -333,6 +347,16 @@ add_subdirectory(${EXTERNAL}/smol-v/tnt)
|
||||
add_subdirectory(${EXTERNAL}/benchmark/tnt)
|
||||
add_subdirectory(${EXTERNAL}/meshoptimizer)
|
||||
|
||||
if (FILAMENT_BUILD_FILAMAT)
|
||||
# spirv-tools must come before filamat, as filamat relies on the presence of the
|
||||
# spirv-tools_SOURCE_DIR variable.
|
||||
add_subdirectory(${EXTERNAL}/spirv-tools)
|
||||
add_subdirectory(${EXTERNAL}/glslang/tnt)
|
||||
add_subdirectory(${EXTERNAL}/spirv-cross/tnt)
|
||||
add_subdirectory(android/filamat-android)
|
||||
add_subdirectory(${LIBRARIES}/filamat)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
add_subdirectory(${LIBRARIES}/bluevk)
|
||||
add_subdirectory(${EXTERNAL}/vkmemalloc/tnt)
|
||||
@@ -354,13 +378,13 @@ if (WEBGL)
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
|
||||
add_subdirectory(${FILAMENT}/samples)
|
||||
|
||||
add_subdirectory(${LIBRARIES}/bluegl)
|
||||
add_subdirectory(${LIBRARIES}/filagui)
|
||||
add_subdirectory(${LIBRARIES}/imageio)
|
||||
|
||||
add_subdirectory(${FILAMENT}/java)
|
||||
add_subdirectory(${FILAMENT}/samples)
|
||||
|
||||
add_subdirectory(${EXTERNAL}/astcenc/tnt)
|
||||
add_subdirectory(${EXTERNAL}/etc2comp)
|
||||
add_subdirectory(${EXTERNAL}/getopt)
|
||||
@@ -375,6 +399,7 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
|
||||
|
||||
add_subdirectory(${TOOLS}/cmgen)
|
||||
add_subdirectory(${TOOLS}/filamesh)
|
||||
add_subdirectory(${TOOLS}/glslminifier)
|
||||
add_subdirectory(${TOOLS}/matc)
|
||||
add_subdirectory(${TOOLS}/matinfo)
|
||||
add_subdirectory(${TOOLS}/mipgen)
|
||||
@@ -387,5 +412,5 @@ endif()
|
||||
|
||||
# Generate exported executables for cross-compiled builds (Android, WebGL, and iOS)
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
export(TARGETS matc cmgen filamesh mipgen resgen FILE ${IMPORT_EXECUTABLES})
|
||||
export(TARGETS matc cmgen filamesh mipgen resgen glslminifier FILE ${IMPORT_EXECUTABLES})
|
||||
endif()
|
||||
|
||||
51
README.md
@@ -18,6 +18,9 @@ Android devices and as the renderer inside the Android Studio plugin.
|
||||
|
||||
[Download Filament releases](https://github.com/google/filament/releases) to access stable builds.
|
||||
|
||||
Make sure you always use tools from the same release as the runtime library. This is particularly
|
||||
important for `matc` (material compiler).
|
||||
|
||||
If you prefer to live on the edge, you can download a continuous build by clicking one of the build
|
||||
badges above.
|
||||
|
||||
@@ -102,6 +105,7 @@ and tools.
|
||||
|
||||
- `android`: Android libraries and projects
|
||||
- `build`: Custom Gradle tasks for Android builds
|
||||
- `filamat-android`: Filament material generation library (AAR) for Android
|
||||
- `filament-android`: Filament library (AAR) for Android
|
||||
- `samples`: Android-specific Filament samples
|
||||
- `art`: Source for various artworks (logos, PDF manuals, etc.)
|
||||
@@ -133,6 +137,7 @@ and tools.
|
||||
- `tools`: Host tools
|
||||
- `cmgen`: Image-based lighting asset generator
|
||||
- `filamesh`: Mesh converter
|
||||
- `glslminifier`: Minifies GLSL source code
|
||||
- `matc`: Material compiler
|
||||
- `matinfo` Displays information about materials compiled with `matc`
|
||||
- `mipgen` Generates a series of miplevels from a source image
|
||||
@@ -150,7 +155,7 @@ and tools.
|
||||
To build Filament, you must first install the following tools:
|
||||
|
||||
- CMake 3.4 (or more recent)
|
||||
- clang 5.0 (or more recent)
|
||||
- clang 7.0 (or more recent)
|
||||
- [ninja 1.8](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) (or more recent)
|
||||
|
||||
To build the Java based components of the project you can optionally install (recommended):
|
||||
@@ -162,7 +167,7 @@ section below.
|
||||
|
||||
To build Filament for Android you must also install the following:
|
||||
|
||||
- Android Studio 3.1
|
||||
- Android Studio 3.3
|
||||
- Android SDK
|
||||
- Android NDK
|
||||
|
||||
@@ -226,8 +231,8 @@ If you use CMake directly instead of the build script, pass `-DENABLE_JAVA=OFF`
|
||||
Make sure you've installed the following dependencies:
|
||||
|
||||
- `libglu1-mesa-dev`
|
||||
- `libc++-dev` (`libcxx-devel` on Fedora)
|
||||
- `libc++abi-dev`
|
||||
- `libc++-7-dev` (`libcxx-devel` on Fedora)
|
||||
- `libc++abi-7-dev`
|
||||
- `ninja-build`
|
||||
- `libxi-dev`
|
||||
|
||||
@@ -256,8 +261,8 @@ Your Linux distribution might default to `gcc` instead of `clang`, if that's the
|
||||
```
|
||||
$ mkdir out/cmake-release
|
||||
$ cd out/cmake-release
|
||||
# Or use a specific version of clang, for instance /usr/bin/clang-5.0
|
||||
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ \
|
||||
# Or use a specific version of clang, for instance /usr/bin/clang-7
|
||||
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ LDFLAGS=-lc++abi \
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
|
||||
```
|
||||
|
||||
@@ -268,8 +273,8 @@ specific version of clang:
|
||||
```
|
||||
$ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
|
||||
$ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
|
||||
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-5.0 100
|
||||
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-5.0 100
|
||||
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
|
||||
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100
|
||||
```
|
||||
|
||||
Finally, invoke `ninja`:
|
||||
@@ -327,14 +332,21 @@ Google employees require additional steps which can be found here [go/filawin](h
|
||||
Install the following components:
|
||||
|
||||
- [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
|
||||
- [Visual Studio 2015](https://www.visualstudio.com/downloads)
|
||||
- [Visual Studio 2015 or 2017](https://www.visualstudio.com/downloads)
|
||||
- [Clang 6](http://releases.llvm.org/download.html)
|
||||
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
|
||||
- [Git 2.16.1 or later](https://github.com/git-for-windows/git/releases/download/v2.16.1.windows.4/PortableGit-2.16.1.4-64-bit.7z.exe)
|
||||
- [Cmake 3.11 or later](https://cmake.org/files/v3.11/cmake-3.11.0-rc1-win64-x64.msi)
|
||||
|
||||
Open an VS2015 x64 Native Tools terminal (click the start button, type "x64 native tools" and
|
||||
select: "VS2015 x64 Native Tools Command Prompt").
|
||||
If you're using Visual Studio 2017, you'll also need to install the [LLVM Compiler
|
||||
Toolchain](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.llvm-toolchain)
|
||||
extension.
|
||||
|
||||
Open an appropriate Native Tools terminal for the version of Visual Studio you are using:
|
||||
- VS 2015: VS2015 x64 Native Tools Command Prompt
|
||||
- VS 2017: x64 Native Tools Command Prompt for VS 2017
|
||||
|
||||
You can find these by clicking the start button and typing "x64 native tools".
|
||||
|
||||
Create a working directory:
|
||||
```
|
||||
@@ -344,11 +356,20 @@ Create a working directory:
|
||||
|
||||
Create the msBuild project:
|
||||
```
|
||||
# Visual Studio 2015:
|
||||
> cmake -T"LLVM-vs2014" -G "Visual Studio 14 2015 Win64" ../..
|
||||
|
||||
# Visual Studio 2017
|
||||
> cmake ..\.. -T"LLVM" -G "Visual Studio 15 2017 Win64" ^
|
||||
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
|
||||
-DCMAKE_C_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
|
||||
-DCMAKE_LINKER:PATH="C:\Program Files\LLVM\bin\lld-link.exe"
|
||||
```
|
||||
|
||||
Check out the output and make sure Clang for Windows frontend was found. You should see a line
|
||||
showing the following output.
|
||||
showing the following output. Note that for Visual Studio 2017 this line may list Microsoft's
|
||||
compiler, but the build will still in fact use Clang and you can proceed.
|
||||
|
||||
```
|
||||
Clang:C:/Program Files/LLVM/msbuild-bin/cl.exe
|
||||
```
|
||||
@@ -379,11 +400,11 @@ Alternatively, you can use [Ninja](https://ninja-build.org/) to build for Window
|
||||
installation is still necessary.
|
||||
|
||||
First, install the dependencies listed under [Windows](#Windows) as well as Ninja. Then open up a
|
||||
VS2015 x64 Native Tools terminal as before. Create a build directory inside Filament and run the
|
||||
Native Tools terminal as before. Create a build directory inside Filament and run the
|
||||
following CMake command:
|
||||
|
||||
```
|
||||
cmake .. -G Ninja ^
|
||||
> cmake .. -G Ninja ^
|
||||
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
|
||||
-DCMAKE_C_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
|
||||
-DCMAKE_LINKER:PATH="C:\Program Files\LLVM\bin\lld-link.exe" ^
|
||||
@@ -426,6 +447,8 @@ Filament can be built for the following architectures:
|
||||
Note that the main target is the ARM 64-bit target. Our implementation is optimized first and
|
||||
foremost for `arm64-v8a`.
|
||||
|
||||
To build Android on Windows machines, see [android/Windows.md](android/Windows.md).
|
||||
|
||||
#### Easy Android build
|
||||
|
||||
The easiest way to build Filament for Android is to use `build.sh` and the
|
||||
|
||||
160
android/Windows.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# Building Filament for Android on Windows
|
||||
|
||||
## Prerequisites
|
||||
|
||||
In addition to the requirements for [building Filament on Windows](../README.md#windows), you'll
|
||||
need the Android SDK and NDK. See [Getting Started with the
|
||||
NDK](https://developer.android.com/ndk/guides/) for detailed installation instructions.
|
||||
|
||||
Ensure the `%ANDROID_HOME%` environment variable is set to your Android SDK installation location.
|
||||
|
||||
All of the following commands should be executed in a Visual Studio x64 Native Tools Command Prompt.
|
||||
|
||||
## Desktop Tools
|
||||
|
||||
First, a few Filament tools need to be compiled for desktop.
|
||||
|
||||
1. From Filament's root directory, create a desktop build directory and run CMake.
|
||||
|
||||
```
|
||||
mkdir out\cmake-release
|
||||
cd out\cmake-release
|
||||
cmake ^
|
||||
-G Ninja ^
|
||||
-DCMAKE_CXX_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
|
||||
-DCMAKE_C_COMPILER:PATH="C:\Program Files\LLVM\bin\clang-cl.exe" ^
|
||||
-DCMAKE_LINKER:PATH="C:\Program Files\LLVM\bin\lld-link.exe" ^
|
||||
-DCMAKE_INSTALL_PREFIX=..\release\filament ^
|
||||
-DENABLE_JAVA=NO ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
..\..
|
||||
```
|
||||
|
||||
2. Build the required desktop host tools.
|
||||
|
||||
```
|
||||
ninja matc resgen cmgen
|
||||
```
|
||||
|
||||
The build should succeed and a `ImportExecutables-Release.cmake` file should automatically be
|
||||
created at Filament's root directory.
|
||||
|
||||
## Toolchains
|
||||
|
||||
Generate a toolchain for each Android architecture you're interested in building for.
|
||||
|
||||
From Filament's root directory, run the NDK `make_standalone_toolchain.py` script for each
|
||||
architecture.
|
||||
|
||||
```
|
||||
python %ANDROID_HOME%\ndk-bundle\build\tools\make_standalone_toolchain.py ^
|
||||
--arch arm64 ^
|
||||
--api 21 ^
|
||||
--stl libc++ ^
|
||||
--force ^
|
||||
--install-dir "toolchains/Windows/aarch64-linux-android-4.9"
|
||||
|
||||
python %ANDROID_HOME%\ndk-bundle\build\tools\make_standalone_toolchain.py ^
|
||||
--arch arm ^
|
||||
--api 21 ^
|
||||
--stl libc++ ^
|
||||
--force ^
|
||||
--install-dir "toolchains/Windows/arm-linux-android-4.9"
|
||||
|
||||
python %ANDROID_HOME%\ndk-bundle\build\tools\make_standalone_toolchain.py ^
|
||||
--arch x86_64 ^
|
||||
--api 21 ^
|
||||
--stl libc++ ^
|
||||
--force ^
|
||||
--install-dir "toolchains/Windows/x86_64-linux-android-4.9"
|
||||
|
||||
python %ANDROID_HOME%\ndk-bundle\build\tools\make_standalone_toolchain.py ^
|
||||
--arch x86 ^
|
||||
--api 21 ^
|
||||
--stl libc++ ^
|
||||
--force ^
|
||||
--install-dir "toolchains/Windows/x86-linux-android-4.9"
|
||||
````
|
||||
|
||||
## Build
|
||||
|
||||
1. Create the build directories.
|
||||
|
||||
```
|
||||
mkdir out\cmake-android-release-aarch64
|
||||
mkdir out\cmake-android-release-arm7
|
||||
mkdir out\cmake-android-release-x86_64
|
||||
mkdir out\cmake-android-release-x86
|
||||
```
|
||||
|
||||
2. Run CMake for each architecture.
|
||||
|
||||
```
|
||||
cd out\cmake-android-release-aarch64
|
||||
cmake ^
|
||||
-G Ninja ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCMAKE_INSTALL_PREFIX=..\android-release\filament ^
|
||||
-DCMAKE_TOOLCHAIN_FILE=..\..\build\toolchain-aarch64-linux-android.cmake ^
|
||||
..\..
|
||||
|
||||
cd out\cmake-android-release-arm7
|
||||
cmake ^
|
||||
-G Ninja ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCMAKE_INSTALL_PREFIX=..\android-release\filament ^
|
||||
-DCMAKE_TOOLCHAIN_FILE=..\..\build\toolchain-arm7-linux-android.cmake ^
|
||||
..\..
|
||||
|
||||
cd out\cmake-android-release-x86_64
|
||||
cmake ^
|
||||
-G Ninja ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCMAKE_INSTALL_PREFIX=..\android-release\filament ^
|
||||
-DCMAKE_TOOLCHAIN_FILE=..\..\build\toolchain-x86_64-linux-android.cmake ^
|
||||
..\..
|
||||
|
||||
cd out\cmake-android-release-x86
|
||||
cmake ^
|
||||
-G Ninja ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCMAKE_INSTALL_PREFIX=..\android-release\filament ^
|
||||
-DCMAKE_TOOLCHAIN_FILE=..\..\build\toolchain-x86-linux-android.cmake ^
|
||||
..\..
|
||||
```
|
||||
|
||||
3. Build.
|
||||
|
||||
Inside of each build directory, run:
|
||||
|
||||
```
|
||||
ninja install
|
||||
```
|
||||
|
||||
## Generate AAR
|
||||
|
||||
The Gradle project used to generate the AAR is located at `<filament>\android\filament-android`.
|
||||
|
||||
```
|
||||
cd android\filament-android
|
||||
gradlew -Pfilament_dist_dir=..\..\out\android-release\filament assembleRelease
|
||||
copy build\outputs\aar\filament-android-release.aar ..\..\out\
|
||||
```
|
||||
|
||||
If you're only interested in building for a single ABI, you'll need to add an `abiFilters` override
|
||||
inside the `build.gradle` file underneath `defaultConfig`:
|
||||
|
||||
```
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a'
|
||||
}
|
||||
```
|
||||
|
||||
See
|
||||
[NdkOptions](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.NdkOptions.html#com.android.build.gradle.internal.dsl.NdkOptions:abiFilters)
|
||||
for more information.
|
||||
|
||||
`filament-android-release.aar` should now be present at `<filament>\out\filament-android-release.aar`.
|
||||
|
||||
See [Using Filament's AAR](../README.md#using-filaments-aar) for usage instructions.
|
||||
|
||||
@@ -96,7 +96,7 @@ class MaterialCompiler extends DefaultTask {
|
||||
standardOutput out
|
||||
errorOutput err
|
||||
executable "${matcPath}"
|
||||
args('-p', 'mobile', '-o', getOutputFile(file), file)
|
||||
args('-a', 'all', '-p', 'mobile', '-o', getOutputFile(file), file)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
android/filamat-android/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
/.idea/caches
|
||||
/.idea/gradle.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
95
android/filamat-android/CMakeLists.txt
Normal file
@@ -0,0 +1,95 @@
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(filamat-java)
|
||||
|
||||
if (NOT ENABLE_JAVA)
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Java)
|
||||
if (NOT Java_FOUND)
|
||||
message(WARNING "JDK not found, skipping Java projects")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Android already has the JNI headers in its system include path.
|
||||
if (NOT ANDROID)
|
||||
find_package(JNI)
|
||||
if (NOT JNI_FOUND)
|
||||
message(WARNING "JNI not found, skipping Java projects")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED ENV{JAVA_HOME})
|
||||
message(WARNING "The JAVA_HOME environment variable must be set to compile Java projects")
|
||||
message(WARNING "Skipping Java projects")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# JNI bindings
|
||||
# ==================================================================================================
|
||||
set(TARGET filamat-jni)
|
||||
|
||||
set(JNI_SOURCE_FILES
|
||||
src/main/cpp/MaterialBuilder.cpp)
|
||||
|
||||
add_library(${TARGET} SHARED ${JNI_SOURCE_FILES})
|
||||
|
||||
target_include_directories(${TARGET} PRIVATE ${JNI_INCLUDE_DIRS})
|
||||
|
||||
set(EXPORTED_SYMBOLS)
|
||||
if (APPLE)
|
||||
set(EXPORTED_SYMBOLS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/libfilamat-jni.symbols")
|
||||
elseif (ANDROID)
|
||||
set(EXPORTED_SYMBOLS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilamat-jni.map")
|
||||
endif()
|
||||
|
||||
# This is necessary to avoid a CMake error due to setting RPATH on non-elf platforms.
|
||||
# Setting this also causes CMake to issue a warning on Mac:
|
||||
# "Policy CMP0068 is not set: RPATH settings on macOS do not affect install_name." which can be
|
||||
# safely ignored.
|
||||
set(CMAKE_SKIP_RPATH TRUE)
|
||||
|
||||
set_target_properties(${TARGET} PROPERTIES
|
||||
CXX_STANDARD 14
|
||||
COMPILE_FLAGS "-fno-exceptions -fvisibility=hidden"
|
||||
LINK_FLAGS "${GC_SECTIONS} ${EXPORTED_SYMBOLS}")
|
||||
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
$<$<PLATFORM_ID:Linux>:-fPIC>
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET} filamat)
|
||||
|
||||
set(INSTALL_TYPE LIBRARY)
|
||||
if (WIN32 OR CYGWIN)
|
||||
set(INSTALL_TYPE RUNTIME)
|
||||
endif()
|
||||
install(TARGETS ${TARGET} ${INSTALL_TYPE} DESTINATION lib/${DIST_DIR})
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_STRIP} -x ${CMAKE_INSTALL_PREFIX}/lib/${DIST_DIR}/lib${TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX})")
|
||||
|
||||
# ==================================================================================================
|
||||
# Java APIs
|
||||
# ==================================================================================================
|
||||
|
||||
# Android builds its Java bindings for filamat through Gradle.
|
||||
if (ANDROID)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(TARGET filamat-java)
|
||||
|
||||
include(UseJava)
|
||||
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.8" "-target" "1.8")
|
||||
|
||||
set(JAVA_SOURCE_FILES
|
||||
src/main/java/com/google/android/filament/filamat/MaterialBuilder.java
|
||||
src/main/java/com/google/android/filament/filamat/MaterialPackage.java)
|
||||
|
||||
add_jar(${TARGET}
|
||||
SOURCES ${JAVA_SOURCE_FILES}
|
||||
INCLUDE_JARS ../../java/lib/support-annotations.jar)
|
||||
|
||||
install_jar(${TARGET} lib)
|
||||
78
android/filamat-android/build.gradle
Normal file
@@ -0,0 +1,78 @@
|
||||
// This script accepts the following parameters:
|
||||
//
|
||||
// filament_dist_dir
|
||||
// Path to the Filament distribution/install directory for Android
|
||||
// (produced by make/ninja install). This directory must contain lib/arm64-v8a/ etc.
|
||||
//
|
||||
// Example:
|
||||
// ./gradlew -Pfilament_dist_dir=../../dist-android-release assembleRelease
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
group = "com.google.android.filament"
|
||||
version = "0.1"
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
def filament_path = file("../../out/android-release/filament").absolutePath
|
||||
if (project.hasProperty("filament_dist_dir")) {
|
||||
filament_path = file("$filament_dist_dir").absolutePath
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs "${filament_path}/lib"
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that only the libfilamat-jni.so library is included in the AAR, in case any other
|
||||
// libraries happen to be present.
|
||||
packagingOptions {
|
||||
exclude '**/*.so'
|
||||
merge '**/libfilamat-jni.so'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
}
|
||||
|
||||
BIN
android/filamat-android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
5
android/filamat-android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
172
android/filamat-android/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
android/filamat-android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
4
android/filamat-android/libfilamat-jni.map
Normal file
@@ -0,0 +1,4 @@
|
||||
LIBFILAMAT {
|
||||
global: Java_com_google_android_filament_*; JNI*;
|
||||
local: *;
|
||||
};
|
||||
1
android/filamat-android/libfilamat-jni.symbols
Normal file
@@ -0,0 +1 @@
|
||||
_Java_com_google_android_filament_*
|
||||
10
android/filamat-android/settings.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user guide at https://docs.gradle.org/4.6/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'filamat-android'
|
||||
2
android/filamat-android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.filamat" />
|
||||
121
android/filamat-android/src/main/cpp/MaterialBuilder.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
|
||||
#include <filament/EngineEnums.h>
|
||||
|
||||
using namespace filament;
|
||||
using namespace filamat;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nCreateMaterialBuilder(JNIEnv *env,
|
||||
jclass type) {
|
||||
return (jlong) new MaterialBuilder();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nDestroyMaterialBuilder(JNIEnv *env,
|
||||
jclass type, jlong nativeBuilder) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
delete builder;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nBuilderBuild(JNIEnv* env, jclass type,
|
||||
jlong nativeBuilder) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
return (jlong) new Package(builder->build());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jbyteArray JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nGetPackageBytes(JNIEnv* env, jclass type,
|
||||
jlong nativePackage) {
|
||||
auto package = (Package*) nativePackage;
|
||||
auto size = jsize(package->getSize());
|
||||
jbyteArray ret = env->NewByteArray(size);
|
||||
auto data = (jbyte*) package->getData();
|
||||
env->SetByteArrayRegion(ret, 0, size, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nGetPackageIsValid(JNIEnv* env,
|
||||
jclass type, jlong nativePackage) {
|
||||
auto* package = (Package*) nativePackage;
|
||||
return jboolean(package->isValid());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nDestroyPackage(JNIEnv* env, jclass type,
|
||||
jlong nativePackage) {
|
||||
Package* package = (Package*) nativePackage;
|
||||
delete package;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderName(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jstring name_) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
const char* name = env->GetStringUTFChars(name_, nullptr);
|
||||
builder->name(name);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderShading(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jint shading) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
builder->shading((Shading) shading);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderRequire(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jint attribute) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
builder->require((VertexAttribute) attribute);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderMaterial(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jstring code_) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
const char* code = env->GetStringUTFChars(code_, nullptr);
|
||||
builder->material(code);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderMaterialVertex(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jstring code_) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
const char* code = env->GetStringUTFChars(code_, nullptr);
|
||||
builder->materialVertex(code);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderColorWrite(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jboolean enable) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
builder->colorWrite(enable);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderPlatform(JNIEnv* env,
|
||||
jclass type, jlong nativeBuilder, jint platform) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
builder->platform((MaterialBuilder::Platform) platform);
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.filamat;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MaterialBuilder {
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
|
||||
// Keep to finalize native resources
|
||||
private final BuilderFinalizer mFinalizer;
|
||||
private final long mNativeObject;
|
||||
|
||||
public enum VertexAttribute {
|
||||
POSITION, // XYZ position (float3)
|
||||
TANGENTS, // tangent, bitangent and normal, encoded as a quaternion (4 floats or half floats)
|
||||
COLOR, // vertex color (float4)
|
||||
UV0, // texture coordinates (float2)
|
||||
UV1, // texture coordinates (float2)
|
||||
BONE_INDICES, // indices of 4 bones (uvec4)
|
||||
BONE_WEIGHTS // weights of the 4 bones (normalized float4)
|
||||
}
|
||||
|
||||
public enum Shading {
|
||||
UNLIT, // no lighting applied, emissive possible
|
||||
LIT, // default, standard lighting
|
||||
SUBSURFACE, // subsurface lighting model
|
||||
CLOTH // cloth lighting model
|
||||
}
|
||||
|
||||
public enum Platform {
|
||||
DESKTOP,
|
||||
MOBILE,
|
||||
ALL
|
||||
}
|
||||
|
||||
public MaterialBuilder() {
|
||||
mNativeObject = nCreateMaterialBuilder();
|
||||
mFinalizer = new BuilderFinalizer(mNativeObject);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder name(@NonNull String name) {
|
||||
nMaterialBuilderName(mNativeObject, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder shading(@NonNull Shading shading) {
|
||||
nMaterialBuilderShading(mNativeObject, shading.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder require(@NonNull VertexAttribute attribute) {
|
||||
nMaterialBuilderRequire(mNativeObject, attribute.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder material(@NonNull String code) {
|
||||
nMaterialBuilderMaterial(mNativeObject, code);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder materialVertex(@NonNull String code) {
|
||||
nMaterialBuilderMaterialVertex(mNativeObject, code);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder colorWrite(boolean enable) {
|
||||
nMaterialBuilderColorWrite(mNativeObject, enable);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialBuilder platform(@NonNull Platform platform) {
|
||||
nMaterialBuilderPlatform(mNativeObject, platform.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MaterialPackage build() {
|
||||
long nativePackage = nBuilderBuild(mNativeObject);
|
||||
byte[] data = nGetPackageBytes(nativePackage);
|
||||
MaterialPackage result =
|
||||
new MaterialPackage(ByteBuffer.wrap(data), nGetPackageIsValid(nativePackage));
|
||||
nDestroyPackage(nativePackage);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class BuilderFinalizer {
|
||||
private final long mNativeObject;
|
||||
|
||||
BuilderFinalizer(long nativeObject) {
|
||||
mNativeObject = nativeObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalize() {
|
||||
try {
|
||||
super.finalize();
|
||||
} catch (Throwable t) { // Ignore
|
||||
} finally {
|
||||
nDestroyMaterialBuilder(mNativeObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native long nCreateMaterialBuilder();
|
||||
private static native void nDestroyMaterialBuilder(long nativeBuilder);
|
||||
|
||||
private static native long nBuilderBuild(long nativeBuilder);
|
||||
private static native byte[] nGetPackageBytes(long nativePackage);
|
||||
private static native boolean nGetPackageIsValid(long nativePackage);
|
||||
private static native void nDestroyPackage(long nativePackage);
|
||||
|
||||
private static native void nMaterialBuilderName(long nativeBuilder, String name);
|
||||
private static native void nMaterialBuilderShading(long nativeBuilder, int shading);
|
||||
private static native void nMaterialBuilderRequire(long nativeBuilder, int attribute);
|
||||
private static native void nMaterialBuilderMaterial(long nativeBuilder, String code);
|
||||
private static native void nMaterialBuilderMaterialVertex(long nativeBuilder, String code);
|
||||
private static native void nMaterialBuilderColorWrite(long nativeBuilder, boolean enable);
|
||||
private static native void nMaterialBuilderPlatform(long nativeBuilder, int platform);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.filament.filamat;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MaterialPackage {
|
||||
|
||||
private final ByteBuffer mBuffer;
|
||||
private final boolean mIsValid;
|
||||
|
||||
MaterialPackage(@NonNull ByteBuffer buffer, boolean isValid) {
|
||||
mBuffer = buffer;
|
||||
mIsValid = isValid;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ByteBuffer getBuffer() {
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return mIsValid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Aug 28 15:45:13 PDT 2018
|
||||
#Mon Jan 14 11:04:36 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
@@ -22,9 +22,9 @@ using namespace filament;
|
||||
using namespace utils;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Engine_nCreateEngine(JNIEnv*, jclass,
|
||||
Java_com_google_android_filament_Engine_nCreateEngine(JNIEnv*, jclass, jlong backend,
|
||||
jlong sharedContext) {
|
||||
return (jlong) Engine::create(Engine::Backend::OPENGL, nullptr, (void*) sharedContext);
|
||||
return (jlong) Engine::create((Engine::Backend) backend, nullptr, (void*) sharedContext);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
|
||||
@@ -36,8 +36,10 @@ using namespace driver;
|
||||
|
||||
static size_t getTextureDataSize(const Texture *texture, size_t level,
|
||||
Texture::Format format, Texture::Type type, size_t stride, size_t alignment) {
|
||||
// Zero stride implies tight row-to-row packing.
|
||||
stride = stride == 0 ? texture->getWidth(level) : std::max(size_t(1), stride >> level);
|
||||
return Texture::computeTextureDataSize(format, type,
|
||||
std::max(size_t(1), stride >> level), texture->getHeight(level), alignment);
|
||||
stride, texture->getHeight(level), alignment);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
|
||||
@@ -65,9 +65,9 @@ Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv *env, jcl
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderNormalized(JNIEnv *env, jclass type,
|
||||
jlong nativeBuilder, jint attribute) {
|
||||
jlong nativeBuilder, jint attribute, jboolean normalized) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
builder->normalized((VertexAttribute) attribute);
|
||||
builder->normalized((VertexAttribute) attribute, normalized);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
|
||||
@@ -24,6 +24,13 @@ public class Engine {
|
||||
@NonNull private final LightManager mLightManager;
|
||||
@NonNull private final RenderableManager mRenderableManager;
|
||||
|
||||
public enum Backend {
|
||||
DEFAULT, // Automatically selects an appropriate driver for the platform.
|
||||
OPENGL, // Selects the OpenGL ES driver.
|
||||
VULKAN, // Selects the experimental Vulkan driver.
|
||||
NOOP, // Selects the no-op driver for testing purposes.
|
||||
}
|
||||
|
||||
private Engine(long nativeEngine) {
|
||||
mNativeObject = nativeEngine;
|
||||
mTransformManager = new TransformManager(nGetTransformManager(nativeEngine));
|
||||
@@ -33,7 +40,14 @@ public class Engine {
|
||||
|
||||
@NonNull
|
||||
public static Engine create() {
|
||||
long nativeEngine = nCreateEngine(0);
|
||||
long nativeEngine = nCreateEngine(0, 0);
|
||||
if (nativeEngine == 0) throw new IllegalStateException("Couldn't create Engine");
|
||||
return new Engine(nativeEngine);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Engine create(@NonNull Backend backend) {
|
||||
long nativeEngine = nCreateEngine(backend.ordinal(), 0);
|
||||
if (nativeEngine == 0) throw new IllegalStateException("Couldn't create Engine");
|
||||
return new Engine(nativeEngine);
|
||||
}
|
||||
@@ -46,7 +60,7 @@ public class Engine {
|
||||
@NonNull
|
||||
public static Engine create(@NonNull Object sharedContext) {
|
||||
if (Platform.get().validateSharedContext(sharedContext)) {
|
||||
long nativeEngine = nCreateEngine(
|
||||
long nativeEngine = nCreateEngine(0,
|
||||
Platform.get().getSharedContextNativeHandle(sharedContext));
|
||||
if (nativeEngine == 0) throw new IllegalStateException("Couldn't create Engine");
|
||||
return new Engine(nativeEngine);
|
||||
@@ -263,7 +277,7 @@ public class Engine {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static native long nCreateEngine(long sharedContext);
|
||||
private static native long nCreateEngine(long backend, long sharedContext);
|
||||
private static native void nDestroyEngine(long nativeEngine);
|
||||
private static native long nCreateSwapChain(long nativeEngine, Object nativeWindow, long flags);
|
||||
private static native long nCreateSwapChainFromRawPointer(long nativeEngine, long pointer, long flags);
|
||||
|
||||
@@ -108,7 +108,13 @@ public class VertexBuffer {
|
||||
|
||||
@NonNull
|
||||
public Builder normalized(@NonNull VertexAttribute attribute) {
|
||||
nBuilderNormalized(mNativeBuilder, attribute.ordinal());
|
||||
nBuilderNormalized(mNativeBuilder, attribute.ordinal(), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Builder normalized(@NonNull VertexAttribute attribute, boolean enabled) {
|
||||
nBuilderNormalized(mNativeBuilder, attribute.ordinal(), enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -183,7 +189,8 @@ public class VertexBuffer {
|
||||
private static native void nBuilderBufferCount(long nativeBuilder, int bufferCount);
|
||||
private static native void nBuilderAttribute(long nativeBuilder, int attribute,
|
||||
int bufferIndex, int attributeType, int byteOffset, int byteStride);
|
||||
private static native void nBuilderNormalized(long nativeBuilder, int attribute);
|
||||
private static native void nBuilderNormalized(long nativeBuilder, int attribute,
|
||||
boolean normalized);
|
||||
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
|
||||
|
||||
private static native int nGetVertexCount(long nativeVertexBuffer);
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.graphics.PixelFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
@@ -27,6 +29,98 @@ import android.view.SurfaceView;
|
||||
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.
|
||||
*
|
||||
* Here is a simple example with a SurfaceView. The code would be exactly the same with a
|
||||
* TextureView:
|
||||
*
|
||||
* <pre>
|
||||
* public class FilamentActivity extends Activity {
|
||||
* private UiHelper mUiHelper;
|
||||
* private SurfaceView mSurfaceView;
|
||||
*
|
||||
* // Filament specific APIs
|
||||
* private Engine mEngine;
|
||||
* private Renderer mRenderer;
|
||||
* private View mView; // com.google.android.filament.View, not android.view.View
|
||||
* private SwapChain mSwapChain;
|
||||
*
|
||||
* public void onCreate(Bundle savedInstanceState) {
|
||||
* super.onCreate(savedInstanceState);
|
||||
*
|
||||
* // Create a SurfaceView and add it to the activity
|
||||
* mSurfaceView = new SurfaceView(this);
|
||||
* setContentView(mSurfaceView);
|
||||
*
|
||||
* // Create the Filament UI helper
|
||||
* mUiHelper = new UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK);
|
||||
*
|
||||
* // Attach the SurfaceView to the helper, you could do the same with a TextureView
|
||||
* mUiHelper.attachTo(surfaceView)
|
||||
*
|
||||
* // Set a rendering callback that we will use to invoke Filament
|
||||
* mUiHelper.setRenderCallback(new UiHelper.RendererCallback() {
|
||||
* public void onNativeWindowChanged(Surface surface) {
|
||||
* if (mSwapChain != null) mEngine.destroySwapChain(mSwapChain);
|
||||
* mSwapChain = mEngine.createSwapChain(surface, mUiHelper.getSwapChainFlags());
|
||||
* }
|
||||
*
|
||||
* // The native surface went away, we must stop rendering.
|
||||
* public void onDetachedFromSurface() {
|
||||
* if (mSwapChain != null) {
|
||||
* mEngine.destroySwapChain(mSwapChain);
|
||||
*
|
||||
* // Required to ensure we don't return before Filament is done executing the
|
||||
* // destroySwapChain command, otherwise Android might destroy the Surface
|
||||
* // too early
|
||||
* mEngine.flushAndWait();
|
||||
*
|
||||
* mSwapChain = null;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // The native surface has changed size. This is always called at least once
|
||||
* // after the surface is created (after onNativeWindowChanged() is invoked).
|
||||
* public void onResized(int width, int height) {
|
||||
* // Compute camera projection and set the viewport on the view
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* mEngine = Engine.create();
|
||||
* mRenderer = mEngine.createRenderer();
|
||||
* mView = mEngine.createView();
|
||||
* // Create scene, camera, etc.
|
||||
* }
|
||||
*
|
||||
* public void onDestroy() {
|
||||
* super.onDestroy()
|
||||
* // Always detach the surface before destroying the engine
|
||||
* mUiHelper.detach()
|
||||
*
|
||||
* // This ensures that all the commands we've sent to Filament have
|
||||
* // been processed before we attempt to destroy anything
|
||||
* Fence.waitAndDestroy(mEngine.createFence(Fence.Type.SOFT), Fence.Mode.FLUSH);
|
||||
*
|
||||
* mEngine.destroy()
|
||||
* }
|
||||
*
|
||||
* // This is an example of a render function. You will most likely invoke this from
|
||||
* // a Choreographer callback to trigger rendering at vsync.
|
||||
* public void render() {
|
||||
* if (mUiHelper.isReadyToRender) {
|
||||
* // If beginFrame() returns false you should skip the frame
|
||||
* // This means you are sending frames too quickly to the GPU
|
||||
* if (mRenderer.beginFrame(swapChain)) {
|
||||
* mRenderer.render(mView)
|
||||
* mRenderer.endFrame()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class UiHelper {
|
||||
private static final String LOG_TAG = "UiHelper";
|
||||
private static final boolean LOGGING = false;
|
||||
@@ -42,22 +136,39 @@ public class UiHelper {
|
||||
|
||||
private boolean mOpaque = true;
|
||||
|
||||
/**
|
||||
* Enum used to decide whether UiHelper should perform extra error checking.
|
||||
*
|
||||
* @see UiHelper#UiHelper(ContextErrorPolicy)
|
||||
*/
|
||||
public enum ContextErrorPolicy {
|
||||
CHECK, DONT_CHECK
|
||||
/** Check for extra errors. */
|
||||
CHECK,
|
||||
/** Do not check for extra errors. */
|
||||
DONT_CHECK
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used to know when the native surface is created, destroyed or resized.
|
||||
*
|
||||
* @see #setRenderCallback(RendererCallback)
|
||||
*/
|
||||
public interface RendererCallback {
|
||||
|
||||
// called when the underlying native window has changed
|
||||
// NOTE: this could be called from UiHelper's constructor.
|
||||
/**
|
||||
* Called when the underlying native window has changed.
|
||||
*/
|
||||
void onNativeWindowChanged(Surface surface);
|
||||
|
||||
// called when the surface is going away. after this call isReadyToRender() returns false.
|
||||
// you MUST have stopped drawing when returning.
|
||||
// This is called from detach() or if the surface disappears on its own.
|
||||
/**
|
||||
* Called when the surface is going away. After this call <code>isReadyToRender()</code>
|
||||
* returns false. You MUST have stopped drawing when returning.
|
||||
* This is called from detach() or if the surface disappears on its own.
|
||||
*/
|
||||
void onDetachedFromSurface();
|
||||
|
||||
// called when the underlying native window has been resized
|
||||
/**
|
||||
* Called when the underlying native window has been resized.
|
||||
*/
|
||||
void onResized(int width, int height);
|
||||
}
|
||||
|
||||
@@ -114,29 +225,44 @@ public class UiHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a UiHelper which will help manage the EGL context
|
||||
* and EGL surfaces. UiHelper handles SurfaceView and TextureView.
|
||||
*
|
||||
* When this call returns, OpenGL ES is ready to use.
|
||||
* Creates a UiHelper which will help manage the native surface provided by a
|
||||
* SurfaceView or a TextureView.
|
||||
*/
|
||||
public UiHelper() {
|
||||
this(ContextErrorPolicy.CHECK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a UiHelper which will help manage the native surface provided by a
|
||||
* SurfaceView or a TextureView.
|
||||
*
|
||||
* @param policy The error checking policy to use.
|
||||
*/
|
||||
public UiHelper(ContextErrorPolicy policy) {
|
||||
// TODO: do something with policy
|
||||
}
|
||||
|
||||
public void setRenderCallback(RendererCallback renderCallback) {
|
||||
/**
|
||||
* Sets the renderer callback that will be notified when the native surface is
|
||||
* created, destroyed or resized.
|
||||
*
|
||||
* @param renderCallback The callback to register.
|
||||
*/
|
||||
public void setRenderCallback(@Nullable RendererCallback renderCallback) {
|
||||
mRenderCallback = renderCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current render callback associated with this UiHelper.
|
||||
*/
|
||||
@Nullable
|
||||
public RendererCallback getRenderCallback() {
|
||||
return mRenderCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources associated to the native window specified in attachTo().
|
||||
* Free resources associated to the native window specified in {@link #attachTo(SurfaceView)}
|
||||
* or {@link #attachTo(TextureView)}.
|
||||
*/
|
||||
public void detach() {
|
||||
destroySwapChain();
|
||||
@@ -144,13 +270,6 @@ public class UiHelper {
|
||||
mRenderSurface = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
// TODO: check that detach() has been called
|
||||
// TODO: call Surface.release() if not already done
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we are ready to render into the attached surface.
|
||||
*
|
||||
@@ -164,7 +283,7 @@ public class UiHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of the render target buffers.
|
||||
* Set the size of the render target buffers of the native surface.
|
||||
*/
|
||||
public void setDesiredSize(int width, int height) {
|
||||
mDesiredWidth = width;
|
||||
@@ -174,10 +293,16 @@ public class UiHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested width for the native surface.
|
||||
*/
|
||||
public int getDesiredWidth() {
|
||||
return mDesiredWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested height for the native surface.
|
||||
*/
|
||||
public int getDesiredHeight() {
|
||||
return mDesiredHeight;
|
||||
}
|
||||
@@ -202,6 +327,11 @@ public class UiHelper {
|
||||
mOpaque = opaque;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flags to pass to
|
||||
* {@link com.google.android.filament.Engine#createSwapChain(Object, long)} to honor all
|
||||
* the options set on this UiHelper.
|
||||
*/
|
||||
public long getSwapChainFlags() {
|
||||
return isOpaque() ? SwapChain.CONFIG_DEFAULT : SwapChain.CONFIG_TRANSPARENT;
|
||||
}
|
||||
@@ -212,7 +342,7 @@ public class UiHelper {
|
||||
* As soon as SurfaceView is ready (i.e. has a Surface), we'll create the
|
||||
* EGL resources needed, and call user callbacks if needed.
|
||||
*/
|
||||
public void attachTo(SurfaceView view) {
|
||||
public void attachTo(@NonNull SurfaceView view) {
|
||||
if (attach(view)) {
|
||||
if (!isOpaque()) {
|
||||
view.setZOrderOnTop(true);
|
||||
@@ -261,7 +391,7 @@ public class UiHelper {
|
||||
* As soon as TextureView is ready (i.e. has a buffer), we'll create the
|
||||
* EGL resources needed, and call user callbacks if needed.
|
||||
*/
|
||||
public void attachTo(TextureView view) {
|
||||
public void attachTo(@NonNull TextureView view) {
|
||||
if (attach(view)) {
|
||||
view.setOpaque(isOpaque());
|
||||
|
||||
@@ -274,13 +404,20 @@ public class UiHelper {
|
||||
if (LOGGING) Log.d(LOG_TAG, "onSurfaceTextureAvailable()");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
surfaceTexture.setDefaultBufferSize(mDesiredWidth, mDesiredHeight);
|
||||
if (mDesiredWidth > 0 && mDesiredHeight > 0) {
|
||||
surfaceTexture.setDefaultBufferSize(mDesiredWidth, mDesiredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
Surface surface = new Surface(surfaceTexture);
|
||||
TextureViewHandler textureViewHandler = (TextureViewHandler) mRenderSurface;
|
||||
textureViewHandler.setSurface(surface);
|
||||
|
||||
createSwapChain(surface);
|
||||
|
||||
// Call this the first time because onSurfaceTextureSizeChanged()
|
||||
// isn't called at initialization time
|
||||
mRenderCallback.onResized(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -311,7 +448,7 @@ public class UiHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean attach(Object nativeWindow) {
|
||||
private boolean attach(@NonNull Object nativeWindow) {
|
||||
if (mNativeWindow != null) {
|
||||
// we are already attached to a native window
|
||||
if (mNativeWindow == nativeWindow) {
|
||||
@@ -324,8 +461,8 @@ public class UiHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createSwapChain(Surface sur) {
|
||||
mRenderCallback.onNativeWindowChanged(sur);
|
||||
private void createSwapChain(@NonNull Surface surface) {
|
||||
mRenderCallback.onNativeWindowChanged(surface);
|
||||
mHasSwapChain = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@ Demonstrates how to render into a transparent `SurfaceView`:
|
||||
|
||||

|
||||
|
||||
### `texture-view`
|
||||
|
||||
Demonstrates how to render into a `TextureView` instead of a `SurfaceView`:
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you start, make sure to read [Filament's README](../../README.md). You need to be able to
|
||||
@@ -66,8 +72,7 @@ SDK. This includes the project `filament-android` in the parent directory.
|
||||
|
||||
## Android Studio
|
||||
|
||||
Due to issues with composite builds in Android Studio 3.1, it is highly recommended to use
|
||||
Android Studio 3.2 or higher to open this project.
|
||||
You must use Android Studio 3.3 or higher to open these projects.
|
||||
|
||||
## Compiling
|
||||
|
||||
|
||||
@@ -18,23 +18,20 @@ package com.google.android.filament.hellotriangle
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.graphics.PixelFormat
|
||||
import android.opengl.Matrix
|
||||
import android.os.Bundle
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceView
|
||||
import android.view.animation.LinearInterpolator
|
||||
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.RenderableManager.*
|
||||
import com.google.android.filament.VertexBuffer.*
|
||||
import com.google.android.filament.RenderableManager.PrimitiveType
|
||||
import com.google.android.filament.VertexBuffer.AttributeType
|
||||
import com.google.android.filament.VertexBuffer.VertexAttribute
|
||||
import com.google.android.filament.android.UiHelper
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.channels.Channels
|
||||
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.0'
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Aug 28 15:45:13 PDT 2018
|
||||
#Mon Jan 14 11:09:37 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
@@ -60,7 +60,7 @@ private fun loadIndirectLight(
|
||||
assets: AssetManager,
|
||||
name: String,
|
||||
engine: Engine): Pair<IndirectLight, Texture> {
|
||||
val (w, h) = peekSize(assets, "$name/nx.rgbm")
|
||||
val (w, h) = peekSize(assets, "$name/m0_nx.rgbm")
|
||||
val texture = Texture.Builder()
|
||||
.width(w)
|
||||
.height(h)
|
||||
@@ -142,6 +142,7 @@ private fun loadCubemap(texture: Texture,
|
||||
|
||||
// Rewind the texture buffer
|
||||
storage.flip()
|
||||
android.util.Log.d("Texture", "Cubemap level: $level $faceSize ${texture.getWidth(level)}")
|
||||
|
||||
val buffer = Texture.PixelBufferDescriptor(storage, Texture.Format.RGBM, Texture.Type.UBYTE)
|
||||
texture.setImage(engine, level, buffer, offsets)
|
||||
|
||||
@@ -69,12 +69,18 @@ fun loadMesh(assets: AssetManager, name: String,
|
||||
private const val FILAMESH_FILE_IDENTIFIER = "FILAMESH"
|
||||
private const val MAX_UINT32 = 4294967295
|
||||
|
||||
@Suppress("unused")
|
||||
private const val HEADER_FLAG_INTERLEAVED = 0x1L
|
||||
private const val HEADER_FLAG_SNORM16_UV = 0x2L
|
||||
@Suppress("unused")
|
||||
private const val HEADER_FLAG_COMPRESSED = 0x4L
|
||||
|
||||
private class Header {
|
||||
var valid = false
|
||||
var versionNumber = 0L
|
||||
var parts = 0L
|
||||
var aabb = Box()
|
||||
var interleaved = 0L
|
||||
var flags = 0L
|
||||
var posOffset = 0L
|
||||
var positionStride = 0L
|
||||
var tangentOffset = 0L
|
||||
@@ -121,7 +127,7 @@ private fun readHeader(input: InputStream): Header {
|
||||
header.aabb = Box(
|
||||
readFloat32LE(input), readFloat32LE(input), readFloat32LE(input),
|
||||
readFloat32LE(input), readFloat32LE(input), readFloat32LE(input))
|
||||
header.interleaved = readUIntLE(input)
|
||||
header.flags = readUIntLE(input)
|
||||
header.posOffset = readUIntLE(input)
|
||||
header.positionStride = readUIntLE(input)
|
||||
header.tangentOffset = readUIntLE(input)
|
||||
@@ -142,7 +148,6 @@ private fun readHeader(input: InputStream): Header {
|
||||
return header
|
||||
}
|
||||
|
||||
|
||||
private fun readSizedData(channel: ReadableByteChannel, sizeInBytes: Long): ByteBuffer {
|
||||
val buffer = ByteBuffer.allocateDirect(sizeInBytes.toInt())
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||
@@ -190,7 +195,15 @@ private fun createIndexBuffer(engine: Engine, header: Header, data: ByteBuffer):
|
||||
.apply { setBuffer(engine, data) }
|
||||
}
|
||||
|
||||
private fun uvNormalized(header: Header) = header.flags and HEADER_FLAG_SNORM16_UV != 0L
|
||||
|
||||
private fun createVertexBuffer(engine: Engine, header: Header, data: ByteBuffer): VertexBuffer {
|
||||
val uvType = if (!uvNormalized(header)) {
|
||||
HALF2
|
||||
} else {
|
||||
SHORT2
|
||||
}
|
||||
|
||||
val vertexBufferBuilder = VertexBuffer.Builder()
|
||||
.bufferCount(1)
|
||||
.vertexCount(header.totalVertices.toInt())
|
||||
@@ -203,11 +216,18 @@ private fun createVertexBuffer(engine: Engine, header: Header, data: ByteBuffer)
|
||||
.attribute(POSITION, 0, HALF4, header.posOffset.toInt(), header.positionStride.toInt())
|
||||
.attribute(TANGENTS, 0, SHORT4, header.tangentOffset.toInt(), header.tangentStride.toInt())
|
||||
.attribute(COLOR, 0, UBYTE4, header.colorOffset.toInt(), header.colorStride.toInt())
|
||||
.attribute(UV0, 0, HALF2, header.uv0Offset.toInt(), header.uv0Stride.toInt())
|
||||
// UV coordinates are stored as normalized 16-bit integers or half-floats depending on
|
||||
// the range they span. When stored as half-float, there is only enough precision for
|
||||
// sub-pixel addressing in textures that are <= 1024x1024
|
||||
.attribute(UV0, 0, uvType, header.uv0Offset.toInt(), header.uv0Stride.toInt())
|
||||
// When UV coordinates are stored as 16-bit integers we must normalize them (we want
|
||||
// values in the range -1..1)
|
||||
.normalized(UV0, uvNormalized(header))
|
||||
|
||||
if (header.uv1Offset != MAX_UINT32 && header.uv1Stride != MAX_UINT32) {
|
||||
vertexBufferBuilder
|
||||
.attribute(UV1, 0, HALF2, header.uv1Offset.toInt(), header.uv1Stride.toInt())
|
||||
.attribute(UV1, 0, uvType, header.uv1Offset.toInt(), header.uv1Stride.toInt())
|
||||
.normalized(UV1, uvNormalized(header))
|
||||
}
|
||||
|
||||
return vertexBufferBuilder.build(engine).apply { setBufferAt(engine, 0, data) }
|
||||
@@ -224,7 +244,7 @@ private fun createRenderable(
|
||||
|
||||
val builder = RenderableManager.Builder(header.parts.toInt()).boundingBox(header.aabb)
|
||||
|
||||
(0 until header.parts.toInt()).forEach { i ->
|
||||
repeat(header.parts.toInt()) { i ->
|
||||
builder.geometry(i,
|
||||
RenderableManager.PrimitiveType.TRIANGLES,
|
||||
vertexBuffer,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.0'
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Aug 28 15:45:13 PDT 2018
|
||||
#Mon Jan 14 11:08:47 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.0'
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Aug 28 15:45:13 PDT 2018
|
||||
#Mon Jan 14 11:08:15 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
12
android/samples/texture-view/.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
|
||||
/app/src/main/assets/materials/*.filamat
|
||||
.externalNativeBuild
|
||||
1
android/samples/texture-view/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
80
android/samples/texture-view/app/build.gradle
Normal file
@@ -0,0 +1,80 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
apply from: '../../../build/filament-tasks.gradle'
|
||||
|
||||
compileMaterials {
|
||||
group 'Filament'
|
||||
description 'Compile materials'
|
||||
|
||||
inputDir = file("src/main/materials")
|
||||
outputDir = file("src/main/assets/materials")
|
||||
}
|
||||
|
||||
preBuild.dependsOn compileMaterials
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.textureview"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
// Filament comes with native code, the following declarations
|
||||
// can be used to generate architecture specific APKs
|
||||
flavorDimensions 'cpuArch'
|
||||
productFlavors {
|
||||
arm8 {
|
||||
dimension 'cpuArch'
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a'
|
||||
}
|
||||
}
|
||||
arm7 {
|
||||
dimension 'cpuArch'
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a'
|
||||
}
|
||||
}
|
||||
x86_64 {
|
||||
dimension 'cpuArch'
|
||||
ndk {
|
||||
abiFilters 'x86_64'
|
||||
}
|
||||
}
|
||||
x86 {
|
||||
dimension 'cpuArch'
|
||||
ndk {
|
||||
abiFilters 'x86'
|
||||
}
|
||||
}
|
||||
universal {
|
||||
dimension 'cpuArch'
|
||||
}
|
||||
}
|
||||
|
||||
// We use the .filamat extension for materials compiled with matc
|
||||
// Telling aapt to not compress them allows to load them efficiently
|
||||
aaptOptions {
|
||||
noCompress 'filamat'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
// Depend on Filament
|
||||
implementation 'com.google.android.filament:filament-android'
|
||||
}
|
||||
21
android/samples/texture-view/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.textureview">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.textureview
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.opengl.Matrix
|
||||
import android.os.Bundle
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
import android.view.TextureView
|
||||
import android.view.animation.LinearInterpolator
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.RenderableManager.PrimitiveType
|
||||
import com.google.android.filament.VertexBuffer.AttributeType
|
||||
import com.google.android.filament.VertexBuffer.VertexAttribute
|
||||
import com.google.android.filament.android.UiHelper
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.channels.Channels
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class MainActivity : Activity() {
|
||||
// Make sure to initialize Filament first
|
||||
// This loads the JNI library needed by most API calls
|
||||
companion object {
|
||||
init {
|
||||
Filament.init()
|
||||
}
|
||||
}
|
||||
|
||||
// The View we want to render into
|
||||
private lateinit var textureView: TextureView
|
||||
// UiHelper is provided by Filament to manage SurfaceView and SurfaceTexture
|
||||
private lateinit var uiHelper: UiHelper
|
||||
// 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: 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
|
||||
|
||||
private lateinit var material: Material
|
||||
private lateinit var vertexBuffer: VertexBuffer
|
||||
private lateinit var indexBuffer: IndexBuffer
|
||||
|
||||
// Filament entity representing a renderable object
|
||||
@Entity private var renderable = 0
|
||||
|
||||
// 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()
|
||||
|
||||
private val animator = ValueAnimator.ofFloat(0.0f, 360.0f)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
textureView = TextureView(this)
|
||||
setContentView(textureView)
|
||||
|
||||
choreographer = Choreographer.getInstance()
|
||||
|
||||
setupSurfaceView()
|
||||
setupFilament()
|
||||
setupView()
|
||||
setupScene()
|
||||
}
|
||||
|
||||
private fun setupSurfaceView() {
|
||||
uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
|
||||
uiHelper.renderCallback = SurfaceCallback()
|
||||
|
||||
// NOTE: To choose a specific rendering resolution, add the following line:
|
||||
// uiHelper.setDesiredSize(1280, 720)
|
||||
uiHelper.attachTo(textureView)
|
||||
}
|
||||
|
||||
private fun setupFilament() {
|
||||
engine = Engine.create()
|
||||
renderer = engine.createRenderer()
|
||||
scene = engine.createScene()
|
||||
view = engine.createView()
|
||||
camera = engine.createCamera()
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
// Clear the background to middle-grey
|
||||
// Setting up a clear color is useful for debugging but usually
|
||||
// unnecessary when using a skybox
|
||||
view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f)
|
||||
|
||||
// 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() {
|
||||
loadMaterial()
|
||||
createMesh()
|
||||
|
||||
// To create a renderable we first create a generic entity
|
||||
renderable = EntityManager.get().create()
|
||||
|
||||
// We then create a renderable component on that entity
|
||||
// A renderable is made of several primitives; in this case we declare only 1
|
||||
RenderableManager.Builder(1)
|
||||
// Overall bounding box of the renderable
|
||||
.boundingBox(Box(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.01f))
|
||||
// Sets the mesh data of the first primitive
|
||||
.geometry(0, PrimitiveType.TRIANGLES, vertexBuffer, indexBuffer, 0, 3)
|
||||
// Sets the material of the first primitive
|
||||
.material(0, material.defaultInstance)
|
||||
.build(engine, renderable)
|
||||
|
||||
// Add the entity to the scene to render it
|
||||
scene.addEntity(renderable)
|
||||
|
||||
startAnimation()
|
||||
}
|
||||
|
||||
private fun loadMaterial() {
|
||||
readUncompressedAsset("materials/baked_color.filamat").let {
|
||||
material = Material.Builder().payload(it, it.remaining()).build(engine)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMesh() {
|
||||
val intSize = 4
|
||||
val floatSize = 4
|
||||
val shortSize = 2
|
||||
// A vertex is a position + a color:
|
||||
// 3 floats for XYZ position, 1 integer for color
|
||||
val vertexSize = 3 * floatSize + intSize
|
||||
|
||||
// Define a vertex and a function to put a vertex in a ByteBuffer
|
||||
data class Vertex(val x: Float, val y: Float, val z: Float, val color: Int)
|
||||
fun ByteBuffer.put(v: Vertex): ByteBuffer {
|
||||
putFloat(v.x)
|
||||
putFloat(v.y)
|
||||
putFloat(v.z)
|
||||
putInt(v.color)
|
||||
return this
|
||||
}
|
||||
|
||||
// We are going to generate a single triangle
|
||||
val vertexCount = 3
|
||||
val a1 = PI * 2.0 / 3.0
|
||||
val a2 = PI * 4.0 / 3.0
|
||||
|
||||
val vertexData = ByteBuffer.allocate(vertexCount * vertexSize)
|
||||
// It is important to respect the native byte order
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.put(Vertex(1.0f, 0.0f, 0.0f, 0xffff0000.toInt()))
|
||||
.put(Vertex(cos(a1).toFloat(), sin(a1).toFloat(), 0.0f, 0xff00ff00.toInt()))
|
||||
.put(Vertex(cos(a2).toFloat(), sin(a2).toFloat(), 0.0f, 0xff0000ff.toInt()))
|
||||
// Make sure the cursor is pointing in the right place in the byte buffer
|
||||
.flip()
|
||||
|
||||
// Declare the layout of our mesh
|
||||
vertexBuffer = VertexBuffer.Builder()
|
||||
.bufferCount(1)
|
||||
.vertexCount(vertexCount)
|
||||
// Because we interleave position and color data we must specify offset and stride
|
||||
// We could use de-interleaved data by declaring two buffers and giving each
|
||||
// attribute a different buffer index
|
||||
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT3, 0, vertexSize)
|
||||
.attribute(VertexAttribute.COLOR, 0, AttributeType.UBYTE4, 3 * floatSize, vertexSize)
|
||||
// We store colors as unsigned bytes but since we want values between 0 and 1
|
||||
// in the material (shaders), we must mark the attribute as normalized
|
||||
.normalized(VertexAttribute.COLOR)
|
||||
.build(engine)
|
||||
|
||||
// Feed the vertex data to the mesh
|
||||
// We only set 1 buffer because the data is interleaved
|
||||
vertexBuffer.setBufferAt(engine, 0, vertexData)
|
||||
|
||||
// Create the indices
|
||||
val indexData = ByteBuffer.allocate(vertexCount * shortSize)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.putShort(0)
|
||||
.putShort(1)
|
||||
.putShort(2)
|
||||
.flip()
|
||||
|
||||
indexBuffer = IndexBuffer.Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(IndexBuffer.Builder.IndexType.USHORT)
|
||||
.build(engine)
|
||||
indexBuffer.setBuffer(engine, indexData)
|
||||
}
|
||||
|
||||
private fun startAnimation() {
|
||||
// Animate the triangle
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.duration = 4000
|
||||
animator.repeatMode = ValueAnimator.RESTART
|
||||
animator.repeatCount = ValueAnimator.INFINITE
|
||||
animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
|
||||
val transformMatrix = FloatArray(16)
|
||||
override fun onAnimationUpdate(a: ValueAnimator) {
|
||||
Matrix.setRotateM(transformMatrix, 0, -(a.animatedValue as Float), 0.0f, 0.0f, 1.0f)
|
||||
val tcm = engine.transformManager
|
||||
tcm.setTransform(tcm.getInstance(renderable), transformMatrix)
|
||||
}
|
||||
})
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
choreographer.postFrameCallback(frameScheduler)
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
choreographer.removeFrameCallback(frameScheduler)
|
||||
animator.cancel()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// Always detach the surface before destroying the engine
|
||||
uiHelper.detach()
|
||||
|
||||
// This ensures that all the commands we've sent to Filament have
|
||||
// been processed before we attempt to destroy anything
|
||||
Fence.waitAndDestroy(engine.createFence(Fence.Type.SOFT), Fence.Mode.FLUSH)
|
||||
|
||||
// Cleanup all resources
|
||||
engine.destroyEntity(renderable)
|
||||
engine.destroyRenderer(renderer)
|
||||
engine.destroyVertexBuffer(vertexBuffer)
|
||||
engine.destroyIndexBuffer(indexBuffer)
|
||||
engine.destroyMaterial(material)
|
||||
engine.destroyView(view)
|
||||
engine.destroyScene(scene)
|
||||
engine.destroyCamera(camera)
|
||||
|
||||
// Engine.destroyEntity() destroys Filament related resources only
|
||||
// (components), not the entity itself
|
||||
val entityManager = EntityManager.get()
|
||||
entityManager.destroy(renderable)
|
||||
|
||||
// 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!!)) {
|
||||
renderer.render(view)
|
||||
renderer.endFrame()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class SurfaceCallback : UiHelper.RendererCallback {
|
||||
override fun onNativeWindowChanged(surface: Surface) {
|
||||
swapChain?.let { engine.destroySwapChain(it) }
|
||||
swapChain = engine.createSwapChain(surface, uiHelper.swapChainFlags)
|
||||
}
|
||||
|
||||
override fun onDetachedFromSurface() {
|
||||
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 zoom = 1.5
|
||||
val aspect = width.toDouble() / height.toDouble()
|
||||
camera.setProjection(Camera.Projection.ORTHO,
|
||||
-aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0)
|
||||
|
||||
view.viewport = Viewport(0, 0, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
private fun readUncompressedAsset(assetName: String): ByteBuffer {
|
||||
assets.openFd(assetName).use { fd ->
|
||||
val input = fd.createInputStream()
|
||||
val dst = ByteBuffer.allocate(fd.length.toInt())
|
||||
|
||||
val src = Channels.newChannel(input)
|
||||
src.read(dst)
|
||||
src.close()
|
||||
|
||||
return dst.apply { rewind() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Simple unlit material that uses the colors associated with each vertex.
|
||||
//
|
||||
// This source material must be compiled to a binary material using the matc tool.
|
||||
// The command used to compile this material is:
|
||||
// matc -p mobile -a opengl -o app/src/main/assets/baked_color.filamat app/src/materials/baked_color.mat
|
||||
//
|
||||
// See build.gradle for an example of how to compile materials automatically
|
||||
// Please refer to the documentation for more information about matc and the materials system.
|
||||
|
||||
material {
|
||||
name : baked_color,
|
||||
|
||||
// Lists the required vertex attributes
|
||||
// Here we only need a color (RGBA)
|
||||
requires : [
|
||||
color
|
||||
],
|
||||
|
||||
// This material disables all lighting
|
||||
shadingModel : unlit,
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
// You must always call the prepareMaterial() function
|
||||
prepareMaterial(material);
|
||||
|
||||
// We set the material's color to the color interpolated from
|
||||
// the model's vertices
|
||||
material.baseColor = getColor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Texture View</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>
|
||||
27
android/samples/texture-view/build.gradle
Normal file
@@ -0,0 +1,27 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
13
android/samples/texture-view/gradle.properties
Normal file
@@ -0,0 +1,13 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
BIN
android/samples/texture-view/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
android/samples/texture-view/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Mon Jan 14 11:07:34 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
172
android/samples/texture-view/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
android/samples/texture-view/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
3
android/samples/texture-view/settings.gradle
Normal file
@@ -0,0 +1,3 @@
|
||||
includeBuild '../../filament-android'
|
||||
|
||||
include ':app'
|
||||
@@ -60,7 +60,7 @@ private fun loadIndirectLight(
|
||||
assets: AssetManager,
|
||||
name: String,
|
||||
engine: Engine): Pair<IndirectLight, Texture> {
|
||||
val (w, h) = peekSize(assets, "$name/nx.rgbm")
|
||||
val (w, h) = peekSize(assets, "$name/m0_nx.rgbm")
|
||||
val texture = Texture.Builder()
|
||||
.width(w)
|
||||
.height(h)
|
||||
|
||||
@@ -69,12 +69,16 @@ fun loadMesh(assets: AssetManager, name: String,
|
||||
private const val FILAMESH_FILE_IDENTIFIER = "FILAMESH"
|
||||
private const val MAX_UINT32 = 4294967295
|
||||
|
||||
private const val HEADER_FLAG_INTERLEAVED = 0x1L
|
||||
private const val HEADER_FLAG_SNORM16_UV = 0x2L
|
||||
private const val HEADER_FLAG_COMPRESSED = 0x4L
|
||||
|
||||
private class Header {
|
||||
var valid = false
|
||||
var versionNumber = 0L
|
||||
var parts = 0L
|
||||
var aabb = Box()
|
||||
var interleaved = 0L
|
||||
var flags = 0L
|
||||
var posOffset = 0L
|
||||
var positionStride = 0L
|
||||
var tangentOffset = 0L
|
||||
@@ -121,7 +125,7 @@ private fun readHeader(input: InputStream): Header {
|
||||
header.aabb = Box(
|
||||
readFloat32LE(input), readFloat32LE(input), readFloat32LE(input),
|
||||
readFloat32LE(input), readFloat32LE(input), readFloat32LE(input))
|
||||
header.interleaved = readUIntLE(input)
|
||||
header.flags = readUIntLE(input)
|
||||
header.posOffset = readUIntLE(input)
|
||||
header.positionStride = readUIntLE(input)
|
||||
header.tangentOffset = readUIntLE(input)
|
||||
@@ -142,7 +146,6 @@ private fun readHeader(input: InputStream): Header {
|
||||
return header
|
||||
}
|
||||
|
||||
|
||||
private fun readSizedData(channel: ReadableByteChannel, sizeInBytes: Long): ByteBuffer {
|
||||
val buffer = ByteBuffer.allocateDirect(sizeInBytes.toInt())
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||
@@ -190,7 +193,15 @@ private fun createIndexBuffer(engine: Engine, header: Header, data: ByteBuffer):
|
||||
.apply { setBuffer(engine, data) }
|
||||
}
|
||||
|
||||
private fun uvNormalized(header: Header) = header.flags and HEADER_FLAG_SNORM16_UV != 0L
|
||||
|
||||
private fun createVertexBuffer(engine: Engine, header: Header, data: ByteBuffer): VertexBuffer {
|
||||
val uvType = if (!uvNormalized(header)) {
|
||||
HALF2
|
||||
} else {
|
||||
SHORT2
|
||||
}
|
||||
|
||||
val vertexBufferBuilder = VertexBuffer.Builder()
|
||||
.bufferCount(1)
|
||||
.vertexCount(header.totalVertices.toInt())
|
||||
@@ -203,13 +214,18 @@ private fun createVertexBuffer(engine: Engine, header: Header, data: ByteBuffer)
|
||||
.attribute(POSITION, 0, HALF4, header.posOffset.toInt(), header.positionStride.toInt())
|
||||
.attribute(TANGENTS, 0, SHORT4, header.tangentOffset.toInt(), header.tangentStride.toInt())
|
||||
.attribute(COLOR, 0, UBYTE4, header.colorOffset.toInt(), header.colorStride.toInt())
|
||||
// UV coordinates are stored in fp16, which gives sub-pixel precision only
|
||||
// for textures up to 1024x1024
|
||||
.attribute(UV0, 0, HALF2, header.uv0Offset.toInt(), header.uv0Stride.toInt())
|
||||
// UV coordinates are stored as normalized 16-bit integers or half-floats depending on
|
||||
// the range they span. When stored as half-float, there is only enough precision for
|
||||
// sub-pixel addressing in textures that are <= 1024x1024
|
||||
.attribute(UV0, 0, uvType, header.uv0Offset.toInt(), header.uv0Stride.toInt())
|
||||
// When UV coordinates are stored as 16-bit integers we must normalize them (we want
|
||||
// values in the range -1..1)
|
||||
.normalized(UV0, uvNormalized(header))
|
||||
|
||||
if (header.uv1Offset != MAX_UINT32 && header.uv1Stride != MAX_UINT32) {
|
||||
vertexBufferBuilder
|
||||
.attribute(UV1, 0, HALF2, header.uv1Offset.toInt(), header.uv1Stride.toInt())
|
||||
.attribute(UV1, 0, uvType, header.uv1Offset.toInt(), header.uv1Stride.toInt())
|
||||
.normalized(UV1, uvNormalized(header))
|
||||
}
|
||||
|
||||
return vertexBufferBuilder.build(engine).apply { setBufferAt(engine, 0, data) }
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.0'
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Aug 28 15:45:13 PDT 2018
|
||||
#Mon Jan 14 11:04:36 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.0'
|
||||
ext.kotlin_version = '1.3.11'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Tue Aug 28 15:45:13 PDT 2018
|
||||
#Mon Jan 14 11:05:59 PST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
||||
70
build.sh
@@ -4,7 +4,8 @@ set -e
|
||||
# NDK API level
|
||||
API_LEVEL=21
|
||||
# Host tools required by Android, WebGL, and iOS builds
|
||||
HOST_TOOLS="matc cmgen filamesh mipgen resgen"
|
||||
MOBILE_HOST_TOOLS="matc resgen cmgen"
|
||||
WEB_HOST_TOOLS="${MOBILE_HOST_TOOLS} mipgen filamesh"
|
||||
IOS_TOOLCHAIN_URL="https://opensource.apple.com/source/clang/clang-800.0.38/src/cmake/platforms/iOS.cmake"
|
||||
|
||||
function print_help {
|
||||
@@ -40,6 +41,8 @@ function print_help {
|
||||
echo " Add Vulkan support to the Android build."
|
||||
echo " -s"
|
||||
echo " Add iOS simulator support to the iOS build."
|
||||
echo " -l"
|
||||
echo " Add filamat support to the Android build."
|
||||
echo ""
|
||||
echo "Build types:"
|
||||
echo " release"
|
||||
@@ -99,6 +102,9 @@ GENERATE_TOOLCHAINS=false
|
||||
|
||||
VULKAN_ANDROID_OPTION="-DFILAMENT_SUPPORTS_VULKAN=OFF"
|
||||
|
||||
BUILD_FILAMAT_ANDROID=false
|
||||
FILAMAT_ANDROID_OPTION="-DFILAMENT_BUILD_FILAMAT=OFF"
|
||||
|
||||
IOS_BUILD_SIMULATOR=false
|
||||
|
||||
BUILD_GENERATOR=Ninja
|
||||
@@ -116,6 +122,7 @@ function build_clean {
|
||||
echo "Cleaning build directories..."
|
||||
rm -Rf out
|
||||
rm -Rf android/filament-android/build
|
||||
rm -Rf android/filament-android/.externalNativeBuild
|
||||
}
|
||||
|
||||
function generate_toolchain {
|
||||
@@ -215,6 +222,8 @@ function build_webgl_with_target {
|
||||
ISSUE_CMAKE_ALWAYS=true
|
||||
fi
|
||||
if [ ! -d "CMakeFiles" ] || [ "$ISSUE_CMAKE_ALWAYS" == "true" ]; then
|
||||
# Apply the emscripten environment within a subshell.
|
||||
(
|
||||
source ${EMSDK}/emsdk_env.sh
|
||||
cmake \
|
||||
-G "$BUILD_GENERATOR" \
|
||||
@@ -224,6 +233,7 @@ function build_webgl_with_target {
|
||||
-DWEBGL=1 \
|
||||
../..
|
||||
${BUILD_COMMAND} ${BUILD_TARGETS}
|
||||
)
|
||||
fi
|
||||
|
||||
if [ -d "web/filament-js" ]; then
|
||||
@@ -263,7 +273,7 @@ function build_webgl {
|
||||
OLD_INSTALL_COMMAND=${INSTALL_COMMAND}; INSTALL_COMMAND=
|
||||
OLD_ISSUE_DEBUG_BUILD=${ISSUE_DEBUG_BUILD}; ISSUE_DEBUG_BUILD=false
|
||||
OLD_ISSUE_RELEASE_BUILD=${ISSUE_RELEASE_BUILD}; ISSUE_RELEASE_BUILD=true
|
||||
build_desktop "${HOST_TOOLS}"
|
||||
build_desktop "${WEB_HOST_TOOLS}"
|
||||
INSTALL_COMMAND=${OLD_INSTALL_COMMAND}
|
||||
ISSUE_DEBUG_BUILD=${OLD_ISSUE_DEBUG_BUILD}
|
||||
ISSUE_RELEASE_BUILD=${OLD_ISSUE_RELEASE_BUILD}
|
||||
@@ -293,6 +303,7 @@ function build_android_target {
|
||||
-DCMAKE_INSTALL_PREFIX=../android-${LC_TARGET}/filament \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-${ARCH}-linux-android.cmake \
|
||||
$VULKAN_ANDROID_OPTION \
|
||||
$FILAMAT_ANDROID_OPTION \
|
||||
../..
|
||||
fi
|
||||
|
||||
@@ -338,7 +349,7 @@ function build_android {
|
||||
# Supress intermediate desktop tools install
|
||||
OLD_INSTALL_COMMAND=${INSTALL_COMMAND}
|
||||
INSTALL_COMMAND=
|
||||
build_desktop "${HOST_TOOLS}"
|
||||
build_desktop "${MOBILE_HOST_TOOLS}"
|
||||
INSTALL_COMMAND=${OLD_INSTALL_COMMAND}
|
||||
|
||||
build_android_arch "aarch64" "aarch64-linux-android" "arm64"
|
||||
@@ -377,6 +388,33 @@ function build_android {
|
||||
fi
|
||||
|
||||
cd ../..
|
||||
|
||||
|
||||
if [ "$BUILD_FILAMAT_ANDROID" == "true" ]; then
|
||||
|
||||
cd android/filamat-android
|
||||
|
||||
if [ "$ISSUE_DEBUG_BUILD" == "true" ]; then
|
||||
./gradlew -Pfilament_dist_dir=../../out/android-debug/filament assembleDebug
|
||||
|
||||
if [ "$INSTALL_COMMAND" ]; then
|
||||
echo "Installing out/filamat-android-debug.aar..."
|
||||
cp build/outputs/aar/filamat-android-debug.aar ../../out/
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$ISSUE_RELEASE_BUILD" == "true" ]; then
|
||||
./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
|
||||
|
||||
if [ "$INSTALL_COMMAND" ]; then
|
||||
echo "Installing out/filamat-android-release.aar..."
|
||||
cp build/outputs/aar/filamat-android-release.aar ../../out/
|
||||
fi
|
||||
fi
|
||||
|
||||
cd ../..
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
function ensure_ios_toolchain {
|
||||
@@ -450,7 +488,7 @@ function build_ios {
|
||||
# Supress intermediate desktop tools install
|
||||
OLD_INSTALL_COMMAND=${INSTALL_COMMAND}
|
||||
INSTALL_COMMAND=
|
||||
build_desktop "${HOST_TOOLS}"
|
||||
build_desktop "${MOBILE_HOST_TOOLS}"
|
||||
INSTALL_COMMAND=${OLD_INSTALL_COMMAND}
|
||||
|
||||
ensure_ios_toolchain
|
||||
@@ -523,16 +561,24 @@ function run_test {
|
||||
}
|
||||
|
||||
function run_tests {
|
||||
while read test; do
|
||||
run_test "$test"
|
||||
done < build/common/test_list.txt
|
||||
if [ "$ISSUE_WEBGL_BUILD" == "true" ]; then
|
||||
echo "TypeScript `tsc --version`"
|
||||
tsc --noEmit \
|
||||
third_party/gl-matrix/gl-matrix.d.ts \
|
||||
web/filament-js/filament.d.ts \
|
||||
web/filament-js/test.ts
|
||||
else
|
||||
while read test; do
|
||||
run_test "$test"
|
||||
done < build/common/test_list.txt
|
||||
fi
|
||||
}
|
||||
|
||||
# Beginning of the script
|
||||
|
||||
pushd `dirname $0` > /dev/null
|
||||
|
||||
while getopts ":hacfijmp:tuvs" opt; do
|
||||
while getopts ":hacfijmp:tuvsl" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
@@ -599,7 +645,13 @@ while getopts ":hacfijmp:tuvs" opt; do
|
||||
echo "To switch your application to Vulkan, in Android Studio go to "
|
||||
echo "File > Settings > Build > Compiler. In the command-line options field, "
|
||||
echo "add -Pextra_cmake_args=-DFILAMENT_SUPPORTS_VULKAN=ON."
|
||||
echo "Also be sure to pass Backend::VULKAN to Engine::create."
|
||||
echo "Also be sure to pass Engine.Backend.VULKAN to Engine.create."
|
||||
echo ""
|
||||
;;
|
||||
l)
|
||||
FILAMAT_ANDROID_OPTION="-DFILAMENT_BUILD_FILAMAT=ON"
|
||||
BUILD_FILAMAT_ANDROID=true
|
||||
echo "Building filamat JNI library for Android."
|
||||
echo ""
|
||||
;;
|
||||
s)
|
||||
|
||||
@@ -26,5 +26,8 @@ elif [ "$LC_UNAME" == "darwin" ]; then
|
||||
fi
|
||||
source `dirname $0`/../common/build-common.sh
|
||||
|
||||
yes | $ANDROID_HOME/tools/bin/sdkmanager --update >/dev/null && \
|
||||
yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses >/dev/null
|
||||
|
||||
pushd `dirname $0`/../.. > /dev/null
|
||||
./build.sh -p android -c $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
filament/test/test_filament --gtest_filter=-FilamentTest.FroxelData
|
||||
filament/test/test_filament_exposure --gtest_filter=-FilamentExposureWithEngineTest.SetExposure:FilamentExposureWithEngineTest.ComputeEV100
|
||||
filament/test/test_filament --gtest_filter=-FilamentTest.FroxelData:FilamentExposureWithEngineTest.SetExposure:FilamentExposureWithEngineTest.ComputeEV100
|
||||
libs/math/test_math
|
||||
libs/image/test_image compare libs/image/tests/reference/
|
||||
libs/utils/test_utils
|
||||
libs/filamat/test_filamat
|
||||
tools/matc/test_matc
|
||||
tools/cmgen/test_cmgen compare
|
||||
tools/glslminifier/test_glslminifier
|
||||
libs/filameshio/test_filameshio
|
||||
|
||||
@@ -28,8 +28,13 @@ set(DIST_ARCH arm64-v8a)
|
||||
set(TOOLCHAIN ${CMAKE_SOURCE_DIR}/toolchains/${CMAKE_HOST_SYSTEM_NAME}/${ARCH}-4.9)
|
||||
|
||||
# specify the cross compiler
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++)
|
||||
set(COMPILER_SUFFIX)
|
||||
if(WIN32)
|
||||
set(COMPILER_SUFFIX ".cmd")
|
||||
set(CMAKE_AR ${TOOLCHAIN}/bin/${ARCH}-ar.exe CACHE FILEPATH "Archiver")
|
||||
endif()
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang${COMPILER_SUFFIX})
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++${COMPILER_SUFFIX})
|
||||
|
||||
# where is the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/sysroot)
|
||||
|
||||
@@ -28,8 +28,13 @@ set(DIST_ARCH armeabi-v7a)
|
||||
set(TOOLCHAIN ${CMAKE_SOURCE_DIR}/toolchains/${CMAKE_HOST_SYSTEM_NAME}/${ARCH}-4.9)
|
||||
|
||||
# specify the cross compiler
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++)
|
||||
set(COMPILER_SUFFIX)
|
||||
if(WIN32)
|
||||
set(COMPILER_SUFFIX ".cmd")
|
||||
set(CMAKE_AR ${TOOLCHAIN}/bin/${ARCH}-ar.exe CACHE FILEPATH "Archiver")
|
||||
endif()
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang${COMPILER_SUFFIX})
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++${COMPILER_SUFFIX})
|
||||
|
||||
# where is the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/sysroot)
|
||||
|
||||
@@ -28,8 +28,13 @@ set(DIST_ARCH x86)
|
||||
set(TOOLCHAIN ${CMAKE_SOURCE_DIR}/toolchains/${CMAKE_HOST_SYSTEM_NAME}/${ARCH}-4.9)
|
||||
|
||||
# specify the cross compiler
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++)
|
||||
set(COMPILER_SUFFIX)
|
||||
if(WIN32)
|
||||
set(COMPILER_SUFFIX ".cmd")
|
||||
set(CMAKE_AR ${TOOLCHAIN}/bin/${ARCH}-ar.exe CACHE FILEPATH "Archiver")
|
||||
endif()
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang${COMPILER_SUFFIX})
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++${COMPILER_SUFFIX})
|
||||
|
||||
# where is the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/sysroot)
|
||||
|
||||
@@ -28,8 +28,13 @@ set(DIST_ARCH x86_64)
|
||||
set(TOOLCHAIN ${CMAKE_SOURCE_DIR}/toolchains/${CMAKE_HOST_SYSTEM_NAME}/${ARCH}-4.9)
|
||||
|
||||
# specify the cross compiler
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++)
|
||||
set(COMPILER_SUFFIX)
|
||||
if(WIN32)
|
||||
set(COMPILER_SUFFIX ".cmd")
|
||||
set(CMAKE_AR ${TOOLCHAIN}/bin/${ARCH}-ar.exe CACHE FILEPATH "Archiver")
|
||||
endif()
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang${COMPILER_SUFFIX})
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${ARCH}-clang++${COMPILER_SUFFIX})
|
||||
|
||||
# where is the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/sysroot)
|
||||
|
||||
@@ -14,6 +14,6 @@ set -x
|
||||
source `dirname $0`/../common/ci-common.sh
|
||||
source `dirname $0`/ci-common.sh
|
||||
source `dirname $0`/../common/build-common.sh
|
||||
|
||||
pushd `dirname $0`/../.. > /dev/null
|
||||
./build.sh -p webgl -c $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
|
||||
|
||||
./build.sh -p webgl -c $RUN_TESTS $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
|
||||
|
||||
@@ -10,6 +10,10 @@ export PATH="$PWD:$PATH"
|
||||
python3 --version
|
||||
pip3 install mistletoe pygments jsbeautifier future_fstrings
|
||||
|
||||
# Install a typescript compiler to allow testing.
|
||||
npm install -g typescript
|
||||
|
||||
# Install a specific version of emscripen to avoid surprises.
|
||||
curl -L https://github.com/juj/emsdk/archive/0d8576c.zip > emsdk.zip
|
||||
unzip emsdk.zip
|
||||
mv emsdk-* emsdk
|
||||
|
||||
@@ -2367,7 +2367,8 @@ using an environment made of colored vertical stripes (skybox hidden).](images/i
|
||||
When sampling the IBL, the clear coat layer is calculated as a second specular lobe. This specular lobe is oriented along the view direction since we cannot reasonably integrate over the hemisphere. Listing [clearCoatIBL] demonstrates this approximation in practice. It also shows the energy conservation step. It is important to note that this second specular lobe is computed exactly the same way as the main specular lobe, using the same DFG approximation.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
float Fc = F_Schlick(0.04, 1.0, shading_NoV) * clearCoat;
|
||||
// clearCoat_NoV == shading_NoV if the clear coat layer doesn't have its own normal map
|
||||
float Fc = F_Schlick(0.04, 1.0, clearCoat_NoV) * clearCoat;
|
||||
// base layer attenuation for energy compensation
|
||||
iblDiffuse *= 1.0 - Fc;
|
||||
iblSpecular *= sq(1.0 - Fc);
|
||||
|
||||
@@ -1084,6 +1084,48 @@ fragment {
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### curvatureToRoughness
|
||||
|
||||
Type
|
||||
: `boolean`
|
||||
|
||||
Value
|
||||
: `true` or `false`. Defaults to `false`.
|
||||
|
||||
Description
|
||||
: Reduces specular aliasing by increasing roughness based on the local geometric curvature.
|
||||
This property is particularly effective if you only use MSAA.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
curvatureToRoughness : true
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
![Figure [curvatureToRoughness]: Close up of a glossy metallic surface rendered normally (left) and
|
||||
with `curvatureToRoughness` (right).](images/screenshot_curvature_to_roughness.png)
|
||||
|
||||
### limitOverInterpolation
|
||||
|
||||
Type
|
||||
: `boolean`
|
||||
|
||||
Value
|
||||
: `true` or `false`. Defaults to `false`.
|
||||
|
||||
Description
|
||||
: Reduces specular aliasing by attempting to eliminate normal over-interpolation. When this
|
||||
property is turned on, the material switches to centroid normal interpolation when the
|
||||
interpolated normals are too long. This property should only be used if your anti-aliasing
|
||||
method is MSAA. The effects are a lot more subtle than `curvatureToRoughness`, which should be
|
||||
used first to eliminate specular aliasing.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
limitOverInterpolation : true
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### variantFilter
|
||||
|
||||
Type
|
||||
@@ -1117,6 +1159,25 @@ material {
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### flipUV
|
||||
|
||||
Type
|
||||
: `boolean`
|
||||
|
||||
Value
|
||||
: `true` or `false`. Defaults to `true`.
|
||||
|
||||
Description
|
||||
: When set to `true` (default value), the Y coordinate of UV attributes will be flipped when
|
||||
read by this material's vertex shader. Flipping is equivalent to `y = 1.0 - y`. When set
|
||||
to `false`, flipping is disabled and the UV attributes are read as is.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
flipUV : false
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Vertex block
|
||||
|
||||
The vertex block is optional and can be used to control the vertex shading stage of the material.
|
||||
@@ -1173,6 +1234,11 @@ struct MaterialVertexInputs {
|
||||
};
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
!!! TIP: UV attributes
|
||||
By default the vertex shader of a material will flip the Y coordinate of the UV attributes
|
||||
of the current mesh: `material.uv0 = vec2(mesh_uv0.x, 1.0 - mesh_uv0.y)`. You can control
|
||||
this behavior using the `flipUV` property and setting it to `false`.
|
||||
|
||||
## Fragment block
|
||||
|
||||
The fragment block must be used to control the fragment shading stage of the material. The vertex
|
||||
|
||||
BIN
docs/images/samples/sample_texture_view.jpg
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
BIN
docs/images/screenshot_curvature_to_roughness.png
Normal file
|
After Width: | Height: | Size: 346 KiB |
@@ -46,6 +46,9 @@ set(SRCS
|
||||
src/components/LightManager.cpp
|
||||
src/components/RenderableManager.cpp
|
||||
src/components/TransformManager.cpp
|
||||
src/fg/FrameGraph.cpp
|
||||
src/driver/noop/NoopDriver.cpp
|
||||
src/driver/noop/PlatformNoop.cpp
|
||||
src/driver/opengl/gl_headers.cpp
|
||||
src/driver/opengl/OpenGLBlitter.cpp
|
||||
src/driver/opengl/GLUtils.cpp
|
||||
@@ -100,6 +103,10 @@ set(PRIVATE_HDRS
|
||||
src/components/LightManager.h
|
||||
src/components/RenderableManager.h
|
||||
src/components/TransformManager.h
|
||||
src/fg/FrameGraph.h
|
||||
src/fg/FrameGraphPass.h
|
||||
src/fg/FrameGraphPassResources.h
|
||||
src/fg/FrameGraphResource.h
|
||||
src/details/Allocators.h
|
||||
src/details/Camera.h
|
||||
src/details/Culler.h
|
||||
@@ -128,6 +135,7 @@ set(PRIVATE_HDRS
|
||||
src/driver/CommandBufferQueue.h
|
||||
src/driver/CommandStream.h
|
||||
src/driver/CommandStreamDispatcher.h
|
||||
src/driver/DataReshaper.h
|
||||
src/driver/Driver.h
|
||||
src/driver/DriverAPI.inc
|
||||
src/driver/DriverApi.h
|
||||
@@ -152,17 +160,6 @@ set(MATERIAL_SRCS
|
||||
src/materials/skyboxRGBM.mat
|
||||
)
|
||||
|
||||
# The noop driver is only useful for ensuring we don't have certain build issues.
|
||||
# Remove it from release builds, since it uses some space needlessly.
|
||||
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
list(APPEND SRCS src/driver/noop/NoopDriver.cpp)
|
||||
list(APPEND SRCS src/driver/noop/PlatformNoop.cpp)
|
||||
endif()
|
||||
|
||||
if(IOS AND NOT FILAMENT_SUPPORTS_VULKAN)
|
||||
message(FATAL_ERROR "Filament for iOS must be built with Vulkan support.")
|
||||
endif()
|
||||
|
||||
# Embed the binary resource blob for materials.
|
||||
get_resgen_vars(${RESOURCE_DIR} materials)
|
||||
list(APPEND PRIVATE_HDRS ${RESGEN_HEADER})
|
||||
@@ -200,6 +197,17 @@ endif()
|
||||
# "2" corresponds to SYSTRACE_TAG_FILEMENT (See: utils/Systrace.h)
|
||||
add_definitions(-DSYSTRACE_TAG=2 )
|
||||
|
||||
# ==================================================================================================
|
||||
# Metal Sources
|
||||
# ==================================================================================================
|
||||
|
||||
if (FILAMENT_SUPPORTS_METAL)
|
||||
list(APPEND SRCS
|
||||
src/driver/metal/MetalDriver.mm
|
||||
src/driver/metal/PlatformMetal.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Vulkan Sources
|
||||
# ==================================================================================================
|
||||
@@ -247,8 +255,8 @@ else()
|
||||
set(MATC_TARGET desktop)
|
||||
endif()
|
||||
|
||||
# Include SPIRV when building default materials on platforms that support Vulkan.
|
||||
if (FILAMENT_SUPPORTS_VULKAN)
|
||||
# Generate shader code for all platforms when Vulkan or Metal is supported.
|
||||
if (FILAMENT_SUPPORTS_VULKAN OR FILAMENT_SUPPORTS_METAL)
|
||||
set(MATC_BASE_FLAGS -a all)
|
||||
else()
|
||||
set(MATC_BASE_FLAGS -a opengl)
|
||||
@@ -348,6 +356,10 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
target_link_libraries(${TARGET} PUBLIC bluevk vkmemalloc)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_METAL)
|
||||
target_link_libraries(${TARGET} PUBLIC "-framework Metal")
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
target_link_libraries(${TARGET} PRIVATE dl)
|
||||
endif()
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <math/vec4.h>
|
||||
#include <math/vec2.h>
|
||||
|
||||
#include <utils/unwindows.h> // Because we define NEAR and FAR in the Plane enum.
|
||||
|
||||
namespace filament {
|
||||
|
||||
namespace details {
|
||||
|
||||
@@ -136,8 +136,6 @@ class FLightManager;
|
||||
* On the other hand, a scene can contain hundreds of non overlapping lights without
|
||||
* incurring a significant overhead.
|
||||
*
|
||||
* 3. Use Type.Static Lights as much as possible.
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC LightManager : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
@@ -477,8 +475,6 @@ public:
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param position Light's position in world space. The default is at the origin.
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.position()
|
||||
*/
|
||||
void setPosition(Instance i, const math::float3& position) noexcept;
|
||||
@@ -493,8 +489,6 @@ public:
|
||||
* @param direction Light's direction in world space. Should be a unit vector.
|
||||
* The default is {0,-1,0}.
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.direction()
|
||||
*/
|
||||
void setDirection(Instance i, const math::float3& direction) noexcept;
|
||||
@@ -509,8 +503,6 @@ public:
|
||||
* @param color Color of the light specified in the linear sRGB color-space.
|
||||
* The default is white {1,1,1}.
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.color(), getInstance()
|
||||
*/
|
||||
void setColor(Instance i, const LinearColor& color) noexcept;
|
||||
@@ -531,8 +523,6 @@ public:
|
||||
* - For point lights and spot lights, it specifies the luminous power
|
||||
* in *lumen*.
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.intensity()
|
||||
*/
|
||||
void setIntensity(Instance i, float intensity) noexcept;
|
||||
@@ -554,8 +544,6 @@ public:
|
||||
* LED | 8.7%
|
||||
* Fluorescent | 10.7%
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.intensity(float watts, float efficiency)
|
||||
*/
|
||||
void setIntensity(Instance i, float watts, float efficiency) noexcept {
|
||||
@@ -579,8 +567,6 @@ public:
|
||||
* @param i Instance of the component obtained from getInstance().
|
||||
* @param radius falloff distance in world units. Default is 1 meter.
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.falloff()
|
||||
*/
|
||||
void setFalloff(Instance i, float radius) noexcept;
|
||||
@@ -599,8 +585,6 @@ public:
|
||||
* @param inner inner cone angle in *radians* between 0 and @f$ \pi @f$
|
||||
* @param outer outer cone angle in *radians* between 0 and @f$ \pi @f$
|
||||
*
|
||||
* @note ignored for Mode.STATIC lights.
|
||||
*
|
||||
* @see Builder.spotLightCone()
|
||||
*/
|
||||
void setSpotLightCone(Instance i, float inner, float outer) noexcept;
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
uint8_t byteStride = 0) noexcept; // default is attribute size
|
||||
|
||||
// no-op if attribute is an invalid enum
|
||||
Builder& normalized(VertexAttribute attribute) noexcept;
|
||||
Builder& normalized(VertexAttribute attribute, bool normalize = true) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the VertexBuffer object and returns a pointer to it.
|
||||
|
||||
@@ -118,6 +118,12 @@ public:
|
||||
uint32_t* width, uint32_t* height) noexcept = 0;
|
||||
};
|
||||
|
||||
class UTILS_PUBLIC MetalPlatform : public Platform {
|
||||
public:
|
||||
~MetalPlatform() noexcept override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace driver
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -257,6 +257,8 @@ void FEngine::shutdown() {
|
||||
destroy(mDefaultIblTexture);
|
||||
destroy(mDefaultIbl);
|
||||
|
||||
destroy(mDefaultMaterial);
|
||||
|
||||
/*
|
||||
* clean-up after the user -- we call terminate on each "leaked" object and clear each list.
|
||||
*
|
||||
@@ -354,10 +356,25 @@ int FEngine::loop() {
|
||||
if (platform == nullptr) {
|
||||
platform = Platform::create(&mBackend);
|
||||
mPlatform = platform;
|
||||
#if !defined(NDEBUG)
|
||||
slog.d << "FEngine resolved backend: "
|
||||
<< (mBackend == driver::Backend::VULKAN ? "Vulkan" : "OpenGL") << io::endl;
|
||||
#endif
|
||||
slog.d << "FEngine resolved backend: ";
|
||||
switch (mBackend) {
|
||||
case driver::Backend::OPENGL:
|
||||
slog.d << "OpenGL";
|
||||
break;
|
||||
|
||||
case driver::Backend::VULKAN:
|
||||
slog.d << "Vulkan";
|
||||
break;
|
||||
|
||||
case driver::Backend::METAL:
|
||||
slog.d << "Metal";
|
||||
break;
|
||||
|
||||
default:
|
||||
slog.d << "Unknown";
|
||||
break;
|
||||
}
|
||||
slog.d << io::endl;
|
||||
}
|
||||
mDriver = platform->createDriver(mSharedGLContext);
|
||||
mDriverBarrier.latch();
|
||||
@@ -416,9 +433,10 @@ Handle<HwProgram> FEngine::createPostProcessProgram(MaterialParser& parser,
|
||||
// need to populate a SamplerBindingMap and pass a weak reference to Program. Binding maps are
|
||||
// normally owned by Material, but in this case we'll simply own a copy right here in static
|
||||
// storage.
|
||||
static const SamplerBindingMap* pBindings = [] {
|
||||
static const SamplerBindingMap* pBindings = [backend = this->mBackend] {
|
||||
static SamplerBindingMap bindings;
|
||||
bindings.populate();
|
||||
uint8_t offset = filament::getSamplerBindingsStart(backend);
|
||||
bindings.populate(offset);
|
||||
return &bindings;
|
||||
}();
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "FilamentAPI-impl.h"
|
||||
|
||||
#include <filament/driver/DriverEnums.h>
|
||||
|
||||
#include <private/filament/SibGenerator.h>
|
||||
#include <private/filament/UibGenerator.h>
|
||||
#include <private/filament/Variant.h>
|
||||
@@ -123,9 +125,9 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
|
||||
UTILS_UNUSED_IN_RELEASE bool uibOK = parser->getUIB(&mUniformInterfaceBlock);
|
||||
assert(uibOK);
|
||||
|
||||
// Sampler bindings are only required for Vulkan.
|
||||
UTILS_UNUSED_IN_RELEASE bool sbOK = parser->getSamplerBindingMap(&mSamplerBindings);
|
||||
assert(engine.getBackend() == Backend::OPENGL || sbOK);
|
||||
// Populate sampler bindings for the backend that will consume this Material.
|
||||
const uint8_t offset = getSamplerBindingsStart(engine.getBackend());
|
||||
mSamplerBindings.populate(offset, &mSamplerInterfaceBlock);
|
||||
|
||||
parser->getShading(&mShading);
|
||||
parser->getBlendingMode(&mBlendingMode);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "details/Engine.h"
|
||||
|
||||
#include "fg/FrameGraph.h"
|
||||
|
||||
#include <private/filament/SibGenerator.h>
|
||||
|
||||
#include <utils/Log.h>
|
||||
@@ -39,7 +41,8 @@ void PostProcessManager::init(FEngine& engine) noexcept {
|
||||
// create sampler for post-process FBO
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
mPostProcessSbh = driver.createSamplerBuffer(engine.getPostProcessSib().getSize());
|
||||
mPostProcessUbh = driver.createUniformBuffer(engine.getPerPostProcessUib().getSize(), driver::BufferUsage::DYNAMIC);
|
||||
mPostProcessUbh = driver.createUniformBuffer(engine.getPerPostProcessUib().getSize(),
|
||||
driver::BufferUsage::DYNAMIC);
|
||||
driver.bindSamplers(BindingPoints::POST_PROCESS, mPostProcessSbh);
|
||||
driver.bindUniformBuffer(BindingPoints::POST_PROCESS, mPostProcessUbh);
|
||||
}
|
||||
@@ -50,7 +53,7 @@ void PostProcessManager::terminate(driver::DriverApi& driver) noexcept {
|
||||
}
|
||||
|
||||
void PostProcessManager::setSource(uint32_t viewportWidth, uint32_t viewportHeight,
|
||||
const RenderTargetPool::Target* pos) const noexcept {
|
||||
Handle<HwTexture> texture, uint32_t textureWidth, uint32_t textureHeight) const noexcept {
|
||||
FEngine& engine = *mEngine;
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
@@ -60,7 +63,7 @@ void PostProcessManager::setSource(uint32_t viewportWidth, uint32_t viewportHeig
|
||||
params.filterMag = SamplerMagFilter::LINEAR;
|
||||
params.filterMin = SamplerMinFilter::LINEAR;
|
||||
SamplerBuffer sb(engine.getPostProcessSib());
|
||||
sb.setSampler(PostProcessSib::COLOR_BUFFER, pos->texture, params);
|
||||
sb.setSampler(PostProcessSib::COLOR_BUFFER, texture, params);
|
||||
|
||||
auto duration = engine.getEngineTime();
|
||||
float fraction = (duration.count() % 1000000000) / 1000000000.0f;
|
||||
@@ -68,11 +71,11 @@ void PostProcessManager::setSource(uint32_t viewportWidth, uint32_t viewportHeig
|
||||
UniformBuffer& ub = mPostProcessUb;
|
||||
ub.setUniform(offsetof(PostProcessingUib, time), fraction);
|
||||
ub.setUniform(offsetof(PostProcessingUib, uvScale),
|
||||
math::float2{ viewportWidth, viewportHeight } / math::float2{ pos->w, pos->h });
|
||||
math::float2{ viewportWidth, viewportHeight } / math::float2{ textureWidth, textureHeight });
|
||||
|
||||
// The shader may need to know the offset between the top of the texture and the top
|
||||
// of the rectangle that it actually needs to sample from.
|
||||
const float yOffset = pos->h - viewportHeight;
|
||||
const float yOffset = textureHeight - viewportHeight;
|
||||
ub.setUniform(offsetof(PostProcessingUib, yOffset), yOffset);
|
||||
|
||||
driver.updateSamplerBuffer(mPostProcessSbh, std::move(sb));
|
||||
@@ -134,7 +137,7 @@ void PostProcessManager::finish(driver::TargetBufferFlags discarded,
|
||||
|
||||
if (commands[i].program) {
|
||||
// set the source for this pass (i.e. previous target)
|
||||
setSource(params.width, params.height, previous);
|
||||
setSource(params.width, params.height, previous->texture, previous->w, previous->h);
|
||||
|
||||
// draw a full screen triangle
|
||||
pipeline.program = commands[i].program;
|
||||
@@ -164,7 +167,7 @@ void PostProcessManager::finish(driver::TargetBufferFlags discarded,
|
||||
params.width = vp.width;
|
||||
params.height = vp.height;
|
||||
|
||||
setSource(params.width, params.height, previous);
|
||||
setSource(params.width, params.height, previous->texture, previous->w, previous->h);
|
||||
pipeline.program = commands.back().program;
|
||||
driver.beginRenderPass(viewRenderTarget, params);
|
||||
driver.draw(pipeline, fullScreenRenderPrimitive);
|
||||
@@ -182,4 +185,175 @@ void PostProcessManager::finish(driver::TargetBufferFlags discarded,
|
||||
commands.clear();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
FrameGraphResource PostProcessManager::msaa(FrameGraph& fg,
|
||||
FrameGraphResource input, driver::TextureFormat outFormat) noexcept {
|
||||
|
||||
struct PostProcessMSAA {
|
||||
FrameGraphResource input;
|
||||
FrameGraphResource output;
|
||||
};
|
||||
|
||||
auto& ppMSAA = fg.addPass<PostProcessMSAA>("msaa",
|
||||
[&](FrameGraph::Builder& builder, PostProcessMSAA& data) {
|
||||
auto const* inputDesc = fg.getDescriptor(input);
|
||||
data.input = builder.blit(input);
|
||||
|
||||
FrameGraphResource::Descriptor outputDesc{
|
||||
.width = inputDesc->width,
|
||||
.height = inputDesc->height,
|
||||
.format = outFormat
|
||||
};
|
||||
data.output = builder.write(builder.createResource("msaa output", outputDesc));
|
||||
},
|
||||
[=](FrameGraphPassResources const& resources,
|
||||
PostProcessMSAA const& data, DriverApi& driver) {
|
||||
auto in = resources.getRenderTarget(data.input);
|
||||
auto out = resources.getRenderTarget(data.output);
|
||||
auto const& desc = resources.getDescriptor(data.input);
|
||||
driver.blit(TargetBufferFlags::COLOR,
|
||||
out.target, 0, 0, desc.width, desc.height,
|
||||
in.target, 0, 0, desc.width, desc.height);
|
||||
});
|
||||
|
||||
return ppMSAA.getData().output;
|
||||
}
|
||||
|
||||
FrameGraphResource PostProcessManager::toneMapping(FrameGraph& fg,
|
||||
FrameGraphResource input, driver::TextureFormat outFormat, bool translucent) noexcept {
|
||||
|
||||
FEngine* engine = mEngine;
|
||||
Handle<HwRenderPrimitive> const& fullScreenRenderPrimitive = engine->getFullScreenRenderPrimitive();
|
||||
|
||||
struct PostProcessToneMapping {
|
||||
FrameGraphResource input;
|
||||
FrameGraphResource output;
|
||||
};
|
||||
Handle<HwProgram> toneMappingProgram = engine->getPostProcessProgram(
|
||||
translucent ? PostProcessStage::TONE_MAPPING_TRANSLUCENT
|
||||
: PostProcessStage::TONE_MAPPING_OPAQUE);
|
||||
|
||||
auto& ppToneMapping = fg.addPass<PostProcessToneMapping>("tonemapping",
|
||||
[&](FrameGraph::Builder& builder, PostProcessToneMapping& data) {
|
||||
auto const* inputDesc = fg.getDescriptor(input);
|
||||
data.input = builder.read(input);
|
||||
|
||||
FrameGraphResource::Descriptor outputDesc{
|
||||
.width = inputDesc->width,
|
||||
.height = inputDesc->height,
|
||||
.format = outFormat
|
||||
};
|
||||
data.output = builder.write(
|
||||
builder.createResource("tonemapping output", outputDesc));
|
||||
},
|
||||
[=](FrameGraphPassResources const& resources,
|
||||
PostProcessToneMapping const& data, DriverApi& driver) {
|
||||
Driver::PipelineState pipeline;
|
||||
pipeline.rasterState.culling = Driver::RasterState::CullingMode::NONE;
|
||||
pipeline.rasterState.colorWrite = true;
|
||||
pipeline.rasterState.depthFunc = Driver::RasterState::DepthFunc::A;
|
||||
pipeline.program = toneMappingProgram;
|
||||
|
||||
auto const& targetDesc = resources.getDescriptor(data.output);
|
||||
auto const& textureDesc = resources.getDescriptor(data.input);
|
||||
auto const& texture = resources.getTexture(data.input, TextureUsage::COLOR_ATTACHMENT);
|
||||
setSource(targetDesc.width, targetDesc.height, texture, textureDesc.width, textureDesc.height);
|
||||
|
||||
auto const& target = resources.getRenderTarget(data.output);
|
||||
driver.beginRenderPass(target.target, target.params);
|
||||
driver.draw(pipeline, fullScreenRenderPrimitive);
|
||||
driver.endRenderPass();
|
||||
});
|
||||
|
||||
return ppToneMapping.getData().output;
|
||||
}
|
||||
|
||||
FrameGraphResource PostProcessManager::fxaa(FrameGraph& fg,
|
||||
FrameGraphResource input, driver::TextureFormat outFormat, bool translucent) noexcept {
|
||||
|
||||
FEngine* engine = mEngine;
|
||||
Handle<HwRenderPrimitive> const& fullScreenRenderPrimitive = engine->getFullScreenRenderPrimitive();
|
||||
|
||||
struct PostProcessFXAA {
|
||||
FrameGraphResource input;
|
||||
FrameGraphResource output;
|
||||
};
|
||||
|
||||
Handle<HwProgram> antiAliasingProgram = engine->getPostProcessProgram(
|
||||
translucent ? PostProcessStage::ANTI_ALIASING_TRANSLUCENT
|
||||
: PostProcessStage::ANTI_ALIASING_OPAQUE);
|
||||
|
||||
auto& ppFXAA = fg.addPass<PostProcessFXAA>("fxaa",
|
||||
[&](FrameGraph::Builder& builder, PostProcessFXAA& data) {
|
||||
auto* inputDesc = fg.getDescriptor(input);
|
||||
inputDesc->format = TextureFormat::RGBA8;
|
||||
data.input = builder.read(input);
|
||||
|
||||
FrameGraphResource::Descriptor outputDesc{
|
||||
.width = inputDesc->width,
|
||||
.height = inputDesc->height,
|
||||
.format = outFormat
|
||||
};
|
||||
data.output = builder.write(builder.createResource("fxaa output", outputDesc));
|
||||
},
|
||||
[=](FrameGraphPassResources const& resources,
|
||||
PostProcessFXAA const& data, DriverApi& driver) {
|
||||
Driver::PipelineState pipeline;
|
||||
pipeline.rasterState.culling = Driver::RasterState::CullingMode::NONE;
|
||||
pipeline.rasterState.colorWrite = true;
|
||||
pipeline.rasterState.depthFunc = Driver::RasterState::DepthFunc::A;
|
||||
pipeline.program = antiAliasingProgram;
|
||||
|
||||
auto const& targetDesc = resources.getDescriptor(data.output);
|
||||
auto const& textureDesc = resources.getDescriptor(data.input);
|
||||
auto const& texture = resources.getTexture(data.input, TextureUsage::COLOR_ATTACHMENT);
|
||||
setSource(targetDesc.width, targetDesc.height, texture, textureDesc.width, textureDesc.height);
|
||||
|
||||
auto const& target = resources.getRenderTarget(data.output);
|
||||
driver.beginRenderPass(target.target, target.params);
|
||||
driver.draw(pipeline, fullScreenRenderPrimitive);
|
||||
driver.endRenderPass();
|
||||
});
|
||||
|
||||
return ppFXAA.getData().output;
|
||||
}
|
||||
|
||||
FrameGraphResource PostProcessManager::dynamicScaling(FrameGraph& fg,
|
||||
FrameGraphResource input, driver::TextureFormat outFormat,
|
||||
Viewport const& outViewport) noexcept {
|
||||
|
||||
struct PostProcessScaling {
|
||||
FrameGraphResource input;
|
||||
FrameGraphResource output;
|
||||
};
|
||||
|
||||
auto& ppScaling = fg.addPass<PostProcessScaling>("scaling",
|
||||
[&](FrameGraph::Builder& builder, PostProcessScaling& data) {
|
||||
auto* inputDesc = fg.getDescriptor(input);
|
||||
data.input = builder.blit(input);
|
||||
|
||||
FrameGraphResource::Descriptor outputDesc{
|
||||
.width = inputDesc->width,
|
||||
.height = inputDesc->height,
|
||||
.format = outFormat
|
||||
};
|
||||
data.output = builder.write(builder.createResource("scale output", outputDesc));
|
||||
},
|
||||
[=](FrameGraphPassResources const& resources,
|
||||
PostProcessScaling const& data, DriverApi& driver) {
|
||||
auto in = resources.getRenderTarget(data.input);
|
||||
auto out = resources.getRenderTarget(data.output);
|
||||
auto const& inDesc = resources.getDescriptor(data.input);
|
||||
driver.blit(TargetBufferFlags::COLOR,
|
||||
out.target, outViewport.left, outViewport.bottom, outViewport.width,
|
||||
outViewport.height,
|
||||
in.target, 0, 0, inDesc.width, inDesc.height);
|
||||
});
|
||||
|
||||
return ppScaling.getData().output;
|
||||
}
|
||||
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "UniformBuffer.h"
|
||||
|
||||
#include "fg/FrameGraphResource.h"
|
||||
|
||||
#include "driver/DriverApiForward.h"
|
||||
#include "driver/Handle.h"
|
||||
|
||||
@@ -41,8 +43,8 @@ class PostProcessManager {
|
||||
public:
|
||||
void init(details::FEngine& engine) noexcept;
|
||||
void terminate(driver::DriverApi& driver) noexcept;
|
||||
void setSource(uint32_t viewportWidth, uint32_t viewportHeight,
|
||||
const RenderTargetPool::Target* pos) const noexcept;
|
||||
void setSource(uint32_t viewportWidth, uint32_t viewportHeight, Handle <HwTexture> texture,
|
||||
uint32_t textureWidth, uint32_t textureHeight) const noexcept;
|
||||
|
||||
// start() is a scam, it does nothing
|
||||
void start() noexcept { }
|
||||
@@ -60,6 +62,23 @@ public:
|
||||
Viewport const& svp);
|
||||
|
||||
|
||||
FrameGraphResource msaa(
|
||||
FrameGraph& fg, FrameGraphResource input,
|
||||
driver::TextureFormat outFormat) noexcept;
|
||||
|
||||
FrameGraphResource toneMapping(
|
||||
FrameGraph& fg, FrameGraphResource input, driver::TextureFormat outFormat,
|
||||
bool translucent) noexcept;
|
||||
|
||||
FrameGraphResource fxaa(
|
||||
FrameGraph& fg, FrameGraphResource input, driver::TextureFormat outFormat,
|
||||
bool translucent) noexcept;
|
||||
|
||||
FrameGraphResource dynamicScaling(
|
||||
FrameGraph& fg, FrameGraphResource input,
|
||||
driver::TextureFormat outFormat, Viewport const& outViewport) noexcept;
|
||||
|
||||
|
||||
private:
|
||||
details::FEngine* mEngine = nullptr;
|
||||
|
||||
|
||||
@@ -25,15 +25,18 @@
|
||||
#include "details/View.h"
|
||||
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Renderer.h>
|
||||
|
||||
#include <filament/driver/PixelBufferDescriptor.h>
|
||||
|
||||
#include "fg/FrameGraph.h"
|
||||
#include "fg/FrameGraphResource.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/vector.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <filament/Renderer.h>
|
||||
|
||||
|
||||
using namespace math;
|
||||
@@ -146,7 +149,6 @@ void FRenderer::render(FView const* view) {
|
||||
|
||||
// and wait for all jobs to finish as a safety (this should be a no-op)
|
||||
js.runAndWait(masterJob);
|
||||
js.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,37 +230,89 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
* Post Processing...
|
||||
*/
|
||||
|
||||
|
||||
#define USE_FRAME_GRAPH false
|
||||
|
||||
if (UTILS_LIKELY(hasPostProcess)) {
|
||||
driver.pushGroupMarker("Post Processing");
|
||||
|
||||
ppm.start();
|
||||
assert(colorTarget);
|
||||
|
||||
if (USE_FRAME_GRAPH) {
|
||||
FrameGraph fg;
|
||||
|
||||
const bool translucent = mSwapChain->isTransparent();
|
||||
|
||||
FrameGraphResource::Descriptor colorDesc{
|
||||
.width = colorTarget->w,
|
||||
.height= colorTarget->h,
|
||||
.format= colorTarget->format,
|
||||
.samples= colorTarget->samples
|
||||
};
|
||||
|
||||
FrameGraphResource::Descriptor viewRenderTargetDesc{
|
||||
.width = vp.width,
|
||||
.height= vp.height
|
||||
};
|
||||
|
||||
FrameGraphResource input = fg.importResource("colorTarget", colorDesc,
|
||||
colorTarget->target, colorTarget->texture);
|
||||
|
||||
FrameGraphResource output = fg.importResource("viewRenderTarget",
|
||||
viewRenderTargetDesc, viewRenderTarget);
|
||||
|
||||
if (useMSAA > 1) {
|
||||
input = ppm.msaa(fg, input, hdrFormat);
|
||||
}
|
||||
input = ppm.toneMapping(fg, input, ldrFormat, translucent);
|
||||
if (useFXAA) {
|
||||
input = ppm.fxaa(fg, input, ldrFormat, translucent);
|
||||
}
|
||||
if (scaled) {
|
||||
input = ppm.dynamicScaling(fg, input, ldrFormat, vp);
|
||||
}
|
||||
|
||||
fg.moveResource(output, input);
|
||||
fg.present(output, FrameGraph::Builder::COLOR);
|
||||
|
||||
fg.compile();
|
||||
//fg.export_graphviz(slog.d);
|
||||
fg.execute(driver);
|
||||
|
||||
rtp.put(colorTarget);
|
||||
|
||||
} else {
|
||||
|
||||
ppm.start();
|
||||
|
||||
if (useMSAA > 1) {
|
||||
// Note: MSAA, when used is applied before tone-mapping (which is not ideal)
|
||||
// (tone mapping currently only works without multi-sampling)
|
||||
// this blit does a MSAA resolve
|
||||
ppm.blit(hdrFormat);
|
||||
}
|
||||
|
||||
const bool translucent = mSwapChain->isTransparent();
|
||||
Handle<HwProgram> toneMappingProgram = engine.getPostProcessProgram(
|
||||
translucent ? PostProcessStage::TONE_MAPPING_TRANSLUCENT
|
||||
: PostProcessStage::TONE_MAPPING_OPAQUE);
|
||||
ppm.pass(useFXAA ? TextureFormat::RGBA8 : ldrFormat, toneMappingProgram);
|
||||
|
||||
if (useFXAA) {
|
||||
Handle<HwProgram> antiAliasingProgram = engine.getPostProcessProgram(
|
||||
translucent ? PostProcessStage::ANTI_ALIASING_TRANSLUCENT
|
||||
: PostProcessStage::ANTI_ALIASING_OPAQUE);
|
||||
ppm.pass(ldrFormat, antiAliasingProgram);
|
||||
}
|
||||
|
||||
if (scaled) {
|
||||
// because it's the last command, the TextureFormat is not relevant
|
||||
ppm.blit();
|
||||
}
|
||||
ppm.finish(view.getDiscardedTargetBuffers(), viewRenderTarget, vp, colorTarget, svp);
|
||||
|
||||
if (useMSAA > 1) {
|
||||
// Note: MSAA, when used is applied before tone-mapping (which is not ideal)
|
||||
// (tone mapping currently only works without multi-sampling)
|
||||
// this blit does a MSAA resolve
|
||||
ppm.blit(hdrFormat);
|
||||
}
|
||||
|
||||
const bool translucent = mSwapChain->isTransparent();
|
||||
Handle<HwProgram> toneMappingProgram = engine.getPostProcessProgram(
|
||||
translucent ? PostProcessStage::TONE_MAPPING_TRANSLUCENT
|
||||
: PostProcessStage::TONE_MAPPING_OPAQUE);
|
||||
ppm.pass(useFXAA ? TextureFormat::RGBA8 : ldrFormat, toneMappingProgram);
|
||||
|
||||
if (useFXAA) {
|
||||
Handle<HwProgram> antiAliasingProgram = engine.getPostProcessProgram(
|
||||
translucent ? PostProcessStage::ANTI_ALIASING_TRANSLUCENT
|
||||
: PostProcessStage::ANTI_ALIASING_OPAQUE);
|
||||
ppm.pass(ldrFormat, antiAliasingProgram);
|
||||
}
|
||||
|
||||
if (scaled) {
|
||||
// because it's the last command, the TextureFormat is not relevant
|
||||
ppm.blit();
|
||||
}
|
||||
ppm.finish(view.getDiscardedTargetBuffers(), viewRenderTarget, vp, colorTarget, svp);
|
||||
|
||||
driver.popGroupMarker();
|
||||
}
|
||||
|
||||
@@ -384,13 +438,13 @@ void FRenderer::endFrame() {
|
||||
}
|
||||
mFrameSkipper.endFrame();
|
||||
|
||||
driver.endFrame(mFrameId);
|
||||
|
||||
if (mSwapChain) {
|
||||
mSwapChain->commit(driver);
|
||||
mSwapChain = nullptr;
|
||||
}
|
||||
|
||||
driver.endFrame(mFrameId);
|
||||
|
||||
// Run the component managers' GC in parallel
|
||||
// WARNING: while doing this we can't access any component manager
|
||||
auto& js = engine.getJobSystem();
|
||||
|
||||
@@ -67,21 +67,26 @@ void FScene::prepare(const math::mat4f& worldOriginTransform) {
|
||||
// NOTE: we can't know in advance how many entities are renderable or lights because the corresponding
|
||||
// component can be added after the entity is added to the scene.
|
||||
|
||||
// for the purpose of allocation, we'll assume all our entities are renderables
|
||||
size_t capacity = entities.size();
|
||||
size_t renderableDataCapacity = entities.size();
|
||||
// we need the capacity to be multiple of 16 for SIMD loops
|
||||
capacity = (capacity + 0xF) & ~0xF;
|
||||
renderableDataCapacity = (renderableDataCapacity + 0xF) & ~0xF;
|
||||
// we need 1 extra entry at the end for the summed primitive count
|
||||
capacity = capacity + 1;
|
||||
renderableDataCapacity = renderableDataCapacity + 1;
|
||||
|
||||
sceneData.clear();
|
||||
if (sceneData.capacity() < capacity) {
|
||||
sceneData.setCapacity(capacity);
|
||||
if (sceneData.capacity() < renderableDataCapacity) {
|
||||
sceneData.setCapacity(renderableDataCapacity);
|
||||
}
|
||||
|
||||
// The light data list will always contain at least one entry for the
|
||||
// dominating directional light, even if there are no entities.
|
||||
size_t lightDataCapacity = std::max<size_t>(1, entities.size());
|
||||
// we need the capacity to be multiple of 16 for SIMD loops
|
||||
lightDataCapacity = (lightDataCapacity + 0xF) & ~0xF;
|
||||
|
||||
lightData.clear();
|
||||
if (lightData.capacity() < capacity) {
|
||||
lightData.setCapacity(capacity);
|
||||
if (lightData.capacity() < lightDataCapacity) {
|
||||
lightData.setCapacity(lightDataCapacity);
|
||||
}
|
||||
// the first entries are reserved for the directional lights (currently only one)
|
||||
lightData.resize(DIRECTIONAL_LIGHTS_COUNT);
|
||||
|
||||