Compare commits

...

773 Commits

Author SHA1 Message Date
Romain Guy
07d6aebafc Update release action 2020-03-30 21:48:41 -07:00
Romain Guy
32604e2c57 Fix sample-textured-object 2020-03-30 18:54:46 -07:00
Romain Guy
adb107afc2 Fix sample-gltf-viewer 2020-03-30 18:53:14 -07:00
Romain Guy
8d9bd5f4fa Fix flavor dependencies, introduce flavors for filament-utils 2020-03-30 18:28:18 -07:00
Ben Doherty
c88bbc21d0 Link hello-gltf iOS project with Draco (#2311) 2020-03-30 17:11:49 -07:00
Romain Guy
917edec0a7 Update RELEASE_NOTES.md 2020-03-30 16:22:45 -07:00
Philip Rideout
34959dd5e8 New version number for release notes, npm, maven. 2020-03-30 16:19:37 -07:00
Ben Doherty
82ab74efb0 Update RELEASE_NOTES and LightManager documentation for spot shadows (#2310) 2020-03-30 16:14:07 -07:00
Pixelflinger
968dbdb847 make sure "structure" pass is culled when not needed
the structure (depth path) wasn't culled even if both ssao and
contact-shadows were disabled.
2020-03-30 16:13:41 -07:00
Philip Rideout
e43466d2bc Enable Draco for WebGL and iOS. 2020-03-30 15:58:55 -07:00
Philip Rideout
cdf03f91c9 Apply Draco compression to FlightHelmet. 2020-03-30 15:58:55 -07:00
Philip Rideout
abe70caeae Bump material version to prep for release. 2020-03-30 15:58:35 -07:00
Philip Rideout
4891bb6157 Fix SameSite warning for locally run web samples. 2020-03-30 15:58:24 -07:00
Ben Doherty
f5e6ec42b3 Fix draco build with Xcode (#2306) 2020-03-30 15:06:53 -07:00
Romain Guy
92b2dd835d Add support for bent normals (#2303)
* Add support for bent normals

Bent normals can be enabled via the bentNormal property of a material.
When specular occlusion is enabled, bent normals improve the quality
of the computation.

* Save a couple of multiplications in bent specular AO
2020-03-29 17:00:03 -07:00
Philip Rideout
76f0309b58 Remove unused Draco targets from build. 2020-03-27 17:07:55 -07:00
Philip Rideout
d9e9fabec5 Disable unused Draco features. 2020-03-27 16:32:44 -07:00
Philip Rideout
a922e914b4 Enable Draco for Android. 2020-03-27 16:32:44 -07:00
Philip Rideout
4b7677fd13 Apply Draco compression to BusterDrone. 2020-03-27 16:32:44 -07:00
Ben Doherty
0474a6b8b5 Try to fix Windows build by reducing disk space footprint (#2301) 2020-03-27 16:05:50 -07:00
Philip Rideout
241f08bd74 Draco: do not add files to the build root. 2020-03-27 13:59:41 -07:00
Ben Doherty
b8f8067a87 Support lights in gltfio (#2288) 2020-03-27 13:56:28 -07:00
Pixelflinger
965777da85 fix an assert() when using custom render targets
we now always mask out target bits that don't exist in the render
target before converting them to GLenums.

Fixes #2285
2020-03-27 13:45:54 -07:00
Romain Guy
ffa62d4236 Check for CMake version before setting the policy 2020-03-27 11:50:21 -07:00
Romain Guy
94a01c6010 Be compatible with CMake 3.10 again (#2296)
* Be compatible with CMake 3.10 again

* Windows fix

* Add CMake changes to patch file
2020-03-27 11:15:18 -07:00
Romain Guy
232bf728c6 Update readme for Windows 2020-03-27 09:31:50 -07:00
Romain Guy
0e367580da Update CMake requirement to 3.12 2020-03-27 09:25:23 -07:00
Romain Guy
40aad197da Fixes various issues (#2292)
* Fixes various issues

- Fix gltf_baker crash
- Fix Python3 discovery on macOS
- Fix TBB CMake warning
- Fix bent normals baking

* Find Python 3 on Windows
2020-03-26 22:53:44 -07:00
Kai Chieh Liu (KJ) 劉凱傑
124fd2c978 Fix NameComponentManager dependency and Android build (#2291) 2020-03-26 20:02:03 -07:00
Philip Rideout
0d32c58e41 gltfio: add support for Draco (desktop only)
This needs a bit more testing before merging, but I wanted to put up the
PR for review. I will look into supporting Android after we land this.

Fixes #1932.
2020-03-26 19:52:26 -07:00
Romain Guy
09fa87ddfa Update README.md 2020-03-26 16:58:51 -07:00
Pixelflinger
cb356606d9 fog improvements
- handle heightFalloff=0 (i.e. fog doesn't depend on height) correctly,
  previously, a divide-by-zero on the cpu side would get in the way.
  The fix is to clamp heightFalloff to a small-enough value, and to
  make sure that this is handled correctly in the shader.

- default fog distance is 0 instead of 1m

- inScatteringSize parameter should be allowed to be large in samples
2020-03-26 16:01:56 -07:00
Kai Chieh Liu (KJ) 劉凱傑
3de9cc1533 Expose Renderable::getLayerMask() (#2289)
TEST: built on mac

Co-authored-by: KJ Liu <kjliu@amazon.com>
2020-03-26 15:31:38 -07:00
Ben Doherty
f1aaf16082 Add spot light controls to material_sandbox (#2270) 2020-03-26 13:29:39 -07:00
Kai Chieh Liu (KJ) 劉凱傑
4c23f7a436 Fix cmakelist to install subdir properly (#2283) 2020-03-25 18:20:24 -07:00
Pixelflinger
2188923153 Fix fog with transparent objects 2020-03-25 17:10:36 -07:00
Romain Guy
2f47bab237 Update README screenshots 2020-03-25 14:23:36 -07:00
prewettg
fe547a7690 Fixes resizing window not resizing the framebuffer on macOS (#2281) 2020-03-25 14:03:49 -07:00
Pixelflinger
b4f5a4a0a0 Fog improvements
- optimized the fog computations
- fixed issues with the skybox
- added the option of getting the fog color modulated by the IBL envmap
2020-03-24 22:29:25 -07:00
Pixelflinger
5929d5d9dd improve quality of diffuse sampling on desktop
We 4-tap filter the diffuse map, which generally is very small
(e.g. 16x16), to improve quality a bit.
2020-03-24 22:28:59 -07:00
Romain Guy
0b7de0ec65 Turn off contact shadows by default in gltf viewer (#2277) 2020-03-24 16:44:48 -07:00
Romain Guy
87ac282014 Export missing headers for NameComponentManager (#2276) 2020-03-24 16:32:48 -07:00
Pixelflinger
e525a7c7c4 enable some more features in lightbulb
spotlight/contact shadows, ssao, fog, bloom.
2020-03-24 16:15:58 -07:00
Romain Guy
8a84c7f0a3 Install all public headers from libutils 2020-03-24 15:46:23 -07:00
Ben Doherty
e462c22a07 Fix MetalBufferPool crash in completion handler (#2273) 2020-03-24 12:35:54 -07:00
Philip Rideout
3ea8a25127 Add Draco 1.3.6 to third_party. 2020-03-24 10:13:13 -07:00
Romain Guy
45df197bd6 Expose libutils APIs that should have been public (#2269)
* Expose libutils APIs that should have been public

* Don't make JobSystem public for now
2020-03-24 09:57:04 -07:00
Philip Rideout
1ecb83bf73 gltfio: Big internal refactoring / simplification.
This replaces the "bindings" structures with simple types that re-use
data structures from cgltf.

This also moves some trivial work from ResourceLoader to AssetLoader,
which simplifies the communication between these two classes.

Motivated by #1932.
2020-03-24 09:22:20 -07:00
Ben Doherty
aefa03291e Fix spot light shadow bugs related to light culling (#2264) 2020-03-23 16:12:44 -07:00
Pixelflinger
6e02fa186a generateMipmap needs at least 2 levels allocated 2020-03-23 15:05:00 -07:00
Pixelflinger
756074d8bd don't generate fog code in post-process materials 2020-03-23 15:04:42 -07:00
Pixelflinger
2caa09bebd Fix IBL mip calculation
The max mip (i.e. mip at roughness 1) was off by one.
2020-03-23 15:04:24 -07:00
Ben Doherty
72a182122a Update spirv-cross to 871c85d (#2262) 2020-03-20 16:59:47 -07:00
Pixelflinger
0688db7da3 fix a shadow clipping bug
In some situations the shadow map would be too aggressively clipped.
This was due to a bug in the box-frustum intersection algorithm, which
could fail when some vertices of the frustum were inside the box, and
some vertices of the box inside the frustum and the total number
of vertices such classified was 8.
2020-03-20 11:13:18 -07:00
Mathias Agopian
0c6d96c407 Add support for basic fog (#2256)
* Add support for basic fog

* address reviewers comments
2020-03-19 18:01:07 -07:00
Pixelflinger
1f48bd3e79 fix contact-shadows with shadow multiplier 2020-03-19 18:00:41 -07:00
Ben Doherty
7103f4f0b3 Share material dictionaries between GLSL / MSL (#2252) 2020-03-19 11:16:01 -07:00
Ben Doherty
210234255c Fix contact shadow GLSL compilation error (#2254) 2020-03-18 10:05:58 -07:00
Romain Guy
73312bc6bb Update README.md 2020-03-17 12:42:23 -07:00
Pixelflinger
6ea9872a3e fix computation of shading_posiiton for clip space domain shader
When reconstructing the position from clip-space, we need to apply
the .w divide.

Also use getWorldFromClipMatrix() directly.
2020-03-17 00:01:50 -07:00
Mathias Agopian
d54ceff7a3 Add support for screen-space contact shadows (#2245)
* Add support for screen-space contact shadows

This CL adds support and always enables it.
toggles and setting in the next CL (same PR).

* Plumb settings for screen-space contact shadows

screen-space contact shadows is handled like a shadow option,
parameters (including on/off) are set in the LightManager, using
the existing ShadowOptions API.

Additionally there is a per-renderable toggle.

Both toggles are off by default.

* Allow contact shadows when shadowing is auto-disabled


Shadowing can be auto-disabled when for instance there are no
shadow casters in the scene. We still allow contact shadows in
that case.

This would allow for instance, to make the vegetation on a terrain
not shadow-casting, and still get some shadowing there by using
contact shadows instead.

* apply micro-shadowing after contact shadows

also, don't compute contact shadows when we know we're fully shadowed.
2020-03-16 22:39:24 -07:00
Ben Doherty
6cf3e86c8a Fix iOS build samples CI (#2249) 2020-03-13 14:34:37 -07:00
Ben Doherty
acc36e8d9b Deprecating Clang on Windows in CMakeLists (#2243) 2020-03-13 12:33:02 -07:00
Pixelflinger
1670e73287 Revert "enable ASAN's -fsanitize=address in debug builds"
This caused failures in CI builds.

This reverts commit c132ede510.
2020-03-13 11:20:47 -07:00
Romain Guy
3b52b89fd6 Update release notes 2020-03-12 19:18:55 -07:00
Pixelflinger
c132ede510 enable ASAN's -fsanitize=address in debug builds 2020-03-12 19:18:29 -07:00
Pixelflinger
4e62e4f696 include alpha-masked objects in SSAO
this helps a lot with vegetations, which often uses alpha masking
2020-03-12 19:17:39 -07:00
Pixelflinger
c0addf22ed Cleanup render loop to prepare for more features
- decouple the depth and ssao passes, so that the depth
  pass could be used by another client, down the framegraph

- set uniforms/samplers from the execute closure of the color pass,
  instead of using a separate pass. This is more correct and it 
  potentially reduces calls to commitUniforms.

- make setSampler check that the value set is different,
  the idea here is that it's much more costly to have to commit the
  samplers rather than having to compare them. Also realistically we
  don't have a lot of samplers in a frame, so that's not a lot of
  compares.

- one downside of this change is that commands for the SSAO pass are
  always generated, we will fix that in an upcoming change.
2020-03-12 14:31:56 -07:00
Romain Guy
880642ef4a Fix crash in glTF sample for Android 2020-03-12 14:27:11 -07:00
Pixelflinger
2f94e5990c workaround a framegraph bug with imported rendertargets
Imported render targets are only partially implemented, which
caused a discard flags bug. It would happen when an imported
 render target is used more than once like when using SSrefr
without tone mapping.  In that case, the 2nd pass would use the same
discard flags as the first pass.
2020-03-11 22:58:22 -07:00
Pixelflinger
4a5ce16322 Trivially make LinearAllocator 16 bytes instead of 24 2020-03-11 17:04:08 -07:00
Pixelflinger
454b08362d minor code cleanups
- go through 'FIXMEs' & `TODOs` and either fix or remove obsolete ones.
- add a few asserts
- fix some comments and IDE warnings
2020-03-11 17:04:08 -07:00
Ben Doherty
f80c584db0 Update glslang to dbb56a1 (#2232) 2020-03-11 12:34:08 -07:00
Pixelflinger
68bcd6c159 fix setting an array mat3 as a parameter of material instance
this actually makes it possible to set mat3s from java.
2020-03-11 12:26:52 -07:00
Pixelflinger
a9a9061f96 update GLSLPostProcessor optimization passes to latest
deactivate "mergeReturnPass" because it triggers a segfault with
AMD drivers on MacOS.
2020-03-11 11:11:28 -07:00
Pixelflinger
196c98fc2a Fix framebuffer clears
We make sure to only (and always) clear newly allocated buffers,
but only clear existing buffers based on the user request. This
should allow to share the depth buffer between drawing two
Views (if post-process is disabled). This should also fix 
a bug where the intermediate buffer wasn't cleared when blending
a view on to of another.

This should fix #2138
2020-03-11 11:11:09 -07:00
Ben Doherty
9ea2e69579 Fix gltf_viewer (#2233) 2020-03-10 17:57:59 -07:00
Ben Doherty
f4da2ef8ec Add support for spot light shadows (#2209) 2020-03-10 17:53:25 -07:00
Pixelflinger
8fb65a19b4 fix utils::ctz() when builtins are not available
Our fallback 64-bits ctz() was completely wrong. 
The unit tests were wrong too.
2020-03-10 15:41:43 -07:00
Ben Doherty
a2c6c34739 Update SPIRV-Tools to 2020.1 / SPIRV-Cross to 65aa0c3 (#2121) 2020-03-10 15:32:41 -07:00
Romain Guy
a2818037b3 matinfo can print dictionaries, shrink Metal dictionary (#2230)
This change adds new commands to matinfo to print dictionaries.
This feature is useful to debug dictionaries, and I just used
it to identify that using a shared dictionary would save ~12 KiB
in the Android build. The macOS build (GLSL + Metal) would go
down to 71 KiB from 136 KiB.

The SPIRV to Metal conversion leaves leading spaces and some
comments. This change also runs the shrinker on optimized Metal
shaders to further reduce the size of shaders.
2020-03-10 11:42:19 -07:00
Romain Guy
02c7a22d43 Remove build time warning 2020-03-10 08:41:28 -07:00
Pixelflinger
f6e993dfc8 fix bloom upsample shaders
We were not using the correct offsets, however because everything
was so blurry, it wasn't obvious that something was wrong.
This should result in a bit smoother bloom effect.
2020-03-08 22:28:25 -07:00
Pixelflinger
8866e2829f Add a quality option to dynamic-scaling
It controls the quality of the upsampling filter. This can help a lot
if heavy scaling is needed to maintain performance, it also helps if
MSAA is not enabled.

There are 3 quality levels, low, medium and high. 1, 4 and 9 bilinear
taps are used for each level respectively. The high quality setting
employs a tent filter.
2020-03-08 22:28:10 -07:00
Matthias Moulin
d016e0f443 Replaced unnecessary std::forward with std::move
`execute` is an rvalue reference and not a forwarding reference, so `std::move` is more appropriate
2020-03-08 22:27:46 -07:00
Pixelflinger
0cbf6f8d76 disable spinlocks on ARMv7
we've had issues with some devices running in arm mode, where they
would throw spurious SIGILL on the WFE instruction used in spin locks.
Since on Android Mutexes are very efficient, we just use that instead.

This might fix #2197
2020-03-07 13:54:58 -08:00
Romain Guy
641b58c409 Be explicit about which NDK to use (#2221) 2020-03-06 16:53:41 -08:00
Romain Guy
5f0204f7b1 Clean build script 2020-03-06 15:36:14 -08:00
Romain Guy
660d1a1800 Enforce NDK 21 2020-03-06 15:24:45 -08:00
Pixelflinger
8d209a16c5 framegraph: destroy resources in reverse order
This is so that render targets are destroyed before their
attachments. In practice it doesn't matter too much, at least
on OpenGL, but it is cleaner.
2020-03-06 11:21:35 -08:00
Pixelflinger
ed786701fc The FrameGraph is now emitting debug markers
A debug marker is emitted for each pass.
This greatly improves debugging with RenderDoc for instance.
2020-03-06 11:21:17 -08:00
Mathias Agopian
4842b1ca13 rework stream operators for libmath
libmath itself doesn't expose any stream operators anymore. However,
libutils is able to automatically print libmath types into its
io::ostream -- however matrices are not formatted nicely.

Added a new optional library, libmathio, that provides std::ostream
operators for all libmath types. libmathio does a better job at
formating matrices.

Also removed apply() and map() from libmath because there were not used
anywhere and they forced us to depend on <functional> in public headers.
2020-03-05 22:50:49 -08:00
Ben Doherty
0990550f45 Fix, mathfwd does not work correctly with MSVC (#2214) 2020-03-05 17:46:21 -08:00
Romain Guy
84b215c3b0 Switch to AGP 3.6.1 2020-03-05 17:11:47 -08:00
Ben Doherty
2a7724f601 Introduce ShadowMapManager class (#2207) 2020-03-05 15:32:00 -08:00
Ben Doherty
b119d763da Fix visibility mask, encode enough SENTINEL commands (#2210) 2020-03-05 15:31:38 -08:00
Mathias Agopian
ff25e6c18f Add support for MRT in the framegraph 2020-03-05 13:17:18 -08:00
Mathias Agopian
2677f05f0d get rid of the 'ignoreScissor' flag in beginRenderPass
The scissor is now always ignored -- i.e. when we clear, the whole
surface is cleared, which echoes how discard flags work. 
Geometry must be used to clear only a sub-region of the screen.

This simplifies a lot of things because we had workaround for Adreno
GPUs, which were slow when clearing with the scissor enabled.
2020-03-05 13:17:18 -08:00
Mathias Agopian
bbfa47bbf0 More MRT support in the GL backend
in particular, we can now clear the proper draw buffer and
basic functionality works (tested on Adreno with systrace)
2020-03-05 13:17:18 -08:00
Mathias Agopian
060c0d2e6f remove discardSubRenderTargetBuffers() which isn't used right now 2020-03-05 13:17:18 -08:00
Romain Guy
414396efb6 Add background color selector to gltf_viewer 2020-03-05 12:58:52 -08:00
Philip Rideout
6825781718 gltf_viewer: fix string lifetime for #2190. 2020-03-05 09:26:27 -08:00
Ben Doherty
2494fff094 Refactor renderable partitioning scheme for spot light shadows (#2195) 2020-03-04 20:46:35 -08:00
Ben Doherty
924422261f Update ShadowMap for spot light shadows (#2206) 2020-03-04 20:20:32 -08:00
Philip Rideout
f81e819901 gltfio: simplify API, privatize bindings.
The binding list can be internalized, clients should instead use
`getResourceUris` and `ResourceLoader` to load external resources.
2020-03-04 16:30:12 -08:00
Ben Doherty
81a2d70251 Use array texture for shadow maps (#2199) 2020-03-04 11:59:25 -08:00
Ben Doherty
3a2a40c76a Add additional shadow info to lights uniform (#2200) 2020-03-04 11:58:51 -08:00
Ben Doherty
6c3fa13e41 Changes to frameUniforms for spot shadows (#2201) 2020-03-04 11:58:31 -08:00
Philip Rideout
0ea2354be5 More TypeScript annotations. 2020-03-04 11:20:01 -08:00
Mathias Agopian
079056cfbc major FrameGraph rewrite (#2202)
Major changes are:

- RenderTarget are now real resources as opposed to ad-hoc objects.
  This allows to remove a lot of code and simply a lot of things.

- ResouceNode now have a level of indirection (i.e. we store a pointer
  to them), which allow fast and more correct implementation of
  moveResource(). 
  A new unit test checks that all scenarios of moveResource with a 
  generic resource are working.

- We have a special version of moveResource that moves a RenderTarget
  resource into a TextureResource -- this shouldn't be allowed, but
  this helps make the API better. What it means is that
  "all rendertargets that use the specified texture as attachment
   are replaced with the given rendertarget".

- In this version there are a lot of limitations when moving
  a rendertarget into a texture resource; be we cover the case that
  is useful to us.
2020-03-04 11:13:29 -08:00
Philip Rideout
1230fccbf9 JavaScript: Expose bloom and SSAO options.
Fixes #2198.
2020-03-04 08:43:20 -08:00
Ben Doherty
73e0facaed Save spot light outer clamped radius in light manager (#2193) 2020-03-03 14:25:26 -08:00
Ben Doherty
94b1ad52fa Add new Shadows uniform buffer (#2194) 2020-03-03 14:25:03 -08:00
Philip Rideout
6878d0d6e6 npm package now has a gl-matrix dep.
Our wasm API does not actually use gl-matrix, but we do import it
from our TypeScript declarations file.
2020-03-03 09:46:53 -08:00
Ben Doherty
76e7568994 Add visibility mask to RenderPass (#2183) 2020-03-02 16:14:52 -08:00
Romain Guy
b176b2f0e6 Remove broken setLensProjection API (#2192) 2020-03-02 14:35:35 -08:00
Ben Doherty
af5805e396 Update XcodeGen and iOS sample projects (#2191) 2020-03-02 12:54:17 -08:00
Romain Guy
b98f45df60 Fix WebGL build (#2189) 2020-02-29 09:14:49 -08:00
Romain Guy
bb2571233d Update RELEASE_NOTES 2020-02-28 23:50:35 -08:00
Romain Guy
00629bac48 Add camera controls to gltf_viewer (#2188)
Exposure: shutter speed, aperture and ISO
Focal length

The shadow plane can now be toggled  at runtime.
2020-02-28 23:46:17 -08:00
Romain Guy
81e7f619eb Try to fix compilation error on Android (#2187)
* Try to fix compilation error on Android

* Try with a newer NDK...
2020-02-28 13:10:16 -08:00
Ben Doherty
b0ab9bb697 Remove unnecessary quotes from shader (#2186) 2020-02-28 10:50:52 -08:00
Romain Guy
ae1e6f43f2 Only compile materials for Vulkan when necessary 2020-02-28 09:51:47 -08:00
Romain Guy
6eba2f145e Properly fetch project properties (#2185) 2020-02-28 09:20:35 -08:00
Romain Guy
13666027cc Switch native code API level back to 21 2020-02-28 07:55:09 -08:00
Ben Doherty
62cef096e1 Refactor computeVisibilityMasks logic, visibility bits (#2179) 2020-02-27 16:28:47 -08:00
Mathias Agopian
af48b60876 split FrameGraphPassResources out of FrameGraph.cpp 2020-02-27 14:15:26 -08:00
Mathias Agopian
b71357a955 Allocators shouldn't crash when allocation fails
The allocator debug code didn't check that allocations where
successful before filling buffers.
2020-02-27 14:15:11 -08:00
Romain Guy
9865a609da Refactor Gradle files (#2180)
We now share all the C++/CMake flags from the root project.
2020-02-27 12:46:01 -08:00
Romain Guy
77bafb295e Fix library loading issue on API level 22 and below (#2178)
This change fixes #2176
2020-02-27 11:30:47 -08:00
Philip Rideout
ba4c9dbd09 Vulkan: use GENERAL layout for render target textures.
This fixes the validation error that occurs when rendering to one
miplevel while sampling from another. It might even be faster since
fewer layout transitions are required.
2020-02-27 09:33:38 -08:00
Mathias Agopian
4e9cf8ac02 Fir a deadlock when exiting on MacOS (GL backend)
Closes #2159

There was two issues:
1) Fence::wait would return prematurely when the the timeout was
   set to WAIT_FOREVER.

2) (At least) when running from the command line, events were not
   read from the main queue. Instead we have to use NSRunLoop instead
   of NSApplication APIs.
2020-02-27 09:33:14 -08:00
Romain Guy
108dae11e9 Add ground shadow option to gltf_viewer (#2174)
* Add ground shadow option to gltf_viewer

The shadow is always positioned at the bottom of the loaded object's
bounding box to ground it perfectly.

* Remove unused include
2020-02-26 17:09:31 -08:00
Benjamin Doherty
16de98291f Fix Metal filtering bug 2020-02-26 16:00:01 -08:00
Benjamin Doherty
547f8917b4 Update comment 2020-02-26 15:58:16 -08:00
Benjamin Doherty
f1da2ca643 Update RELEASE_NOTES 2020-02-26 15:58:16 -08:00
Benjamin Doherty
9e6ea9454f Refactor depth variant 2020-02-26 15:58:16 -08:00
Pixelflinger
fcd7e198c2 First step in reworking how rendertargets work in the framegraph
The ultimate goal is to get rid of the concept of render targets in
the framegraph, and this is the first step. Here RenderTarget doesn't
store the discard flags anymore. These flags are now calculated
per-resource, per-pass.

A side effect of this change is that the discard flags are now slightly
better, as they don't contain attachments that don't exist.
i.e. we won't see the STENCIL flag set for instance.
2020-02-26 15:57:42 -08:00
Pixelflinger
82523bd1d3 Add support for MRT to the backend
- this simply changes the createRenderTarget() API to take an
  'MRT' structure for the color attachment. The MRT structure is
  just a wrapper around an array of four TargetBufferInfo.

- in this PR only implemented for OpenGL
2020-02-26 11:39:57 -08:00
Romain Guy
4ec5fac95c Add support for KHR_materials_clearcoat to gltfio (#2169) 2020-02-26 10:11:34 -08:00
Pixelflinger
7fb3810eb1 cleanup command stream parameter passing
- the tuple<> where we store the parameters should only remove the
  reference, but not decay, so that arrays could theoretically
  be stored (more on this below).

- use std::forward<> instead of std::move<> in Command's ctor, this is
  more appropriate, we just want to forward the arguments unchanged.

- add std::move() to all parameters on the command stream stub, it is
  appropriate here, because we receive parameters by value or r-value 
  references.

All this was an attempt to support C-style arrays as parameters, but
it doesn't work because they are decay'ed to pointers when they
appear as parameters.
2020-02-25 21:29:59 -08:00
Romain Guy
ed2fe83491 Update cgltf to latest (#2168) 2020-02-25 19:21:48 -08:00
Philip Rideout
3fd9c49fb9 Update WebGL docs and website. 2020-02-25 13:50:34 -08:00
Philip Rideout
69c0843d20 MaterialInstance refactor duplicated code. 2020-02-25 13:43:32 -08:00
Philip Rideout
3f7ef9738d Fix regression with getDefaultInstance().
This caused color writes to be disabled in our "hello triangle" samples.

Fixes #2164.
2020-02-25 13:43:32 -08:00
Romain Guy
3cfc6981a4 Only build OpenGL and Vulkan shaders in Android samples 2020-02-25 10:24:25 -08:00
Romain Guy
8b2ea72be2 Fix emissive in unlit shaders
This change applies exposure compensation just like with
lit shaders.
2020-02-25 09:47:06 -08:00
Romain Guy
8eaa1f5e88 Add options to skip samples (#2163)
-DFILAMENT_SKIP_SAMPLES=ON with CMake
-Pfilament_skip_samples with gradle

This change also renames CMake options specific to Filament
to avoid clashes with subprojects.
2020-02-24 18:15:33 -08:00
Pixelflinger
c72f622a87 Minor changes to SAO
- minor uniform optimizations (saves ~0.1ms)
- fix some missing highp precision qualifers
- make it easier to tweak the blur filter
- make sure samples's radius goes from 0 to 1
- update comments
2020-02-24 18:06:49 -08:00
Ben Doherty
8a0505eb6f Fix Metal crash on Catalina (#2161) 2020-02-24 17:18:43 -08:00
Romain Guy
799e837f35 Upgrade to latest AGP 2020-02-24 12:28:29 -08:00
Philip Rideout
4690ce5602 WebGL: Improve the callback API for glTF.
After the native async functionality landed, there was no way for web
clients to be notified that the decoding has finished. This PR changes
the existing `onDone` callback so that it gets called after all textures
have been decoded. (Previously it was called after downloading rather
than decoding.)

This has the side effect of simplifying the API because clients no
longer need to call a finalize function.
2020-02-24 11:38:55 -08:00
Philip Rideout
e972126cea Add missing TypeScript declarations.
This patches up all the holes discovered when I tried porting the
fidelity tests in `model-viewer` to our TypeScript declarations.
2020-02-24 09:35:22 -08:00
Mathias Agopian
db40fd8983 More accurately evaluate the size of MSAA textures 2020-02-22 00:18:30 -08:00
Mathias Agopian
c2db7b8afd fix a crasher when enabling bloom from java 2020-02-21 16:55:59 -08:00
Philip Rideout
f403876784 Fix JNI signature for RenderTarget API.
Fixes #2151
2020-02-21 15:08:47 -08:00
Mathias Agopian
3a9d4c7c77 Another SSAO optimization saving another ~16%
During the SSAO pass, we pack the decoded depth to the GB channels of
the AO texture, which reduces our bandwidth requirements during the
blurring pass, as well as some ALU usage.
It puts SSAO at about 2ms on pixel4/1080p.
2020-02-21 14:15:06 -08:00
Mathias Agopian
e737ece570 rollback misguided "optimization"
use gpu's sin/cos instead of approximation
2020-02-21 14:15:06 -08:00
Philip Rideout
948d19c446 Fix typo in upload script. 2020-02-20 16:31:57 -08:00
Philip Rideout
ee81c9516a gltfio full flavor should use the old aar and maven names.
This should fix the Android build break. We do not want to change the
maven package name for existing gltfio clients.
2020-02-20 15:05:31 -08:00
Pixelflinger
675012a2eb Added a quality level parameter for SSAO
Currently it only selects how many samples are used.
Low,medium,high and ultra respectively map to 7,11,16 and 32 samples.
The default is "low", which is sufficient for most mobile applications.
2020-02-20 11:26:10 -08:00
Pixelflinger
31a4ef10e1 Use a smoother falloff function.
The improvement is really subtle, it makes the SSAO effect a bit 
softer.
2020-02-20 11:26:10 -08:00
Philip Rideout
a0d43d51c9 Add gradle flavor for gltfio-lite.
This cribs the strategy from filamat-lite and also fixes a "more than
one file" gradle error.
2020-02-20 09:45:33 -08:00
Philip Rideout
31035d2b3c Optimize filament-utils (230 KB => 190 KB). 2020-02-20 09:45:33 -08:00
Mathias Agopian
4e8f323e47 Reduced AO processing time by 1/3
This is achieved by computing a small 2x2 box blur in the AO pass
taking advantage of quad shading, which allows to halve the size
of the bilateral blur kernel.

Reducing the size of the blur kernel has a side effect to kick Adreno
gpu into direct mode, which apparently is much faster here.

Overall we go from 3.4ms to 2.4ms on Pixel4.

The quality is impacted, but not severely. This probably assumes 
GPU that have working derivatives.
2020-02-19 22:09:53 -08:00
Pixelflinger
4dd3d7ab5e Greatly improve SSAO quality by using better samples
The power parameter now really controls the contrast. It's default value
is now 1, instead of 0.
2020-02-19 22:09:53 -08:00
Mathias Agopian
63a7bf5ee9 tweak SSAO
- got rid of all the precomputed samples for now, it makes things
  much more simple, and actually doesn't slow things down. Use the
  analytic offsets (spiral) instead.

- use textureLod instead of texelFetch in places where we need to do
  how own clamping, turns out it's faster (as measured on pixel4).

- use a interleaved gradient noise instead of a hardcoded blue noise,
  the difference isn't big.

Overall we're actually 0.2ms faster out of 3.5ms. It's not immediately
clear why, might just be noise.
2020-02-19 22:09:53 -08:00
Romain Guy
0473da9f05 Add support for ccache (#2148)
* Add support for ccache

To benefit from ccache, first install ccache (for instance with
brew install ccache on macOS). On my machine a clean build takes
~5 minutes the first time. A second clean build with ccache enabled
takes 34 seconds.

* Enable more aggressive caching
2020-02-20 11:36:36 +09:00
Pixelflinger
e5447f7417 Cleanp-up PostProcessManager a bit 2020-02-19 14:41:00 -08:00
Ben Doherty
62810d8c87 Rework array texture support (#2136) 2020-02-19 10:52:12 -08:00
Philip Rideout
ca81d48432 gltfio-lite: add BLEND material
This increases the size to 538K.
2020-02-18 11:55:47 -08:00
Philip Rideout
b9c857130a Introduce gltfio-lite.
This is 466 KB insted of the usual 850 KB. It assumes that users do not
need spec-gloss, non-lit, or a special transparency mode.

(uncompressed SO size on arm64)

We can add a new maven project for this next week.
2020-02-18 11:55:47 -08:00
Philip Rideout
a9bbc6d3c4 Fix syntax error in TypeScript annotations. 2020-02-17 09:26:27 -08:00
Pixelflinger
3a273b1837 fix a typo when thresholding for bloom
- also use step() to implement the threshold
- improve bloomOptions documentation
2020-02-15 22:19:35 -08:00
Romain Guy
5e6ff5a44f Update to a more recent version of AGP 2020-02-14 15:26:05 -08:00
Philip Rideout
65129d1b52 filament-utils-android: fix recent crash regression. 2020-02-14 14:56:38 -08:00
Philip Rideout
54d9d870ee gltfio size reduction 3/3: compile gltfio directly
This takes libgltfio-jni.so from 882 KB to 850 KB
2020-02-14 14:56:38 -08:00
Philip Rideout
ffff6dd580 gltfio size reduction 2/3: proper shared linking
This takes libgltfio-jni.so from 966 KB to 882 KB
This takes libfilament-jni.so from 810 KB to 802 KB
2020-02-14 14:56:38 -08:00
Philip Rideout
dc4a1ed5e5 gltfio size reduction 1/3: add more opt flags
This takes libgltfio-jni.so from 1.5 MB to 966 KB.
2020-02-14 14:56:38 -08:00
Mathias Agopian
8bbf0ce9ef Bloom can now have a dirt texture applied 2020-02-13 20:51:43 -08:00
Romain Guy
a4e4021950 Update README.md 2020-02-13 20:03:51 -08:00
Mathias Agopian
87fe48225f On mobile, use a more efficient up-sampler
This doesn't affect quality significantly, but saves 30% of gpu time
on the upsampling, overall it's about 0.1 ms. This brings The bloom
effect below 2ms on Pixel4.
2020-02-13 17:40:55 -08:00
Ben Doherty
af47fa9b6d Fix incorrect twoPassesOneSide rendering with Metal (#2133) 2020-02-13 17:32:26 -08:00
Mathias Agopian
3de1e197aa improve SSrefr highlights at low roughness
We untonemap/tonemap the first level of blur to reduce the very high
frequencies due to HDR highlights in the image, this produce a softer
image at higher roughness. This can programmatically be turned off,
but that setting is not exposed.
2020-02-13 12:26:25 -08:00
Mathias Agopian
2a1cbe67c6 Improve bloom performance on mobile
The very first downsample stage costs us a lot because it reads from
a full-res texture. We mitigate this by always doing a blit to
1/4 res. Blits are quite a bit faster, this saves about 1ms on
Pixel4.
2020-02-12 17:19:26 -08:00
Mathias Agopian
f57404a3f0 split downsample and upsample passes 2020-02-12 17:19:26 -08:00
Mathias Agopian
87d815c659 Minor cleanup. Add FTexture::maxLevelCount()
We were computing this is many places. Validate better SSAO depth
buffer size.
2020-02-12 17:19:26 -08:00
Mathias Agopian
651ccb183e New mathfwd.h header
math/mathwfd.h forward declares all {mat|vec}{2|3|4}<> classes,
which allows us to remove their respective #include in a lot of
our public headers.
Our math headers are full of templates, so this should help build times
a bit.

Also we want to keep the public headers as minimalist as possible.
2020-02-12 15:30:13 -08:00
Philip Rideout
67406c42ec Clamp viewport width to prevent floating point exception.
To trigger an exception users could either shrink the window or enlarge
the sidebar. Constraining both of these is somewhat tricky so let's
just clamp the viewport width at a low level.
2020-02-12 12:07:51 -08:00
Philip Rideout
cb953b4203 Remove usage of <regex> from Path.
There was actually no need to give special treatment to leading drive
designators since they effectively form the first path segment anyway.
To help prevent regressions, I added a few unit tests in a previous CL.

The motivation for the CL is to remove a dependency on `locale.cpp`,
which can result in shorter build times and reduced binary sizes.
2020-02-12 10:03:06 -08:00
Philip Rideout
c0e2cfb684 Minor enhancements to test_Path. 2020-02-12 10:03:06 -08:00
Philip Rideout
9358c7313e Remove STL from ResourceLoader API. 2020-02-12 10:03:06 -08:00
Philip Rideout
02b377c244 gltfio: remove locale.cpp dependency
For Android and wasm we do not use the filesystem and therefore do not
need `utils::Path`.

```
libgltfio-jni.so BEFORE 1.9 MB (693 KB gzipped)
libgltfio-jni.so AFTER  1.4 MB (542 KB gzipped)
```
2020-02-12 10:03:06 -08:00
Romain Guy
d2287f584a Fix comment 2020-02-11 17:33:56 -08:00
Mathias Agopian
cc94820cb3 clean-up of dynamic scaling code 2020-02-11 16:31:21 -08:00
Mathias Agopian
b17c51e340 Add a threshold option (enabled by default) for bloom.
Threshold can be either on or off, and only thresholds at 1.0 when 
activated (in pre-exposed mode).

This allows to use very high strengths values for the bloom without
softening the rest of the image, and is useful for artistic considerations.
2020-02-11 16:15:04 -08:00
Romain Guy
34dcc90ac7 Save a couple of mul 2020-02-11 16:12:23 -08:00
Mathias Agopian
8a1dc0ac65 Make sure sun in the skybox blooms enough
This is a temporary (hopefully) hack to make the skybox sun look 
better when bloom is enabled (this doesn't affect how the "sun" lights
objects, only how it looks in the skybox).
This scale factor was adjusted empirically.
2020-02-11 16:12:23 -08:00
Philip Rideout
a61bc51271 Add Java bindings for SurfaceOrientation.
Note that libgeometry is already included in `filament-android`, this
simply exposes more of its existing functionality.

The Java version of SurfaceOrientation is similar to the JavaScript
version because we are bundling it into the main Filament package, even
though it is a separate library in C++. This is much simpler than
creating a brand new Java package.

New Android sample that tests this is forthcoming.

Fixes #1729.
2020-02-11 12:38:06 -08:00
Mathias Agopian
bccb8260e2 Implement a Bloom post-process effect 2020-02-11 12:15:57 -08:00
Philip Rideout
bedc609051 RenderPass: remove overrideMaterial. 2020-02-10 17:05:02 -08:00
Mathias Agopian
f1cab9296a Fix a SSRefr when dynamic-scaling is enabled
because the intermediate buffer could have non-square pixels, blurring
the buffer would result in an anamorphic blur.

We fix this by properly scaling the buffer before blurring.
2020-02-10 16:07:40 -08:00
Philip Rideout
4665f6027f Add dynamic raster states to MaterialInstance.
Fulfills a request from tirichards@.

This is similar in some ways to dynamic backface culling but simpler
because there is no interaction with double-sided lighting.

For reference, dynamic backface culling was implemented with #1936, #1877, #1641.
2020-02-10 14:33:14 -08:00
Philip Rideout
891e85ba2b gltfio: add nominal support for flat shading.
This "fixes" the new animated Fox model in the glTF conformance suite.
As per the glTF spec, we now generate per-face normals for the case
where normals are not specified in the model.

Note that true flat shading (i.e. flat interpolation) is not a
requirement in the glTF spec, since some Khronos members advocate for
WebGL 1.0 compatibility.

Fixes #2088.
2020-02-10 14:29:04 -08:00
Mathias Agopian
6957f54547 improve SSRefr roughness with very strong highlight
Chose a filter width that preserve the "gaussianness" of the 
blur filter.
2020-02-10 11:22:15 -08:00
Ben Doherty
48ba111ccc Fix crash in Metal backend with screen-space refractions (#2104) 2020-02-10 10:34:44 -08:00
Philip Rideout
8f2df79a96 gltfio: clean up finalize(). 2020-02-07 18:54:46 -08:00
Philip Rideout
415aeef95b gltfio JNI: fix broken getName() method. 2020-02-07 17:15:28 -08:00
Philip Rideout
cabd9be5f0 ModelViewer now implements OnTouchListener for convenience. 2020-02-07 15:20:41 -08:00
Philip Rideout
45e6e6eb18 sample-gltf-viewer now supports landscape orientation. 2020-02-07 15:20:41 -08:00
Philip Rideout
b89cac48c5 gltfio: fix regression with un-textured renderables. 2020-02-07 09:44:42 -08:00
Mathias Agopian
00d55cddb5 fix screen-space refraction roughness calculation (#2108)
It turns out that textureLod() only reads the base layer if the sampler
is not set to xxx_MIPMAP_xxx. This prevented the gaussian-blur code
to work properly.
Specifically, the horizontal pass would always use the base layer. Not
only this made the blur unstable, but also hurt performance significantly.

With this change, the untonamap/tonemap is no longer needed and the 
results are much more convincing with objects with highlights.
2020-02-07 08:55:23 -08:00
Romain Guy
88dd32b1a7 Add emissive to material_sandbox 2020-02-06 16:20:22 -08:00
Mathias Agopian
20e7acd24d fix a typo in blit post-process material 2020-02-06 15:32:25 -08:00
Romain Guy
9be871f14b Don't use a LOD bias but a specific LOD in SSAO code 2020-02-06 15:31:33 -08:00
Pixelflinger
0b358081c3 make the gaussian blur pass more generic
the input and output are now separate (don't need to be the same
texture)
2020-02-06 14:37:04 -08:00
Mathias Agopian
d172ae78fd minor improvements to SSRef code 2020-02-06 13:05:25 -08:00
Pixelflinger
5f1c9bc41b More comments and small bug fixes regarding MSAA
- always take the "blit" path (rather than quad path) when MSAA
  and is on. we now rely on the render target to have been resolved
  into its texture (implicitly or explicitly). This means in some cases
  there will be 2 bliss in a row -- but that's still better than a
  blit and a quad. These are unavoidable without using a custom resolve.

- removed creating renderbuffer with the EXT_multisampled_render_to_texture
  extension because we didn't support it fully and didn't support
  the fallback mode (for desktop or if the extension is not there).
  Also this case never happens currently.

- added more assert()

- added a bunch of comments explaining the restrictions of using MSAA
  regarding blitting.
2020-02-06 13:05:02 -08:00
Philip Rideout
317d78d7c6 sample-gltf-viewer: enable gzip compression for bin and ktx. 2020-02-05 18:45:30 -08:00
Romain Guy
46090793a8 Fully document refraction properties 2020-02-05 17:45:03 -08:00
Romain Guy
c3a995dd3d Update README.md 2020-02-05 11:01:26 -08:00
Philip Rideout
8020f7eb78 gltfio: add plural version of popRenderable 2020-02-04 12:47:32 -08:00
Philip Rideout
e8e847a662 gltfio: various cleanup in response to PR review 2020-02-04 12:47:32 -08:00
Philip Rideout
d2c883877d gltfio: hide entities with not-yet-ready textures.
This feature adds one new method to `FilamentAsset` and uses it in our
Kotlin, JavaScript, and C++ helpers:

    utils::Entity popRenderable() noexcept;

This pops a ready renderable off an internal queue, or returns 0 if no
renderables have become ready. It provides a simple way for clients to
gradually add renderables to the scene as they become ready. Previously
clients could only get the entire list of entities, regardless of
whether they had Renderable components or complete textures.

To facilitate this feature, this PR adds a new internal-only class to
gltfio called `DependencyGraph`, which is a temporary object used for
bookkeeping during the asynchronous load.

`DependencyGraph` discovers ready-to-render entities by tracking the
textures that each entity depends on. This is a graph because
renderables connect to a set of material instances, which in turn
connect to a set of parameter names, which in turn connect to a set of
texture objects. These relationships are not easily inspectable using
the Filament API or ECS.
2020-02-04 12:47:32 -08:00
Romain Guy
0f7f6f6004 Update to cgltf v1.5 (#2097) 2020-02-04 12:27:38 -08:00
Philip Rideout
ebadf9d6a3 Fix gradle invocation in build.sh for Vulkan. 2020-02-04 11:06:20 -08:00
Philip Rideout
94fb74d6aa Missing backend now throws Java exception, not segfault.
If a client application selects a backend that is not supported by the
build, Engine::create() now returns null, which allows the Java wrapper
to throw IllegalStateException. Prevously, we would crash in the native
layer by hitting a null pointer in Engine::loop().
2020-02-04 11:06:20 -08:00
Mathias Agopian
60b664d3b9 rework refraction filtering/blurring to improve performance
We now use a fixed-size kernel (right now 17), for each mip-level.
And we workout the mapping from roughness to such mip.

This improves performance by reducing significantly the number of taps
per mip, however, we don't control how much blur is actually applied
at each level. This gives a mip-chain that is proportional to
'roughness'.

It's now easier to tune quality vs. speed by tweaking the kernel's width
as well as how we map 'sigma' to a the kernel width.
2020-02-03 11:45:17 -08:00
Romain Guy
eee9249dfc Fix table 2020-02-03 09:35:30 -08:00
Philip Rideout
7f7625b4a0 gltfio internal rename: URL => URI 2020-01-31 09:31:04 -08:00
Philip Rideout
c681cd243a gltfio: Introduce the asynchronous API and use it.
We were already using jobs for decoding PNG and JPEG files, but we were
doing a join. This add three methods to ResourceLoader that allow
clients to amortize the decoding process across multiple frames, even on
single-threaded platforms like WebGL.

This PR adds async loading to the following demos:
- samples/gltf_viewer (now shows a progress bar in the UI)
- android/sample-gltf-viewer
- web/samples/helmet.html

Fixes #1876.
2020-01-31 09:20:48 -08:00
Romain Guy
503e66790b Docs fixup 2020-01-30 17:52:39 -08:00
Romain Guy
a8dc91c238 Update static version of Materials.md.html 2020-01-30 17:46:46 -08:00
Romain Guy
bc554f77f4 Add documentation for refractive materials 2020-01-30 17:43:21 -08:00
brian.wang
dada7332c6 fixed compile error by vs2019 (#2087) 2020-01-30 16:50:23 -08:00
Philip Rideout
02b1d0a950 Add validation to VertexBuffer::build()
Clients should be prevented from allocating unused buffer slots because
uploading to an unused slot triggers undefined behavior in the backend.

Motivated by #2042
2020-01-30 15:25:18 -08:00
Pixelflinger
bcde742bbc Revert "wip: rework filtering"
This reverts commit 79a83e8c46.
2020-01-30 11:37:41 -08:00
Mathias Agopian
79a83e8c46 wip: rework filtering 2020-01-30 11:33:06 -08:00
Mathias Agopian
3d56ff3547 Process SSR buffer in 11.11.10 format
This will help reducing bandwidth requirements while not affecting
quality significantly.
2020-01-30 11:33:06 -08:00
Mathias Agopian
218c3af11b Fix documentation about Camera's field-of-view. 2020-01-30 11:32:46 -08:00
Philip Rideout
ad20a312d6 gltfio: refactor to prep for async API.
This adds most of the asynchronous functionality but does not expose it.
2020-01-30 08:53:01 -08:00
Benjamin Doherty
ad788d6338 Fix some warnings 2020-01-29 13:33:02 -08:00
Benjamin Doherty
02b2b79060 Fix iOS samples 2020-01-29 13:32:45 -08:00
Mathias Agopian
610dca88a3 Remove everything related to the depth-prepass
depth-preass is no longer supported.
2020-01-29 13:32:45 -08:00
Romain Guy
00a6a68b9c Update Gradle plugin 2020-01-29 11:52:20 -08:00
Ben Doherty
7852fd2ffb Build iOS samples during CI jobs (#2076) 2020-01-29 10:59:19 -08:00
Mathias Agopian
ead4b1d222 Stabilize the blur with an invertible tone-mapping
This helps if some refracted objects have very strong highlights.
2020-01-29 10:17:08 -08:00
Mathias Agopian
f290742f1b Screen-space refraction
With this PR screen-space refraction is functional.

Caveats:

The blur passes for supporting rough refractive materials is quite
heavy and increases with the resolution.

SSR uses a gaussian approximation for the brdf and therefore doesn’t
match perfectly cubemap-based refraction and IBL.

The use of MSAA with screen-space effects, while working, is going
to incur a large cost, especially on tilers.
2020-01-29 10:17:08 -08:00
Mathias Agopian
b31f267467 Get one step closer to have screen-space refraction
In this PR we look for object rendered with refraction
(which currently never happens), and split the command buffer into
two passes in that case.
2020-01-29 10:17:08 -08:00
Mathias Agopian
47db11a205 Added a post-process resolve() and blit() utility pass
- resolve can be used when resolving a multi-sample color
  buffer is needed

- quadBlit() can be used to blit a texture using a quad.
2020-01-29 10:17:08 -08:00
Mathias Agopian
b263a89b07 Use SFINAE for Material::setParameter
This gives us a compile time error instead of link-time error, when
using a parameter type not supported. The code is also a bit more
self-documenting.
2020-01-29 10:17:08 -08:00
Mathias Agopian
dbe01d76a2 Minor shader improvement to the bilateral blur 2020-01-29 10:17:08 -08:00
Romain Guy
aa3b0a4e16 Add --single to only edit the first renderable 2020-01-28 17:12:20 -08:00
Philip Rideout
ff66e980eb Add ResourceLoader::hasResourceData. 2020-01-28 14:51:02 -08:00
Philip Rideout
6fbf8a8be0 Fix event pumping with non-owned platforms.
Tested with WebGL and macOS.
2020-01-28 13:39:58 -08:00
Philip Rideout
1452ce62f4 Remove srcDirs hack, use packagingOptions / exclude. 2020-01-28 12:31:14 -08:00
Philip Rideout
d84d095c97 The Android support libs now use dynamic linking.
In my first attempt I kept the multiple project-level dependencies in
each sample's `build.gradle` but that resulted in a gradle error
concerning multiple copies of the same SO file. To work around this
we now append to "srcDirs" to bring in Java dependencies rather than
using project-level dependencies.

The new APK contents are now much more reasonably sized:

    libfilament-jni.so         981 KB
    libgltfio-jni.so           817 KB
    libfilament-utils-jni.so    96 KB

Previously this was:

    libfilament-utils-jni.so    1.8 MB
    libgltfio-jni.so            1.8 MB (unused)
    libfilament-jni.so          1 MB (unused)

Fixes #2070
2020-01-28 12:31:14 -08:00
Philip Rideout
e1b498f82c Repair iOS error due to STBI_NO_STDIO.
Fixes #2072.
2020-01-28 12:26:31 -08:00
Benjamin Doherty
06726fe361 Regenerate Xcode project for hello-ar iOS sample 2020-01-28 11:09:34 -08:00
Ben Doherty
ba3a274357 Fix headers in iOS samples (#2074) 2020-01-28 10:56:28 -08:00
Romain Guy
30a3d31a3d Update README 2020-01-27 13:46:56 -08:00
Romain Guy
191c89c3b1 Exclude .kt files from javadocs 2020-01-27 13:46:25 -08:00
Romain Guy
42b739154e Update Maven library version 2020-01-27 13:30:34 -08:00
Philip Rideout
721a251b34 Bump package.json to 1.4.5 2020-01-27 13:02:19 -08:00
Ben Doherty
1a66f85b67 Update RELEASE_NOTES for 1.4.5 2020-01-27 12:59:35 -08:00
Romain Guy
3bba92f813 Fix build message 2020-01-27 12:03:56 -08:00
Philip Rideout
93c9674e2a Fix WebGL build. 2020-01-27 11:37:17 -08:00
John Davis
a4b879227d fix case sensitivity problem for linux 2020-01-26 19:17:57 -08:00
Philip Rideout
485dfa6cde Fix typo. 2020-01-24 20:51:31 -08:00
Mathias Agopian
3105a8330e remove unneeded includes in public headers
Replace with forward declarations if needed and includes in .cpp that
now need them.
The idea here is to have our headers have the least amount of impact as
possible on our clients (e.g. compilation time).
2020-01-24 12:13:48 -08:00
Mathias Agopian
88e8661bf3 New API to import textures into filament
If you need this, you know who you are.
The new Texture::Builder::import() allows to specify a OpenGLES texture
id from a shared GL context, effectively importing the texture into
filament.
The texture is NOT destroyed when calling Engine::destroy(Texture*), only
its filament handle.
2020-01-24 12:13:20 -08:00
Mathias Agopian
3a9629d93c Fix a NOOP backend threading bug (#2064)
The NOOP backend didn’t call user-API callbacks from the main thread
(instead calling them from the “backend thread”). This caused problems
with unit tests for instance.
2020-01-23 14:55:25 -10:00
Mathias Agopian
29c14b1053 Fix typo in documentation (#2065)
lastest -> latest
2020-01-23 14:55:09 -10:00
Philip Rideout
bd5aeb6b69 Allow non-WebGL builds to disable threads. 2020-01-23 11:06:17 -08:00
Philip Rideout
3674361f20 ModelViewer now automatically detaches. 2020-01-23 09:55:51 -08:00
Philip Rideout
4a29456a7a ModelViewer now works with TextureView. 2020-01-23 09:55:51 -08:00
Philip Rideout
3179a83cfb Android: introduce ModelViewer helper.
This reduces the LOC of our gltf-viewer app from 260 to 146. This could
have been more, but I feel this provides good balance between
flexibility and convenience.

The raw gltfio API involves multiple objects (FilamentAsset,
AssetLoader, ResourceLoader) whereas the ModelViewer has a simple facade
consisting of two methods, one for GLB and one for GLTF. The underlying
gltfio objects are available via non-settable properties.
2020-01-23 09:55:51 -08:00
Ben Doherty
5fe1fe73c4 Use Objective-C availability tests for Metal backend (#2046) 2020-01-23 09:16:19 -08:00
Philip Rideout
5025d8eb6e Remove usage of the invariant keyword. 2020-01-21 14:42:58 -08:00
Philip Rideout
71697b59a3 Disable depth prepass everywhere.
Fixes #737 and #1472. See also #475 and #1295.
2020-01-21 14:42:58 -08:00
Philip Rideout
518ae9658f gltfio + Android: improve memory management.
Add bindings for releaseSourceAsset() and fix a double-free issue.

According to the Android Studio profiler, this makes Java memory usage
go from 18.6 MB to 6.5 MB.
2020-01-21 13:01:55 -08:00
Philip Rideout
41ad8b5c18 Remove unused copy of the parquet PNG. 2020-01-21 12:58:46 -08:00
Philip Rideout
51cef3b5ca WebGL: unify the PNG and JPEG codepaths.
Fixes #2055.
2020-01-21 12:58:46 -08:00
Philip Rideout
491d16a4e5 Exercise JPG decoding in web samples. 2020-01-21 12:58:46 -08:00
Philip Rideout
e752b6fb6f Factor STB config into a header. 2020-01-21 12:58:46 -08:00
Philip Rideout
46bf6fbfdd Simplify sample-gltf-viewer as much as possible. 2020-01-21 12:57:50 -08:00
Philip Rideout
fd5fe3d18d Convert KtxLoader to Kotlin and remove usage of reflection.
Fixes #1510
2020-01-21 12:57:09 -08:00
Philip Rideout
ca2da39614 Migrate TextureLoader to filament-utils. 2020-01-21 07:59:51 -08:00
Philip Rideout
067dad2d38 camutils: rename internal enums. 2020-01-17 11:37:57 -08:00
Philip Rideout
f91a8890a6 camutils: fix bad defaults in Manipulator. 2020-01-17 11:37:10 -08:00
Philip Rideout
dd9b84f06e GestureDetector cleanup. 2020-01-17 10:45:17 -08:00
Philip Rideout
9ac17a88b3 Add new sample for glTF models and the camera manipulator.
This differs from the bloom demo in that it supports touch interaction,
has animation, loads from GLTF rather than GLB, and is overall simpler.
2020-01-17 09:09:46 -08:00
Philip Rideout
9ea8148d84 Add doubles to Manipulator for convenience. 2020-01-17 09:09:46 -08:00
Romain Guy
16c65550bb Fix javadoc syntax 2020-01-16 17:27:06 -08:00
Philip Rideout
961860adee Introduce filament-utils and Java bindings for camutils.
This library houses the KTX loader, camutils bindings, and a Kotlin math
library. More will come later. Sample app is forthcoming.
2020-01-16 16:00:23 -08:00
Philip Rideout
6146b4d2d9 Fix out-of-bounds when glTF has many UV sets.
glTF specifies that client implementations must support at least two UV
texture coordinate sets but does not seem to have an upper limit.

We use a mapping table in order to honor high-numbered UV set indices,
but our mapping table only accomodates 8 entries.

Fixes #2042
2020-01-16 14:09:48 -08:00
Philip Rideout
274cd3a1f3 Refactor some Android build things for gltfio.
We currently use static linking and will continue to do so. This means
that libfilament-jni is a subset of of libgltfio-jni, and libgltfio-jni
will become a subset of the upcoming libutils-jni.

This is a simple layer cake, but requires adding some CMake logic to the
gltfio-android CMakeLists, similar to what we already did for the
filament-android CMakeLists. This prevents an obscure CMake error about
duplicated build artifacts.

Also, previously we required clients to call AssetLoader#init(), this
is now renamed to Gltfio#init(), which is more consistent with
Filament#init().
2020-01-16 10:11:36 -08:00
Romain Guy
762e8b8b6a Add more control to surface ordering (#2041)
When UiHelper is set to translucent with setOpaque(false), the
target SurfaceView's surface is set to be composited on top of
the activity's window. There are situations however where one
may want to render regular Views on top of the SurfaceView.

The new setMediaOverlay() API allows exactly that: when this
property is enabled, rendering to a translucent target will
cause the SurfaceView's surface to be composited above other
surfaces, but below the activity's surface.
2020-01-16 10:00:26 -08:00
Philip Rideout
a5a6e9be8a Add animated GLTF model to third_party.
This asset will be used in an upcoming Android sample. I converted the
textures from PNG to JPG to reduce the footprint.
2020-01-15 16:56:46 -08:00
Philip Rideout
4ab65975f4 Update Android Studio required version. 2020-01-15 11:22:57 -08:00
BStringhamVRSK
041f26a7c5 Implemented sRGB support for DXT encoded textures (#2026)
* Added sRGB support for DXT compressed textures - OpenGL

* Added sRGB support for DXT compressed textures - Vulkan and Metal

* Added detection if OpenGL driver supports sRGB compressed textures (EXT_texture_sRGB extension)

* Fixed whitespace to use spaces rather than tabs

* Test for GL_EXT_texture_sRGB or GL_EXT_texture_compression_s3tc_srgb support for sRGB DXT compressed textures

* GL ES uses GL_EXT_texture_compression_s3tc_srgb instead of GL_EXT_texture_sRGB
2020-01-15 10:26:29 -08:00
Mathias Agopian
b351e709c1 Framegraph improvements
- added a way to compare two handle's underlaying resource
  (i.e. do they refer to the same resource)

- minor refactoring and comment fixes
2020-01-15 10:22:10 -08:00
Mathias Agopian
fbad683810 Implement a "black board" for the framegraph
FrameGraph always keeps a default Blackboard, but additional ones 
can be created if needed.

A blackboard is just a registry of FrameGraphHandles, queryable by name.
2020-01-15 10:22:10 -08:00
Philip Rideout
2854c0627d camutils: add support for Builder pattern.
This makes the upcoming Java bindings simpler and improves parity with
existing API conventions.

Note that camutils does not depend on filament and therefore cannot use
BuilderBase.

Note that the Manipulator Builder state is public which breaks with
convention but makes implementation simple and allows C++ clients to
continue using modern initializer syntax if they wish.
2020-01-14 15:26:22 -08:00
Mathias Agopian
c5fa6fe7f2 More fixes to sampled textures in the framegraph
The main purpose of this change is to fix a problem where a resource
marked as sampleable by a *culled* pass would stay sampleable.
This happened because the sampleable state was tracked on the resource
itself.

We fix this by treating sample() just like read(), such resources are
added to an array living in the pass, which ensures the state is correct
when passes are culled.

Also fixed:
- simplified read() code a bit (minor)
- simplified resource aliasing code
- don't resolve() renderTargets of culled passes
2020-01-14 11:16:34 -08:00
Mathias Agopian
40c7232bb2 revert part of a recent TransformManager change
setParent() is not supposed to reorder child/parents in the array
because it doesn't rely on them being orderer. This also has the
advantage of not invalidating Instances.

However, commitLocalTransformTransaction() does rely on child/parent
ordering and the previous change did fix that.
2020-01-14 11:16:07 -08:00
Ben Doherty
59e3465b6b Update Assimp to 5.0.1 (#2027) 2020-01-13 15:00:27 -08:00
tpsiaki
2c591d2dca Correct out-of-order transform instances (#2025)
The current code only updates the order in the transaction commit if there's a single out-of-order node in the scene graph, but if multiple are out of order (or one swap doesn't fully fix the ordering), then we end up with out of order scenes, and incorrect world transforms.

Additionally, when nodes are reparented outside of a transaction, the order is not updated.
2020-01-13 13:22:49 -08:00
Mathias Agopian
4673545f45 Fix a multisample related bug in the FrameGraph
The FrameGraph would erroneously specify a sample count on textures
that are sampleable and used as an attachment to a multisampled 
target -- however, that's not allowed.

We didn't run into issues, because had a workaround for this when
creating the texture. This is augmented by an assertion.
2020-01-13 11:29:14 -08:00
Mathias Agopian
4703a45ff5 Ensure we don't use RTTI when not available
also don't implement the graphviz export in release builds.
2020-01-13 11:28:50 -08:00
Mathias Agopian
35aabd5e44 Fix a couple minor issues in the OpenGLES backend
- we were not unbinding the renderbuffer int the right place,
  when it's created, instead we were doing that when using it the 
  first time. Unbinding soon makes sense because we never need to
  rebind it after that.

- in debug builds we were clearing render targets at creation time,
  but this was wrong because a render target won't necessarily be written
  (it could be used as the source of the blit for instance).
  This didn't cause any trouble in the framegraph, by chance, it was smart
  enough to reuse existing render targets in the case of blitting.
  Ideally we'd clear textures/renderbuffer at creation time,
2020-01-13 11:28:50 -08:00
Mathias Agopian
118944be9a Improve/simplify OpenGLDriver a bit
merge frameBufferRenderbuffer() and framebufferTexture() because
the filament API doesn't have a distinction. This actually removes
quite a bit of code too.
2020-01-13 11:28:50 -08:00
Mathias Agopian
8e1ecbb0ea Minor FrameGraph improvements
- write() is marked as [[nodiscard]] since it's
  generally an error to discard it

- graphviz export not display wether a texture resource is
an actual texture or renderbuffer
2020-01-13 11:28:50 -08:00
Romain Guy
00ba8c09f8 Rewrite Maven publish tasks to support multiple flavors (#2022)
* Rewrite Maven publish tasks to support multiple flavors

* Don't build filamat with an unused CMake option

* Don't compiler debug in release mode

* ... for real

* Link to BUILDING.md
2020-01-10 18:02:46 -08:00
Philip Rideout
15b071acaa gltfio: support external resources on Android.
This was untested because our only glTF Android sample uses glb instead
of JSON. We will soon be adding a new Android demo that uses an actual
gltf file.

This fixes #1841.
2020-01-10 09:15:38 -08:00
Romain Guy
aa3dfb9a4b Revert "Disable filamat-android's flavors for now"
This reverts commit 95e22d878a.
2020-01-09 19:17:50 -08:00
Romain Guy
95e22d878a Disable filamat-android's flavors for now 2020-01-09 17:49:30 -08:00
Philip Rideout
4f8c495563 Another gltf_bloom fixup. 2020-01-09 14:31:43 -08:00
Romain Guy
1d6ea1db0f Update README.md 2020-01-09 14:23:41 -08:00
Romain Guy
393cc5c634 Update README 2020-01-09 14:23:05 -08:00
Philip Rideout
34c2772a60 Remove unused source file. 2020-01-09 14:10:33 -08:00
Philip Rideout
4d258ab5e8 Remove a build output file. 2020-01-09 14:07:20 -08:00
Philip Rideout
a306f9074a Clean up gltf-bloom to prep for new gltf-viewer app.
This renames the app namespace and removes the unused Io file.
2020-01-09 13:49:24 -08:00
Philip Rideout
6e30566363 Bump version number in package.json 2020-01-09 12:33:17 -08:00
Romain Guy
2908224c95 Filament 1.4.4 2020-01-09 12:19:05 -08:00
Romain Guy
e011853e7e Update androidx.annotation to 1.1.0 2020-01-09 08:55:43 -08:00
Romain Guy
104105c937 Fix the build 2020-01-08 18:01:18 -08:00
Romain Guy
3fa98419a6 Add more .gitignore 2020-01-08 17:59:49 -08:00
Romain Guy
44d08ce41e Fixup javadocs 2020-01-08 17:55:17 -08:00
Mathias Agopian
0a1c1be00e Refactoring to allow rendering multi-pass rendering
specifically into the same render target.
2020-01-08 16:10:09 -08:00
Mathias Agopian
7efd7abffe Don't combine clearFlags when retrieving a rendertarget
Instead we use the clear flags that the user specified. This is needed
in the case where we're rendering in the target in two passes, the
first pass might want to clear the buffers, while the 2nd one will not.
If we were combining the clear flags, the first pass's flags would be
sticky and the view would always be cleared.

If combining is needed it must be specified by the user.
2020-01-08 16:10:09 -08:00
Mathias Agopian
e27158507e refactor Renderer to make it more flexible
This is in preparation to supporting screen-space effects.
There are two major changes:

- RenderPass is now copiable and intended to be passed by copy to
  the execute stage of frame graph passes

- The color pass is in its own function now


This actually simplify RenderPass api.
2020-01-08 16:10:09 -08:00
Romain Guy
d9ee2fa10d Use a proper Gradle plugin to generate Filament assets in samples (#2018) 2020-01-08 15:45:44 -08:00
Mathias Agopian
b30a7aa5a2 Make ResourceAllocator mockable and update test
We have one very important unit test that is supposed to make sure
the framegraph reuses the same rendertarget between 2 passes, this
unit test would always succeed when using the NoopDriver.
Now that we can mock the ResourceAllocator, we can ensure this unit
test is doing its job.
2020-01-08 15:39:40 -08:00
Mathias Agopian
34c1aaac18 improve cmgen prefiltered cubemaps
Rotate the sample pattern at every light direction, which trades
aliasing for noise (which is arguably more pleasant) for IBLs with
very high frequency (i.e. high level of HDR-ness).
2020-01-08 15:39:21 -08:00
Ben Doherty
8dbb4c6b7e Add new heightfield sample (#2004) 2020-01-08 11:55:28 -08:00
Romain Guy
f5d5afba74 Re-organize Android Gradle files (#2013)
* Re-organize Android Gradle files

Clean up our Gradle files, share versioning, etc. and prepare for
publication to sonatype.

* Use androix annotations for desktop

* Add samples as subprojects to root Gradle

* Fix build script

* Don't break when samples aren't compiled

* Better organize the Android Studio project
2020-01-07 18:37:45 -08:00
Philip Rideout
e09f0bb99f Repair gradle IBL path for gltf_bloom.
I broke this when I changed the cmgen KTX behavior.
2020-01-07 14:05:40 -08:00
Mathias Agopian
fddf51dc74 cmgen -d would force importance sampling mips generation 2020-01-06 17:43:11 -08:00
Mathias Agopian
b8d4b981e0 Better roughness remapping and comments
We were conflating two concepts in our comments about the roughness
remapping, which was confusing. Also changed the remapping so it 
matches a log2 mapping in our default configuration.
2020-01-06 17:42:56 -08:00
Daniel Lehmann
892302442f Fix Backend enum in Java to be consistent with C definition (#2006)
The C definition was changed to include METAL, moving NOOP further down.
The Java definition never caught up, making NOOP mean METAL and making the
real NOOP unreachable.

This patch puts them back in sync. Also, updated the Java comments to match
the comments from the C definition.
2020-01-06 16:27:15 -08:00
Philip Rideout
39046ddfe1 camutils: fix MSVC error. 2020-01-06 16:12:05 -08:00
Philip Rideout
ac14074bc4 camutils: flip zoom to match old manipulator. 2020-01-06 16:12:05 -08:00
Philip Rideout
7d548151d7 Introduce camutils library.
This moves the camera manipulator into its own library and adds new
functionality including a new "Google Maps" manipulator and a bookmark
feature to facilitate camera animation.

Java bindings and an Android sample will land later this week.
2020-01-06 16:12:05 -08:00
Philip Rideout
898ed70aa0 Remove <iostream> from math headers.
This speeds up our build time by using <iosfwd> and un-inlining the
vector print functions.
2020-01-06 15:09:06 -08:00
Romain Guy
78842b59c9 Only build FBX and OBJ importers (#2003) 2020-01-06 14:38:32 -08:00
Ben Doherty
f4f4f9ccd5 Implement flush for Metal backend (#1999) 2020-01-06 12:28:11 -08:00
Mathias Agopian
2ef9d72dbd Simply refraction code
This makes it easier to add new shapes and experiment.
Added a "sold box" shape that is not used yet.
2020-01-06 11:33:06 -08:00
Tim Psiaki
b030f67eb7 Make EntityManager and Panic dynamic-linkable. 2020-01-06 10:24:17 -08:00
Romain Guy
8380a87a6e Update HTML docs 2020-01-05 11:44:45 -08:00
Philip Rideout
06b9bb0c34 gltfio: honor node labels if they exist.
In glTF, multiple nodes can refer to the same mesh, and each node can be
assigned a unqiue string label. Previously we used NameComponentManager
to annotate entities with mesh labels rather than node labels. This was
wrong because Filament entities are 1:1 with nodes, not meshes.

We still fall back to mesh labels when node labels are not provided.
2020-01-03 10:13:59 -08:00
Philip Rideout
17893ecefd Repair Android extension pointers.
Fixes #1989 by fetching extension function pointers that were refactored
in #1977. Moved string-splitting utility to a common location so that
the base class and concrete classes can both use it.
2020-01-03 07:16:56 -08:00
Ben Doherty
efc1b01901 Respect colorWrite in Metal backend (#1996) 2020-01-02 13:36:59 -07:00
Ben Doherty
88fa93f1de Add support for ASTC textures on iOS / Metal (#1992) 2020-01-02 11:35:23 -07:00
Ben Doherty
36385a2432 Improve Metal textures (#1991) 2019-12-30 11:15:04 -07:00
brian.wang
1e05327c5d Fix compile error for VS 2019 16.4.2 with Vulkan (#1990) 2019-12-27 10:44:24 -07:00
Philip Rideout
0b7a08a2d8 Repair web samples by fixing typo in previous fix. 2019-12-18 18:06:21 -08:00
Philip Rideout
237e0ee367 Revert "Revert "gltfio: enable specular AO to "fix" #1870""
This reverts commit f9230856af.
2019-12-18 13:56:13 -08:00
Philip Rideout
f9230856af Revert "gltfio: enable specular AO to "fix" #1870"
This reverts commit 9bf9c3a439.
2019-12-18 13:17:52 -08:00
Philip Rideout
9bf9c3a439 gltfio: enable specular AO to "fix" #1870 2019-12-18 13:07:05 -08:00
Philip Rideout
25c4efd2db cmgen: do not create useless folder for KTX files
With KTX, we should simply create the specified output folder and put
the KTX file(s) in there. There is no need to create a subfolder of the
output folder.

This change also allows users to pick a custom name for their KTX file,
because we only use the "deployment" name when generating filenames.
2019-12-18 13:03:02 -08:00
Ben Doherty
8f6f0ef511 Add continuous build artifacts (#1978) 2019-12-16 10:38:57 -08:00
Pixelflinger
a924fbb490 Better roughness remapping for IBLs
This greatly improves the quality of semi-rough
materials.
2019-12-14 16:36:58 -08:00
Philip Rideout
4c01dfc9fd macOS: fix flash of red upon resize.
Previous to this change, we suffered from a flash-of-red followed by a
flash-with-wrong-projection every time we resized an OpenGL window.

SDL throttles the window resize events, so FilamentApp updates the View
only on the final low-level resize event. However we were calling
Cocoa's update method on every low-level resize event. Thus we were
showing uninitialized content during the resize.

FilamentApp recreates the SwapChain after the final resize event; one
reason for this is the fact that Vulkan swap chains must be recreated.

The fix is to defer the Cocoa update until the swap chain gets
recreated. This is the perfect time because FilamentApp has already set
the new Viewport at this point.
2019-12-14 09:29:35 -08:00
Mathias Agopian
5ee15239fd Split Android specific code out of PlatformEGL (#1977)
We now should be able to use PlatformEGL for all generic EGL platforms
(not tested though). Most texture streaming operations are not supported
in that case, since they're platform specific.
2019-12-13 14:23:19 -08:00
Philip Rideout
69d36b0226 WebGL: fix usage of direction estimator. 2019-12-13 12:46:11 -08:00
Philip Rideout
87db1aaa57 WebGL: remove old broken test. 2019-12-13 12:46:11 -08:00
Philip Rideout
5e096de534 Disable rounding FBO sizes on WebGL. 2019-12-13 12:46:11 -08:00
Philip Rideout
97d53bf7e9 Remove warnings about deadlock. 2019-12-13 10:25:38 -08:00
Philip Rideout
6fbc690097 macOS: pump the event queue while waiting. 2019-12-13 10:25:38 -08:00
Jordan Rupprecht
311f6eacd7 Add missing <assert.h> include. (#1969)
An version of clang is smarter about generating warnings for template code. `assert` here is not included, so clang generates: `error: use of undeclared identifier 'assert'`
2019-12-13 09:26:02 -08:00
Ben Doherty
0dee8c5f34 Deprecate Kokoro-specific logic from build scripts (#1973) 2019-12-12 13:23:43 -08:00
Philip Rideout
ddf85bae72 CMake: add a convenient "run" target for quick testing.
This is just a shortcut for building gltf_viewer, then immediately
running it, which is something we do a lot.
2019-12-12 13:12:23 -08:00
Pixelflinger
695d61f87c fix CubemapUtils::processSingleThreaded()
the state wasn't initialized from the user given prototype
2019-12-11 15:26:12 -08:00
Philip Rideout
9584371f89 macOS: add a check for "is this the right view?" 2019-12-11 14:49:23 -08:00
Philip Rideout
509bfb5b5e Add warnings (hopefully temporary) about macOS deadlock. 2019-12-11 14:49:23 -08:00
Philip Rideout
f853b7dc40 macOS: add cleanup for observer. 2019-12-11 14:49:23 -08:00
Philip Rideout
0693a97577 macOS: fix window resizing regression. 2019-12-11 14:49:23 -08:00
Romain Guy
8e00df1de5 Add Color::absorptionAtDistance() to compute absorption for refraction. (#1964)
Specifying the transmittance color at a specific distance is more
user-friendly than specifying absorption coefficients directly.
2019-12-10 18:20:23 -08:00
Philip Rideout
28f0536b31 Repair JavaScript bindings for IndirectLight. 2019-12-10 18:19:38 -08:00
Mathias Agopian
639bfbfc9a Fix SSAO when blending is used
When doing the depth path for ssao, we need to remove the blended
objects, i.e. produce a depth path similar to the regular depth prepass.

We also need to clear the SAO buffer. It's not needed for opaque
objects because they are written in the SAO's depth buffer. This fixes
"ship in a bottle" scenario.
2019-12-10 17:53:02 -08:00
Philip Rideout
0c734d6db0 Simplify PlatformCocoaGL. 2019-12-10 17:19:41 -08:00
Philip Rideout
e0f5b5125c Fix Catalina by moving some calls to the UI thread.
Fixes #1839.
2019-12-10 17:19:41 -08:00
Philip Rideout
28065e36e8 Make builds less verbose.
Fixes #1956.
2019-12-10 17:19:06 -08:00
Mathias Agopian
8088f0cd6f fix android samples
these samples broke with the new 5 lods ibls
2019-12-10 16:56:19 -08:00
Mathias Agopian
36cdadd238 fix gltf_viewer calculated light position/intensity 2019-12-10 14:44:23 -08:00
Ben Doherty
1061d5c5fa Fix MSVC 2019 16.4 build (#1943) 2019-12-10 13:34:48 -08:00
Mathias Agopian
c1bd438d89 temporary workaround for build break 2019-12-10 12:26:52 -08:00
Pixelflinger
dd8c0a759f Improve IBL's diffuse
If spherical harmonics are not specified in IndirectLight (i.e. 
omitted entirely), we instead use the roughness==1 LOD in the shader.
This produce much better results with absolute HDR environment, and 
generally works better more often.

This is now the preferred solution.

For cases where spherical harmonicas are better or preferred, they
can simply be supplied as before.
2019-12-10 12:26:52 -08:00
Mathias Agopian
0f16f3177e some cmgen fixes
- support equirect/octahedron save in more cases
- apply 1/pi when rendering SH so it's easier to compare 
  (this is used only for debugging anyways)
2019-12-10 12:26:52 -08:00
Ben Doherty
acc2fd9c94 Add depth32 fallback for GPUs without packed depth support (#1957) 2019-12-10 12:23:17 -08:00
Romain Guy
8feb842717 Ignore metallicness when refracted objects don't specify reflectance
Metals need a complex IOR but we only accept a scalar IOR.
2019-12-10 11:56:00 -08:00
Romain Guy
f19eaaa557 Fix directoy based cubemap loading 2019-12-10 10:03:56 -08:00
Romain Guy
3fa0c2d18b Add refraction to material_sandbox 2019-12-10 09:51:54 -08:00
Mathias Agopian
9393e1369b don't apply roughness remapping for solid refraction
The thin roughness remapping only makes sense for thin surfaces, it was
a mistake to apply it to solids. It assumes that a ray will go
undisturbed though the thin surface with an ior of 1.
2019-12-10 00:02:17 -08:00
Ben Doherty
8342b0ecec Update Windows READMEs for building with VS2019 (#1952) 2019-12-09 17:09:45 -08:00
Ben Doherty
9a291b6543 Refactor Metal buffers, allow in-frame vertex and index updates (#1950) 2019-12-09 15:54:40 -08:00
Romain Guy
ec403f8940 Fix material_sandbox 2019-12-09 13:37:09 -08:00
Mathias Agopian
047dab769d fix unit tests 2019-12-09 13:24:49 -08:00
Philip Rideout
5d8cd288d3 Fixed formatting in release notes. 2019-12-09 12:42:17 -08:00
Philip Rideout
8a63682382 Remove unused includes. 2019-12-09 12:41:02 -08:00
Philip Rideout
036f151a42 WebGL: enable depth buffer in swap chain.
In PR #1906 we enabled depth for all backends, but we forgot web.

Note that this required 0 new codelines whereas Vulkan required 116
additional codelines. :)
2019-12-09 10:18:23 -08:00
Ben Doherty
5bc1356192 Update RELEASE_NOTES.md 2019-12-09 10:01:25 -08:00
Ben Doherty
c04a111d10 Fix froxel coordinate calculation on Metal and Vulkan (#1934) 2019-12-09 09:57:59 -08:00
Philip Rideout
da5eabc91f Fix bad state after setIndirectLight(null).
This cleans up 3 related issues, but only the first of these caused an
actual user-visible bug:

(1) When the IBL was null, prepareLighting was failing to bind the black
1x1 texture.

(2) If you added and removed an IBL from a Scene, then Scene was not
returned to its initial state.

(3) The default 1x1 IBL used an intensity of 1 rather than 30000, which
is inconsistent with the null IBL.

Fixes #1940.
2019-12-09 09:30:59 -08:00
Mathias Agopian
79f8947bfa Improve thin layer refraction
We now take into account the light bouncing between the two interfaces
of the materials. We can do this because we assume thin surfaces, 
meaning that the light will exit where it entered and with the same
direction that the specular.

This strengthen the specular at grazing angles (and reduces the transmission).
2019-12-08 22:18:18 -08:00
Mathias Agopian
160a22519e Use unclamped roughness for IBls
This allows us to have sharp reflection and refraction -- the later
is very important.
2019-12-08 22:18:18 -08:00
Mathias Agopian
cc9a1d446c added the concept of micro thickness for thin objects
When dealing with thin objects we really have two thicknesses to 
consider, the thickness in the direction of the normal, which 
corresponds to the value used for solid objects, and the thickness of
the object's walls, which generally is a constant.

Reusing thickness in the later case is problematic for assets that have
a thickness map, but are rendered hollow.

In the future we can even imagine handling double-sided hollow objects
by using the thickness information -- e.g. a hollow cube.
2019-12-08 22:18:18 -08:00
Mathias Agopian
b78ea90c27 apply thin roughness remapping to solid as well
this is because for solids we're also handling both interfaces in one
go (as opposed to calculate the actual btdf), and roughness should
depend on the ior.

Also rename some variables for less confusion (we now use 
incident(I)/refracted(R)).
2019-12-08 22:18:18 -08:00
Mathias Agopian
cbb5d2b423 fix typos and rename refraction to refractionMode 2019-12-08 22:18:18 -08:00
Pixelflinger
c759743e40 Don't saturate absorption, unless it's a constant
Update documentation.
2019-12-08 22:18:18 -08:00
Pixelflinger
3b2ecc6003 Fix a material compiling issue when thickness wasn't defined
We also now assume a thickness of 0, if it's not set in the material.
We don't want to assume any particular thickness, because it depends
on the scene's scale.

Also clamp the remapped roughness.
2019-12-08 22:18:18 -08:00
Mathias Agopian
4790cb5009 Allow materials to override the IOR
Normally the IOR is deduced from the reflectance, but now we allow to
specify the IOR instead or in addition to the reflectance.
In the later case, it's possible to create physically impossible
materials, but this can be useful for artistic reasons.
2019-12-08 22:18:18 -08:00
Pixelflinger
ee0080487a finish plumbing for new material parameters 2019-12-08 22:18:18 -08:00
Pixelflinger
f70b820cbe update material documentation 2019-12-08 22:18:18 -08:00
Pixelflinger
1ccae61d40 shader plumbing for screen-space refraction
In this PR, the filament side is missing, so we're outputting back.
But all codepaths in the shader are implemented:
 cubemap/screenspace, solid/thin
2019-12-08 22:18:18 -08:00
Mathias Agopian
f670472e55 implement thin layers 2019-12-08 22:18:18 -08:00
Mathias Agopian
f94aa731ed Add plumbing for refraction type (solid or thin) 2019-12-08 22:18:18 -08:00
Mathias Agopian
5c80bfe430 update documentations with common IOR values 2019-12-08 22:18:18 -08:00
Mathias Agopian
8d7866b58d apply fresnel to refraction
fixes white furnace test.
2019-12-08 22:18:18 -08:00
Mathias Agopian
179bf03caf implement absorption 2019-12-08 22:18:18 -08:00
Pixelflinger
0371a805ed basic refraction 2019-12-08 22:18:18 -08:00
Pixelflinger
57b48e0719 address reviewers comments
- get rid of "thin layer thickness" property
- make absorption a vec3
2019-12-08 22:18:18 -08:00
Mathias Agopian
eb767abc55 Add material properties needed for refraction 2019-12-08 22:18:18 -08:00
Mathias Agopian
dbda77b091 Improve low roughness significantly
Filament will now allow incomplete mipmap chains for the IBL and
map the roughness to the available chain.

This allows to create roughness cubemaps with a minim size for
roughness==1, instead of always mapping it to 1x1.

cmgen will now use 16x16 cubemaps for roughness==1, which
improves the quality of rough objects significantly.

The beauty of this is that there is no asset or API change. Old assets
will continue to work like before.
2019-12-08 22:17:08 -08:00
Philip Rideout
2c1454270e OpenGL: enable cubemap filtering on desktop.
According to the OpenGL spec, proper cubemap filtering is disabled by
default in non-ES OpenGL.
2019-12-08 22:16:52 -08:00
Mathias Agopian
1ec72e606b Round non-texture FBO attachments to 32 pixels
this helps reducing churn in the resourceallocator cache.
2019-12-06 14:03:07 -08:00
Philip Rideout
24bfdd741a Revert "Fix bad state after setIndirectLight(null)."
This reverts commit f0ce4094dd.
2019-12-06 13:56:21 -08:00
Philip Rideout
f0ce4094dd Fix bad state after setIndirectLight(null).
This cleans up 3 related issues, but only the first of these caused an
actual user-visible bug:

(1) When the IBL was null, prepareLighting was failing to bind the black
1x1 texture.

(2) If you added and removed an IBL from a Scene, then Scene was not
returned to its initial state.

(3) The default 1x1 IBL used an intensity of 1 rather than 30000, which
is inconsistent with the null IBL.

Fixes #1940.
2019-12-06 13:54:49 -08:00
Philip Rideout
9cbcd88d4e WebGL: tweak helmet demo for shadows. 2019-12-06 10:27:00 -08:00
Philip Rideout
8ea6e6ce59 Upgrade hello-camera to use AHardwareBuffer. 2019-12-06 08:46:37 -08:00
Philip Rideout
6d0f8c9ead cmgen: add support for non-RLE HDR images.
The new conditional is cribbed from STB, which checks the first three
bytes.

Fixes #1937.
2019-12-06 08:45:12 -08:00
Philip Rideout
43d91a5c40 Repair twoPassesTwoSides transparency.
This regressed when we added support for dynamic backface culling
(#1641). Also note another fix we made: #1877.
2019-12-05 09:00:57 -08:00
Romain Guy
564e527ac7 Fix docs typo 2019-12-05 10:17:00 +01:00
Philip Rideout
6d3b733cb1 Bump package.json version. 2019-12-04 15:59:52 -08:00
Philip Rideout
0e967726de Simplify CameraManipulator.
This removes a lot of code and will make it easier to migrate into a new
library with Java bindings, etc.

- The clipping planes and projection matrix were unused, removed them.

- In split view mode, our demos were using only 2 of the 3 manipulators,
  removed one.

- Instead of callbacks and update methods, users can simply ask for the
  current matrix at every frame.

- The manipulator's job is to consume mouse events and maintain an
  "look at" basis, there is no need to store a reference to a Filament
  Camera.
2019-12-04 08:05:17 -08:00
Mathias Agopian
001a4c46db Added a property chunk to materials
Materials can now reflect which property is in use.
2019-12-03 17:51:44 -08:00
Mathias Agopian
1a9d0926ee Added a torus and simple cube shapes
renamed "cube.obj" to "rounded_cube.obj", which it was (rounded)
2019-12-03 17:49:40 -08:00
Mathias Agopian
05a756beaa ResourceAllocator: minor clean-up and comments 2019-12-03 17:42:43 -08:00
Mathias Agopian
1014847e9d workaround OpenGLES driver bug
some drivers declare supporting anisotropic filtering, but don't
support calling glSamplerParameter() to set the max anisotropy, presumably because they only support glTexParameter().
We simply turn off anisotropic filtering on these drivers.
2019-12-03 17:41:41 -08:00
Ben Doherty
d3309c2e84 Fix Windows build variants (#1926) 2019-12-02 17:16:15 -08:00
Romain Guy
565002a918 Remove obsolete comment 2019-12-02 14:23:12 -08:00
Romain Guy
08b83e7ed1 Make including jawt_md.h more resilient (#1922)
Sometimes CMake decides to use the JNI bits included with XCode instead
of those from the installed JDK. The header files are located in different
directories. This does the proper include.
2019-12-02 08:45:20 -08:00
Ben Doherty
b4c2f523fe Update RELEASE_NOTES.md 2019-11-27 13:14:12 -08:00
Romain Guy
4ba5d6b9a8 Update release notes 2019-11-27 13:05:34 -08:00
Ben Doherty
59ceb05f99 Add support for mapping individual planes of iOS external images (#1917) 2019-11-27 10:38:13 -08:00
Benjamin Doherty
929c8e96c6 Handle surface size changes in Metal 2019-11-27 01:08:40 -08:00
Philip Rideout
1b5a730358 VulkanDriver: add depth buffer to swap chain. 2019-11-27 01:08:40 -08:00
Benjamin Doherty
79255e8e7d Implement default depth buffer for Metal 2019-11-27 01:08:40 -08:00
Mathias Agopian
50845261fe Swap chains are now always created with a depth buffer
This is to allow direct rendering of 3D objects into the swapchain 
under certain circumstances (no msaa or postprocessing).
2019-11-27 01:08:40 -08:00
Philip Rideout
da090f0ff6 Fix missing call to glInvalidateFramebuffer().
We were over-optimizing, not always honoring the flag. This was
incorrect since bindFramebuffer can be called from other places.

Fixes #1914.
2019-11-26 15:25:59 -08:00
Philip Rideout
60ead8c5f3 Add Android sample for testing the Stream API.
This new sample differs from "Hello Camera" in that it exercises all
three ways of using Stream. It also uses Canvas instead of Camera2 to
draw into the external texture. It shows two sets of stripes, one
animated using the shader and the other animated using Canvas. If the
two stripes are aligned, then the stream is perfectly synchronized.
Users can tap the screen to cycle between the three modes.
2019-11-26 07:58:52 -08:00
Ben Doherty
6942569409 Pass shared context on Windows to wglCreateContextAttribs (#1913) 2019-11-25 13:38:07 -08:00
Romain Guy
498a608941 Remove unused lambda capture 2019-11-23 19:55:05 -08:00
Philip Rideout
eee7154c33 wasm: add support for DEBUG builds by disabling RTTI.
Unfortunately we require RTTI to be disabled for web builds
due to the way in which we handle array buffers. This may change
in the future but for now I think it's an acceptable constraint,
especially given the fact that RTTI adds bloat anyway.
2019-11-22 14:33:03 -08:00
Ben Doherty
a735660af8 Separate resource packages for gltf_viewer and lucy demo (#1908) 2019-11-22 11:34:42 -08:00
Ben Doherty
c5ed7172b3 Add release GitHub workflow (#1903) 2019-11-21 11:04:20 -08:00
Mathias Agopian
4b28362920 Better workaround a resource culling issue.
A texture resource can end-up with not usage bit set if it is used as
an attachment of a render target that gets replaced by a moveResource()
call. The framegraph should take care of culling our this resource,
in that case, but currently doesn't.

We worked around this issue by not declaring the resources, but it's
better to do this in the frame graph code, as to not affect the 
user facing API.
2019-11-20 22:26:00 -08:00
Mathias Agopian
dfeaa416c0 Tone mapping always sets alpha channel to 1 in opaque mode
This fixes an issue where the alpha channel could be left to garbage in
opaque mode with FXAA disabled.
2019-11-20 17:34:59 -08:00
Mathias Agopian
3ce4dd94f7 Use a larger blur filter for SSAO
We go from 9 to 15 taps to better match the 16x16 noise pattern.
2019-11-20 16:32:28 -08:00
Ben Doherty
0ee1d406e0 Update README.md to reflect build link removal (#1902) 2019-11-20 13:29:51 -08:00
Mathias Agopian
dad814e046 Fix a long standing bug preventing the use of transparent views (#1893)
Fix #1165

In order to use transparent views, post-processing had to be disabled
because we were not able to blit post-processed buffers with blending.
This is now fixed by simply reverting to a quad.

A side effect of this, is improved performance when a scaling blit is
needed when MSAA is active.


This also introduced new "bugs", or at least weird behaviors: the
system needs to know when blending is needed, and this has to be
based on heuristics (unless we add a new api). Currently the heuristic
is that the COLOR buffer is not discarded and the view is cleared with 
an alpha value (or not cleared).
2019-11-19 14:05:22 -08:00
Pixelflinger
6246f20e63 Always use SH3 for indirect lighting
We used to use SH2 on mobile/webgl, but the quality degradation is too
prominent. This adds ~16 adds though.
2019-11-19 14:00:37 -08:00
Ben Doherty
f4ad55f6d7 Fix Windows CI failures by specifying shell (#1890) 2019-11-19 11:20:59 -08:00
Pixelflinger
027c4b42f7 fix a few issues with MSAA blits
1) When scaling is enabled, we're using a blit at the end of the frame,
   however, if MSAA is also enabled, this blit is not allowed, so we
   need an explicit MSAA resolve.

2) When rendering directly into the default render target with MSAA
   enabled, we need an explicit resolve ONLY IF there is a format
   conversion, because those are also not allowed. 
   Before, we were doing this resolve regardless.

3) The test for "rendering directly into the default target" had
   become wrong because, the Render target can now be a user texture
   (which is assumed to have the proper MSAA-ness and a depth buffer),
   so no intermediate buffer should be needed for those. We now
   check that render target is actually the default render target
2019-11-18 20:25:53 -08:00
Pixelflinger
fb6c9f8b7d Use 16x16 blue noise for SSAO samples
The larger, blue noise texture gives a more pleasant, smoother SSAO
effect.
2019-11-18 20:25:29 -08:00
Pixelflinger
33d2eaee5b remove old 'SSAO' algorithm 2019-11-18 16:16:29 -08:00
Ben Doherty
ae3ccd7fb6 Implement headless swap chains and readPixels for Metal (#1885) 2019-11-18 11:28:20 -08:00
Russell Chou
72dbea256a Fix comment. 2019-11-16 15:10:15 -08:00
Pixelflinger
ea0ff1bc01 Add a way to override the material of a RenderPass
We used to have this functionality, but it we removed it because we
didn't have a use for it and it was costly.

This new implementation is only internal, and would (will?) be useful
if we wanted to generate a special buffer for SSAO for instance (instead
of just depth). This implementation, overrides the material at the time
the commands are executed, which is much cheaper than the previous
implementation.
2019-11-15 17:37:18 -08:00
Philip Rideout
2bca33f535 gltfio: Use JobSystem to decode PNG / JPEG.
For the street light glb from the Khronos suite, this reduces texture
loading time from 290 ms to 110 ms.

Stay tuned for another feature: notification callbacks.

Related to #1876.
2019-11-15 17:30:52 -08:00
Ben Doherty
75c5bb846b Use checkout action for GitHub Actions (#1886) 2019-11-15 16:33:23 -08:00
Pixelflinger
0da551c7fd More improvements to SSAO
- we add an 'intensity' parameter that allows to control the strength
  of the AO effect. This is useful for aesthetic reasons.

- the default intensity is now 2x that of before this change, which
  makes the intensity parameter match AO papers this implementation
  is inspired of.

- bias is now z-dependent, which reduces some self shadowing wrt the
  depth.
2019-11-15 09:42:37 -08:00
Mathias Agopian
5583dc26f9 Added a parameter to control the bilateral filter
This is needed because filament doesn't make strong assumptions about
the units used (e.g. meters), so we can't hardcode a distance in the
shader. But also, this is a cheap change.
2019-11-15 09:42:37 -08:00
Mathias Agopian
339fa3bd60 SAO and ssaogen cleanup
ssaogen now produces better formatted tables, directly usable in
shader code.

SAO shader now squares the sample radius outside of `tapLocation`, also
added some comments.
2019-11-15 09:42:37 -08:00
Mathias Agopian
dbaaa977e7 Fix depth mipmaping program
Due to a typo, we were using a nearest neighbor downsampling, instead
of picking one of the 4 pixels based on position.
2019-11-15 09:42:37 -08:00
Mathias Agopian
b10e99d374 Turn mipmapDepth material to a post-process material 2019-11-15 09:42:37 -08:00
Philip Rideout
a7d572f060 Stream API: improve dlsym usage. 2019-11-15 08:40:41 -08:00
Philip Rideout
127234f655 Stream API: release image sooner. 2019-11-15 08:40:41 -08:00
Philip Rideout
2c13c8fe6e Stream API: rename createAcquiredImage => transformAcquiredImage. 2019-11-15 08:40:41 -08:00
Philip Rideout
c0b9900cdc Stream API: privatize the AcquiredImage struct. 2019-11-15 08:40:41 -08:00
Philip Rideout
44e8d57935 Stream API: cleanup as per code review feedback. 2019-11-15 08:40:41 -08:00
Philip Rideout
d85f8164c0 Stream API: add support for acquire / release semantics.
Previously, Streams had two modes (native and texid), this adds a third
mode called "acquired", which allows for copy-free synchronized external
textures in OpenGL and paves the way for Vulkan.

The native mode is now deprecated but texid mode needs to stay around
until all clients can be upgraded.

In an early prototype, this functionality was added directly into
Texture but required quite a bit of additional state tracking, so the
Stream API seemed like a better fit.

This API is probably not necessary for Metal due to Metal's shared
ownership semantics.

This has been tested with a new Android sample that will be added in a
subsequent PR.
2019-11-15 08:40:41 -08:00
Mathias Agopian
32407c2ba5 RenderPass cleanup/refactoring
RenderPass's API now doesn't need to know about FScene, instead we
pass the geometry info as parameters.

This is one step towards keeping the "scene" concept more away from
rendering.
2019-11-14 15:31:59 -08:00
Philip Rideout
51e82a5561 Fix dynamic backface culling.
This fixes an oversight in #1641 for scenes that have only 1 primitive
when the depth prepass is enabled. In such cases, the same prim is
rendered twice in a row: once for depth and once for color.

We had enhanced the main render loop to override the primitive's
backface culling state when the material instance changed, but that was
not sufficient since the same material instance can be used for depth
and color passes.

Fixes #1872.
2019-11-13 12:15:44 -08:00
Mathias Agopian
3fb75ca904 custom command support in the renderloop
New internal API to add custom commands (lambda) before or after each
pass. These commands can be added at any point and will be sorted
properly.

e.g.:

    appendCustomCommand(Pass::COLOR, CustomCommand::PROLOG, 0, [](){
       // custom code
    });


Also split appendSortedCommands() in two functions to make it easier
to insert custom commands.
2019-11-13 11:34:34 -08:00
Tim Psiaki
64a70c7c18 Flip Tangents and Bitangents on backfaces. 2019-11-13 11:31:57 -08:00
Mathias Agopian
b9a68090b1 fix a data race on Debug builds
On Debug builds, HeapAllocatorArena needs LockingPolicy::Mutex because
it uses a TrackingPolicy, which needs to be synchronized.
On Release builds, HeapAllocatorArena doesn't need a LockingPolicy 
because HeapAllocator is intrinsically synchronized as it relies on
heap allocations (i.e.: malloc/free)
2019-11-13 09:18:57 -08:00
Mathias Agopian
5344854056 tweak how we invoke commandstream's commands
- this is to allow the use of C++17 std::invoke
- don't std::move() each argument of the tuple<> instead
  std::move() the tuple itself and perfectly-forward each argument.
- handle return values
- handle synchronous commands
2019-11-12 11:29:05 -08:00
Ben Doherty
abad894fd5 Fix UB inside FMaterial (#1862) 2019-11-12 10:08:42 -08:00
Philip Rideout
8872227af5 Fix normals with skinning when there is no normal map.
I tested this with the CesiumMan model, the lighting seems improved
around his hands.

Fixes #1848.
2019-11-11 15:03:17 -08:00
Mathias Agopian
30a07a49d0 add a way to import/export an Entity from/to an integer
This is intended to be used for interop with other programing languages.
2019-11-11 14:37:10 -08:00
Mathias Agopian
0a37cce5fe don't use our own sync primitives when TSAN is used
TSAN seems to have problems with homegrown sync primitives, such as
spinlocks, so we just don't use them when TSAN is enabled.
2019-11-11 14:36:49 -08:00
flashk
fc76ed9949 clampNoV function ignores argument
The "clampNoV" shader function is ignoring the passed dot product argument and recomputing the dot product itself. This will result in the wrong NoV value being used for clear coat IBL computations.
2019-11-08 15:34:25 -08:00
Philip Rideout
d55d042a14 Renderer: call updateStreams AFTER makeCurrent.
When using the OpenGL backend, updateStreams makes GL calls such as
glEGLImageTargetTexture2DOES and therefore requires a valid GL context.
2019-11-08 12:21:25 -08:00
Ben Doherty
d7e07f4d51 Transition to GitHub Actions for continuous builds (#1850) 2019-11-07 13:38:37 -08:00
Ben Doherty
22a6ecadbb Disable RenderingTest from CI test suite (#1858) 2019-11-07 11:17:41 -08:00
Mathias Agopian
53ff133b03 fix a possible memory corruption in debug builds
TrackingPolicy::Debug didn't store the base pointer of the Area, and
instead relied on the first allocation to discover it, however, because
of alignment, the first allocation may not match the base pointer.
Because of that there could be an overflow in onRewind(), i.e. we
could rewind to a pointer before the (wrongly computed) base. This
overflow caused the debug memset to go awry and stomped on memory.

This is fixed by passing the base pointer to the constructor of the
TrackingPolicy. This base pointer could be nullptr with certain
allocators, but in that case, onReset/onRewind should never be called;
and this is enforced at compile time.

Also fixed a (luckily) harmless buffer overflow when preparing the
dynamic lights, if the number of lights wasn't a multiple of 4. This
was harmless because we use a linear allocator, so overflows are not 
really overflows.
2019-11-07 10:03:41 -08:00
Benjamin Doherty
d1ab68ebfa Fix KTX image test on Windows 2019-11-07 09:15:07 -08:00
Philip Rideout
655b7dc13c Emit warning for too many morph targets.
Motivated by #1852.
2019-11-06 15:39:38 -08:00
Philip Rideout
48bfe0453b Fix an assert when the last uniform is an array.
Clients who do not yet have this fix can usually work around this issue
by calling the non-array overload of `MaterialInstance::setParameter`
when the array size is 1.
2019-11-06 15:39:17 -08:00
Philip Rideout
87a05f057a Fix out-of-bounds in an [unused] utility.
This was caught by ASAN.

Our algorithm header has many one-liners that compute the "next power of
two length / 2" but they all have the caveat that if the input is
already POT, then the "/ 2" part does not occur.

Usually we deal with this by testing the difference against zero.
However in `partition_point` we were skipping the test, thus causing a
potential out-of-bounds access.

I fixed `partition_point` and added a few more tests for non-POT cases.
2019-11-05 17:14:15 -08:00
Mathias Agopian
4f540fe7fd Better handling of engine shutdown
- we make sure we don't leak user callbacks or fences
- fix typos
2019-11-05 16:17:46 -08:00
Pixelflinger
1fd675fd09 Make filament's readPixels() asynchronous wrt the GPU
This doesn't change the user facing API because it already used a
callback.

With this change we implement readPixels() with a PBO, which won't
stall the GPU. Then we periodically check a fence to see when the
command is completed, at which point we map the PBO and copy the data
to the user buffer.
2019-11-05 16:17:46 -08:00
Mathias Agopian
bf72adbb57 Implement Headless SwapChain mode.
This is useful for unit tests. The content of the swapchain can be
read to main memory with Renderer::readPixels().


This PR doesn't implement this new feature in the following backends and
platforms (TODO):

VulkanDriver.cpp
MetalDriver.mm

PlatformWGL.cpp
PlatformWebGL.cpp
PlatformCocoaTouchGL.mm
2019-11-05 12:19:29 -08:00
Ben Doherty
dd45703d73 Fix Metal backend crash when rendering external image before set (#1847) 2019-11-05 09:23:58 -08:00
Ben Doherty
7c0d3cdb10 Add EAC / ETC2 and DXT compression formats to Metal backend (#1800) 2019-11-05 09:21:41 -08:00
Mathias Agopian
5462cc0fcf Renderer::readPixels() can now read back from a RenderTarget
Before it was limited to reading back from the SwapChain.
2019-11-04 17:18:39 -08:00
Philip Rideout
8fe9f15b3b JavaScript: add documentation for fetch utility. 2019-11-04 14:20:51 -08:00
Philip Rideout
c49c6e5d19 JavaScript: allow pre-population of asset data.
Fixes #1843.
2019-11-04 14:20:51 -08:00
Philip Rideout
636c54ec6f gltfio: support mesh-level morph weights.
We honored node-level defaults but not mesh-level.

Fixes #1840.
2019-11-04 12:32:02 -08:00
Nicklas Ansman Giertz
52ee07f2fd Add a clarifying comment 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
02ef4a99b7 Add some missing nullability annotations to the gltfio android bindings 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
73a4431a34 Fix some warnings in the gltfio android jni code 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
e252558ef6 Expose FilamentAsset.getResourceUris in the Android bindings 2019-11-03 15:03:13 -08:00
Nicklas Ansman Giertz
5680b5d9a6 Add support for GLTF files in the android gltfio bindings 2019-11-03 15:03:13 -08:00
Philip Rideout
86c0a68ccd Work around unaligned stack with clang 11.
Optimized macOS builds can trigger "stack_not_16_byte_aligned_error"
when building with clang 11. We happen to see this with resgen but it
could happen anywhere.

https://forums.developer.apple.com/thread/121887

Fixes #1823
2019-11-01 13:52:47 -07:00
Ben Doherty
9379e7ce45 Use ARC for Metal backend (#1824) 2019-11-01 10:28:28 -07:00
Philip Rideout
04d2234169 Fix WebGL debug build. 2019-11-01 09:14:38 -07:00
Philip Rideout
66f4419518 gltfio: Fix black default material.
Fixes #1828.
2019-10-31 16:45:01 -07:00
Philip Rideout
be4ad2ec07 WebGL: add a light source to the animation demo. 2019-10-31 16:45:01 -07:00
Philip Rideout
853b2205dd Upgrade emsdk for improved wasm generation.
This uses clang's wasm backend rather than fastcomp.
2019-10-31 16:41:29 -07:00
Philip Rideout
80f104c522 OpenGL: Fix up my previous fix for uvec4 attribs.
The previous fix for #1726 was not quite right because it did not
set the INTEGER flag unless the attribute was declared.

Fixes #1726.
2019-10-31 11:57:43 -07:00
Philip Rideout
1fa2fd9b7f WebGL: add morphing demo. 2019-10-31 11:57:43 -07:00
Philip Rideout
fa108d6a65 Use the Jim Arvo method for transforming AABB's.
This is from the 1990 Graphics Gems article.
2019-10-30 16:15:55 -07:00
prideout
a82d93914e Bump to v1.4.2 2019-10-30 13:49:36 -07:00
Philip Rideout
389349198f gltfio-jni: Fix double-init panic caused by build issues.
Filament keeps a global static list of engines for verification purposes
which was being recreated multiple times, causing a panic. After a lot
of experimentation with the build, I was not able to fix this while
keeping the current scheme of dynamically loading both libraries.

As a "solution", we now staticly link filament into gltfio-jni, and ask
clients to load only that.

Fixes #1811.
2019-10-30 09:51:14 -07:00
Philip Rideout
225a844e0f Minor improvements to Engine validation.
This enhances the assert added in 2548da9 in the following ways:

- Adds console output at startup to help detect "double load" bugs.
- Adds PRETTY_FUNCTION to show where the invalid usage is coming from.
- Tweaks the wording since use-after-destroy is not always the cause.
- Consolidates usage of static globals into a helper class.

Motivated by #1811.
2019-10-29 15:48:29 -07:00
Mathias Agopian
f018c719a6 a test for the skinning math 2019-10-29 15:38:40 -07:00
Philip Rideout
2a229571ad Minor fixes to gltf-bloom demo. 2019-10-29 10:20:28 -07:00
Romain Guy
35959b547c Use unnormalized vectors to compute bump mapping. (#1813)
If we assume the tangents and bitangents were generated using mikktspace,
we should use the unnormalized vectors, as indicated at mikktspace.com
or in http://www.metalliandy.com/mikktspace/downloads/mikktspace/mikktspace.h
(see last comment at the end of the file).
2019-10-29 09:41:15 +00:00
Philip Rideout
796007377d Revert the Engine validation commit.
This needs to wait until code review and was pushed by accident.

This reverts commit bb90103e74.
2019-10-28 16:14:07 -07:00
Philip Rideout
5c73d0ae75 Update package.json for npm release. 2019-10-28 16:05:45 -07:00
Philip Rideout
bb90103e74 Minor improvements to Engine validation.
This enhances the assert added in 2548da9 in the following ways:

- Adds console output at startup to help detect "double load" bugs.
- Adds PRETTY_FUNCTION to show where the invalid usage is coming from.
- Tweak the wording since use-after-destroy is not always the cause.

Motivated by #1811.
2019-10-28 14:08:54 -07:00
Ben Doherty
0149bc504d Fix Windows GitHub Action (#1814) 2019-10-28 12:22:42 -07:00
Philip Rideout
3db035520b gltf-bloom now invokes the gltfio animator.
Tested with CesiumMan.
2019-10-28 09:32:39 -07:00
Philip Rideout
618b59932c gltfio: Add Java / Kotlin bindings for Animator.
Fixes #1529.
2019-10-28 09:32:39 -07:00
Mathias Agopian
9ef05ad456 better fix for NoopDriver on iOS 2019-10-24 14:17:29 -07:00
Adrian Perez
c8a0dbb59a Fix OpenGL ES 3.0 support on iOS (#1803) 2019-10-24 12:43:23 -07:00
dsternfeld7
35a0b045f8 Adds missing include in NoopDriver that prevented the correct shader model from being picked when using the Noop backend. 2019-10-24 10:58:16 -07:00
Ben Doherty
a4369c833d Add README section on Filament CMake options (#1801) 2019-10-23 13:27:08 -07:00
Philip Rideout
354f1da708 Enhance KHR_debug output + code cleanup. 2019-10-22 12:41:34 -07:00
Philip Rideout
7e47d257d1 OpenGL Driver: add support for KHR_debug.
This extension dumps out some interesting vendor-specific information
to the log, which could be useful for debugging. Interestingly, some
of Android demos produce this output on Pixel 3:

  KHR_debug: EsxBufferObject::Map - Ignoring EsxBufferMapUnsyncedBit

Enabled for debug builds only.
2019-10-22 12:41:34 -07:00
Ben Doherty
c3d2b3578d Add Javadoc for Colors, Box, and MathUtils (#1796) 2019-10-21 17:59:05 -07:00
tpsiaki
783aa06a46 Fix typo in Noop on mobile. (#1799) 2019-10-21 17:41:32 -07:00
Mathias Agopian
faa82ff35a implement diag() in TMatSquareFunctions
this requires using 'auto' as the return type.
2019-10-21 14:27:40 -07:00
Ben Doherty
3008123d6b Update RELEASE_NOTES for v1.4.1 (#1793) 2019-10-18 13:36:34 -07:00
Ben Doherty
2d2987066d Implement user-controlled frame presentation in Metal (#1760) 2019-10-17 17:11:34 -07:00
Mathias Agopian
c84ec04efa remove unneeded loop in TransformManager
during a transaction, it makes no sense iterating through all
children just so that we can iterate through their children...
and do nothing else.
2019-10-17 16:17:32 -07:00
Mathias Agopian
197b45c1d1 fix a double-free when exiting the FroxelData test
We were destroying the engine manually (by calling delete) which is
not allowed.

Also made FEngine::shutdown() private.
2019-10-17 16:17:12 -07:00
Mathias Agopian
af9ecf0a61 minor cleanup based on clion suggestions 2019-10-17 16:16:51 -07:00
Ben Doherty
530fb58337 Add Javadoc to IndexBuffer and VertexBuffer (#1788) 2019-10-16 17:59:53 -07:00
Philip Rideout
6a891021b1 MSVC fixes for Vulkan.
Should fix #1772, hopefully.
2019-10-16 17:37:33 -07:00
Ben Doherty
0e7c68b50d Fix, assertion using bones with Metal backend (#1787) 2019-10-16 15:54:08 -07:00
Ben Doherty
32a32d3d21 Remove iOS OpenGL ES 3.1 hack (#1781) 2019-10-16 10:51:55 -07:00
Ben Doherty
fca71813d4 Use CMAKE_COMMAND variable in place of cmake (#1783) 2019-10-16 10:50:55 -07:00
Philip Rideout
3618f14531 Add Android sample for Camera Stream.
This simple Kotlin app projects a live feed on the side of a cube.
It looks very similar to the `lit-cube` demo but there is a new Kotlin
class called `CameraHelper` that creates Camera2 objects, starts
the capture session, creates the Filament texture, etc.

For now, this app uses SurfaceTexture. This is a starting point and
provides a testing ground for tentative improvements to our Stream API.
2019-10-16 09:05:24 -07:00
Romain Guy
9de3e76a53 Remove the use of reflection where it's not necessary (#1782)
Fixes #1510
2019-10-15 17:54:02 -07:00
Romain Guy
e472fdbce4 Remove Kokoro Windows presubmit 2019-10-15 17:40:24 -07:00
Mathias Agopian
c9fcedb40b some optimizations to the math code (#1779)
- we use by-value parameters in some places, which helps the compiler
  (not sure why, but assuming references can be aliased and the
   compiler is cautious about that).
  This helps matrix multiplies (which is almost never inlined) and
  transpose (but that's almost always inlined and merged with
  something else, so the gain here is not completely real)

- remove support for matrices-of-matrices because this wasn't complete
  anyways.

- improve matrix * scalar by inlining the loop manually instead of
  going through *=, this saves some extra writes.
2019-10-15 17:22:54 -07:00
Mathias Agopian
bd8c3e9181 don't limit the near plane to ~1mm (#1778)
We were not checking Camera's preconditions properly -- we assumed that
near < 1/1024 meant "near == 0".

Now we check preconditions properly and revert to the same hardcoded
default if they're not met -- doesn't matter what the default is,
it's there only to avoid NaNs and Infs elsewhere -- rendering will
be bogus eitherway.

Fixes #1766
2019-10-15 17:22:38 -07:00
Gregory Popovitch
26d0aa76f8 README.md: add build steps for Visual Studio 2019 / MSVC (#1775) 2019-10-15 12:02:08 -07:00
Ben Doherty
20f4ec6576 Use platform-specific temporary directories for CircularBuffer (#1769) 2019-10-15 12:01:03 -07:00
Ben Doherty
d0bc23473c Fix crash when using Filamat lite library (#1780) 2019-10-15 10:49:59 -07:00
Ben Doherty
c33f6adf62 Remove BUILD_DEMO CMake option (#1776) 2019-10-14 09:09:46 -07:00
Ben Doherty
d4efa105b7 Set up Windows build through GitHub actions (#1767) 2019-10-11 09:28:57 -07:00
Ben Doherty
e8641ce257 Additional fixes for MSVC (#1765) 2019-10-10 16:45:06 -07:00
Ben Doherty
d7a4bdc3f1 Combine matdbg dependencies into single shared library (#1764) 2019-10-10 12:45:51 -07:00
Philip Rideout
e66215295c gltfio: use the new sparse support in cgltf. 2019-10-09 18:45:27 -07:00
Philip Rideout
552bb3e6db Update cgltf with sparse functionality. 2019-10-09 18:45:27 -07:00
Mathias Agopian
a96da05ab8 fix CircularBuffer ashmem fallback (#1763) 2019-10-09 16:48:22 -07:00
Ben Doherty
fb5ee4a9d0 Add Javadoc comments to Material and MaterialInstance (#1696) 2019-10-08 15:56:26 -07:00
Philip Rideout
da13067b57 libmath: prevent NaN's in slerp due to acos.
Fixes #1749.
2019-10-08 15:37:48 -07:00
Ben Doherty
d48d69c765 Use custom Git checkout action (#1756) 2019-10-08 15:22:09 -07:00
Mathias Agopian
5098b2af77 SwapChain javadoc 2019-10-08 10:31:32 -07:00
Mathias Agopian
5576d6b014 TextureSampler javadoc 2019-10-08 10:31:14 -07:00
Mathias Agopian
b072399229 TransformManager javadoc 2019-10-08 10:30:54 -07:00
Mathias Agopian
4f0ab43d58 Stream Javadoc 2019-10-08 10:27:53 -07:00
Philip Rideout
3f742880b5 gltfio: do not abort for sparse data, warn instead.
Sparse accessors are easy to punt gracefully, we can emit a warning
and instead use the dense "base" data.

Also, after cgltf support for this lands, we will need to apply sparse
data in ResourceLoader, so this adds a bit of plumbing to prep for that.

Relates to #1727.
2019-10-08 08:18:46 -07:00
Mathias Agopian
0704194460 javadoc for Renderer
also made resetUserTime and getUserTime public
2019-10-07 16:13:56 -07:00
Mathias Agopian
56e747f558 Scene javadoc 2019-10-07 16:13:38 -07:00
Ben Doherty
61c22f2295 Fix culling in MaterialInstance (#1750) 2019-10-07 16:08:50 -07:00
Mathias Agopian
c4bbaeda86 improve CircularBuffer error message 2019-10-04 13:18:09 -07:00
Philip Rideout
678ffc7503 gltfio: do not loop animation samplers, fixes #1730. 2019-10-04 08:48:35 -07:00
Philip Rideout
a080a47268 Add RenderTarget javadoc. 2019-10-04 08:47:55 -07:00
Philip Rideout
82e8104539 Fix javadoc warnings. 2019-10-04 08:47:55 -07:00
Mathias Agopian
11bd8e72ef harden lispsm code against div-by-zero 2019-10-03 22:58:26 -07:00
Mathias Agopian
03c2a90206 noexcept-ize libmath a bit move
this gets rid of a few ide-warnings about static initialization of
arrays with math types.
2019-10-03 17:12:35 -07:00
Mathias Agopian
c38ab64b6a Update Engine.cpp 2019-10-03 17:12:18 -07:00
Mathias Agopian
2548da9aed validate Engine in all Builder::build() methods
We now assert if the Engine given is invalid,
which would happen if it was used after being
destroyed.

Builder::build() is a reasonable place for this since it's generally
not in the critical path.
2019-10-03 17:12:18 -07:00
Ben Doherty
2fa08123a0 Add an iOS runner for backend-test (#1720) 2019-10-03 17:02:28 -07:00
Mathias Agopian
20c3d45b9c Engine.flushAndWait() is not needed in most places 2019-10-03 16:04:22 -07:00
Philip Rideout
c8af3226de OpenGL driver: fix error with uvec4 attribs, clean up Vulkan/Metal. (#1735)
The vertex shader in the material variant for skinning-and-morphing
declares a `uvec4` attribute that can be unused and disabled, but still
needs to be typed correctly.

The fix is motivated by WebGL, but the issue might occur with other
OpenGL implementations that have strict drivers.

Fixes #1726
2019-10-03 15:42:07 -07:00
Romain Guy
4b669fb1c7 Fix formatting 2019-10-03 14:25:39 -07:00
Mathias Agopian
340f6d721a Texture javadoc 2019-10-03 13:25:06 -07:00
Philip Rideout
489f3ff3c9 Add javadoc for View and Viewport. (#1734)
This CL also fixes warnings in IndirectLight and adds a new C++ getter
to View for consistency with Java.
2019-10-03 08:38:10 -07:00
Mathias Agopian
566d3613d1 Skybox javadoc 2019-10-02 15:58:57 -07:00
Mathias Agopian
e691cfa9e3 javadoc fixes for IndirectLight 2019-10-02 15:57:31 -07:00
Romain Guy
a4a1bf07aa Use our own constants instead of M_PI, M_*, etc. (#1733)
These constants are not part of the standard. We instead use our own
constexpr definitions in the filament::math namespace, as part of
the scalar.h include.
2019-10-02 15:31:38 -07:00
Ben Doherty
7ea7d1d5f2 Fix, matinfo doesn't work on Windows (#1732) 2019-10-02 13:20:24 -07:00
Philip Rideout
686c68c627 View API: minor doc fixes, add getRenderTarget. (#1723)
Since getRenderTarget() already exists in Java, we should also provide
it for C++ clients.
2019-10-02 10:13:42 -07:00
Romain Guy
c652dcfd2a Fix warning 2019-10-02 08:56:39 -07:00
Ben Doherty
01fab5a6e4 Update gtest to latest master (#1718) 2019-10-01 16:48:10 -07:00
Philip Rideout
16a5adcfde Fix quat slerp so it takes shortest path.
Fixes #1716.

This regressed in c65e561c59.
2019-10-01 16:22:00 -07:00
Philip Rideout
d550d36637 Add javadoc for RenderableManager, fix javadoc warnings. 2019-10-01 16:09:05 -07:00
Mathias Agopian
3857c1a9b2 javadoc for IndirectLight 2019-10-01 13:32:54 -07:00
Philip Rideout
2f8bc9239b Add JS binding to unary Camera::setExposure. 2019-10-01 12:39:40 -07:00
Philip Rideout
9de934e2bd Add Java annotations to setMorphWeights.
Noticed this while working on javadoc stuff.
2019-10-01 11:16:15 -07:00
Philip Rideout
769f1db011 Fix ambiguous atomic-to-bool conversion. 2019-10-01 10:43:15 -07:00
Philip Rideout
da72c58146 mac_runner: disable warning. 2019-10-01 10:43:15 -07:00
Ben Doherty
ef34dd2461 Fix operator overrides for Clang / MSVC on Windows (#1715) 2019-09-30 18:39:38 -07:00
prideout
90fdb95429 Update release notes for v1.4.0 2019-09-30 14:55:39 -07:00
Gregory Popovitch
d5c0d11404 Final changes for building with msvc 2019 on Windows (#1681) 2019-09-30 14:18:06 -07:00
Romain Guy
b0d116632c Add the ability to modify clip space coordinates in the vertex shader (#1704)
* Add the ability to modify clip space coordinates in the vertex shader

This introduces MaterialVertexInputs.clipSpaceTransform, a mat4 that
is applied to gl_Position before exiting the vertex stage.

* Address code review comments
2019-09-28 14:15:32 +03:00
Romain Guy
a67d92c2ca Lower limit from API 21 to API 19 (#1701)
* Lower limit from API 21 to API 19

This was requested by an internal application. API 19 is when OpenGL
ES 3.0 support was added so there is no good reason for us to not
support this API level. The only trick is to avoid referring to the
glTexStorage2DMultisample symbol directly as it only exists in 3.1.

* Compile out code we never use

* Use reflection to handle shared EGL contexts pre-API 21.

* Remove comment

* More fixes required to run on API level 19

- dlym() fails for ashmem on API 19, so we only try on API 26+ instead.
- Older emulation for OpenGL ES 3.0 returns error states for valid API calls so we need to clear the GL error bit before we create the GL driver.
- Activity lifecycle changes since API 19 would cause animations to keep running and to reference destroyed objects.
- EGLContext.getNativeHandle() is new in API 21, we need to use reflection on API 19. The new code path uses the class loading trick to avoid a bytecode verification error on API 19.

* Filament now runs properly on API level 19

This commit adds a new api_level() API to libutils which can be used to
query the platform's API level. On Android it works as expected, other
platforms currently return 0.
2019-09-28 14:13:06 +03:00
Philip Rideout
21b208398b Renderable doxygen now uses \see etc. 2019-09-27 15:26:08 -07:00
Philip Rideout
65b3e956df Add doxygen for RenderableManager and NameComponentMananger. 2019-09-27 15:26:08 -07:00
Mathias Agopian
c8d0715b16 SamplerParams is not default-initialized anymore
This is to allow designated aggregate initialization in C++20.
We do this because we have been relying on C99 designated
initialization, which is only supported by clang, other compilers need
c++20 to get a similar functionality. Therefore, we now try to limit
Ourselves to C++20 rules.

This could break existing code, since now SamplerParams needs to be
zero-initialized:

SamplerParams p{};

This is generally not an issue because the intended use is:

doSomethingWithSamplerParams({
      .filterMag = LINEAR,
   });
2019-09-27 13:53:11 -07:00
Mathias Agopian
16d307e543 enforce that quaternions are made of arithmetic types
I believe this might fix some msvc compiler issues too.
2019-09-26 19:05:33 -07:00
Mathias Agopian
5ed07639af workaround an MSVC bug with brace initialization
the C++ standard says:

   if T is a class type with a default constructor that is neither
   user-provided nor deleted (that is, it may be a class with an
   implicitly-defined or defaulted default constructor), the object
   is zero-initialized and then it is default-initialized if it has a
   non-trivial default constructor

Unfortunately, MSVC always calls the default constructor, even if it
is trivial, which breaks constexpr-ness.
To workaround this, we're always zero-initializing TVecN<>

Also removed constexpr from default constructors, since they never can
be constexpr as they're not initializing the vector.
2019-09-26 19:05:33 -07:00
Ben Doherty
e2655e93bc Add test framework for libbackend (#1697) 2019-09-26 12:30:30 -07:00
Philip Rideout
3a20be1d1a gltfio javadoc: add links, fix formatting. 2019-09-26 14:07:13 -04:00
Philip Rideout
8244f8e9cb Add javadoc comments for gltfio. 2019-09-26 14:07:13 -04:00
Romain Guy
c575fd7395 Add new Camera::setExposure(float) API (#1699)
* Add new setExposure(float) API on Camera

This API can be used to set a specific exposure value. For instance:

camera.setExposure(1.0)

Will set the exposure to 1.0 (or ISO 100, apeture 1.0 and shutter speed 1.2s).
This can be useful to match the lighting setup of other engines/tools. Setting
the exposure to 1.0 can for instance be used to treat lights as being unitless
(a directional light could have a strength of 2.0 for instance).

Fixes #1667

* Update release notes

* Fix Java build error

* Fix Web bindings
2019-09-26 20:08:46 +03:00
Philip Rideout
6a67cf0009 Enhance doxygen annotations for gltfio. 2019-09-26 12:18:56 -04:00
Romain Guy
79292481b3 Update documentation 2019-09-26 16:31:55 +03:00
Mathias Agopian
829f341de3 Engine and Camera javadoc (#1698) 2019-09-26 11:53:14 +03:00
Mathias Agopian
b509ef4dad handle scalar op vector directly to help some compilers 2019-09-25 22:39:13 -07:00
Mathias Agopian
422c8d9a64 Make DriverAPI.inc work with MSVC19 2019-09-25 13:52:41 -07:00
Romain Guy
d0b5c5cee8 Update compile & targetSdk from 28 to 29 (#1691) 2019-09-25 22:25:43 +03:00
Romain Guy
9b9548306d Fix Android samples (#1688)
Fixes #1687
2019-09-25 15:48:30 +03:00
Ben Doherty
b28e535540 Combine license file generation functions for MSVC compatability (#1684) 2019-09-24 12:45:38 -07:00
Mathias Agopian
1f7584ace2 Improve backend documentation (#1674)
We need to document the backend headers that are public.
Added documentation for:
- DriverEnums.h
- BufferDescriptor.h
- PixelBufferDescriptor.h

Disabled doxygen for public headers of backend that don't need to
be public for filament's API.

Also improved documentation for:
- LightManager.h
- RenderTarget.h
- TextureSampler.h
2019-09-24 11:18:15 -07:00
Ben Doherty
21512e8228 Update MaterialBuilder header comments for Doxygen (#1673) 2019-09-24 09:11:35 -07:00
Gregory Popovitch
a34903aa33 Update CMake configuration to support building with MSVC 2019-09-23 10:15:34 -07:00
Philip Rideout
4eba402adb Enhance the deprecation note. 2019-09-23 12:31:24 -04:00
Philip Rideout
64c5f5aee7 Deprecate populateTangentQuaternions. 2019-09-23 12:09:37 -04:00
Philip Rideout
1bda37776b Rename KtxUtility namespace to image::ktx. 2019-09-23 12:08:57 -04:00
Philip Rideout
1c5d7d6cc3 Build OpenImageDenoise only in host builds.
Fixes #1672
2019-09-21 14:31:54 -04:00
Mathias Agopian
b81ff060ae Remove HARD Fence public API
This API will be hard to implement on all backends (e.g. Vulkan) and
isn't that useful other than for timing.
2019-09-20 17:57:48 -07:00
Ben Doherty
0cebbfca23 Fix STB linking issues on Windows (#1669) 2019-09-19 15:31:54 -07:00
prideout
b9c7814dfd Remove unused variable. 2019-09-19 11:05:33 -07:00
Philip Rideout
ba9fd6719a FrameGraph, OpenGL, Vulkan: Clean up RenderPassFlags. 2019-09-19 10:52:29 -07:00
Mathias Agopian
f0ad12ce2e Fix matrix operations when using mixed precision
This is a similar fix to the previous vector fix. Commutative 
operations now always return the same type and the operations are
carried out in the precision resulting from following traditional
C++ rules.
2019-09-18 18:22:05 -07:00
Mathias Agopian
21acf53d3f improve vector operations when using implicit conversion
It used to be that operations e.g. like:

 float3{} + double{} would be computed as
 float3{} + float3{double{}} instead of
 float3{} + double3{double{}}

I other words, when an implicit conversion was involved on the right
it would be converted to the left side’s type, possibly losing 
precision.

Another problem was that swiping the operands could produce different
Results, e.g.:

   float3{1} * 5.0 -> float3{5.0f}
   5.0 * float3{1} -> double3{5.0}


This is no longer the case, now both expressions would return a double3. 

Note:

float3 r{};
r *= 5;

Is now equivalent to:

r[0] *= 5;
r[1] *= 5;
r[2] *= 5;

Instead of before:

r[0] *= 5.0f;
r[1] *= 5.0f;
r[2] *= 5.0f;
2019-09-18 18:22:05 -07:00
Mathias Agopian
2f5927d531 Minor code clean-up 2019-09-18 18:22:05 -07:00
Mathias Agopian
cf950a8d6f improve mixed-precision vector operations
We now follow the same rules than for basic types, when performing
mixed-precision operations, e.g.:

  float3 + double3 -> double3
  double3 + float3 -> double3
  dot(float3, double3) -> double

In particular, e.g. swapping the arguments to arithmetic operations
now always yields to the same result type (before, float3 + double3
would not return the same type than double3 + float3).
2019-09-18 18:22:05 -07:00
Philip Rideout
48b73ad998 Vulkan: use a dummy buffer for missing attributes.
To prevent an excess of variants, sometimes our vertex shaders declare
inputs that they never read from. For example, our skin-and-morph
variant might never read from the skinning attribute, but still declares
the input.

This PR is a sister to #1663, which is a fix for #1525.

See also #1279.
2019-09-18 18:14:45 -07:00
Philip Rideout
8fc94f127b Add language bindings for setCullingMode. 2019-09-18 18:12:02 -07:00
Philip Rideout
ce33f42e62 Fix warning in WebGL builds 2019-09-18 18:12:02 -07:00
Philip Rideout
61032e55b5 Update release notes. 2019-09-18 18:12:02 -07:00
Gregory Popovitch
6160d3f51e more changes for building with vs2019/msvc (#1506) 2019-09-18 17:25:22 -07:00
Ben Doherty
5d725f6de9 Fix, allow missing bone indices vertex attribute in Metal driver (#1663) 2019-09-18 16:59:43 -07:00
Romain Guy
020e9e59ed Don't use shallow fetches
This can cause issues with some PRs.
2019-09-18 16:39:40 -07:00
Mathias Agopian
bd777c1e56 Update View.cpp 2019-09-18 15:25:51 -07:00
Mathias Agopian
087b12c802 Fix minor time calculation imprecision
use double for the shader's 'second' time calculation, since 1 billion cannot be stored
in a float accurately.
2019-09-18 15:25:51 -07:00
prideout
42f2642d72 Vulkan: fix layout and miplevel for depth attachments.
We now use GENERAL layout for depth-sampled images in order to support
the SSAO use case of simultaneous binding + sampling.

We may be able to optimize this in the future by enhancing DriverAPI
so that it feeds more information into the render pass.

Fixes #1627, #1649.
2019-09-18 07:41:04 -07:00
Mathias Agopian
9c8d0ed5a1 handle basis inverting transforms (e.g. planar symmetries)
We now inverse the face winding order based on the determinant of
each render primitive world's transform. This prevents front/back faces
to be reversed when using a left-handed basis, after transform.

Fix #1520
2019-09-17 18:38:52 -07:00
Philip Rideout
9fd1705acf Add support for dynamic backface culling.
Inspired by our recent scissor change (#1639) but motivated by gltfio,
which was forced to create a ton of ubershaders (see #1562).

Tested with:

  gltf_viewer -u ../glTF-Sample-Models/2.0/TextureSettingsTest/glTF/TextureSettingsTest.gltf
2019-09-17 08:22:01 -07:00
Mathias Agopian
c981b52832 use enable_if<> instead of static_assert()
This is nicer because this way the methods that don't match don't
even exist. Also make it better when editing code with a C++ aware
ide.

Also use the less verbose std::enable_if_t<>
2019-09-16 18:13:21 -07:00
prideout
d074b6fd1a Remove unused field from backend::SamplerParams. 2019-09-16 16:04:26 -07:00
Mathias Agopian
7da5a25e2f Split OpenGLDriver in two files
We now have OpenGLContext which only tracks the OpenGL state.
It exposes an API very similar to OpenGL and does all the state
tracking. Currently, it doesn't expose non state-changing APIs 
(e.g. draw methods) and only implements the state-changing API we
need (to track the state of).
2019-09-16 15:53:02 -07:00
Romain Guy
b96b8eb787 Encode sRGB images as sRGB, not linear (#1646)
Fixes #1608
2019-09-16 10:51:17 -07:00
Philip Rideout
a25be5ee6e civetweb: do not build unless matdbg is built 2019-09-16 09:43:49 -07:00
Philip Rideout
bf9d1f1967 civetweb: fix warnings 2019-09-16 09:43:49 -07:00
Philip Rideout
561221fdc3 Rename PostProcessVertexInputs uv to normalizedUV. 2019-09-16 09:04:14 -07:00
Philip Rideout
8548afa231 Fix full-screen triangle winding and tex coords.
If you tried removing `culling: none` from any post-process materials,
everything would be fine in GL but Vulkan would be black because
our full-screen triangle was back-facing.

Continue reading only if you thrive in absurd situations.

- Metal and OpenGL define clip space as Y-up whereas Vulkan is Y-down.
- Metal and Vulkan define tex coords as Y-down whereas OpenGL is Y-up.
2019-09-16 09:04:14 -07:00
Philip Rideout
803e695d5c Add "uvToRenderTargetUV" to public shading API.
Fixes #1626.
2019-09-16 09:03:30 -07:00
Philip Rideout
5c58776313 Repair WebGL builds. 2019-09-16 08:39:20 -07:00
Romain Guy
0db39ea08a Add Android presubmit (#1644)
* Add Android presubmit

* Build Android on Linux, macOS targets have NDK 18 only

* Consolidate workflows and jobs

* Try to build Android on macOS

* Fix typo

* Cleanup scripts

* Try NDK side by side if NDK bundle has the wrong version

* Simplify logic

* Fix NDK logic

* Only update the NDK when necessary

* Fix typo

* Update required NDK version

* Favor NDK side-by-side

* Remove support for obsolete NDK bundle, require NDK side-by-side

* Install the NDK side by side when missing
2019-09-13 19:28:55 -07:00
Romain Guy
d76fb5d7e5 Fix matc dependencies and compilation messages 2019-09-13 18:41:38 -07:00
Romain Guy
f37ab8158c Name build jobs (#1643)
* Name build jobs

* Use build/ prefix instead of presubmit prefix

* Rename desktop workflow for consistency

* Forgot a git add...
2019-09-13 17:01:45 -07:00
Romain Guy
33db5acd13 Add web presubmit (#1642)
* Add web presubmit

* Use macOS not Linux
2019-09-13 16:40:57 -07:00
Mathias Agopian
e068204876 scissor is now part of PipelineState
setViewportScissor is gone, which will avoid a runtime error if
called outside of begin/endRenderPass, making the driver API more
robust.
2019-09-13 13:58:29 -07:00
Ben Doherty
d849231caf Remove old post-process shader pipeline (#1631) 2019-09-13 09:29:28 -07:00
Ben Doherty
996bd58fcb Use bitmask enum utility for MaterialBuilder::TargetApi (#1634) 2019-09-13 09:28:58 -07:00
Mathias Agopian
9b70dc5253 Fix linux/android DEBUG builds 2019-09-12 19:43:27 -07:00
Benjamin Doherty
31af9ca80f Automatically download iOS toolchain for Kokoro / GitHub 2019-09-12 17:41:33 -07:00
Benjamin Doherty
08aa2ec4ca Fix, iOS builds still need to work with Kokoro 2019-09-12 17:15:01 -07:00
Ben Doherty
95be2e24ce Fix iOS CI build (#1635) 2019-09-12 16:59:21 -07:00
Mathias Agopian
7b200ec85e make TextureUsage and TargetBufferFlags enum class
This prevents values like NONE or COLOR which are very generic
names to collide with other classic enums. It also forces us to be
specific about what we're doing when converting to bitfields.

Also added a utility to easily enable any enum or enum class to
support binary operation (i.e. Bitmask contract), e.g.:

template<> struct utils::EnableBitMaskOperators<Foo> : public std::true_type{};

gives all binary operators to 'Foo'. Foo must be an enum.

Also added any() and none() convenience to convert an enum to a boolean.
2019-09-12 11:19:54 -07:00
Mathias Agopian
cf1b45c052 Make SamplerParam a C struct
This simplifies its usage at call sites at lot.

The C++ ctor was needed before to create uninitialized objects, which
was needed in SamplerGroup. Instead we use a custom 'static_vector' 
(instead of std::array), this actually makes SamplerGroup's
implementation clearer.

static_vector<> is just a fixed-capacity, fixed-storage dynamic
vector. we currently don't expose it and implement only what we
need.
2019-09-12 11:18:47 -07:00
Ben Doherty
57e7280ac9 Remove post-process uniform / sampler blocks (#1624) 2019-09-11 16:57:48 -07:00
prideout
64d432cb34 PostProcessManager: another Vulkan-related re-ordering.
My fault, I did not catch this while reviewing #1621.
2019-09-11 11:33:43 -07:00
Ben Doherty
fde23c89e2 Use post-process material domain for FXAA (#1621) 2019-09-11 09:35:40 -07:00
Ben Doherty
0e3bc8a443 Only install iOS builds if requested (#1614) 2019-09-11 09:35:01 -07:00
Philip Rideout
88bcd133f2 filamat: add Backend-to-TargetApi utility. 2019-09-11 08:38:47 -07:00
Philip Rideout
2072b67e04 PostProcessManager: repair Vulkan by re-ordering commands.
The suzanne Vulkan demo was asserting because `setViewportScissor` can
only be called within a render pass, which means that
`MaterialInstance::use` can only be called within a render pass.

We probably need a better way to enforce these rules...
2019-09-11 08:38:19 -07:00
Philip Rideout
2a2974580c resgen: remove unused / incorrect constant. 2019-09-10 10:19:37 -07:00
Ben Doherty
65f72a48fb Terminate tonemapping material (#1619) 2019-09-10 10:15:15 -07:00
Philip Rideout
65674c7c51 filagui: disambiguate the resources header. 2019-09-10 09:08:34 -07:00
Philip Rideout
8d1b630b24 resgen: repair wasm builds. 2019-09-10 08:02:35 -07:00
Philip Rideout
1235a66f83 resgen: avoid overwriting the header if nothing changed. 2019-09-10 08:02:35 -07:00
Philip Rideout
411e7f4511 resgen: use extern int instead of #define. 2019-09-10 08:02:35 -07:00
Philip Rideout
cf095cbdd2 filagui: use resgen for the UI material.
This makes building samples faster when combined with PR #1613.
2019-09-10 08:02:23 -07:00
Philip Rideout
394db90ec9 CMake: Use configure_file for licenses.inc
Every time ninja invoked CMake, we were unconditionally regenerating
all of our "licenses.inc" files which caused a ton of re-compiles.

Before the change, building after touching `ubershader.mat.in` took over
a minute, now it takes 20 seconds.

The CMake "file" commands are bad. The CMake documentation says:

    If the file is a build input, use the configure_file() command
    to update the file only when its content changes.
2019-09-10 08:02:12 -07:00
Philip Rideout
72644f1416 mipgen: add --quiet argument.
Note that some encodings like astc will still be noisy due to
third-party code but this works fine for the s3tc encoder.
2019-09-10 08:01:49 -07:00
Philip Rideout
ed2fc0e391 matdbg: opt-in via environment variable. 2019-09-10 08:01:29 -07:00
Ben Doherty
c9f4d983a0 Convert SSAO shaders to use post-process materials (#1610) 2019-09-09 16:41:49 -07:00
Philip Rideout
694db54d9d Minor cleanup. 2019-09-09 11:10:39 -07:00
Philip Rideout
15b663ba0b matdbg client: show inactive variants in gray.
This makes it easier to find the variants that are actually being used.
2019-09-09 11:04:02 -07:00
Philip Rideout
23ee5e276c matdbg server: add query for active programs.
This uses the program cache to determine the set of variants that
are actually being used.
2019-09-09 11:04:02 -07:00
Ben Doherty
7c24a1bbaa Add custom vertex shaders for post-process materials (#1606) 2019-09-09 09:17:35 -07:00
Ben Doherty
32eee2cdf1 Tungsten: upgrade Gradle, fix IBL (#1604) 2019-09-09 09:13:06 -07:00
Ben Doherty
7dbad8928f Ensure GitHub actions build presubmit (#1605) 2019-09-06 19:43:42 -07:00
Philip Rideout
0e81207758 WebGL: add demo for glTF animation.
Fixes #1583.
2019-09-06 16:44:03 -07:00
Philip Rideout
c67266833a gltfio: rename getResourceUrl => getResourceUri 2019-09-06 16:43:53 -07:00
Philip Rideout
d6b0b6ff52 gltfio: expose all resource URI strings.
Some buffers (like animation data) do not contain any vertex data
but web-based clients still need to know about this.

This interface is much simpler than the bindings lists, and in fact
we might remove the binding lists in the future to simplify the API.

Fixes #1593.
2019-09-06 16:43:53 -07:00
Ben Doherty
9d0ad3586d Update tonemapping to use new post-process material domain (#1428) 2019-09-06 15:04:52 -07:00
Philip Rideout
7393d5d98c WebGL: add LightManager getter methods to fix #1599. 2019-09-06 14:12:33 -07:00
Mathias Agopian
7a819a60ae RGB32F is never supported as a render target 2019-09-06 11:09:20 -07:00
Mathias Agopian
c735659592 better handle float rendertargets. fixes #1533
some driver don't support all float buffers as rendertarget, so we
improve the backends (opengl in this PR) to return what it actually
supports and we update the client (filament) to take that into
account when making decisions.
2019-09-06 11:09:20 -07:00
Mathias Agopian
c36745db97 simplify DriverAPI.inc macros a bit further
we now handle zero argument declaration in some cases.
2019-09-06 11:08:59 -07:00
Philip Rideout
a5284af2b8 Use original glTF filename for FlightHelmet. 2019-09-06 10:47:47 -07:00
Philip Rideout
4989c3dc48 Remove unused material. 2019-09-06 10:47:47 -07:00
Philip Rideout
3925b0a8ec matdbg: Add detailed README describing the design. 2019-09-06 08:17:02 -07:00
Mathias Agopian
356610ba1d simplify DriverAPI.inc macros
by using variadic macros we can greatly simplify the macros
definitions for declaring the backend API.

in particular we don't need a macro per number-of-argument, this is
now done automatically.

Unfortunately, we still can't handle zero-argument declarations, so
we keep the _0 variants.
2019-09-05 15:07:25 -07:00
Philip Rideout
9eae72f99d matdbg: allow editing for GLSL shaders.
This performs surgical modification of the IFF chunks rather than
invoking filamat from within matdbg. Low-level direct manipulation
(bypassing optimization passes etc) allows us to diagnose issues with
the shading pipeline.

This CL also adds keystroke bindings to the Monaco editor. You can
press Cmd+S to rebuild the current materials, or use Ctrl+Arrow to
navigate between shader variants and materials.

In a subsequent CL I will add a README that describes how this works in
detail, it will include a list of limitations and a feature wishlist.
2019-09-05 13:03:49 -07:00
Philip Rideout
1d12fc1aaa Fix default IBL in lucy_bloom. 2019-09-04 13:35:34 -07:00
Philip Rideout
f9bd085757 OpenGL: shader errors should not cause termination.
We now check for FILAMENT_ENABLE_MATDBG and simply skip the draw call
when the program is invalid. The initial error message is still dumped
to the console, but we will not terminate or dump an infinite cascade of
error messages.
2019-09-04 13:11:11 -07:00
Philip Rideout
1003926665 Engine: add support for material edits.
This only adds Engine-side support for edits. The debugger client will
be enhanced in another PR. This works by simply clearing the program
cache and swapping out the MaterialParser. Neat!

However, there are some gotchas:

- The DebugServer callback is triggered on another thread so to be safe
  we defer the swap until the subsequent call to getProgram().

- The getProgram() method is const but in reality it can insert entries
  into a mutable cache. This CL makes the constness of it even more
  misleading by applying edits.

- The edit operation will leak the old HwProgram but I feel this is
  fine because simplicity is crucial for injected behavior and this is
  a developer-only feature.
2019-09-04 13:10:44 -07:00
Mathias Agopian
709180932e use Builder.sample() instead Builder.read() for textures
Texture are special resources that can be read in different ways; either as
attachment (read) or sampled (sample), the user must now declare explicitly if she intends
to sample from a texture.

sample() implies read() so there is no need to call both.

This was already the case, as read() used to take a boolean, essentially meaning the same
thing. However, the bool didn't make sense for non-texture resources.

This also simplifies the implementation.
2019-09-04 11:40:59 -07:00
Mathias Agopian
132326f8f2 getDescriptor() needn't be const 2019-09-04 11:40:59 -07:00
Mathias Agopian
92e86de630 No need to specify the sample count for attachments
the framegraph will figure it out automatically from the 
rendertarget sample count. this is done during resolve(), and after
moveResource is taken into account (so this works with imported and
moved resources).
2019-09-04 11:40:59 -07:00
Mathias Agopian
3e8a145fce importRenderTarget() now returns a FrameGraphRenderTargerHandle
This makes the API more symetric/logical.
2019-09-04 11:40:59 -07:00
Mathias Agopian
a5db6a84b6 add name to rendertarget creation 2019-09-04 11:40:59 -07:00
Mathias Agopian
f192b89ef9 sample count for rendertargets doesn't need to be specified
when creating a rendertarget, if the sample count is not specified,
any existing target with the same attachment will match.
this simplifies both the user and implementation.

getRenderTargetDescriptor() now takes a RenderTargetHandle instead
of a texture handle.
2019-09-04 11:40:59 -07:00
Mathias Agopian
637395b075 declaring a rendertarget now returns a FrameGraphRenderTargetHandle
this makes managing render targets more excplicit and simplify the
code a lot. before, render targets were referenced through one of
their attachment.
2019-09-04 11:40:59 -07:00
Philip Rideout
b03172f4a2 Java bindings: fix CUSTOM attribute mismatch.
Fix #1578
2019-09-03 15:49:22 -07:00
Romain Guy
24225315fa Add iOS presubmit (#1589)
* Add iOS presubmit

* Use a separate workflow for iOS
2019-09-03 11:56:32 -07:00
Romain Guy
2bc9256a7a Fix compilation error when DEBUG_COMMAND_STREAM is true (#1588)
Fixes issue #1585
2019-09-03 10:00:11 -07:00
Philip Rideout
264cf020b6 Minor TypeScript annotations fix. 2019-09-03 08:44:16 -07:00
Romain Guy
ceafc7835b Rename CI workflow to Presubmit 2019-08-31 11:53:20 -07:00
Romain Guy
db8d4ee076 Setup Linux for GitHub CI (#1581)
* Setup Linux for GitHub CI

* Pass env var properly
2019-08-30 15:24:29 -07:00
Romain Guy
26f7907b17 Fix punctuation (#1580) 2019-08-30 14:59:25 -07:00
Romain Guy
c35f1e0b29 More fixes 2019-08-30 14:53:02 -07:00
Romain Guy
e2ee00e36e Fix Linux CI on GitHub 2019-08-30 14:50:40 -07:00
Romain Guy
d87f77c41a Don't set $TARGET 2019-08-30 14:45:03 -07:00
Romain Guy
13fcce2d9a Fix workflow 2019-08-30 14:44:47 -07:00
Romain Guy
216761656f Fix CI 2019-08-30 14:38:37 -07:00
Romain Guy
05e9d708ed Update build scripts for workflows 2019-08-30 14:29:44 -07:00
Romain Guy
cc321385cd Run CI on Linux and macOS 2019-08-30 14:29:18 -07:00
Romain Guy
038d39f294 Fix path 2019-08-30 14:07:01 -07:00
Romain Guy
3555a01541 Support for workflows 2019-08-30 14:03:55 -07:00
Romain Guy
5d52266eac Add workflow 2019-08-30 14:03:37 -07:00
Romain Guy
5368756983 Remove workflow 2019-08-30 13:59:34 -07:00
Romain Guy
f74e136f46 Add GitHub Action for CI duty 2019-08-30 12:02:39 -07:00
Romain Guy
040c1c686a Update build script to support GitHub Actions 2019-08-30 12:02:21 -07:00
Philip Rideout
e74c33ce04 Java bindings now define CUSTOM / MORPH attribs.
Fixes #1578.
2019-08-29 17:13:28 -07:00
Philip Rideout
ab24634637 Add matdbg to READMEs. 2019-08-29 10:19:18 -07:00
Philip Rideout
8f3bdc20ba matdbg: add "install" directive.
Fixes #1576.
2019-08-29 10:19:18 -07:00
Romain Guy
74aaaed4db Code cleanup 2019-08-29 09:34:12 -07:00
Philip Rideout
9c64c20ceb matdbg: fail gracefully, emit logs, fewer threads. 2019-08-29 09:13:20 -07:00
Mathias Agopian
b92c748fcc Use allocator Debug policy in more places 2019-08-28 19:06:54 -07:00
Mathias Agopian
844dde4e6d simple allocation debugger
This can be enabled by using the Tracking::Debug policy,
currently this just fills allocation on alloc() and free(),
which is useful to help detect access to uninitialized memory
and use after free.

Now enabled by default in libfilament allocators on debug builds.

This caught uninitialized access in the froxelizer.
2019-08-28 19:06:54 -07:00
Philip Rideout
c0de0ca36d gltfio: fix transforms for nodes with non-uniform scale.
I tested this with the problem model and a couple other models.

This bug is inherited from cgltf_node_transform_local, so I will
upstream the fix. There are two ways to see that the new math is
correct:

1) Look at decomposeMatrix and note that scales belong to rows,
   not columns.

2) Look at the Brandon Jones implementation:
   http://glmatrix.net/docs/mat4.js.html#line1079

Fixes #1519.
2019-08-28 15:31:33 -07:00
Mathias Agopian
ad3bc4a6f7 ran "optimize imports" on all files
This removed a few unneeded imports.
2019-08-28 15:19:50 -07:00
Mathias Agopian
572b2cff57 fix use after free
We were storing pointer to RenderTarget objects that were allocated
in a vector<>, which obviously is not safe.
This didn't cause any issue most of the time because our allocator is
a linear allocator.
2019-08-28 15:19:26 -07:00
Philip Rideout
fb9cf43768 WebGL: fix JPEG decoding.
We've been using STB for a while now and we already include a JPEG
decoder in our wasm bundle. This removes some vestigial code that was
getting in the way.

Fixes #1565.
2019-08-28 13:15:15 -07:00
Philip Rideout
f41db8bb91 gltfio: add lazy loading to ubershader mode. 2019-08-28 13:01:05 -07:00
Philip Rideout
89c8e7c51a gltfio: support doubleSided in ubershader mode.
Fixes #1562
2019-08-28 13:01:05 -07:00
Jordan Rupprecht
0ad21cd47a Avoid undefined behavior when doing pointer calculation.
Performing `base + offset` pointer arithmetic is only allowed when `base` itself is not nullptr. In other words, the compiler is assumed to allow that `base + offset` is always non-null, which an upcoming compiler release will do in this case. The result is that CommandStream.cpp, which calls this in a loop until the result is nullptr, will never terminate (until it runs junk data and crashes).

Avoid this by using intptr_t instead of actual pointers (i.e. char*), which seems to avoid this failure.
2019-08-28 12:13:09 -07:00
Mathias Agopian
7dbf81fe3d FrameGraphPassResources should use typed FrameGraphId<> 2019-08-28 11:43:27 -07:00
Mathias Agopian
3072309574 rename FrameGraphResource to FrameGraphHandle
also FrameFrapheResourceId to FrameGraphId.
2019-08-28 11:43:27 -07:00
Mathias Agopian
573e9220a2 Improve import API and code 2019-08-28 11:43:27 -07:00
Mathias Agopian
e22f02d228 public APIs only use FrameGraphResourceId<> 2019-08-28 11:43:27 -07:00
Mathias Agopian
b620b7efa1 major framegraph overhaul 2019-08-28 11:43:27 -07:00
Philip Rideout
d1593326cb gltfio: support spec-gloss in ubershader mode.
Fixes #1564.
2019-08-28 10:56:56 -07:00
Romain Guy
6a8e6d45b5 Improve materials under white furnace test (#1563)
* Improve materials under white furnace test

Two major changes:
- Mobile target now implements a cheaper variant of the off specular
  peak bias (which moves the reflected vector towards the normal).
  This greatly helps with rough surfaces that may otherwise point
  toward a bright part of the IBL.
- The indirect diffuse love is now properly attenuated to avoid adding
  the energy reflected by the specular layer. This allows dielectrics
  to be correctly energy conserving under a white furnace.
- Tweak the (hacky) clear coat layer attenuation to behave properly
  under a white furnace.

* Use the same reflected vector modification everywhere
2019-08-28 10:39:57 -07:00
Ben Doherty
11336964a1 Add startCapture and stopCapture debug driver methods (#1560) 2019-08-28 10:34:46 -07:00
Mathias Agopian
71e98d54f5 add missing includes 2019-08-27 18:03:45 -07:00
Mathias Agopian
417ba87fcb don't use hard-coded values for Builder::radiance()
Instead we use constexpr expressions of the values,
which makes it much easier to remember where they
come from.
2019-08-26 17:47:28 -07:00
prideout
f71fea4ef5 Update release notes. 2019-08-26 14:16:07 -07:00
6376 changed files with 550916 additions and 482163 deletions

View File

@@ -0,0 +1,41 @@
name: Android
on:
push:
branches:
- master
jobs:
build-android:
name: build-android
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/android && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-android
path: out/filament-android-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: filamat-android-full
path: out/filamat-android-full-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: filamat-android-lite
path: out/filamat-android-lite-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: gltfio-android-release
path: out/gltfio-android-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: gltfio-android-lite-release
path: out/gltfio-android-lite-release.aar
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-utils-android-release
path: out/filament-utils-android-release.aar

24
.github/workflows/ios-continuous.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: iOS
on:
push:
branches:
- master
jobs:
build-ios:
name: build-ios
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/ios && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-ios
path: out/filament-release-ios.tgz
- name: Build iOS samples
run: |
cd build/ios && ./build-samples.sh continuous

21
.github/workflows/linux-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Linux
on:
push:
branches:
- master
jobs:
build-linux:
name: build-linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/linux && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-linux
path: out/filament-release-linux.tgz

21
.github/workflows/mac-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: macOS
on:
push:
branches:
- master
jobs:
build-mac:
name: build-mac
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/mac && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-mac
path: out/filament-release-darwin.tgz

63
.github/workflows/presubmit.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Presubmit
on: [pull_request]
jobs:
build-desktop:
name: build-desktop
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
cd build/$WORKFLOW_OS && ./build.sh presubmit
build-windows:
name: build-windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
build\windows\build-github.bat presubmit
shell: cmd
build-android:
name: build-android
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/android && ./build.sh presubmit
build-ios:
name: build-iOS
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/ios && ./build.sh presubmit
- name: Build iOS samples
run: |
cd build/ios && ./build-samples.sh presubmit
build-web:
name: build-web
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/web && ./build.sh presubmit

178
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,178 @@
name: Release
# This Workflow can be triggered two ways:
# 1. A GitHub release is created (using the GitHub web UI). This triggers all of the platforms to build and upload assets.
# 2. A repository_dispatch API event is sent. This triggers a build for only the platform specified in the dispatch event.
env:
RELEASE_TAG: ${{ github.event.client_payload.release_tag }}
on:
repository_dispatch:
release:
types: [created]
jobs:
build-desktop:
name: build-desktop
runs-on: ${{ matrix.os }}
if: github.event_name == 'release' || github.event.client_payload.platform == 'desktop'
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v2.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
cd build/$WORKFLOW_OS && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
if [ -f out/filament-release-darwin.tgz ]; then mv out/filament-release-darwin.tgz out/filament-${DATE}-mac.tgz; fi;
if [ -f out/filament-release-linux.tgz ]; then mv out/filament-release-linux.tgz out/filament-${DATE}-linux.tgz; fi;
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-web:
name: build-web
runs-on: macos-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'web'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v2.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
cd build/web && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-release-web.tgz out/filament-${DATE}-web.tgz
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-android:
name: build-android
runs-on: macos-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'android'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v2.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
cd build/android && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-android-release.aar out/filament-${DATE}-android.aar
mv out/filamat-android-full-release.aar out/filamat-${DATE}-android.aar
mv out/filamat-android-lite-release.aar out/filamat-${DATE}-lite-android.aar
mv out/gltfio-android-release.aar out/gltfio-${DATE}-android.aar
mv out/gltfio-android-release.aar out/gltfio-${DATE}-lite-android.aar
mv out/filament-utils-android-release.aar out/filament-utils-${DATE}-android.aar
mv out/filament-utils-android-release.aar out/filament-utils-${DATE}-lite-android.aar
python3 build/common/upload-assets.py ${TAG} out/*.aar
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-ios:
name: build-ios
runs-on: macos-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'ios'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
- uses: actions/checkout@v2.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
cd build/ios && ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-release-ios.tgz out/filament-${DATE}-ios.tgz
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}
build-windows:
name: build-windows
runs-on: windows-latest
if: github.event_name == 'release' || github.event.client_payload.platform == 'windows'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo ::set-output name=ref::${REF}
echo ::set-output name=tag::${TAG}
shell: bash
- uses: actions/checkout@v2.0.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
run: |
build\windows\build-github.bat release
shell: cmd
- name: Upload release assets
run: |
pip3 install PyGithub
DATE=`date +%Y%m%d`
mv out/filament-windows.tgz out/filament-${DATE}-windows.tgz
python build/common/upload-assets.py ${TAG} out/*.tgz
shell: bash
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}

21
.github/workflows/web-continuous.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Web
on:
push:
branches:
- master
jobs:
build-web:
name: build-web
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
cd build/web && ./build.sh continuous
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-web
path: out/filament-release-web.tgz

View File

@@ -0,0 +1,22 @@
name: Windows
on:
push:
branches:
- master
jobs:
build-windows:
name: build-windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v2.0.0
- name: Run build script
run: |
build\windows\build-github.bat continuous
shell: cmd
- uses: actions/upload-artifact@v1.0.0
with:
name: filament-windows
path: out/filament-windows.tgz

4
.gitignore vendored
View File

@@ -3,7 +3,7 @@
imgui.ini
cmake-*
ImportExecutables-*.cmake
out
/out*
dist
dist-*
toolchains
@@ -11,3 +11,5 @@ filament/docs/html/**
.vscode
gltf_baker.ini
*tmp*.png
civetweb.txt
/TAGS

451
BUILDING.md Normal file
View File

@@ -0,0 +1,451 @@
## Building Filament
### Prerequisites
To build Filament, you must first install the following tools:
- CMake 3.10 (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):
- OpenJDK 1.8 (or more recent)
Additional dependencies may be required for your operating system. Please refer to the appropriate
section below.
Building the `rays` library (used for light baking) is optional and requires the following packages:
- embree 3.0+
- libtbb-dev
To build Filament for Android you must also install the following:
- Android Studio 3.6 or more recent
- Android SDK
- Android NDK "side-by-side" 21 or higher
### Environment variables
Make sure the environment variable `ANDROID_HOME` points to the location of your Android SDK.
By default our build system will attempt to compile the Java bindings. To do so, the environment
variable `JAVA_HOME` should point to the location of your JDK.
When building for WebGL, you'll also need to set `EMSDK`. See [WebAssembly](#webassembly).
### IDE
We recommend using CLion to develop for Filament. Simply open the root directory's CMakeLists.txt
in CLion to obtain a usable project.
### Easy build
Once the required OS specific dependencies listed below are installed, you can use the script
located in `build.sh` to build Filament easily on macOS and Linux.
This script can be invoked from anywhere and will produce build artifacts in the `out/` directory
inside the Filament source tree.
To trigger an incremental debug build:
```
$ ./build.sh debug
```
To trigger an incremental release build:
```
$ ./build.sh release
```
To trigger both incremental debug and release builds:
```
$ ./build.sh debug release
```
To install the libraries and executables in `out/debug/` and `out/release/`, add the `-i` flag.
You can force a clean build by adding the `-c` flag. The script offers more features described
by executing `build.sh -h`.
### Disabling Java builds
By default our build system will attempt to compile the Java bindings. If you wish to skip this
compilation step simply pass the `-j` flag to `build.sh`:
```
$ ./build.sh -j release
```
If you use CMake directly instead of the build script, pass `-DFILAMENT_ENABLE_JAVA=OFF`
to CMake instead.
### Filament-specific CMake Options
The following CMake options are boolean options specific to Filament:
- `FILAMENT_ENABLE_JAVA`: Compile Java projects: requires a JDK and the JAVA_HOME env var
- `FILAMENT_ENABLE_LTO`: Enable link-time optimizations if supported by the compiler
- `FILAMENT_BUILD_FILAMAT`: Build filamat and JNI buildings
- `FILAMENT_SUPPORTS_METAL`: Include the Metal backend
- `FILAMENT_SUPPORTS_VULKAN`: Include the Vulkan backend
- `FILAMENT_GENERATE_JS_DOCS`: Build WebGL documentation and tutorials
- `FILAMENT_INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
- `FILAMENT_USE_EXTERNAL_GLES3`: Experimental: Compile Filament against OpenGL ES 3
- `FILAMENT_SKIP_SAMPLES`: Don't build sample apps
To turn an option on or off:
```
$ cd <cmake-build-directory>
$ cmake . -DOPTION=ON # Relace OPTION with the option name, set to ON / OFF
```
Options can also be set with the CMake GUI.
### Linux
Make sure you've installed the following dependencies:
- `clang-7` or higher
- `libglu1-mesa-dev`
- `libc++-7-dev` (`libcxx-devel` and `libcxx-static` on Fedora) or higher
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora) or higher
- `ninja-build`
- `libxi-dev`
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
script.
If you'd like to run `cmake` directly rather than using the build script, it can be invoked as
follows, with some caveats that are explained further down.
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
Your Linux distribution might default to `gcc` instead of `clang`, if that's the case invoke
`cmake` with the following command:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
# Or use a specific version of clang, for instance /usr/bin/clang-7
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
You can also export the `CC` and `CXX` environment variables to always point to `clang`. Another
solution is to use `update-alternatives` to both change the default compiler, and point to a
specific version of clang:
```
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100
$ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
$ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
```
Finally, invoke `ninja`:
```
$ ninja
```
This will build Filament, its tests and samples, and various host tools.
### macOS
To compile Filament you must have the most recent version of Xcode installed and you need to
make sure the command line tools are setup by running:
```
$ xcode-select --install
```
After installing Java 1.8 you must also ensure that your `JAVA_HOME` environment variable is
properly set. If it doesn't already point to the appropriate JDK, you can simply add the following
to your `.profile`:
```
export JAVA_HOME="$(/usr/libexec/java_home)"
```
Then run `cmake` and `ninja` to trigger a build:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
$ ninja
```
### iOS
The easiest way to build Filament for iOS is to use `build.sh` and the
`-p ios` flag. For instance to build the debug target:
```
$ ./build.sh -p ios debug
```
See [ios/samples/README.md](./ios/samples/README.md) for more information.
### Windows
#### Building on Windows with Visual Studio 2019
Install the following components:
- [Visual Studio 2019](https://www.visualstudio.com/downloads)
- [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
- [CMake 3.14 or later](https://github.com/Kitware/CMake/releases/download/v3.14.7/cmake-3.14.7-win64-x64.msi)
The latest Windows SDK can also by installed by opening Visual Studio and selecting _Get Tools and
Features..._ under the _Tools_ menu.
Open the `x64 Native Tools Command Prompt for VS 2019`.
Create a working directory, and run cmake in it:
```
> mkdir out
> cd out
> cmake ..
```
Open the generated solution file `TNT.sln` in Visual Studio.
To build all targets, run _Build Solution_ from the _Build_ menu. Alternatively, right click on a
target in the _Solution Explorer_ and choose _Build_ to build a specific target.
For example, build the `material_sandbox` sample and run it from the `out` directory with:
```
> samples\Debug\material_sandbox.exe ..\assets\models\monkey\monkey.obj
```
### Android
Before building Filament for Android, make sure to build Filament for your host. Some of the
host tools are required to successfully build for Android.
Filament can be built for the following architectures:
- ARM 64-bit (`arm64-v8a`)
- ARM 32-bit (`armeabi-v7a`)
- Intel 64-bit (`x86_64`)
- Intel 32-bit (`x86`)
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
`-p android` flag. For instance to build the release target:
```
$ ./build.sh -p android release
```
Run `build.sh -h` for more information.
#### Manual builds
Invoke CMake in a build directory of your choice, inside of filament's directory. The commands
below show how to build Filament for ARM 64-bit (`aarch64`).
```
$ mkdir out/android-build-release-aarch64
$ cd out/android-build-release-aarch64
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-aarch64-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/arm64-v8a`.
#### AAR
Before you attempt to build the AAR, make sure you've compiled and installed the native libraries
as explained in the sections above. You must have the following ABIs built in
`out/android-release/filament/lib/`:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To build Filament's AAR simply open the Android Studio project in `android/`. The
AAR is a universal AAR that contains all supported build targets:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To filter out unneeded ABIs, rely on the `abiFilters` of the project that links against Filament's
AAR.
Alternatively you can build the AAR from the command line by executing the following in the
`android/` directory:
```
$ ./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
```
The `-Pfilament_dist_dir` can be used to specify a different installation directory (it must match
the CMake install prefix used in the previous steps).
#### Using Filament's AAR
Create a new module in your project and select _Import .JAR or .AAR Package_ when prompted. Make
sure to add the newly created module as a dependency to your application.
If you do not wish to include all supported ABIs, make sure to create the appropriate flavors in
your Gradle build file. For example:
```
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'
}
}
```
### WebAssembly
The core Filament library can be cross-compiled to WebAssembly from either macOS or Linux. To get
started, follow the instructions for building Filament on your platform ([macOS](#macos) or
[linux](#linux)), which will ensure you have the proper dependencies installed.
Next, you need to install the Emscripten SDK. The following instructions show how to install the
same version that our continuous builds use.
```
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/1b1f08f.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
python ./emsdk.py install latest
python ./emsdk.py activate latest
source ./emsdk_env.sh
```
After this you can invoke the [easy build](#easy-build) script as follows:
```
export EMSDK=<your chosen home for the emscripten SDK>
./build.sh -p webgl release
```
The EMSDK variable is required so that the build script can find the Emscripten SDK. The build
creates a `samples` folder that can be used as the root of a simple static web server. Note that you
cannot open the HTML directly from the filesystem due to CORS. One way to deal with this is to
use Python to create a quick localhost server:
```
cd out/cmake-webgl-release/web/samples
python3 -m http.server # Python 3
python -m SimpleHTTPServer # Python 2.7
```
You can then open http://localhost:8000/suzanne.html in your web browser.
Alternatively, if you have node installed you can use the
[live-server](https://www.npmjs.com/package/live-server) package, which automatically refreshes the
web page when it detects a change.
Each sample app has its own handwritten html file. Additionally the server folder contains assets
such as meshes, textures, and materials.
## Running the native samples
The `samples/` directory contains several examples of how to use Filament with SDL2.
Some of the samples accept FBX/OBJ meshes while others rely on the `filamesh` file format. To
generate a `filamesh ` file from an FBX/OBJ asset, run the `filamesh` tool
(`./tools/filamesh/filamesh` in your build directory):
```
filamesh ./assets/models/monkey/monkey.obj monkey.filamesh
```
Most samples accept an IBL that must be generated using the `cmgen` tool (`./tools/filamesh/cmgen`
in your build directory). These sample apps expect a path to a directory containing the '.rgb32f'
files for the IBL (which are PNGs containing `R11F_G11F_B10F` data). To generate an IBL simply use
this command:
```
cmgen -x ./ibls/ my_ibl.exr
```
The source environment map can be a PNG (8 or 16 bit), a PSD (16 or 32 bit), an HDR or an OpenEXR
file. The environment map can be an equirectangular projection, a horizontal cross, a vertical
cross, or a list of cubemap faces (horizontal or vertical).
`cmgen` will automatically create a directory based on the name of the source environment map. In
the example above, the final directory will be `./ibls/my_ibl/`. This directory should contain the
pre-filtered environment map (one file per cubemap face and per mip level), the environment map
texture for the skybox and a text file containing the level harmonics for indirect diffuse
lighting.
If you prefer a blurred background, run `cmgen` with this flag: `--extract-blur=0.1`. The numerical
value is the desired roughness between 0 and 1.
## Generating C++ documentation
To generate the documentation you must first install `doxygen` and `graphviz`, then run the
following commands:
```
$ cd filament/filament
$ doxygen docs/doxygen/filament.doxygen
```
Finally simply open `docs/html/index.html` in your web browser.

View File

@@ -11,14 +11,49 @@ project(TNT)
# ==================================================================================================
# Options
# ==================================================================================================
option(FILAMENT_ENABLE_JAVA "Compile Java projects, requires a JDK and the JAVA_HOME env var" ON)
option(ENABLE_JAVA "Compile Java projects, requires a JDK and the JAVA_HOME env var" ON)
option(FILAMENT_USE_EXTERNAL_GLES3 "Experimental: Compile Filament against OpenGL ES 3" OFF)
option(USE_EXTERNAL_GLES3 "Experimental: Compile Filament against OpenGL ES 3" OFF)
option(FILAMENT_GENERATE_JS_DOCS "Build WebGL documentation and tutorials" OFF)
option(GENERATE_JS_DOCS "Build WebGL documentation and tutorials" OFF)
option(FILAMENT_ENABLE_LTO "Enable link-time optimizations if supported by the compiler" OFF)
option(ENABLE_LTO "Enable link-time optimizations if supported by the compiler" OFF)
option(FILAMENT_SKIP_SAMPLES "Don't build samples" OFF)
# ==================================================================================================
# CMake policies
# ==================================================================================================
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.12")
cmake_policy(SET CMP0074 NEW)
endif()
# ==================================================================================================
# Support for ccache
# ==================================================================================================
find_program(CCACHE_PROGRAM ccache)
if (CCACHE_PROGRAM)
set(C_LAUNCHER "${CCACHE_PROGRAM}")
set(CXX_LAUNCHER "${CCACHE_PROGRAM}")
configure_file(build/launch-c.in launch-c)
configure_file(build/launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx"
)
if (CMAKE_GENERATOR STREQUAL "Xcode")
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
else()
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
endif()
# ==================================================================================================
# OS specific
@@ -69,16 +104,15 @@ endif()
# Check if embree is available.
# This is an optional dependency and can be installed with homebrew, apt-get, etc.
# ==================================================================================================
find_package(embree 3.0 QUIET PATHS /usr/lib64/cmake)
if (embree_FOUND AND NOT ANDROID)
if (embree_FOUND AND NOT ANDROID AND NOT IOS)
message("Found embree in ${embree_DIR}")
set(MKLDNN_THREADING "TBB")
include(third_party/OpenImageDenoise/cmake/resource.cmake)
include(third_party/OpenImageDenoise/mkl-dnn/cmake/Threading.cmake)
include(third_party/OpenImageDenoise/mkl-dnn/cmake/TBB.cmake)
find_package(TBB QUIET)
if (TBB_FOUND AND "${TBB_VERSION_MAJOR}" VERSION_EQUAL 2019)
if (TBB_FOUND)
message("Found TBB ${TBB_VERSION}")
add_definitions(-DFILAMENT_HAS_EMBREE)
set(DENOISE_LIBRARY OpenImageDenoise)
@@ -113,7 +147,7 @@ if (CMAKE_C_COMPILER_ID MATCHES "Clang")
if (CMAKE_C_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION)
message(FATAL_ERROR "Detected C compiler Clang ${CMAKE_C_COMPILER_VERSION} < ${MIN_CLANG_VERSION}")
endif()
else()
elseif (NOT MSVC)
message(FATAL_ERROR "Detected C compiler ${CMAKE_C_COMPILER_ID} is unsupported")
endif()
@@ -121,19 +155,21 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION)
message(FATAL_ERROR "Detected CXX compiler Clang ${CMAKE_CXX_COMPILER_VERSION} < ${MIN_CLANG_VERSION}")
endif()
else()
elseif (NOT MSVC)
message(FATAL_ERROR "Detected CXX compiler ${CMAKE_CXX_COMPILER_ID} is unsupported")
endif()
# Detect use of the clang-cl.exe frontend, which does not support all of clangs normal options
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
set(CLANG_CL true)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if ("${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
message(FATAL_ERROR "Building with Clang on Windows is no longer supported. Use MSVC 2019 instead.")
endif()
endif()
# ==================================================================================================
# Link time optimizations (LTO)
# ==================================================================================================
if (ENABLE_LTO)
if (FILAMENT_ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORT)
@@ -152,9 +188,14 @@ if (WIN32)
set(CXX_STANDARD "/std:c++14")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function")
if (MSVC)
set(CXX_STANDARD "/std:c++latest")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} /W0 /Zc:__cplusplus")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function")
endif()
if (USE_EXTERNAL_GLES3)
if (FILAMENT_USE_EXTERNAL_GLES3)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_EXTERNAL_GLES3")
endif()
@@ -173,7 +214,7 @@ if (CYGWIN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
endif()
if (CLANG_CL)
if (MSVC)
# Since the "secure" replacements that MSVC suggests are not portable, disable
# the deprecation warnings. Also disable warnings about use of POSIX functions (i.e. "unlink").
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE")
@@ -189,7 +230,7 @@ endif()
# ==================================================================================================
# Release compiler flags
# ==================================================================================================
if (NOT CLANG_CL)
if (NOT MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ffunction-sections -fdata-sections")
endif()
@@ -199,6 +240,13 @@ if (ANDROID OR WEBGL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
endif()
# With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth
# between C++ and JavaScript in order to efficiently access typed arrays, which are unbound.
# NOTE: This is not documented in emscripten so we should consider a different approach.
if (WEBGL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-rtti")
endif()
# ==================================================================================================
# Debug compiler flags
# ==================================================================================================
@@ -206,17 +254,24 @@ 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")
# clang-cl.exe on Windows does not support -fstack-protector.
if (NOT CLANG_CL)
if (NOT MSVC AND NOT WEBGL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
# Disable the stack check for macOS to workaround a known issue in clang 11.0.0.
# See: https://forums.developer.apple.com/thread/121887
if (APPLE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-stack-check")
endif()
# ==================================================================================================
# Linker flags
# ==================================================================================================
# Strip unused sections
set(GC_SECTIONS "-Wl,--gc-sections")
if (NOT WEBGL)
set(GC_SECTIONS "-Wl,--gc-sections")
endif()
set(B_SYMBOLIC_FUNCTIONS "-Wl,-Bsymbolic-functions")
if (APPLE)
@@ -229,9 +284,6 @@ if (APPLE)
# prevents ar from invoking ranlib, let CMake do it
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qc -S <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qc -S <TARGET> <LINK_FLAGS> <OBJECTS>")
elseif (CLANG_CL)
set(GC_SECTIONS "")
set(B_SYMBOLIC_FUNCTIONS "")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GC_SECTIONS}")
@@ -324,20 +376,47 @@ endif()
# ==================================================================================================
# Functions
# ==================================================================================================
## The MSVC compiler has a limitation on literal string length which is reached when all the
## licenses are concatenated together into a large string... so split them into multiple strings.
function(list_licenses OUTPUT MODULES)
file(WRITE ${OUTPUT} "R\"FILAMENT__(\n")
set(STR_OPENER "R\"FILAMENT__(")
set(STR_CLOSER ")FILAMENT__\"")
set(CONTENT)
set(_MODULES ${MODULES} ${ARGN})
foreach(module ${_MODULES})
set(license_path "../../third_party/${module}/LICENSE")
get_filename_component(fullname "${license_path}" ABSOLUTE)
file(APPEND ${OUTPUT} "License and copyrights for ${module}:\n\n")
file(READ ${license_path} license)
file(APPEND ${OUTPUT} ${license})
file(APPEND ${OUTPUT} "\n\n")
string(APPEND CONTENT "${STR_OPENER}License and copyrights for ${module}:\n${STR_CLOSER},\n")
file(READ ${license_path} license_long)
string(REPLACE "\n" "${STR_CLOSER},\n${STR_OPENER}" license ${license_long})
string(APPEND CONTENT ${STR_OPENER}${license}\n${STR_CLOSER},)
string(APPEND CONTENT "\n\n")
endforeach()
file(APPEND ${OUTPUT} ")FILAMENT__\"\n")
configure_file(${FILAMENT}/build/licenses.inc.in ${OUTPUT})
endfunction(list_licenses)
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/linux/combine-static-libs.sh")
if (WIN32)
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/windows/combine-static-libs.bat")
set(CMAKE_AR "lib.exe")
endif()
# Add a custom command to TARGET that combines the static libraries in DEPS into a single archive.
function(combine_static_libs TARGET OUTPUT DEPS)
# Loop through the dependent libraries and query their location on disk.
set(DEPS_FILES )
foreach(DEPENDENCY ${DEPS})
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
endforeach()
add_custom_command(
TARGET ${TARGET} POST_BUILD
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
COMMENT "Combining ${target} dependencies into single shared library"
VERBATIM
)
endfunction()
# ==================================================================================================
# Configuration for CMAKE_CROSSCOMPILING.
# ==================================================================================================
@@ -404,6 +483,7 @@ endfunction()
# Common to all platforms
add_subdirectory(${EXTERNAL}/libgtest/tnt)
add_subdirectory(${LIBRARIES}/camutils)
add_subdirectory(${LIBRARIES}/filabridge)
add_subdirectory(${LIBRARIES}/filaflat)
add_subdirectory(${LIBRARIES}/filameshio)
@@ -413,17 +493,19 @@ add_subdirectory(${LIBRARIES}/ibl)
add_subdirectory(${LIBRARIES}/image)
add_subdirectory(${LIBRARIES}/rays)
add_subdirectory(${LIBRARIES}/math)
add_subdirectory(${LIBRARIES}/mathio)
add_subdirectory(${LIBRARIES}/utils)
add_subdirectory(${FILAMENT}/filament)
add_subdirectory(${FILAMENT}/shaders)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/robin-map/tnt)
add_subdirectory(${EXTERNAL}/smol-v/tnt)
add_subdirectory(${EXTERNAL}/benchmark/tnt)
add_subdirectory(${EXTERNAL}/meshoptimizer)
add_subdirectory(${EXTERNAL}/cgltf/tnt)
add_subdirectory(${EXTERNAL}/draco/tnt)
add_subdirectory(${EXTERNAL}/xatlas/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
if (FILAMENT_BUILD_FILAMAT)
# spirv-tools must come before filamat, as filamat relies on the presence of the
@@ -443,13 +525,13 @@ if (APPLE)
add_subdirectory(${EXTERNAL}/moltenvk/tnt)
endif()
set (FILAMENT_SAMPLES_BINARY_DIR ${PROJECT_BINARY_DIR}/samples)
set(FILAMENT_SAMPLES_BINARY_DIR ${PROJECT_BINARY_DIR}/samples)
if (WEBGL)
add_subdirectory(web/filament-js)
add_subdirectory(web/samples)
if (GENERATE_JS_DOCS)
if (FILAMENT_GENERATE_JS_DOCS)
add_subdirectory(web/docs)
endif()
@@ -464,11 +546,12 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
add_subdirectory(${FILAMENT}/java/filamat)
add_subdirectory(${FILAMENT}/java/filament)
add_subdirectory(${FILAMENT}/samples)
add_subdirectory(${EXTERNAL}/astcenc/tnt)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/etc2comp)
add_subdirectory(${EXTERNAL}/getopt)
add_subdirectory(${EXTERNAL}/imgui/tnt)
add_subdirectory(${EXTERNAL}/libassimp/tnt)
add_subdirectory(${EXTERNAL}/libpng/tnt)
@@ -476,6 +559,7 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
add_subdirectory(${EXTERNAL}/libz/tnt)
add_subdirectory(${EXTERNAL}/skylight/tnt)
add_subdirectory(${EXTERNAL}/tinyexr/tnt)
add_subdirectory(${TOOLS}/cmgen)
add_subdirectory(${TOOLS}/filamesh)
add_subdirectory(${TOOLS}/glslminifier)
@@ -487,10 +571,11 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
add_subdirectory(${TOOLS}/roughness-prefilter)
add_subdirectory(${TOOLS}/skygen)
add_subdirectory(${TOOLS}/specular-color)
endif()
if (DENOISE_LIBRARY)
add_subdirectory(${EXTERNAL}/OpenImageDenoise/tnt)
if (DENOISE_LIBRARY)
add_subdirectory(${EXTERNAL}/OpenImageDenoise/tnt)
endif()
endif()
# Generate exported executables for cross-compiled builds (Android, WebGL, and iOS)

View File

@@ -40,3 +40,18 @@ information on using pull requests.
This project follows
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
## Dependencies
One of our design goals is that Filament itself should have no dependencies or as few dependencies
as possible. The current external dependencies of the runtime library include:
- STL
- robin-map (header only library)
When building with Vulkan enabled, we have a few additional small dependencies:
- vkmemalloc
- smol-v
Host tools (such as `matc` or `cmgen`) can use external dependencies freely.

814
README.md
View File

@@ -1,28 +1,61 @@
# Filament
<img alt="Android" src="build/img/android.png" width="20px" height="20px" hspace="2px"/>[![Android Build Status](https://filament-build.storage.googleapis.com/badges/build_status_android.svg)](https://filament-build.storage.googleapis.com/badges/build_link_android.html)
<img alt="iOS" src="build/img/macos.png" width="20px" height="20px" hspace="2px"/>[![iOS Build Status](https://filament-build.storage.googleapis.com/badges/build_status_ios.svg)](https://filament-build.storage.googleapis.com/badges/build_link_ios.html)
<img alt="Linux" src="build/img/linux.png" width="20px" height="20px" hspace="2px"/>[![Linux Build Status](https://filament-build.storage.googleapis.com/badges/build_status_linux.svg)](https://filament-build.storage.googleapis.com/badges/build_link_linux.html)
<img alt="macOS" src="build/img/macos.png" width="20px" height="20px" hspace="2px"/>[![MacOS Build Status](https://filament-build.storage.googleapis.com/badges/build_status_mac.svg)](https://filament-build.storage.googleapis.com/badges/build_link_mac.html)
<img alt="Windows" src="build/img/windows.png" width="20px" height="20px" hspace="2px"/>[![Windows Build Status](https://filament-build.storage.googleapis.com/badges/build_status_windows.svg)](https://filament-build.storage.googleapis.com/badges/build_link_windows.html)
<img alt="Web" src="build/img/web.png" width="20px" height="20px" hspace="2px"/>[![Web Build Status](https://filament-build.storage.googleapis.com/badges/build_status_web.svg)](https://filament-build.storage.googleapis.com/badges/build_link_web.html)
![Android Build Status](https://github.com/google/filament/workflows/Android/badge.svg)
![iOS Build Status](https://github.com/google/filament/workflows/iOS/badge.svg)
![Linux Build Status](https://github.com/google/filament/workflows/Linux/badge.svg)
![macOS Build Status](https://github.com/google/filament/workflows/macOS/badge.svg)
![Windows Build Status](https://github.com/google/filament/workflows/Windows/badge.svg)
![Web Build Status](https://github.com/google/filament/workflows/Web/badge.svg)
Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows,
and WebGL. It is designed to be as small as possible and as efficient as possible on Android.
Filament is currently used in the
[Sceneform](https://developers.google.com/ar/develop/java/sceneform/) library both at runtime on
Android devices and as the renderer inside the Android Studio plugin.
## Download
[Download Filament releases](https://github.com/google/filament/releases) to access stable builds.
Filament release archives contains host-side tools that are required to generate assets.
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.
If you'd rather build Filament yourself, please refer to our [build manual](BUILDING.md).
### Android
Android projects can simply declare Filament libraries as Maven dependencies:
```gradle
repositories {
// ...
mavenCentral()
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.5.0'
}
```
Here are all the libraries available in the group `com.google.android.filament`:
- `filament-android`: the Filament rendering engine itself
- `gltfio-android`: a glTF 2.0 loader for Filament, depends on `filament-android`
- `gltfio-android-lite`: trimmed version of `gltfio` that does not support some glTF features
- `filament-utils-android`: KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`
- `filament-utils-lite-android`: trimmed version of `filament-utils` that does not support some glTF features
- `filamat-android`: a runtime material builder/compiler. This library is large but contains
a full shader compiler/validator/optimizer
- `filamat-android-lite`: a much smaller alternative to `filamat-android` that can only
generate OpenGL shaders. It does not provide validation or optimizations
### Snapshots
If you prefer to live on the edge, you can download a continuous build by following the following
steps:
1. Find the [commit](https://github.com/google/filament/commits/master) you're interested in.
2. Click the green check mark under the commit message.
3. Click on the _Details_ link for the platform you're interested in.
4. On the top right, click on the _Artifacts_ dropdown and choose an artifact.
## Documentation
@@ -36,27 +69,29 @@ badges above.
- [Material Properties](https://google.github.io/filament/Material%20Properties.pdf), a reference
sheet for the standard material model.
## Samples
## Examples
### Materials
Here are a few sample materials rendered with Filament:
![Damaged Helmet](docs/images/samples/model_damaged_helmet.jpg)
![Helmet](docs/images/samples/model_helmet.jpg)
![Brushed copper](docs/images/samples/brushed_copper_2.jpg)
![Material 1](docs/images/samples/material_01.jpg)
![Material 2](docs/images/samples/material_02.jpg)
![Material 6](docs/images/samples/material_06.jpg)
![Material 8](docs/images/samples/material_08.jpg)
![Materials](docs/images/samples/example_materials1.jpg)
![Materials](docs/images/samples/example_materials2.jpg)
![Helmet](docs/images/samples/example_helmet.jpg)
![Car](docs/images/samples/example_car1.jpg)
![Car](docs/images/samples/example_car2.jpg)
![Screen-space refraction](docs/images/samples/example_ssr.jpg)
## Applications
### Applications
Here are a few screenshots of applications that use Filament in production:
### Google Maps AR Navigation
#### Google Maps AR Navigation
![Google Maps AR Navigation](docs/images/samples/app_gmm_ar_nav.jpg)
### Google Search 3D/AR Viewer on Android
#### Google Search 3D/AR Viewer on Android
![Google Search 3D/AR Viewer on Android](docs/images/samples/app_google_3d_viewer.jpg)
@@ -73,7 +108,7 @@ Here are a few screenshots of applications that use Filament in production:
- OpenGL 4.1+ for Linux, macOS and Windows
- OpenGL ES 3.0+ for Android and iOS
- Metal for macOS and iOS
- Vulkan 1.0 for Android, Linux, macOS and iOS (with MoltenVk), and Windows
- Vulkan 1.0 for Android, Linux, macOS, and Windows
- WebGL 2.0 for all platforms
### Rendering
@@ -91,652 +126,18 @@ Here are a few screenshots of applications that use Filament in production:
- Image-based lighting
- Physically-based camera (shutter speed, sensitivity and aperture)
- Physical light units
- Point light, spot light and directional light
- SSAO
- Point lights, spot lights and directional light
- Spot and directional light shadows
- Contact shadows
- Screen-space ambient occlusion
- Screen-space refraction
- Global fog
- HDR bloom
- ACES-like tone-mapping
- Temporal dithering
- FXAA, MSAA and specular anti-aliasing
- Dynamic resolution (on Android and iOS)
### Future
Many other features have been either prototyped or planned:
- IES light profiles/cookies
- Area lights
- Fog
- Color grading
- Bloom
- TAA
- etc.
## Directory structure
This repository not only contains the core Filament engine, but also its supporting libraries
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.)
- `assets`: 3D assets to use with sample applications
- `build`: CMake build scripts
- `docs`: Documentation
- `math`: Mathematica notebooks used to explore BRDFs, equations, etc.
- `filament`: Filament rendering engine (minimal dependencies)
- `ide`: Configuration files for IDEs (CLion, etc.)
- `ios`: Sample projects for iOS
- `java`: Java bindings for Filament libraries
- `libs`: Libraries
- `bluegl`: OpenGL bindings for macOS, Linux and Windows
- `bluevk`: Vulkan bindings for macOS, Linux, Windows and Android
- `filabridge`: Library shared by the Filament engine and host tools
- `filaflat`: Serialization/deserialization library used for materials
- `filagui`: Helper library for [Dear ImGui](https://github.com/ocornut/imgui)
- `filamat`: Material generation library
- `filameshio`: Tiny filamesh parsing library (see also `tools/filamesh`)
- `geometry`: Mesh-related utilities
- `gltfio`: Loader and optional pipeline for glTF 2.0
- `ibl`: IBL generation tools
- `image`: Image filtering and simple transforms
- `imageio`: Image file reading / writing, only intended for internal use
- `math`: Math library
- `rays`: Simple path tracer used for baking ambient occlusion, etc.
- `utils`: Utility library (threads, memory, data structures, etc.)
- `samples`: Sample desktop applications
- `shaders`: Shaders used by `filamat` and `matc`
- `third_party`: External libraries and assets
- `environments`: Environment maps under CC0 license that can be used with `cmgen`
- `models`: Models under permissive licenses
- `textures`: Textures under CC0 license
- `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
- `normal-blending`: Tool to blend normal maps
- `resgen` Aggregates binary blobs into embeddable resources
- `roughness-prefilter`: Pre-filters a roughness map from a normal map to reduce aliasing
- `skygen`: Physically-based sky environment texture generator
- `specular-color`: Computes the specular color of conductors based on spectral data
- `web`: JavaScript bindings, documentation, and samples
## Building Filament
### Prerequisites
To build Filament, you must first install the following tools:
- CMake 3.10 (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):
- OpenJDK 1.8 (or more recent)
Additional dependencies may be required for your operating system. Please refer to the appropriate
section below.
Building the `rays` library (used for light baking) is optional and requires the following packages:
- embree 3.0+
- libtbb-dev
To build Filament for Android you must also install the following:
- Android Studio 3.5
- Android SDK
- Android NDK 19 or higher
### Environment variables
Make sure the environment variable `ANDROID_HOME` points to the location of your Android SDK.
By default our build system will attempt to compile the Java bindings. To do so, the environment
variable `JAVA_HOME` should point to the location of your JDK.
When building for WebGL, you'll also need to set `EMSDK`. See [WebAssembly](#webassembly).
### IDE
We recommend using CLion to develop for Filament. Simply open the root directory's CMakeLists.txt
in CLion to obtain a usable project.
### Easy build
Once the required OS specific dependencies listed below are installed, you can use the script
located in `build.sh` to build Filament easily on macOS and Linux.
This script can be invoked from anywhere and will produce build artifacts in the `out/` directory
inside the Filament source tree.
To trigger an incremental debug build:
```
$ ./build.sh debug
```
To trigger an incremental release build:
```
$ ./build.sh release
```
To trigger both incremental debug and release builds:
```
$ ./build.sh debug release
```
To install the libraries and executables in `out/debug/` and `out/release/`, add the `-i` flag.
You can force a clean build by adding the `-c` flag. The script offers more features described
by executing `build.sh -h`.
### Disabling Java builds
By default our build system will attempt to compile the Java bindings. If you wish to skip this
compilation step simply pass the `-j` flag to `build.sh`:
```
$ ./build.sh -j release
```
If you use CMake directly instead of the build script, pass `-DENABLE_JAVA=OFF` to CMake instead.
### Linux
Make sure you've installed the following dependencies:
- `clang-7` or higher
- `libglu1-mesa-dev`
- `libc++-7-dev` (`libcxx-devel` and `libcxx-static` on Fedora) or higher
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora) or higher
- `ninja-build`
- `libxi-dev`
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
script.
If you'd like to run `cmake` directly rather than using the build script, it can be invoked as
follows, with some caveats that are explained further down.
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
Your Linux distribution might default to `gcc` instead of `clang`, if that's the case invoke
`cmake` with the following command:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
# Or use a specific version of clang, for instance /usr/bin/clang-7
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
You can also export the `CC` and `CXX` environment variables to always point to `clang`. Another
solution is to use `update-alternatives` to both change the default compiler, and point to a
specific version of clang:
```
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100
$ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
$ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
```
Finally, invoke `ninja`:
```
$ ninja
```
This will build Filament, its tests and samples, and various host tools.
### macOS
To compile Filament you must have the most recent version of Xcode installed and you need to
make sure the command line tools are setup by running:
```
$ xcode-select --install
```
After installing Java 1.8 you must also ensure that your `JAVA_HOME` environment variable is
properly set. If it doesn't already point to the appropriate JDK, you can simply add the following
to your `.profile`:
```
export JAVA_HOME="$(/usr/libexec/java_home)"
```
Then run `cmake` and `ninja` to trigger a build:
```
$ mkdir out/cmake-release
$ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
$ ninja
```
### iOS
The easiest way to build Filament for iOS is to use `build.sh` and the
`-p ios` flag. For instance to build the debug target:
```
$ ./build.sh -p ios debug
```
See [ios/samples/README.md](./ios/samples/README.md) for more information.
### Windows
The following instructions have been tested on a machine running Windows 10. They should take you
from a machine with only the operating system to a machine able to build and run Filament.
Google employees require additional steps which can be found here [go/filawin](http://go/filawin).
Install the following components:
- [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
- [Visual Studio 2015 or 2017](https://www.visualstudio.com/downloads)
- [Clang 7](http://releases.llvm.org/download.html)
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
- [Cmake 3.13 or later](https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-win64-x64.msi)
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:
```
> mkdir out/cmake-release
> cd out/cmake-release
```
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. 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
```
You are now ready to build:
```
> msbuild TNT.sln /t:material_sandbox /m /p:configuration=Release
```
Run it:
```
> samples\Release\material_sandbox.exe ..\..\assets\models\monkey\monkey.obj
```
#### Tips
- To troubleshoot an issue, use verbose mode via `/v:d` flag.
- To build a specific project, use `/t:NAME` flag (e.g: `/t:material_sandbox`).
- To build using more than one core, use parallel build flag: `/m`.
- To build a specific profile, use `/p:configuration=` (e.g: `/p:configuration=Debug`,
`/p:configuration=Release`, and `/p:configuration=RelWithDebInfo`).
- The msBuild project is what is used by Visual Studio behind the scene to build. Building from VS
or from the command-line is the same thing.
#### Building with Ninja on Windows
Alternatively, you can use [Ninja](https://ninja-build.org/) to build for Windows. An MSVC
installation is still necessary.
First, install the dependencies listed under [Windows](#Windows) as well as Ninja. Then open up a
Native Tools terminal as before. Create a build directory inside Filament and run the
following CMake command:
```
> 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_BUILD_TYPE=Release
```
You should then be able to build by invoking Ninja:
```
> ninja
```
#### Development tips
- Before shipping a binary, make sure you used Release profile and make sure you have no libc/libc++
dependencies with [Dependency Walker](http://www.dependencywalker.com).
- Application Verifier and gflags.exe can be of great help to trackdown heap corruption. Application
Verifier is easy to setup with a GUI. For gflags, use: `gflags /p /enable pheap-buggy.exe`.
#### Running a simple test
To confirm Filament was properly built, run the following command from the build directory:
```
> samples\material_sandbox.exe --ibl=..\..\samples\envs\pillars ..\..\assets\models\sphere\sphere.obj
```
### Android
Before building Filament for Android, make sure to build Filament for your host. Some of the
host tools are required to successfully build for Android.
Filament can be built for the following architectures:
- ARM 64-bit (`arm64-v8a`)
- ARM 32-bit (`armeabi-v7a`)
- Intel 64-bit (`x86_64`)
- Intel 32-bit (`x86`)
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
`-p android` flag. For instance to build the release target:
```
$ ./build.sh -p android release
```
Run `build.sh -h` for more information.
#### ARM 64-bit target (arm64-v8a)
Then invoke CMake in a build directory of your choice, inside of filament's directory:
```
$ mkdir out/android-build-release-aarch64
$ cd out/android-build-release-aarch64
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-aarch64-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/arm64-v8a`.
#### ARM 32-bit target (armeabi-v7a)
Then invoke CMake in a build directory of your choice, inside of filament's directory:
```
$ mkdir out/android-build-release-arm
$ cd out/android-build-release-arm
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../build/toolchain-arm7-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/armeabi-v7a`.
#### Intel 64-bit target (x86_64)
Then invoke CMake in a build directory of your choice, sibling of filament's directory:
```
$ mkdir out/android-build-release-x86_64
$ cd out/android-build-release-x86_64
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../filament/build/toolchain-x86_64-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../out/android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/x86_64`.
#### Intel 32-bit target (x86)
Then invoke CMake in a build directory of your choice, sibling of filament's directory:
```
$ mkdir out/android-build-release-x86
$ cd out/android-build-release-x86
$ cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../../filament/build/toolchain-x86-linux-android.cmake \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../out/android-release/filament ../..
```
And then invoke `ninja`:
```
$ ninja install
```
or
```
$ ninja install/strip
```
This will generate Filament's Android binaries in `out/android-release`. This location is important
to build the Android Studio projects located in `filament/android`. After install, the library
binaries should be found in `out/android-release/filament/lib/x86`.
### AAR
Before you attempt to build the AAR, make sure you've compiled and installed the native libraries
as explained in the sections above. You must have the following ABIs built in
`out/android-release/filament/lib/`:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To build Filament's AAR simply open the Android Studio project in `android/filament-android`. The
AAR is a universal AAR that contains all supported build targets:
- `arm64-v8a`
- `armeabi-v7a`
- `x86_64`
- `x86`
To filter out unneeded ABIs, rely on the `abiFilters` of the project that links against Filament's
AAR.
Alternatively you can build the AAR from the command line by executing the following the
`android/filament-android` directory:
```
$ ./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
```
The `-Pfilament_dist_dir` can be used to specify a different installation directory (it must match
the CMake install prefix used in the previous steps).
### Using Filament's AAR
Create a new module in your project and select _Import .JAR or .AAR Package_ when prompted. Make
sure to add the newly created module as a dependency to your application.
If you do not wish to include all supported ABIs, make sure to create the appropriate flavors in
your Gradle build file. For example:
```
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'
}
}
```
### WebAssembly
The core Filament library can be cross-compiled to WebAssembly from either macOS or Linux. To get
started, follow the instructions for building Filament on your platform ([macOS](#macos) or
[linux](#linux)), which will ensure you have the proper dependencies installed.
Next, you need to install the Emscripten SDK. The following instructions show how to install the
same version that our continuous builds use.
```
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/a77638d.zip > emsdk.zip
unzip emsdk.zip
mv emsdk-* emsdk
cd emsdk
./emsdk update
./emsdk install sdk-1.38.28-64bit
./emsdk activate sdk-1.38.28-64bit
```
After this you can invoke the [easy build](#easy-build) script as follows:
```
export EMSDK=<your chosen home for the emscripten SDK>
./build.sh -p webgl release
```
The EMSDK variable is required so that the build script can find the Emscripten SDK. The build
creates a `samples` folder that can be used as the root of a simple static web server. Note that you
cannot open the HTML directly from the filesystem due to CORS. One way to deal with this is to
use Python to create a quick localhost server:
```
cd out/cmake-webgl-release/web/samples
python3 -m http.server # Python 3
python -m SimpleHTTPServer # Python 2.7
```
You can then open http://localhost:8000/suzanne.html in your web browser.
Alternatively, if you have node installed you can use the
[live-server](https://www.npmjs.com/package/live-server) package, which automatically refreshes the
web page when it detects a change.
Each sample app has its own handwritten html file. Additionally the server folder contains assets
such as meshes, textures, and materials.
## Running the native samples
The `samples/` directory contains several examples of how to use Filament with SDL2.
Some of the samples accept FBX/OBJ meshes while others rely on the `filamesh` file format. To
generate a `filamesh ` file from an FBX/OBJ asset, run the `filamesh` tool
(`./tools/filamesh/filamesh` in your build directory):
```
filamesh ./assets/models/monkey/monkey.obj monkey.filamesh
```
Most samples accept an IBL that must be generated using the `cmgen` tool (`./tools/filamesh/cmgen`
in your build directory). These sample apps expect a path to a directory containing the '.rgb32f'
files for the IBL (which are PNGs containing `R11F_G11F_B10F` data). To generate an IBL simply use
this command:
```
cmgen -x ./ibls/ my_ibl.exr
```
The source environment map can be a PNG (8 or 16 bit), a PSD (16 or 32 bit), an HDR or an OpenEXR
file. The environment map can be an equirectangular projection, a horizontal cross, a vertical
cross, or a list of cubemap faces (horizontal or vertical).
`cmgen` will automatically create a directory based on the name of the source environment map. In
the example above, the final directory will be `./ibls/my_ibl/`. This directory should contain the
pre-filtered environment map (one file per cubemap face and per mip level), the environment map
texture for the skybox and a text file containing the spherical harmonics for indirect diffuse
lighting.
If you prefer a blurred background, run `cmgen` with this flag: `--extract-blur=0.1`. The numerical
value is the desired roughness between 0 and 1.
## Rendering with Filament
### Native Linux, macOS and Windows
@@ -839,44 +240,73 @@ Filament on iOS is largely the same as native rendering with C++. A `CAEAGLLayer
is passed to the `createSwapChain` method. Filament for iOS supports both OpenGL ES and Vulkan via
MoltenVK.
## Generating C++ documentation
To generate the documentation you must first install `doxygen` and `graphviz`, then run the
following commands:
```
$ cd filament/filament
$ doxygen docs/doxygen/filament.doxygen
```
Finally simply open `docs/html/index.html` in your web browser.
## Assets
To get started you can use the textures and environment maps found respectively in
`third_party/textures` and `third_party/environments`. These assets are under CC0 license. Please
refer to their respective `URL.txt` files to know more about the original authors.
## Dependencies
One of our design goals is that Filament itself should have no dependencies or as few dependencies
as possible. The current external dependencies of the runtime library include:
- STL
- robin-map (header only library)
When building with Vulkan enabled, we have a few additional small dependencies:
- vkmemalloc
- smol-v
Host tools (such as `matc` or `cmgen`) can use external dependencies freely.
## How to make contributions
Please read and follow the steps in [CONTRIBUTING.md](/CONTRIBUTING.md). Make sure you are
familiar with the [code style](/CODE_STYLE.md).
## Directory structure
This repository not only contains the core Filament engine, but also its supporting libraries
and tools.
- `android`: Android libraries and projects
- `filamat-android`: Filament material generation library (AAR) for Android
- `filament-android`: Filament library (AAR) for Android
- `gltfio-android`: Filament glTF loading library (AAR) for Android
- `samples`: Android-specific Filament samples
- `art`: Source for various artworks (logos, PDF manuals, etc.)
- `assets`: 3D assets to use with sample applications
- `build`: CMake build scripts
- `docs`: Documentation
- `math`: Mathematica notebooks used to explore BRDFs, equations, etc.
- `filament`: Filament rendering engine (minimal dependencies)
- `ide`: Configuration files for IDEs (CLion, etc.)
- `ios`: Sample projects for iOS
- `java`: Java bindings for Filament libraries
- `libs`: Libraries
- `bluegl`: OpenGL bindings for macOS, Linux and Windows
- `bluevk`: Vulkan bindings for macOS, Linux, Windows and Android
- `filabridge`: Library shared by the Filament engine and host tools
- `filaflat`: Serialization/deserialization library used for materials
- `filagui`: Helper library for [Dear ImGui](https://github.com/ocornut/imgui)
- `filamat`: Material generation library
- `filameshio`: Tiny filamesh parsing library (see also `tools/filamesh`)
- `geometry`: Mesh-related utilities
- `gltfio`: Loader and optional pipeline for glTF 2.0
- `ibl`: IBL generation tools
- `image`: Image filtering and simple transforms
- `imageio`: Image file reading / writing, only intended for internal use
- `matdbg`: DebugServer for inspecting shaders at run-time (debug builds only)
- `math`: Math library
- `rays`: Simple path tracer used for baking ambient occlusion, etc.
- `utils`: Utility library (threads, memory, data structures, etc.)
- `samples`: Sample desktop applications
- `shaders`: Shaders used by `filamat` and `matc`
- `third_party`: External libraries and assets
- `environments`: Environment maps under CC0 license that can be used with `cmgen`
- `models`: Models under permissive licenses
- `textures`: Textures under CC0 license
- `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
- `normal-blending`: Tool to blend normal maps
- `resgen` Aggregates binary blobs into embeddable resources
- `roughness-prefilter`: Pre-filters a roughness map from a normal map to reduce aliasing
- `skygen`: Physically-based sky environment texture generator
- `specular-color`: Computes the specular color of conductors based on spectral data
- `web`: JavaScript bindings, documentation, and samples
## License
Please see [LICENSE](/LICENSE).

View File

@@ -3,8 +3,132 @@
This file contains one line summaries of commits that are worthy of mentioning in release notes.
A new header is inserted each time a *tag* is created.
- Added a live material debugger with a web-based interface.
## Next release
## v1.5.0
⚠️ This release breaks compiled materials, use matc to recompile.
- The Android support libraries (gltfio and filament-utils) now use dynamic linking.
- Removed depth-prepass related APIs. (⚠ API Change)
- gltfio: add asynchronous API to ResourceLoader.
- gltfio: generate normals for flat-shaded models that do not have normals.
- Material instances now allow dynamic depth testing and other rasterization state.
- Unlit materials now apply emissive in the same way as lit materials.
- Screen-space refraction is now supported.
- Support for HDR Bloom as a post-process effect.
- Alpha masked objects are now part of the SSAO pass.
- Added Java bindings for geometry::SurfaceOrientation.
- Fixed bug rendering transparent objects with Metal backend.
- Fixed crash on macOS Catalina when rendering with Metal backend.
- Fixed bug in Camera::setLensProjection() and added the aspect ratio parameter. (⚠ API Change)
- WebGL: Improved TypeScript annotations.
- WebGL: Simplified callback API for glTF. (⚠ API Change)
- gltfio: Removed deprecated "Bindings" API. (⚠ API Change)
- gltfio: Added support for Draco.
- gltfio: Reduced the size of the library.
- Improved performance of SSAO.
- Added support for screen-space contact shadows.
- Added support for global fog.
- Added support for bent normal maps and specular occlusion from bent normal maps.
- Added support for shadow-casting spot lights.
## v1.4.5
- The depth prepass setting in View is now ignored and deprecated.
- Fixed a threading bug with the NOOP backend.
- Improved memory management for gltfio on Android.
- Introduced `filament-utils` library with `TextureLoader`, `ModelViewer`, and Java bindings for `camutils`.
- Fix out-of-bounds bug when glTF has many UV sets.
- Added new `setMediaOverlay` API to `UiHelper` for controlling surface ordering.
- Implemented sRGB support for DXT encoded textures.
- Fix bug with incorrect world transforms computed in `TransformManager`.
- gltfio: support external resources on Android.
## v1.4.4
- Added support for solid and thin layer cubemap and screen-space refraction.
- Improved high roughness material rendering by default when regenerating environments maps.
- Fix bad instruction exception with macOS Catalina.
- Fixed bad state after removing an IBL from the Scene.
- Fixed incorrect punctual light binning (affected Metal and Vulkan backends).
- Fixed crash when using a Metal headless SwapChain with an Intel integrated GPU.
- Added support for ASTC textures on iOS with Metal backend.
- Added new heightfield sample.
- Removed `<iostream>` from math headers.
- cmgen now places KTX files directly in the specified deployment folder.
## v1.4.3
- Fixed an assertion when a parameter array occurs last in a material definition.
- Fixed morph shapes not rendering in WebGL.
- Added support for the latest version of emscripten.
- gltfio: fixed blackness seen with default material.
- Added ETC2 and BC compressed texture support to Metal backend.
- Rendering a `SAMPLER_EXTERNAL` texture before setting an external image no longer results in GPU errors.
- Fixed a normals issue when skinning without a normal map or anisotropy.
- Fixed an issue where transparent views couldn't be used with post-processing.
- Always use higher quality 3-bands SH for indirect lighting, even on mobile.
- The Metal backend can now handle binding individual planes of YUV external images.
- Added support for depth buffer when post-processing is turned off
- Improved performance on GPUs that use tile-based rendering
## v1.4.2
- Cleaned up the validation strategy in Engine (checks for use-after-destroy etc).
- OpenGL: Fixed ES 3.0 support on iOS.
- OpenGL: Added support for KHR_debug in debug builds.
- gltfio: Added Java / Kotlin bindings for Animator.
- gltfio: Fixed panic with the Android gltf-bloom demo.
- gltfio: Java clients should no longer call Filament#init.
- Improved IBL diffuse by allowing to use the specular cubemap at `roughness` = 1 instead of Spherical Harmonics
## v1.4.1
- Added missing API documentation.
- Fixed crash for sandboxed macOS apps using Filament.
- Fixed an issue that limited the camera near plane to ~1mm.
- Added Android sample for Camera Stream.
- Fixed an Xcode assertion when rendering skinned meshes using the Metal backend.
- Added support for Core Animation / Metal frame synchronization with Metal backend.
- Fixed an issue with culling in `MaterialInstance`.
- Fix additional compatibility issues with MSVC, including the Vulkan backend.
- matdbg: fixed missing symbol issue when linking against debug builds.
- filamat: fixed crash when using the "lite" version of the library.
- matinfo: Fix a crash with on Windows.
- gltfio: fixed an animation loop bug.
- gltfio: added support for sparse accessors.
- Add JS binding to unary `Camera::setExposure`.
## v1.4.0
- API Breakage: Simplified public-facing Fence API.
- Minimum API level on Android is now API 19 instead of API 21.
- Filament can now be built with msvc 2019.
- Added the ability to modify clip space coordinates in the vertex shader.
- Added missing API documentation.
- Improved existing API documentation.
- Added `Camera::setExposure(float)` to directly control the camera's exposure.
- Backface culling can now be toggled on material instances.
- Face direction is now reversed when transforms have negative scale.
- Dielectrics now behave properly under a white furnace (energy preserving and conserving).
- Clear coat roughness now remains in the 0..1 (previously remapped to the 0..0.6 range).
- gltfio: Fixed several limitations with ubershader mode.
- gltfio: Fixed a transforms issue with non-uniform scale.
- webgl: Fixed an issue with JPEG textures.
- Windows: Fix link error in debug builds.
- matdbg: Web server must now be enabled with an environment variable.
- matdbg: Added support for editing GLSL and MSL code.
## v1.3.2
- Added optional web server for real-time inspection of shader code.
- Added basic #include support in material files.
- Fixed potential Metal memory leak.
- Fixed intermittent memory overflow in wasm builds.
- Fix bad normal mapping with skinning.
- Java clients can now call getNativeObject().
## v1.3.1

9
android/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build/

View File

@@ -25,7 +25,7 @@ cmake ^
-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 ^
-DFILAMENT_ENABLE_JAVA=NO ^
-DCMAKE_BUILD_TYPE=Release ^
..\..
```
@@ -96,12 +96,12 @@ ninja install
## Generate AAR
The Gradle project used to generate the AAR is located at `<filament>\android\filament-android`.
The Gradle project used to generate the AAR is located at `<filament>\android`.
```
cd android\filament-android
gradlew -Pfilament_dist_dir=..\..\out\android-release\filament assembleRelease
copy build\outputs\aar\filament-android-release.aar ..\..\out\
cd android
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease
copy filament-android\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
@@ -119,5 +119,5 @@ 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.
See [Using Filament's AAR](../README.md) for usage instructions.

105
android/build.gradle Normal file
View File

@@ -0,0 +1,105 @@
// 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.
//
// filament_tools_dir
// Path to the Filament distribution/install directory for desktop.
// This directory must contain bin/matc.
//
// filament_supports_vulkan
// When set, support for Vulkan will be enabled.
//
// filament_skip_samples
// Exclude samples from the project. Useful to speed up compilation.
//
// Example:
// ./gradlew -Pfilament_dist_dir=../dist-android-release assembleRelease
buildscript {
def filamentPath = file("../out/android-release/filament").absolutePath
if (project.hasProperty("filament_dist_dir")) {
filamentPath = file(project.property("filament_dist_dir")).absolutePath
}
def hasVulkan = project.hasProperty("filament_supports_vulkan")
// Our minSdkVersion is actually 19, we lie and say 14 here so apps don't have
// to increase their minSdkVersion unnecessarily. It is however up to them to
// ensure they do not initialize Filament on API levels < 19.
ext.versions = [
'minSdk': 14,
'targetSdk': 29,
'compileSdk': 29,
'kotlin': '1.3.61',
'buildTools': '29.0.3',
'ndk': '21.0.6113669'
]
ext.deps = [
'androidx': [
'annotations': "androidx.annotation:annotation:1.1.0",
'core': "androidx.core:core:1.1.0",
],
'kotlin': "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}"
]
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}
ext.cmakeArgs = [
"-DANDROID_PIE=ON",
"-DANDROID_PLATFORM=21",
"-DANDROID_STL=c++_static",
"-DFILAMENT_DIST_DIR=${filamentPath}".toString(),
"-DFILAMENT_SUPPORTS_VULKAN=${hasVulkan ? 'ON' : 'OFF'}".toString()
]
ext.cppFlags = [
"-std=c++14",
"-Wno-unused-command-line-argument",
// Required to support API levels below 23
"-Wl,--hash-style=both",
"-fno-stack-protector",
"-fno-exceptions",
"-fno-unwind-tables",
"-fno-asynchronous-unwind-tables",
"-fno-rtti",
"-ffast-math",
"-ffp-contract=fast",
"-fvisibility-inlines-hidden",
"-fvisibility=hidden",
"-fomit-frame-pointer",
"-ffunction-sections",
"-fdata-sections",
"-Wl,--gc-sections",
"-Wl,-Bsymbolic-functions",
]
repositories {
mavenCentral()
google()
jcenter()
}
}
subprojects { project ->
group = GROUP
version = VERSION_NAME
repositories {
mavenCentral()
google()
jcenter()
}
}
gradle.taskGraph.whenReady {
gradle.taskGraph.allTasks.each {
it.onlyIf {
!it.project.ext.has('isSample') || !project.hasProperty('filament_skip_samples')
}
}
}

View File

@@ -1,235 +0,0 @@
// This script accepts the following parameters:
//
// filament_tools_dir
// Path to the Filament distribution/install directory for desktop
// (produced by make/ninja install). This directory must contain bin/matc
//
// Example:
// ./gradlew -Pfilament_tools_dir=../../dist-release assembleDebug
import java.nio.file.Paths
import org.gradle.internal.os.OperatingSystem
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.LogLevel;
def filamentToolsPath = file("../../../../out/release/filament")
if (project.hasProperty("filament_tools_dir")) {
filamentToolsPath = file("$filament_tools_dir")
}
List<File> getBinaries(String name, File toolsPath) {
def tool = ["/bin/${name}.exe", "/bin/${name}"]
def toolFullPath = tool.collect { path -> Paths.get(toolsPath.absolutePath, path).toFile() }
// Ensure that at least one matc binary and Filament library is present
if (!toolFullPath.any { path -> file(path).exists() }) {
throw new StopActionException("No ${name} binary could be found in " + toolsPath +
"/bin. Ensure Filament has been built/installed before building this app.")
}
return toolFullPath
}
ext.matcFullPath = getBinaries('matc', filamentToolsPath)
ext.cmgenFullPath = getBinaries('cmgen', filamentToolsPath)
ext.filameshFullPath = getBinaries('filamesh', filamentToolsPath)
ext.resgenFullPath = getBinaries('resgen', filamentToolsPath)
class LogOutputStream extends ByteArrayOutputStream {
private final Logger logger;
private final LogLevel level;
public LogOutputStream(Logger logger, LogLevel level) {
this.logger = logger;
this.level = level;
}
public Logger getLogger() {
return logger;
}
public LogLevel getLevel() {
return level;
}
@Override
public void flush() {
logger.log(level, toString());
reset();
}
}
// Custom task to compile material files using matc
// This task handles incremental builds
class MaterialCompiler extends DefaultTask {
File matcPath
@SuppressWarnings("GroovyUnusedDeclaration")
@InputDirectory
File inputDir
@OutputDirectory
File outputDir
MaterialCompiler() {
matcPath = OperatingSystem.current().isWindows() ?
project.ext.matcFullPath[0] : project.ext.matcFullPath[1]
}
@SuppressWarnings("GroovyUnusedDeclaration")
@TaskAction
void execute(IncrementalTaskInputs inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir).matching { include '*.filamat' })
}
inputs.outOfDate { InputFileDetails outOfDate ->
if (outOfDate.file.directory) return
def file = outOfDate.file
def out = new LogOutputStream(logger, LogLevel.LIFECYCLE)
def err = new LogOutputStream(logger, LogLevel.ERROR)
def header = ("Compiling material " + file + "\n").getBytes()
out.write(header)
out.flush()
project.exec {
standardOutput out
errorOutput err
executable "${matcPath}"
args('-a', 'all', '-p', 'mobile', '-o', getOutputFile(file), file)
}
}
inputs.removed { InputFileDetails removed ->
getOutputFile(removed.file).delete()
}
}
File getOutputFile(final File file) {
return new File(outputDir, file.name[0..file.name.lastIndexOf('.')] + 'filamat')
}
}
// Custom task to process IBLs using cmgen
// This task handles incremental builds
class IblGenerator extends DefaultTask {
File cmgenPath
String cmgenArgs = null;
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
File inputFile
@OutputDirectory
File outputDir
IblGenerator() {
cmgenPath = OperatingSystem.current().isWindows() ?
project.ext.cmgenFullPath[0] : project.ext.cmgenFullPath[1]
}
@SuppressWarnings("GroovyUnusedDeclaration")
@TaskAction
void execute(IncrementalTaskInputs inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir).matching { include '*' })
}
inputs.outOfDate { InputFileDetails outOfDate ->
def file = outOfDate.file
def out = new LogOutputStream(logger, LogLevel.LIFECYCLE)
def err = new LogOutputStream(logger, LogLevel.ERROR)
def header = ("Generating IBL " + file + "\n").getBytes()
out.write(header)
out.flush()
project.exec {
standardOutput out
errorOutput err
executable "${cmgenPath}"
args('-x', outputDir, file)
}
project.exec {
standardOutput out
if (!cmgenArgs) {
cmgenArgs = '--format=rgb32f --extract-blur=0.08 --extract=' + outputDir.absolutePath
}
cmgenArgs = cmgenArgs + " " + file
errorOutput err
executable "${cmgenPath}"
args(cmgenArgs.split())
}
}
inputs.removed { InputFileDetails removed ->
getOutputFile(removed.file).delete()
}
}
File getOutputFile(final File file) {
return new File(outputDir, file.name[0..file.name.lastIndexOf('.') - 1])
}
}
// Custom task to compile mesh files using filamesh
// This task handles incremental builds
class MeshCompiler extends DefaultTask {
File filameshPath
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
File inputFile
@OutputDirectory
File outputDir
MeshCompiler() {
filameshPath = OperatingSystem.current().isWindows() ?
project.ext.filameshFullPath[0] : project.ext.filameshFullPath[1]
}
@SuppressWarnings("GroovyUnusedDeclaration")
@TaskAction
void execute(IncrementalTaskInputs inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir).matching { include '*.filamesh' })
}
inputs.outOfDate { InputFileDetails outOfDate ->
def file = outOfDate.file
def out = new LogOutputStream(logger, LogLevel.LIFECYCLE)
def err = new LogOutputStream(logger, LogLevel.ERROR)
def header = ("Compiling mesh " + file + "\n").getBytes()
out.write(header)
out.flush()
project.exec {
standardOutput out
errorOutput err
executable "${filameshPath}"
args(file, getOutputFile(file))
}
}
inputs.removed { InputFileDetails removed ->
getOutputFile(removed.file).delete()
}
}
File getOutputFile(final File file) {
return new File(outputDir, file.name[0..file.name.lastIndexOf('.')] + 'filamesh')
}
}
task compileMaterials(type: MaterialCompiler)
task generateIbl(type: IblGenerator)
task compileMesh(type: MeshCompiler)

9
android/buildSrc/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build/

View File

@@ -0,0 +1,291 @@
// This plugin accepts the following parameters:
//
// filament_tools_dir
// Path to the Filament distribution/install directory for desktop.
// This directory must contain bin/matc.
//
// filament_supports_vulkan
// When set, support for Vulkan will be enabled
//
// Example:
// ./gradlew -Pfilament_tools_dir=../../dist-release assembleDebug
import java.nio.file.Paths
import org.gradle.internal.os.OperatingSystem
import org.gradle.api.*
import org.gradle.api.logging.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.incremental.*
class TaskWithBinary extends DefaultTask {
private final String binaryName
private File binaryPath = null
TaskWithBinary(String name) {
binaryName = name
}
String getBinaryName() {
return binaryName
}
File getBinary() {
if (binaryPath == null) {
def tool = ["/bin/${binaryName}.exe", "/bin/${binaryName}"]
def fullPath = tool.collect { path ->
Paths.get(project.ext.filamentToolsPath.absolutePath, path).toFile()
}
binaryPath = OperatingSystem.current().isWindows() ? fullPath[0] : fullPath[1]
}
return binaryPath
}
}
class LogOutputStream extends ByteArrayOutputStream {
private final Logger logger
private final LogLevel level
LogOutputStream(Logger logger, LogLevel level) {
this.logger = logger
this.level = level
}
Logger getLogger() {
return logger
}
LogLevel getLevel() {
return level
}
@Override
void flush() {
logger.log(level, toString())
reset()
}
}
// Custom task to compile material files using matc
// This task handles incremental builds
class MaterialCompiler extends TaskWithBinary {
@SuppressWarnings("GroovyUnusedDeclaration")
@InputDirectory
File inputDir
@OutputDirectory
File outputDir
MaterialCompiler() {
super("matc")
}
@SuppressWarnings("GroovyUnusedDeclaration")
@TaskAction
void execute(IncrementalTaskInputs inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir).matching { include '*.filamat' })
}
inputs.outOfDate { InputFileDetails outOfDate ->
if (outOfDate.file.directory) return
def file = outOfDate.file
def out = new LogOutputStream(logger, LogLevel.LIFECYCLE)
def err = new LogOutputStream(logger, LogLevel.ERROR)
def header = ("Compiling material " + file + "\n").getBytes()
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
" Ensure Filament has been built/installed before building this app.")
}
def matcArgs = []
if (project.hasProperty("filament_supports_vulkan")) {
matcArgs += ['-a', 'vulkan']
}
matcArgs += ['-a', 'opengl', '-p', 'mobile', '-o', getOutputFile(file), file]
project.exec {
standardOutput out
errorOutput err
executable "${getBinary()}"
args matcArgs
}
}
inputs.removed { InputFileDetails removed ->
getOutputFile(removed.file).delete()
}
}
File getOutputFile(final File file) {
return new File(outputDir, file.name[0..file.name.lastIndexOf('.')] + 'filamat')
}
}
// Custom task to process IBLs using cmgen
// This task handles incremental builds
class IblGenerator extends TaskWithBinary {
String cmgenArgs = null
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
File inputFile
@OutputDirectory
File outputDir
IblGenerator() {
super("cmgen")
}
@SuppressWarnings("GroovyUnusedDeclaration")
@TaskAction
void execute(IncrementalTaskInputs inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir).matching { include '*' })
}
inputs.outOfDate { InputFileDetails outOfDate ->
def file = outOfDate.file
def out = new LogOutputStream(logger, LogLevel.LIFECYCLE)
def err = new LogOutputStream(logger, LogLevel.ERROR)
def header = ("Generating IBL " + file + "\n").getBytes()
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
standardOutput out
if (!cmgenArgs) {
cmgenArgs = '-q -x ' + outputDir +
' --format=rgb32f --extract-blur=0.08 --extract=' + outputDir.absolutePath
}
cmgenArgs = cmgenArgs + " " + file
errorOutput err
executable "${getBinary()}"
args(cmgenArgs.split())
}
}
inputs.removed { InputFileDetails removed ->
getOutputFile(removed.file).delete()
}
}
File getOutputFile(final File file) {
return new File(outputDir, file.name[0..file.name.lastIndexOf('.') - 1])
}
}
// Custom task to compile mesh files using filamesh
// This task handles incremental builds
class MeshCompiler extends TaskWithBinary {
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
File inputFile
@OutputDirectory
File outputDir
MeshCompiler() {
super("filamesh")
}
@SuppressWarnings("GroovyUnusedDeclaration")
@TaskAction
void execute(IncrementalTaskInputs inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir).matching { include '*.filamesh' })
}
inputs.outOfDate { InputFileDetails outOfDate ->
def file = outOfDate.file
def out = new LogOutputStream(logger, LogLevel.LIFECYCLE)
def err = new LogOutputStream(logger, LogLevel.ERROR)
def header = ("Compiling mesh " + file + "\n").getBytes()
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
standardOutput out
errorOutput err
executable "${getBinary()}"
args(file, getOutputFile(file))
}
}
inputs.removed { InputFileDetails removed ->
getOutputFile(removed.file).delete()
}
}
File getOutputFile(final File file) {
return new File(outputDir, file.name[0..file.name.lastIndexOf('.')] + 'filamesh')
}
}
class FilamentToolsPluginExtension {
File materialInputDir
File materialOutputDir
String cmgenArgs
File iblInputFile
File iblOutputDir
File meshInputFile
File meshOutputDir
}
class FilamentToolsPlugin implements Plugin<Project> {
void apply(Project project) {
def extension = project.extensions.create('filamentTools', FilamentToolsPluginExtension)
project.ext.filamentToolsPath = project.file("../../../out/release/filament")
if (project.hasProperty("filament_tools_dir")) {
project.ext.filamentToolsPath = project.file(project.property("filament_tools_dir"))
}
project.tasks.register("filamentCompileMaterials", MaterialCompiler) {
enabled = extension.materialInputDir != null && extension.materialOutputDir != null
inputDir = extension.materialInputDir
outputDir = extension.materialOutputDir
}
project.preBuild.dependsOn "filamentCompileMaterials"
project.tasks.register("filamentGenerateIbl", IblGenerator) {
enabled = extension.iblInputFile != null && extension.iblOutputDir != null
cmgenArgs = extension.cmgenArgs
inputFile = extension.iblInputFile
outputDir = extension.iblOutputDir
}
project.preBuild.dependsOn "filamentGenerateIbl"
project.tasks.register("filamentCompileMesh", MeshCompiler) {
enabled = extension.meshInputFile != null && extension.meshOutputDir != null
inputFile = extension.meshInputFile
outputDir = extension.meshOutputDir
}
project.preBuild.dependsOn "filamentCompileMesh"
}
}

View File

@@ -27,39 +27,6 @@ struct {
jmethodID execute;
} gCallbackUtils;
JniCallback* JniCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback) {
void* that = engine->streamAlloc(sizeof(JniCallback), alignof(JniCallback));
return new (that) JniCallback(env, handler, callback);
}
JniCallback::JniCallback(JNIEnv* env, jobject handler, jobject callback)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback)) {
}
JniCallback::~JniCallback() {
if (mHandler && mCallback) {
#ifdef ANDROID
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.handlerClass)) {
mEnv->CallBooleanMethod(mHandler, gCallbackUtils.post, mCallback);
}
#endif
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.executorClass)) {
mEnv->CallVoidMethod(mHandler, gCallbackUtils.execute, mCallback);
}
}
mEnv->DeleteGlobalRef(mHandler);
mEnv->DeleteGlobalRef(mCallback);
}
void JniCallback::invoke(void*, size_t, void* user) {
JniCallback* data = reinterpret_cast<JniCallback*>(user);
// don't call delete here, because we don't own the storage
data->~JniCallback();
}
JniBufferCallback* JniBufferCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
void* that = engine->streamAlloc(sizeof(JniBufferCallback), alignof(JniBufferCallback));
@@ -95,6 +62,37 @@ void JniBufferCallback::invoke(void*, size_t, void* user) {
data->~JniBufferCallback();
}
JniImageCallback* JniImageCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, long image) {
void* that = engine->streamAlloc(sizeof(JniImageCallback), alignof(JniImageCallback));
return new (that) JniImageCallback(env, handler, callback, image);
}
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback))
, mImage(image) { }
JniImageCallback::~JniImageCallback() {
if (mHandler && mCallback) {
#ifdef ANDROID
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.handlerClass)) {
mEnv->CallBooleanMethod(mHandler, gCallbackUtils.post, mCallback);
}
#endif
if (mEnv->IsInstanceOf(mHandler, gCallbackUtils.executorClass)) {
mEnv->CallVoidMethod(mHandler, gCallbackUtils.execute, mCallback);
}
}
mEnv->DeleteGlobalRef(mHandler);
mEnv->DeleteGlobalRef(mCallback);
}
void JniImageCallback::invoke(void* image, void* user) {
reinterpret_cast<JniImageCallback*>(user)->~JniImageCallback();
}
void registerCallbackUtils(JNIEnv *env) {
#ifdef ANDROID
gCallbackUtils.handlerClass = env->FindClass("android/os/Handler");

View File

@@ -23,21 +23,6 @@
#include <filament/Engine.h>
struct JniCallback {
static JniCallback* make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback);
static void invoke(void* buffer, size_t n, void* user);
private:
JniCallback(JNIEnv* env, jobject handler, jobject callback);
~JniCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
};
struct JniBufferCallback {
static JniBufferCallback* make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
@@ -53,3 +38,19 @@ private:
jobject mCallback;
AutoBuffer mBuffer;
};
struct JniImageCallback {
static JniImageCallback* make(filament::Engine* engine, JNIEnv* env, jobject handler,
jobject runnable, long image);
static void invoke(void* image, void* user);
private:
JniImageCallback(JNIEnv* env, jobject handler, jobject runnable, long image);
~JniImageCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
long mImage;
};

View File

@@ -7,6 +7,10 @@ if(FILAMAT_LITE)
set(FILAMAT_FLAVOR "filamat_lite")
endif()
if (FILAMENT_SUPPORTS_VULKAN)
message("Library filamat ignores Vulkan settings")
endif()
add_library(${FILAMAT_FLAVOR} STATIC IMPORTED)
set_target_properties(${FILAMAT_FLAVOR} PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/lib${FILAMAT_FLAVOR}.a)
@@ -29,15 +33,6 @@ set_target_properties(shaders PROPERTIES IMPORTED_LOCATION
include_directories(${FILAMENT_DIR}/include)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-stack-protector")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math -ffp-contract=fast")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility-inlines-hidden")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility=hidden")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ffunction-sections -fdata-sections")
set(CMAKE_SHARED_LINKER_FLAGS" ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
set(CMAKE_SHARED_LINKER_FLAGS" ${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Bsymbolic-functions")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libfilamat-jni.map")
add_library(filamat-jni SHARED
@@ -52,4 +47,3 @@ target_link_libraries(filamat-jni
log
smol-v
)

View File

@@ -1,70 +1,22 @@
// 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.5.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"
buildToolsVersion versions.buildTools
compileSdkVersion versions.compileSdk
ndkVersion versions.ndk
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-21")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")
if (project.hasProperty('extra_cmake_args')) {
arguments.add(extra_cmake_args)
}
arguments.addAll(rootProject.ext.cmakeArgs)
cppFlags.addAll(rootProject.ext.cppFlags)
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
flavorDimensions "functionality"
productFlavors {
full {
@@ -101,6 +53,23 @@ android {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:support-annotations:28.0.0'
implementation deps.androidx.annotations
}
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
afterEvaluate { project ->
publishing {
publications {
fullRelease(MavenPublication) {
artifactId = POM_ARTIFACT_ID_FULL
from components.fullRelease
}
liteRelease(MavenPublication) {
artifactId = POM_ARTIFACT_ID_LITE
from components.liteRelease
}
}
}
}

View File

@@ -0,0 +1,4 @@
POM_NAME=Filament Material Builder
POM_ARTIFACT_ID_FULL=filamat-android
POM_ARTIFACT_ID_LITE=filamat-android-lite
POM_PACKAGING=aar

View File

@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,10 +0,0 @@
/*
* 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'

View File

@@ -16,7 +16,7 @@
package com.google.android.filament.filamat;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import java.nio.ByteBuffer;
public class MaterialBuilder {
@@ -99,14 +99,15 @@ public class MaterialBuilder {
UV1, // texture coordinates (float2)
BONE_INDICES, // indices of 4 bones (uvec4)
BONE_WEIGHTS, // weights of the 4 bones (normalized float4)
CUSTOM0,
CUSTOM1,
CUSTOM2,
CUSTOM3,
CUSTOM4,
CUSTOM5,
CUSTOM6,
CUSTOM7
UNUSED, // reserved for future use
CUSTOM0, // custom or MORPH_POSITION_0
CUSTOM1, // custom or MORPH_POSITION_1
CUSTOM2, // custom or MORPH_POSITION_2
CUSTOM3, // custom or MORPH_POSITION_3
CUSTOM4, // custom or MORPH_TANGENTS_0
CUSTOM5, // custom or MORPH_TANGENTS_1
CUSTOM6, // custom or MORPH_TANGENTS_2
CUSTOM7 // custom or MORPH_TANGENTS_3
}
public enum BlendingMode {

View File

@@ -16,7 +16,7 @@
package com.google.android.filament.filamat;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import java.nio.ByteBuffer;
public class MaterialPackage {

View File

@@ -1,29 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
</code_scheme>
</component>

View File

@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="5">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/filament-android.iml" filepath="$PROJECT_DIR$/filament-android.iml" />
</modules>
</component>
</project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@@ -38,67 +38,67 @@ add_library(smol-v STATIC IMPORTED)
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
include_directories(.. ${FILAMENT_DIR}/include)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-stack-protector")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math -ffp-contract=fast")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility-inlines-hidden")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility=hidden")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ffunction-sections -fdata-sections")
set(CMAKE_SHARED_LINKER_FLAGS" ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
set(CMAKE_SHARED_LINKER_FLAGS" ${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Bsymbolic-functions")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libfilament-jni.map")
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libfilament-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
add_library(filament-jni SHARED
src/main/cpp/Camera.cpp
src/main/cpp/Colors.cpp
src/main/cpp/VertexBuffer.cpp
src/main/cpp/Engine.cpp
src/main/cpp/EntityManager.cpp
src/main/cpp/Fence.cpp
src/main/cpp/IndexBuffer.cpp
src/main/cpp/IndirectLight.cpp
src/main/cpp/LightManager.cpp
src/main/cpp/Material.cpp
src/main/cpp/MaterialInstance.cpp
src/main/cpp/MathUtils.cpp
src/main/cpp/RenderableManager.cpp
src/main/cpp/Renderer.cpp
src/main/cpp/RenderTarget.cpp
src/main/cpp/Scene.cpp
src/main/cpp/SkyBox.cpp
src/main/cpp/Stream.cpp
src/main/cpp/Texture.cpp
src/main/cpp/TextureSampler.cpp
src/main/cpp/TransformManager.cpp
src/main/cpp/View.cpp
# Android specific
src/main/cpp/nativewindow/Android.cpp
# Private utils
src/main/cpp/Filament.cpp
# Common utils
../common/CallbackUtils.cpp
../common/NioUtils.cpp
src/main/cpp/Camera.cpp
src/main/cpp/Colors.cpp
src/main/cpp/VertexBuffer.cpp
src/main/cpp/Engine.cpp
src/main/cpp/EntityManager.cpp
src/main/cpp/Fence.cpp
src/main/cpp/IndexBuffer.cpp
src/main/cpp/IndirectLight.cpp
src/main/cpp/LightManager.cpp
src/main/cpp/Material.cpp
src/main/cpp/MaterialInstance.cpp
src/main/cpp/MathUtils.cpp
src/main/cpp/RenderableManager.cpp
src/main/cpp/Renderer.cpp
src/main/cpp/RenderTarget.cpp
src/main/cpp/Scene.cpp
src/main/cpp/SkyBox.cpp
src/main/cpp/Stream.cpp
src/main/cpp/SurfaceOrientation.cpp
src/main/cpp/Texture.cpp
src/main/cpp/TextureSampler.cpp
src/main/cpp/TransformManager.cpp
src/main/cpp/View.cpp
# Android specific
src/main/cpp/nativewindow/Android.cpp
# Private utils
src/main/cpp/Filament.cpp
# Common utils
../common/CallbackUtils.cpp
../common/NioUtils.cpp
)
# Ordering is significant in the following list. The PRIVATE qualifier prevents transitive deps.
target_link_libraries(filament-jni
filament
backend
filaflat
filabridge
geometry
ibl
utils
log
GLESv3
EGL
android
jnigraphics
PRIVATE filament
PRIVATE backend
PRIVATE filaflat
PRIVATE filabridge
PRIVATE geometry
PRIVATE ibl
PRIVATE log
PRIVATE GLESv3
PRIVATE EGL
PRIVATE android
PRIVATE jnigraphics
PRIVATE utils
)
target_include_directories(filament-jni PRIVATE
..
${FILAMENT_DIR}/include
../../third_party/robin-map
../../libs/utils/include)
# Force a relink when the version script is changed:
set_target_properties(filament-jni PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
if (FILAMENT_SUPPORTS_VULKAN)

View File

@@ -1,73 +1,22 @@
// 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.5.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 {
// Our minSdkVersion is actually 21, we lie and say 14 here so apps don't have
// to increase their minSdkVersion unnecessarily. It is however up to them to
// ensure they do not initialize Filament on API levels < 21.
minSdkVersion 14
targetSdkVersion 28
versionCode 1
versionName "1.0"
buildToolsVersion versions.buildTools
compileSdkVersion versions.compileSdk
ndkVersion versions.ndk
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-21")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")
if (project.hasProperty('extra_cmake_args')) {
arguments.add(extra_cmake_args)
}
arguments.addAll(rootProject.ext.cmakeArgs)
cppFlags.addAll(rootProject.ext.cppFlags)
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
@@ -93,6 +42,18 @@ android {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:support-annotations:28.0.0'
implementation deps.androidx.annotations
}
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
afterEvaluate { project ->
publishing {
publications {
release(MavenPublication) {
artifactId = POM_ARTIFACT_ID
from components.release
}
}
}
}

View File

@@ -0,0 +1,3 @@
POM_NAME=Filament
POM_ARTIFACT_ID=filament-android
POM_PACKAGING=aar

View File

@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,172 +0,0 @@
#!/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='"-Xmx64m"'
# 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" "$@"

View File

@@ -1,84 +0,0 @@
@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="-Xmx64m"
@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

View File

@@ -1,4 +1,4 @@
LIBFILAMENT {
global: Java_com_google_android_filament_*; JNI*;
global: *filament*; JNI*;
local: *;
};

View File

@@ -1,22 +0,0 @@
# 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
# JNI is an entry point that's hard to keep track of, so there's
# an annotation to mark fields and methods used by native code.
# Keep the annotations that proguard needs to process.
-keep class com.google.android.filament.proguard.UsedBy*
# Just because native code accesses members of a class, does not mean that the
# class itself needs to be annotated - only annotate classes that are
# referenced themselves in native code.
-keep @com.google.android.filament.proguard.UsedBy* class * {
<init>();
}
-keepclassmembers class * {
@com.google.android.filament.proguard.UsedBy* *;
}

View File

@@ -1 +0,0 @@
rootProject.name = 'filament-android'

View File

@@ -18,6 +18,8 @@
#include <filament/Camera.h>
#include <math/mat4.h>
using namespace filament;
extern "C" JNIEXPORT void JNICALL
@@ -38,9 +40,9 @@ Java_com_google_android_filament_Camera_nSetProjectionFov(JNIEnv*, jclass ,
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetLensProjection(JNIEnv*, jclass,
jlong nativeCamera, jdouble focalLength, jdouble near, jdouble far) {
jlong nativeCamera, jdouble focalLength, jdouble aspect, jdouble near, jdouble far) {
Camera *camera = (Camera *) nativeCamera;
camera->setLensProjection(focalLength, near, far);
camera->setLensProjection(focalLength, aspect, near, far);
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -18,6 +18,9 @@
#include <filament/Engine.h>
#include <utils/Entity.h>
#include <utils/EntityManager.h>
using namespace filament;
using namespace utils;
@@ -59,6 +62,13 @@ Java_com_google_android_filament_Engine_nCreateSwapChain(JNIEnv* env,
return (jlong) engine->createSwapChain(win, (uint64_t) flags);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateSwapChainHeadless(JNIEnv* env,
jclass klass, jlong nativeEngine, jint width, jint height, jlong flags) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) engine->createSwapChain(width, height, (uint64_t) flags);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateSwapChainFromRawPointer(JNIEnv*,
jclass, jlong nativeEngine, jlong pointer, jlong flags) {
@@ -154,9 +164,9 @@ Java_com_google_android_filament_Engine_nDestroyScene(JNIEnv*, jclass,
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateFence(JNIEnv*, jclass,
jlong nativeEngine, jint fenceType) {
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) engine->createFence((Fence::Type) fenceType);
return (jlong) engine->createFence();
}
extern "C" JNIEXPORT void JNICALL
@@ -252,6 +262,13 @@ Java_com_google_android_filament_Engine_nDestroyEntity(JNIEnv*, jclass,
engine->destroy(entity);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv *env, jclass clazz,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
engine->flushAndWait();
}
// Managers...
extern "C" JNIEXPORT jlong JNICALL

View File

@@ -22,6 +22,8 @@
#include <filament/IndexBuffer.h>
#include <backend/BufferDescriptor.h>
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"

View File

@@ -20,6 +20,7 @@
#include <filament/Texture.h>
#include <common/NioUtils.h>
#include <common/CallbackUtils.h>
#include <math/mat4.h>
using namespace filament;
@@ -135,10 +136,31 @@ Java_com_google_android_filament_IndirectLight_nGetDirectionEstimate(JNIEnv* env
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetColorEstimate(JNIEnv* env, jclass,
jlong nativeIndirectLight, jfloatArray outColor_, float x, float y, float z) {
jlong nativeIndirectLight, jfloatArray outColor_, jfloat x, jfloat y, jfloat z) {
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
jfloat *outColor = env->GetFloatArrayElements(outColor_, NULL);
*reinterpret_cast<filament::math::float4*>(outColor) =
indirectLight->getColorEstimate(math::float3{x, y, z});
env->ReleaseFloatArrayElements(outColor_, outColor, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetDirectionEstimateStatic(JNIEnv *env, jclass,
jfloatArray sh_, jfloatArray outDirection_) {
jfloat* sh = env->GetFloatArrayElements(sh_, NULL);
jfloat *outDirection = env->GetFloatArrayElements(outDirection_, NULL);
*reinterpret_cast<filament::math::float3*>(outDirection) = IndirectLight::getDirectionEstimate((filament::math::float3*)sh);
env->ReleaseFloatArrayElements(outDirection_, outDirection, 0);
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetColorEstimateStatic(JNIEnv *env, jclass,
jfloatArray outColor_, jfloatArray sh_, jfloat x, jfloat y, jfloat z) {
jfloat* sh = env->GetFloatArrayElements(sh_, NULL);
jfloat *outColor = env->GetFloatArrayElements(outColor_, NULL);
*reinterpret_cast<filament::math::float4*>(outColor) =
IndirectLight::getColorEstimate((filament::math::float3*)sh, math::float3{x, y, z});
env->ReleaseFloatArrayElements(outColor_, outColor, 0);
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
}

View File

@@ -18,6 +18,8 @@
#include <filament/LightManager.h>
#include <utils/Entity.h>
using namespace filament;
using namespace utils;
@@ -64,7 +66,8 @@ Java_com_google_android_filament_LightManager_nBuilderCastShadows(JNIEnv*, jclas
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv*, jclass,
jlong nativeBuilder, jint mapSize, jfloat constantBias, jfloat normalBias, jfloat shadowFar,
jfloat shadowNearHint, jfloat shadowFarHint, jboolean stable) {
jfloat shadowNearHint, jfloat shadowFarHint, jboolean stable,
jboolean screenSpaceContactShadows, jint stepCount, jfloat maxShadowDistance) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->shadowOptions(
LightManager::ShadowOptions{.mapSize = (uint32_t)mapSize,
@@ -73,7 +76,10 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv*, jcl
.shadowFar = shadowFar,
.shadowNearHint = shadowNearHint,
.shadowFarHint = shadowFarHint,
.stable = (bool)stable});
.stable = (bool)stable,
.screenSpaceContactShadows = (bool)screenSpaceContactShadows,
.stepCount = uint8_t(stepCount),
.maxShadowDistance = maxShadowDistance});
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -84,6 +84,23 @@ Java_com_google_android_filament_Material_nGetBlendingMode(JNIEnv*, jclass,
return (jint) material->getBlendingMode();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetRefraction(JNIEnv*, jclass,
jlong nativeMaterial) {
Material* material = (Material*) nativeMaterial;
return (jint)material->getRefractionMode();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetRefractionType(JNIEnv*, jclass,
jlong nativeMaterial) {
Material* material = (Material*) nativeMaterial;
return (jint) material->getRefractionType();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetVertexDomain(JNIEnv*, jclass,

View File

@@ -316,3 +316,35 @@ Java_com_google_android_filament_MaterialInstance_nSetDoubleSided(JNIEnv*,
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setDoubleSided(doubleSided);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetCullingMode(JNIEnv*,
jclass, jlong nativeMaterialInstance, jlong cullingMode) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setCullingMode((MaterialInstance::CullingMode) cullingMode);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetColorWrite(JNIEnv*,
jclass, jlong nativeMaterialInstance, jboolean enable) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setColorWrite(enable);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetDepthWrite(JNIEnv*,
jclass, jlong nativeMaterialInstance, jboolean enable) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setDepthWrite(enable);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetDepthCulling(JNIEnv*,
jclass, jlong nativeMaterialInstance, jboolean enable) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setDepthCulling(enable);
}

View File

@@ -39,7 +39,7 @@ Java_com_google_android_filament_RenderTarget_nDestroyBuilder(JNIEnv *env, jclas
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderTexture(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong attachment, jlong nativeTexture) {
jlong nativeBuilder, jint attachment, jlong nativeTexture) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
Texture* texture = (Texture*) nativeTexture;
builder->texture(RenderTarget::AttachmentPoint(attachment), texture);
@@ -47,14 +47,14 @@ Java_com_google_android_filament_RenderTarget_nBuilderTexture(JNIEnv *env, jclas
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderMipLevel(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong attachment, jint level) {
jlong nativeBuilder, jint attachment, jint level) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
builder->mipLevel(RenderTarget::AttachmentPoint(attachment), level);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderFace(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong attachment, jint face) {
jlong nativeBuilder, jint attachment, jint face) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
RenderTarget::CubemapFace cubeface = (RenderTarget::CubemapFace) face;
builder->face(RenderTarget::AttachmentPoint(attachment), cubeface);
@@ -62,7 +62,7 @@ Java_com_google_android_filament_RenderTarget_nBuilderFace(JNIEnv *env, jclass t
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderLayer(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong attachment, jint layer) {
jlong nativeBuilder, jint attachment, jint layer) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
builder->layer(RenderTarget::AttachmentPoint(attachment), layer);
}
@@ -77,7 +77,21 @@ Java_com_google_android_filament_RenderTarget_nBuilderBuild(JNIEnv *env, jclass
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderTarget_nGetMipLevel(JNIEnv *env, jclass type,
jlong nativeTarget, jlong attachment) {
jlong nativeTarget, jint attachment) {
RenderTarget* target = (RenderTarget*) nativeTarget;
return (jint) target->getMipLevel(RenderTarget::AttachmentPoint(attachment));
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderTarget_nGetFace(JNIEnv *env, jclass type,
long nativeTarget, int attachment) {
RenderTarget* target = (RenderTarget*) nativeTarget;
return (jint) target->getFace(RenderTarget::AttachmentPoint(attachment));
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderTarget_nGetLayer(JNIEnv *env, jclass type,
long nativeTarget, int attachment) {
RenderTarget* target = (RenderTarget*) nativeTarget;
return (jint) target->getLayer(RenderTarget::AttachmentPoint(attachment));
}

View File

@@ -18,6 +18,10 @@
#include <jni.h>
#include <filament/RenderableManager.h>
#include <filament/MaterialInstance.h>
#include <utils/Entity.h>
#include "common/NioUtils.h"
using namespace filament;
@@ -160,6 +164,13 @@ Java_com_google_android_filament_RenderableManager_nBuilderReceiveShadows(JNIEnv
builder->receiveShadows(enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderScreenSpaceContactShadows(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->screenSpaceContactShadows(enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderSkinning(JNIEnv*, jclass,
jlong nativeBuilder, jint boneCount) {
@@ -271,6 +282,13 @@ Java_com_google_android_filament_RenderableManager_nSetReceiveShadows(JNIEnv*, j
rm->setReceiveShadows((RenderableManager::Instance) i, enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetScreenSpaceContactShadows(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jboolean enabled) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
rm->setScreenSpaceContactShadows((RenderableManager::Instance) i, enabled);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_RenderableManager_nIsShadowCaster(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i) {

View File

@@ -97,6 +97,42 @@ Java_com_google_android_filament_Renderer_nReadPixels(JNIEnv *env, jclass,
return 0;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Renderer_nReadPixelsEx(JNIEnv *env, jclass,
jlong nativeRenderer, jlong nativeEngine, jlong nativeRenderTarget,
jint xoffset, jint yoffset, jint width, jint height,
jobject storage, jint remaining,
jint left, jint top, jint type, jint alignment, jint stride, jint format,
jobject handler, jobject runnable) {
Renderer *renderer = (Renderer *) nativeRenderer;
Engine *engine = (Engine *) nativeEngine;
RenderTarget *renderTarget = (RenderTarget *) nativeRenderTarget;
stride = stride ? stride : width;
size_t sizeInBytes = PixelBufferDescriptor::computeDataSize(
(PixelDataFormat) format, (PixelDataType) type,
(size_t) stride, (size_t) (height + top), (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
void *buffer = nioBuffer.getData();
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
renderer->readPixels(renderTarget,
uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_Renderer_nGetUserTime(JNIEnv*, jclass, jlong nativeRenderer) {
Renderer *renderer = (Renderer *) nativeRenderer;

View File

@@ -18,6 +18,8 @@
#include <filament/Scene.h>
#include <utils/Entity.h>
using namespace filament;
using namespace utils;

View File

@@ -47,6 +47,13 @@ Java_com_google_android_filament_Skybox_nBuilderShowSun(JNIEnv *env, jclass type
builder->showSun(show);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Skybox_nBuilderIntensity(JNIEnv *env, jclass clazz,
jlong nativeSkyBoxBuilder, jfloat intensity) {
Skybox::Builder *builder = (Skybox::Builder *) nativeSkyBoxBuilder;
builder->intensity(intensity);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Skybox_nBuilderBuild(JNIEnv *env, jclass type,
jlong nativeSkyBoxBuilder, jlong nativeEngine) {
@@ -68,3 +75,10 @@ Java_com_google_android_filament_Skybox_nGetLayerMask(JNIEnv *env, jclass type,
Skybox *skybox = (Skybox *) nativeSkybox;
return static_cast<jint>(skybox->getLayerMask());
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_Skybox_nGetIntensity(JNIEnv *env, jclass clazz,
jlong nativeSkybox) {
Skybox *skybox = (Skybox *) nativeSkybox;
return static_cast<jint>(skybox->getIntensity());
}

View File

@@ -24,6 +24,25 @@
#include "common/NioUtils.h"
#include "common/CallbackUtils.h"
#ifdef ANDROID
#if __has_include(<android/hardware_buffer_jni.h>)
#include <android/hardware_buffer_jni.h>
#else
struct AHardwareBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
#endif
#include <android/log.h>
#include <dlfcn.h>
using PFN_FROMHARDWAREBUFFER = AHardwareBuffer* (*)(JNIEnv*, jobject);
static PFN_FROMHARDWAREBUFFER AHardwareBuffer_fromHardwareBuffer_fn = nullptr;
static bool sHardwareBufferSupported = true;
#endif
using namespace filament;
using namespace backend;
@@ -108,10 +127,10 @@ Java_com_google_android_filament_Stream_nBuilderBuild(JNIEnv*, jclass,
return (jlong) builder->builder()->build(*engine);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Stream_nIsNative(JNIEnv*, jclass, jlong nativeStream) {
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Stream_nGetStreamType(JNIEnv*, jclass, jlong nativeStream) {
Stream* stream = (Stream*) nativeStream;
return (jboolean) stream->isNativeStream();
return (jint) stream->getStreamType();
}
extern "C" JNIEXPORT void JNICALL
@@ -160,3 +179,44 @@ Java_com_google_android_filament_Stream_nGetTimestamp(JNIEnv*, jclass, jlong nat
Stream *stream = (Stream *) nativeStream;
return stream->getTimestamp();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Stream_nSetAcquiredImage(JNIEnv* env, jclass, jlong nativeStream,
jlong nativeEngine, jobject hwbuffer, jobject handler, jobject runnable) {
Engine* engine = (Engine*) nativeEngine;
Stream* stream = (Stream*) nativeStream;
#ifdef ANDROID
// This function is not available before NDK 15 or before Android 8.
if (UTILS_UNLIKELY(!AHardwareBuffer_fromHardwareBuffer_fn)) {
if (!sHardwareBufferSupported) {
return;
}
AHardwareBuffer_fromHardwareBuffer_fn = (PFN_FROMHARDWAREBUFFER) dlsym(RTLD_DEFAULT, "AHardwareBuffer_fromHardwareBuffer");
if (!AHardwareBuffer_fromHardwareBuffer_fn) {
__android_log_print(ANDROID_LOG_WARN, "Filament", "AHardwareBuffer_fromHardwareBuffer is not available.");
sHardwareBufferSupported = false;
}
return;
}
AHardwareBuffer* nativeBuffer = AHardwareBuffer_fromHardwareBuffer_fn(env, hwbuffer);
if (!nativeBuffer) {
__android_log_print(ANDROID_LOG_INFO, "Filament", "Unable to obtain native HardwareBuffer.");
return;
}
auto* callback = JniImageCallback::make(engine, env, handler, runnable, (long) nativeBuffer);
#else
// TODO: for non-Android platforms, it is unclear how to go from "jobject" to "void*"
// For now this code is reserved for future use.
auto* callback = JniImageCallback::make(engine, env, handler, runnable, 0);
void* nativeBuffer = nullptr;
#endif
stream->setAcquiredImage((void*) nativeBuffer, &JniImageCallback::invoke, callback);
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <geometry/SurfaceOrientation.h>
#include "common/NioUtils.h"
#include <algorithm>
using namespace filament;
using namespace filament::geometry;
using namespace filament::math;
namespace {
struct JniWrapper {
SurfaceOrientation::Builder* builder;
AutoBuffer* normals;
AutoBuffer* tangents;
AutoBuffer* uvs;
AutoBuffer* positions;
AutoBuffer* triangles16;
AutoBuffer* triangles32;
};
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_SurfaceOrientation_nCreateBuilder(JNIEnv* env, jclass) {
JniWrapper* wrapper = new JniWrapper();
wrapper->builder = new SurfaceOrientation::Builder();
return (jlong) wrapper;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_nDestroyBuilder(JNIEnv* env, jclass,
jlong nativeBuilder) {
auto wrapper = (JniWrapper*) nativeBuilder;
delete wrapper->builder;
delete wrapper->normals;
delete wrapper->tangents;
delete wrapper->uvs;
delete wrapper->positions;
delete wrapper->triangles16;
delete wrapper->triangles32;
delete wrapper;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_nBuilderVertexCount(JNIEnv* env, jclass,
jlong nativeBuilder, int vertexCount) {
auto wrapper = (JniWrapper *) nativeBuilder;
wrapper->builder->vertexCount(vertexCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderTriangleCount(JNIEnv* env, jclass,
jlong nativeBuilder, int triangleCount) {
auto wrapper = (JniWrapper *) nativeBuilder;
wrapper->builder->triangleCount(triangleCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderNormals(JNIEnv* env, jclass,
jlong nativeBuilder, jobject javaBuffer, jint remaining, int stride) {
auto wrapper = (JniWrapper *) nativeBuilder;
AutoBuffer* buffer = wrapper->normals = new AutoBuffer(env, javaBuffer, remaining);
wrapper->builder->normals((const float3 *) buffer->getData(), stride);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderTangents(JNIEnv* env, jclass,
jlong nativeBuilder, jobject javaBuffer, jint remaining, int stride) {
auto wrapper = (JniWrapper *) nativeBuilder;
AutoBuffer* buffer = wrapper->tangents = new AutoBuffer(env, javaBuffer, remaining);
wrapper->builder->tangents((const float4 *) buffer->getData(), stride);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderUVs(JNIEnv* env, jclass,
jlong nativeBuilder, jobject javaBuffer, int remaining, int stride) {
auto wrapper = (JniWrapper *) nativeBuilder;
AutoBuffer* buffer = wrapper->uvs = new AutoBuffer(env, javaBuffer, remaining);
wrapper->builder->uvs((const float2 *) buffer->getData(), stride);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderPositions(JNIEnv* env, jclass,
jlong nativeBuilder, jobject javaBuffer, int remaining, int stride) {
auto wrapper = (JniWrapper *) nativeBuilder;
AutoBuffer* buffer = wrapper->positions = new AutoBuffer(env, javaBuffer, remaining);
wrapper->builder->positions((const float3 *) buffer->getData(), stride);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderTriangles16(JNIEnv* env, jclass,
jlong nativeBuilder, jobject javaBuffer, int remaining) {
auto wrapper = (JniWrapper *) nativeBuilder;
AutoBuffer* buffer = wrapper->triangles16 = new AutoBuffer(env, javaBuffer, remaining);
wrapper->builder->triangles((const ushort3 *) buffer->getData());
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_mBuilderTriangles32(JNIEnv* env, jclass,
jlong nativeBuilder, jobject javaBuffer, int remaining) {
auto wrapper = (JniWrapper *) nativeBuilder;
AutoBuffer* buffer = wrapper->triangles32 = new AutoBuffer(env, javaBuffer, remaining);
wrapper->builder->triangles((const uint3 *) buffer->getData());
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_SurfaceOrientation_nBuilderBuild(JNIEnv* env, jclass,
jlong nativeBuilder) {
auto wrapper = (JniWrapper *) nativeBuilder;
return (jlong) wrapper->builder->build();
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_SurfaceOrientation_nGetVertexCount(JNIEnv* env, jclass,
jlong nativeObject) {
SurfaceOrientation* helper = (SurfaceOrientation*) nativeObject;
return helper->getVertexCount();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_nGetQuatsAsFloat(JNIEnv* env, jclass,
jlong nativeObject, jobject javaBuffer, int remaining) {
SurfaceOrientation* helper = (SurfaceOrientation*) nativeObject;
AutoBuffer buffer(env, javaBuffer, remaining);
size_t requestedCount = std::min(buffer.getSize() / sizeof(float4), helper->getVertexCount());
helper->getQuats((quatf*) buffer.getData(), requestedCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_nGetQuatsAsHalf(JNIEnv* env, jclass,
jlong nativeObject, jobject javaBuffer, int remaining) {
SurfaceOrientation* helper = (SurfaceOrientation*) nativeObject;
AutoBuffer buffer(env, javaBuffer, remaining);
size_t requestedCount = std::min(buffer.getSize() / sizeof(quath), helper->getVertexCount());
helper->getQuats((quath*) buffer.getData(), requestedCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_nGetQuatsAsShort(JNIEnv* env, jclass,
jlong nativeObject, jobject javaBuffer, int remaining) {
SurfaceOrientation* helper = (SurfaceOrientation*) nativeObject;
AutoBuffer buffer(env, javaBuffer, remaining);
size_t requestedCount = std::min(buffer.getSize() / sizeof(short4), helper->getVertexCount());
helper->getQuats((short4*) buffer.getData(), requestedCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SurfaceOrientation_nDestroy(JNIEnv* env, jclass,
jlong nativeSurfaceOrientation) {
SurfaceOrientation* helper = (SurfaceOrientation*) nativeSurfaceOrientation;
delete helper;
}

View File

@@ -177,7 +177,7 @@ Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong na
(Texture::Type) type, (size_t) stride, (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
@@ -199,8 +199,7 @@ extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Texture_nSetImageCompressed(JNIEnv *env, jclass,
jlong nativeTexture, jlong nativeEngine, jint level, jint xoffset, jint yoffset,
jint width, jint height, jobject storage, jint remaining,
jint left, jint bottom, jint type, jint alignment,
jint compressedSizeInBytes, jint compressedFormat,
jint, jint, jint, jint, jint compressedSizeInBytes, jint compressedFormat,
jobject handler, jobject runnable) {
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
@@ -208,7 +207,7 @@ Java_com_google_android_filament_Texture_nSetImageCompressed(JNIEnv *env, jclass
size_t sizeInBytes = (size_t) compressedSizeInBytes;
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
@@ -235,7 +234,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, NULL);
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, nullptr);
Texture::FaceOffsets faceOffsets;
std::copy_n(faceOffsetsInBytes, 6, faceOffsets.offsets);
env->ReleaseIntArrayElements(faceOffsetsInBytes_, faceOffsetsInBytes, JNI_ABORT);
@@ -244,7 +243,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
(Texture::Type) type, (size_t) stride, (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
@@ -271,7 +270,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env,
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, NULL);
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, nullptr);
Texture::FaceOffsets faceOffsets;
std::copy_n(faceOffsetsInBytes, 6, faceOffsets.offsets);
env->ReleaseIntArrayElements(faceOffsetsInBytes_, faceOffsetsInBytes, JNI_ABORT);
@@ -279,7 +278,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env,
size_t sizeInBytes = 6 * (size_t) compressedSizeInBytes;
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
@@ -340,28 +339,29 @@ Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, j
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, NULL);
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, nullptr);
Texture::FaceOffsets faceOffsets;
std::copy_n(faceOffsetsInBytes, 6, faceOffsets.offsets);
env->ReleaseIntArrayElements(faceOffsetsInBytes_, faceOffsetsInBytes, JNI_ABORT);
stride = stride ? stride : width;
size_t sizeInBytes = 6 *
Texture::computeTextureDataSize((Texture::Format) format, (Texture::Type) type,
(size_t) stride, (size_t) height, (size_t) alignment);
Texture::computeTextureDataSize((Texture::Format) format, (Texture::Type) type,
(size_t) stride, (size_t) height, (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
void *buffer = nioBuffer.getData();
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
void* buffer = nioBuffer.getData();
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t)0, (uint32_t)0,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(backend::PixelDataType) type, (uint8_t) alignment,
(uint32_t) left, (uint32_t) top, (uint32_t) stride,
&JniBufferCallback::invoke, callback);
Texture::PrefilterOptions options;
options.sampleCount = sampleCount;

View File

@@ -17,9 +17,12 @@
#include <jni.h>
#include <utils/Entity.h>
#include <filament/TransformManager.h>
#include <utils/Entity.h>
#include <math/mat4.h>
using namespace utils;
using namespace filament;

View File

@@ -17,6 +17,7 @@
#include <jni.h>
#include <filament/View.h>
#include <filament/Viewport.h>
using namespace filament;
@@ -161,17 +162,18 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetDynamicResolutionOptions(JNIEnv*,
jclass, jlong nativeView, jboolean enabled, jboolean homogeneousScaling,
jfloat targetFrameTimeMilli, jfloat headRoomRatio, jfloat scaleRate,
jfloat minScale, jfloat maxScale, jint history) {
View* view = (View*) nativeView;
jfloat minScale, jfloat maxScale, jint history, jint quality) {
View* view = (View*)nativeView;
View::DynamicResolutionOptions options;
options.enabled = enabled;
options.homogeneousScaling = homogeneousScaling;
options.targetFrameTimeMilli = targetFrameTimeMilli;
options.headRoomRatio = headRoomRatio;
options.scaleRate = scaleRate;
options.minScale = filament::math::float2{minScale};
options.maxScale = filament::math::float2{maxScale};
options.history = (uint8_t) history;
options.minScale = filament::math::float2{ minScale };
options.maxScale = filament::math::float2{ maxScale };
options.history = (uint8_t)history;
options.quality = (View::QualityLevel)quality;
view->setDynamicResolutionOptions(options);
}
@@ -192,13 +194,6 @@ Java_com_google_android_filament_View_nSetDynamicLightingOptions(JNIEnv*,
view->setDynamicLightingOptions(zLightNear, zLightFar);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetDepthPrepass(JNIEnv*,
jclass, jlong nativeView, jint value) {
View* view = (View*) nativeView;
view->setDepthPrepass(View::DepthPrepass(value));
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetPostProcessingEnabled(JNIEnv*,
jclass, jlong nativeView, jboolean enabled) {
@@ -241,8 +236,58 @@ Java_com_google_android_filament_View_nGetAmbientOcclusion(JNIEnv*, jclass, jlon
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetAmbientOcclusionOptions(JNIEnv*, jclass,
jlong nativeView, jfloat radius, jfloat bias, jfloat power, jfloat resolution) {
jlong nativeView, jfloat radius, jfloat bias, jfloat power, jfloat resolution, jfloat intensity,
jint quality) {
View* view = (View*) nativeView;
View::AmbientOcclusionOptions options = { .radius = radius, .bias = bias, .power = power, .resolution = resolution};
View::AmbientOcclusionOptions options = {
.radius = radius,
.power = power,
.bias = bias,
.resolution = resolution,
.intensity = intensity,
.quality = (View::QualityLevel)quality
};
view->setAmbientOcclusionOptions(options);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetBloomOptions(JNIEnv*, jclass,
jlong nativeView, jlong nativeTexture,
jfloat dirtStrength, jfloat strength, jint resolution, jfloat anamorphism, jint levels,
jint blendMode, jboolean threshold, jboolean enabled) {
View* view = (View*) nativeView;
Texture* dirt = (Texture*) nativeTexture;
View::BloomOptions options = {
.dirt = dirt,
.dirtStrength = dirtStrength,
.strength = strength,
.resolution = (uint32_t)resolution,
.anamorphism = anamorphism,
.levels = (uint8_t)levels,
.blendMode = (View::BloomOptions::BlendMode)blendMode,
.threshold = (bool)threshold,
.enabled = (bool)enabled
};
view->setBloomOptions(options);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong nativeView,
jfloat distance, jfloat maximumOpacity, jfloat height, jfloat heightFalloff, jfloat r,
jfloat g, jfloat b, jfloat density, jfloat inScatteringStart,
jfloat inScatteringSize, jboolean fogColorFromIbl, jboolean enabled) {
View* view = (View*) nativeView;
View::FogOptions options = {
.distance = distance,
.maximumOpacity = maximumOpacity,
.height = height,
.heightFalloff = heightFalloff,
.color = math::float3{r, g, b},
.density = density,
.inScatteringStart = inScatteringStart,
.inScatteringSize = inScatteringSize,
.fogColorFromIbl = (bool)fogColorFromIbl,
.enabled = (bool)enabled
};
view->setFogOptions(options);
}

View File

@@ -17,7 +17,16 @@
#include <stdio.h>
#include <jawt.h>
#if defined(__has_include)
#if __has_include(<darwin/jawt_md.h>)
#include <darwin/jawt_md.h>
#else
#include <jawt_md.h>
#endif
#else
#include <darwin/jawt_md.h>
#endif
#include <filament/Engine.h>
#include "JAWTUtils.h"

View File

@@ -19,8 +19,10 @@ package com.google.android.filament;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.EGLContext;
import android.os.Build;
import android.util.Log;
import android.view.Surface;
import java.lang.reflect.Method;
final class AndroidPlatform extends Platform {
private static final String LOG_TAG = "Filament";
@@ -59,6 +61,20 @@ final class AndroidPlatform extends Platform {
@Override
long getSharedContextNativeHandle(Object sharedContext) {
return ((EGLContext) sharedContext).getNativeHandle();
if (Build.VERSION.SDK_INT >= 21) {
return AndroidPlatform21.getSharedContextNativeHandle(sharedContext);
} else {
try {
//noinspection JavaReflectionMemberAccess
Method method = EGLContext.class.getDeclaredMethod("getHandle");
Integer handle = (Integer) method.invoke(sharedContext);
//noinspection ConstantConditions
return handle.longValue();
} catch (Exception e) {
Log.d(LOG_TAG, "Could not access shared context's native handle", e);
}
// Should not happen
return 0;
}
}
}

View File

@@ -0,0 +1,25 @@
/*
* 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;
import android.opengl.EGLContext;
final class AndroidPlatform21 {
static long getSharedContextNativeHandle(Object sharedContext) {
return ((EGLContext) sharedContext).getNativeHandle();
}
}

View File

@@ -16,10 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
final class Asserts {
private Asserts() {

View File

@@ -16,15 +16,28 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
/**
* An axis-aligned 3D box represented by its center and half-extent.
*
* The half-extent is a vector representing the distance from the center to the edge of the box in
* each dimension. For example, a box of size 2 units in X, 4 units in Y, and 10 units in Z would
* have a half-extent of (1, 2, 5).
*/
public class Box {
private final float[] mCenter = new float[3];
private final float[] mHalfExtent = new float[3];
/**
* Default-initializes the 3D box to have a center and half-extent of (0,0,0).
*/
public Box() { }
/**
* Initializes the 3D box from its center and half-extent.
*/
public Box(float centerX, float centerY, float centerZ,
float halfExtentX, float halfExtentY, float halfExtentZ) {
mCenter[0] = centerX;
@@ -35,6 +48,13 @@ public class Box {
mHalfExtent[2] = halfExtentZ;
}
/**
* Initializes the 3D box from its center and half-extent.
*
* @param center a float array with XYZ coordinates representing the center of the box
* @param halfExtent a float array with XYZ coordinates representing half the size of the box in
* each dimension
*/
public Box(@NonNull @Size(min = 3) float[] center, @NonNull @Size(min = 3) float[] halfExtent) {
mCenter[0] = center[0];
mCenter[1] = center[1];
@@ -44,21 +64,37 @@ public class Box {
mHalfExtent[2] = halfExtent[2];
}
/**
* Sets the center of of the 3D box.
*/
public void setCenter(float centerX, float centerY, float centerZ) {
mCenter[0] = centerX;
mCenter[1] = centerY;
mCenter[2] = centerZ;
}
/**
* Sets the half-extent of the 3D box.
*/
public void setHalfExtent(float halfExtentX, float halfExtentY, float halfExtentZ) {
mHalfExtent[0] = halfExtentX;
mHalfExtent[1] = halfExtentY;
mHalfExtent[2] = halfExtentZ;
}
/**
* Returns the center of the 3D box.
*
* @return an XYZ float array of size 3
*/
@NonNull @Size(min = 3)
public float[] getCenter() { return mCenter; }
/**
* Returns the half-extent from the center of the 3D box.
*
* @return an XYZ float array of size 3
*/
@NonNull @Size(min = 3)
public float[] getHalfExtent() { return mHalfExtent; }
}

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
/**
* Camera represents the eye through which the scene is viewed.
@@ -157,26 +157,30 @@ public class Camera {
* @param projection type of projection to use
*
* @param left distance in world units from the camera to the left plane,
* at the near plane. Precondition: left != right.
* at the near plane. Precondition: <code>left</code> != <code>right</code>
*
* @param right distance in world units from the camera to the right plane,
* at the near plane. Precondition: left != right.
* at the near plane. Precondition: <code>left</code> != <code>right</code>
*
* @param bottom distance in world units from the camera to the bottom plane,
* at the near plane. Precondition: bottom != top.
* at the near plane. Precondition: <code>bottom</code> != <code>top</code>
*
* @param top distance in world units from the camera to the top plane,
* at the near plane. Precondition: left != right.
* at the near plane. Precondition: <code>bottom</code> != <code>top</code>
*
* @param near distance in world units from the camera to the near plane.
* The near plane's position in view space is z = -near.
* Precondition: near > 0 for {@link Projection#PERSPECTIVE} or
* near != far for {@link Projection#ORTHO}.
* The near plane's position in view space is z = -<code>near</code>.
* Precondition:
* <code>near</code> > 0 for {@link Projection#PERSPECTIVE} or
* <code>near</code> != <code>far</code> for {@link Projection#ORTHO}.
*
* @param far distance in world units from the camera to the far plane.
* The far plane's position in view space is z = -far.
* Precondition: far > near for {@link Projection#PERSPECTIVE} or
* far != near for {@link Projection#ORTHO}.
* The far plane's position in view space is z = -<code>far</code>.
* Precondition:
* <code>far</code> > <code>near</code>
* for {@link Projection#PERSPECTIVE} or
* <code>far</code> != <code>near</code>
* for {@link Projection#ORTHO}.
*
* <p>
* These parameters are silently modified to meet the preconditions above.
@@ -189,12 +193,32 @@ public class Camera {
}
/**
* Sets the projection matrix from the field-of-view.
*
* @param fovInDegrees
* @param aspect
* @param near
* @param far
* @param direction
* @param fovInDegrees full field-of-view in degrees.
* 0 < <code>fovInDegrees</code> < 180
*
* @param aspect aspect ratio width/height. <code>aspect</code> > 0
*
* @param near distance in world units from the camera to the near plane.
* The near plane's position in view space is z = -<code>near</code>.
* Precondition:
* <code>near</code> > 0 for {@link Projection#PERSPECTIVE} or
* <code>near</code> != <code>far</code> for {@link Projection#ORTHO}.
*
* @param far distance in world units from the camera to the far plane.
* The far plane's position in view space is z = -<code>far</code>.
* Precondition:
* <code>far</code> > <code>near</code>
* for {@link Projection#PERSPECTIVE} or
* <code>far</code> != <code>near</code>
* for {@link Projection#ORTHO}.
*
* @param direction direction of the field-of-view parameter.
* <p>
* These parameters are silently modified to meet the preconditions above.
*
* @see Fov
*/
public void setProjection(double fovInDegrees, double aspect, double near, double far,
@NonNull Fov direction) {
@@ -202,47 +226,88 @@ public class Camera {
}
/**
* Sets the projection matrix from the focal length.
*
* @param focalLength lens's focal length in millimeters. <code>focalLength</code> > 0
*
* @param aspect aspect ratio width/height. <code>aspect</code> > 0
*
* @param near distance in world units from the camera to the near plane.
* The near plane's position in view space is z = -<code>near</code>.
* Precondition:
* <code>near</code> > 0 for {@link Projection#PERSPECTIVE} or
* <code>near</code> != <code>far</code> for {@link Projection#ORTHO}.
*
* @param far distance in world units from the camera to the far plane.
* The far plane's position in view space is z = -<code>far</code>.
* Precondition:
* <code>far</code> > <code>near</code>
* for {@link Projection#PERSPECTIVE} or
* <code>far</code> != <code>near</code>
* for {@link Projection#ORTHO}.
*
* @param focalLength
* @param near
* @param far
*/
public void setLensProjection(double focalLength, double near, double far) {
nSetLensProjection(getNativeObject(), focalLength, near, far);
public void setLensProjection(double focalLength, double aspect, double near, double far) {
nSetLensProjection(getNativeObject(), focalLength, aspect, near, far);
}
/**
* Sets the projection matrix.
*
* @param inMatrix
* @param near
* @param far
* @param inMatrix custom projection matrix.
*
* @param near distance in world units from the camera to the near plane.
* The near plane's position in view space is z = -<code>near</code>.
* Precondition:
* <code>near</code> > 0 for {@link Projection#PERSPECTIVE} or
* <code>near</code> != <code>far</code> for {@link Projection#ORTHO}.
*
* @param far distance in world units from the camera to the far plane.
* The far plane's position in view space is z = -<code>far</code>.
* Precondition:
* <code>far</code> > <code>near</code>
* for {@link Projection#PERSPECTIVE} or
* <code>far</code> != <code>near</code>
* for {@link Projection#ORTHO}.
*/
public void setCustomProjection(@NonNull @Size(min = 16) double inMatrix[],
public void setCustomProjection(@NonNull @Size(min = 16) double[] inMatrix,
double near, double far) {
Asserts.assertMat4dIn(inMatrix);
nSetCustomProjection(getNativeObject(), inMatrix, near, far);
}
/**
* Sets the camera's view matrix.
* <p>
* Helper method to set the camera's entity transform component.
* Remember that the Camera "looks" towards its -z axis.
* <p>
* This has the same effect as calling:
*
* @param in
* <pre>
* engine.getTransformManager().setTransform(
* engine.getTransformManager().getInstance(camera->getEntity()), viewMatrix);
* </pre>
*
* @param viewMatrix The camera position and orientation provided as a <b>rigid transform</b> matrix.
*/
public void setModelMatrix(@NonNull @Size(min = 16) float in[]) {
Asserts.assertMat4fIn(in);
nSetModelMatrix(getNativeObject(), in);
public void setModelMatrix(@NonNull @Size(min = 16) float[] viewMatrix) {
Asserts.assertMat4fIn(viewMatrix);
nSetModelMatrix(getNativeObject(), viewMatrix);
}
/**
* Sets the camera's view matrix.
*
* @param eyeX
* @param eyeY
* @param eyeZ
* @param centerX
* @param centerY
* @param centerZ
* @param upX
* @param upY
* @param upZ
* @param eyeX x-axis position of the camera in world space
* @param eyeY y-axis position of the camera in world space
* @param eyeZ z-axis position of the camera in world space
* @param centerX x-axis position of the point in world space the camera is looking at
* @param centerY y-axis position of the point in world space the camera is looking at
* @param centerZ z-axis position of the point in world space the camera is looking at
* @param upX x-axis coordinate of a unit vector denoting the camera's "up" direction
* @param upY y-axis coordinate of a unit vector denoting the camera's "up" direction
* @param upZ z-axis coordinate of a unit vector denoting the camera's "up" direction
*/
public void lookAt(double eyeX, double eyeY, double eyeZ,
double centerX, double centerY, double centerZ, double upX, double upY, double upZ) {
@@ -250,16 +315,14 @@ public class Camera {
}
/**
*
* @return Distance to the near plane.
* @return Distance to the near plane
*/
public float getNear() {
return nGetNear(getNativeObject());
}
/**
*
* @return Distance to the far plane.
* @return Distance to the far plane
*/
public float getCullingFar() {
return nGetCullingFar(getNativeObject());
@@ -267,12 +330,14 @@ public class Camera {
/**
* Retrieves the camera's projection matrix.
*
* @param out A 16-float array where the projection matrix will be stored, or null in which
* case a new array is allocated.
*
* @return A 16-float array containing the camera's projection as a column-major matrix.
*/
@NonNull @Size(min = 16)
public double[] getProjectionMatrix(@Nullable @Size(min = 16) double out[]) {
public double[] getProjectionMatrix(@Nullable @Size(min = 16) double[] out) {
out = Asserts.assertMat4d(out);
nGetProjectionMatrix(getNativeObject(), out);
return out;
@@ -281,12 +346,14 @@ public class Camera {
/**
* Retrieves the camera's model matrix. The model matrix encodes the camera position and
* orientation, or pose.
*
* @param out A 16-float array where the model matrix will be stored, or null in which
* case a new array is allocated.
*
* @return A 16-float array containing the camera's pose as a column-major matrix.
*/
@NonNull @Size(min = 16)
public float[] getModelMatrix(@Nullable @Size(min = 16) float out[]) {
public float[] getModelMatrix(@Nullable @Size(min = 16) float[] out) {
out = Asserts.assertMat4f(out);
nGetModelMatrix(getNativeObject(), out);
return out;
@@ -297,10 +364,11 @@ public class Camera {
*
* @param out A 16-float array where the model view will be stored, or null in which
* case a new array is allocated.
*
* @return A 16-float array containing the camera's view as a column-major matrix.
*/
@NonNull @Size(min = 16)
public float[] getViewMatrix(@Nullable @Size(min = 16) float out[]) {
public float[] getViewMatrix(@Nullable @Size(min = 16) float[] out) {
out = Asserts.assertMat4f(out);
nGetViewMatrix(getNativeObject(), out);
return out;
@@ -308,12 +376,14 @@ public class Camera {
/**
* Retrieves the camera position in world space.
*
* @param out A 3-float array where the position will be stored, or null in which case a new
* array is allocated.
*
* @return A 3-float array containing the camera's position in world units.
*/
@NonNull @Size(min = 3)
public float[] getPosition(@Nullable @Size(min = 3) float out[]) {
public float[] getPosition(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetPosition(getNativeObject(), out);
return out;
@@ -322,12 +392,14 @@ public class Camera {
/**
* Retrieves the camera left unit vector in world space, that is a unit vector that points to
* the left of the camera.
*
* @param out A 3-float array where the left vector will be stored, or null in which case a new
* array is allocated.
*
* @return A 3-float array containing the camera's left vector in world units.
*/
@NonNull @Size(min = 3)
public float[] getLeftVector(@Nullable @Size(min = 3) float out[]) {
public float[] getLeftVector(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetLeftVector(getNativeObject(), out);
return out;
@@ -336,12 +408,14 @@ public class Camera {
/**
* Retrieves the camera up unit vector in world space, that is a unit vector that points up with
* respect to the camera.
*
* @param out A 3-float array where the up vector will be stored, or null in which case a new
* array is allocated.
*
* @return A 3-float array containing the camera's up vector in world units.
*/
@NonNull @Size(min = 3)
public float[] getUpVector(@Nullable @Size(min = 3) float out[]) {
public float[] getUpVector(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetUpVector(getNativeObject(), out);
return out;
@@ -350,46 +424,83 @@ public class Camera {
/**
* Retrieves the camera forward unit vector in world space, that is a unit vector that points
* in the direction the camera is looking at.
*
* @param out A 3-float array where the forward vector will be stored, or null in which case a
* new array is allocated.
*
* @return A 3-float array containing the camera's forward vector in world units.
*/
@NonNull @Size(min = 3)
public float[] getForwardVector(@Nullable @Size(min = 3) float out[]) {
public float[] getForwardVector(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetForwardVector(getNativeObject(), out);
return out;
}
/**
* Sets this camera's exposure (default is f/16, 1/125s, 100 ISO)
*
* @param aperture
* @param shutterSpeed
* @param sensitivity
* The exposure ultimately controls the scene's brightness, just like with a real camera.
* The default values provide adequate exposure for a camera placed outdoors on a sunny day
* with the sun at the zenith.
*
* With the default parameters, the scene must contain at least one Light of intensity
* similar to the sun (e.g.: a 100,000 lux directional light) and/or an indirect light
* of appropriate intensity (30,000).
*
* @param aperture Aperture in f-stops, clamped between 0.5 and 64.
* A lower aperture value increases the exposure, leading to
* a brighter scene. Realistic values are between 0.95 and 32.
*
* @param shutterSpeed Shutter speed in seconds, clamped between 1/25,000 and 60.
* A lower shutter speed increases the exposure. Realistic values are
* between 1/8000 and 30.
*
* @param sensitivity Sensitivity in ISO, clamped between 10 and 204,800.
* A higher sensitivity increases the exposure. Realistic values are
* between 50 and 25600.
*
* @see LightManager
* @see #setExposure(float)
*/
public void setExposure(float aperture, float shutterSpeed, float sensitivity) {
nSetExposure(getNativeObject(), aperture, shutterSpeed, sensitivity);
}
/**
* Sets this camera's exposure directly. Calling this method will set the aperture
* to 1.0, the shutter speed to 1.2 and the sensitivity will be computed to match
* the requested exposure (for a desired exposure of 1.0, the sensitivity will be
* set to 100 ISO).
*
* @return
* This method is useful when trying to match the lighting of other engines or tools.
* Many engines/tools use unit-less light intensities, which can be matched by setting
* the exposure manually. This can be typically achieved by setting the exposure to
* 1.0.
*
* @see LightManager
* @see #setExposure(float, float, float)
*/
public void setExposure(float exposure) {
setExposure(1.0f, 1.2f, 100.0f * (1.0f / exposure));
}
/**
* @return Aperture in f-stops
*/
public float getAperture() {
return nGetAperture(getNativeObject());
}
/**
*
* @return
* @return Shutter speed in seconds
*/
public float getShutterSpeed() {
return nGetShutterSpeed(getNativeObject());
}
/**
*
* @return
* @return Sensitivity in ISO
*/
public float getSensitivity() {
return nGetSensitivity(getNativeObject());
@@ -408,7 +519,7 @@ public class Camera {
private static native void nSetProjection(long nativeCamera, int projection, double left, double right, double bottom, double top, double near, double far);
private static native void nSetProjectionFov(long nativeCamera, double fovInDegrees, double aspect, double near, double far, int fov);
private static native void nSetLensProjection(long nativeCamera, double focalLength, double near, double far);
private static native void nSetLensProjection(long nativeCamera, double focalLength, double aspect, double near, double far);
private static native void nSetCustomProjection(long nativeCamera, double[] inMatrix, double near, double far);
private static native void nSetModelMatrix(long nativeCamera, float[] in);
private static native void nLookAt(long nativeCamera, double eyeX, double eyeY, double eyeZ, double centerX, double centerY, double centerZ, double upX, double upY, double upZ);

View File

@@ -16,8 +16,8 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@@ -28,6 +28,9 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
/**
* Utilities to manipulate and convert colors.
*/
public class Colors {
private Colors() {
}
@@ -37,23 +40,67 @@ public class Colors {
public @interface LinearColor {
}
/**
* Types of RGB colors.
*/
public enum RgbType {
/** The color is defined in sRGB space. */
SRGB,
/** The color is defined in linear space. */
LINEAR
}
/**
* Types of RGBA colors.
*/
public enum RgbaType {
/**
* The color is defined in sRGB space and the RGB values have not been premultiplied by the
* alpha (for instance, a 50% transparent red is <1,0,0,0.5>).
*/
SRGB,
/**
* The color is defined in linear space and the RGB values have not been premultiplied by
* the alpha (for instance, a 50% transparent red is <1,0,0,0.5>).
*/
LINEAR,
/**
* The color is defined in sRGB space and the RGB values have been premultiplied by the
* alpha (for instance, a 50% transparent red is <0.5,0,0,0.5>).
*/
PREMULTIPLIED_SRGB,
/**
* The color is defined in linear space and the RGB values have been premultiplied by the
* alpha (for instance, a 50% transparent red is <0.5,0,0,0.5>).
*/
PREMULTIPLIED_LINEAR
}
/**
* Type of color conversion to use when converting to/from sRGB and linear spaces.
*/
public enum Conversion {
/** Accurate conversion using the sRGB standard. */
ACCURATE,
/** Fast conversion using a simple gamma 2.2 curve. */
FAST
}
/**
* Converts an RGB color to linear space, the conversion depends on the specified type.
*
* @param type the color space of the RGB color values provided
* @param r the red component
* @param g the green component
* @param b the blue component
*
* @return an RGB float array of size 3 with the result of the conversion
*/
@NonNull
@Size(3)
@LinearColor
@@ -61,6 +108,14 @@ public class Colors {
return toLinear(type, new float[] { r, g, b });
}
/**
* Converts an RGB color to linear space, the conversion depends on the specified type.
*
* @param type the color space of the RGB color values provided
* @param rgb an RGB float array of size 3, will be modified
*
* @return the passed-in <code>rgb</code> array, after applying the conversion
*/
@NonNull
@Size(min = 3)
@LinearColor
@@ -68,6 +123,17 @@ public class Colors {
return (type == RgbType.LINEAR) ? rgb : toLinear(Conversion.ACCURATE, rgb);
}
/**
* Converts an RGBA color to linear space, with pre-multiplied alpha.
*
* @param type the color space and type of RGBA color values provided
* @param r the red component
* @param g the green component
* @param b the blue component
* @param a the alpha component
*
* @return an RGBA float array of size 4 with the result of the conversion
*/
@NonNull
@Size(4)
@LinearColor
@@ -75,6 +141,14 @@ public class Colors {
return toLinear(type, new float[] { r, g, b, a });
}
/**
* Converts an RGBA color to linear space, with pre-multiplied alpha.
*
* @param type the color space of the RGBA color values provided
* @param rgba an RGBA float array of size 4, will be modified
*
* @return the passed-in <code>rgba</code> array, after applying the conversion
*/
@NonNull
@Size(min = 4)
@LinearColor
@@ -97,6 +171,15 @@ public class Colors {
return rgba;
}
/**
* Converts an RGB color in sRGB space to an RGB color in linear space.
*
* @param conversion the conversion algorithm to use
* @param rgb an RGB float array of at least size 3, will be modified
*
* @return the passed-in <code>rgb</code> array, after applying the conversion. The alpha
* channel, if present, is left unmodified.
*/
@NonNull
@LinearColor
public static float[] toLinear(@NonNull Conversion conversion, @NonNull @Size(min = 3) float[] rgb) {
@@ -116,6 +199,14 @@ public class Colors {
return rgb;
}
/**
* Converts a correlated color temperature to a linear RGB color in sRGB space. The temperature
* must be expressed in Kelvin and must be in the range 1,000K to 15,000K.
*
* @param temperature the temperature, in Kelvin
*
* @return an RGB float array of size 3 with the result of the conversion
*/
@NonNull
@Size(3)
@LinearColor
@@ -125,6 +216,14 @@ public class Colors {
return color;
}
/**
* Converts a CIE standard illuminant series D to a linear RGB color in sRGB space. The
* temperature must be expressed in Kelvin and must be in the range 4,000K to 25,000K.
*
* @param temperature the temperature, in Kelvin
*
* @return an RGB float array of size 3 with the result of the conversion
*/
@NonNull
@Size(3)
@LinearColor

View File

@@ -16,21 +16,124 @@
package com.google.android.filament;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
import android.support.annotation.NonNull;
/**
* Engine is filament's main entry-point.
* <p>
* An Engine instance main function is to keep track of all resources created by the user and
* manage the rendering thread as well as the hardware renderer.
* <p>
* To use filament, an Engine instance must be created first:
*
* <pre>
* import com.google.android.filament.*
*
* Engine engine = Engine.create();
* </pre>
* <p>
* Engine essentially represents (or is associated to) a hardware context
* (e.g. an OpenGL ES context).
* <p>
* Rendering typically happens in an operating system's window (which can be full screen), such
* window is managed by a {@link Renderer}.
* <p>
* A typical filament render loop looks like this:
*
*
* <pre>
* import com.google.android.filament.*
*
* Engin engine = Engine.create();
* SwapChain swapChain = engine.createSwapChain(nativeWindow);
* Renderer renderer = engine.createRenderer();
* Scene scene = engine.createScene();
* View view = engine.createView();
*
* view.setScene(scene);
*
* do {
* // typically we wait for VSYNC and user input events
* if (renderer.beginFrame(swapChain)) {
* renderer.render(view);
* renderer.endFrame();
* }
* } while (!quit);
*
* engine.destroyView(view);
* engine.destroyScene(scene);
* engine.destroyRenderer(renderer);
* engine.destroySwapChain(swapChain);
* engine.destroy();
* </pre>
*
* <h1><u>Resource Tracking</u></h1>
* <p>
* Each <code>Engine</code> instance keeps track of all objects created by the user, such as vertex
* and index buffers, lights, cameras, etc...
* The user is expected to free those resources, however, leaked resources are freed when the
* engine instance is destroyed and a warning is emitted in the console.
*
* <h1><u>Thread safety</u></h1>
* <p>
* An <code>Engine</code> instance is not thread-safe. The implementation makes no attempt to
* synchronize calls to an <code>Engine</code> instance methods.
* If multi-threading is needed, synchronization must be external.
*
* <h1><u>Multi-threading</u></h1>
* <p>
* When created, the <code>Engine</code> instance starts a render thread as well as multiple worker
* threads, these threads have an elevated priority appropriate for rendering, based on the
* platform's best practices. The number of worker threads depends on the platform and is
* automatically chosen for best performance.
* <p>
* On platforms with asymmetric cores (e.g. ARM's Big.Little), <code>Engine</code> makes some
* educated guesses as to which cores to use for the render thread and worker threads. For example,
* it'll try to keep an OpenGL ES thread on a Big core.
*
* <h1><u>Swap Chains</u></h1>
* <p>
* A swap chain represents an Operating System's <b>native</b> renderable surface.
* Typically it's a window or a view. Because a {@link SwapChain} is initialized from a native
* object, it is given to filament as an <code>Object</code>, which must be of the proper type for
* each platform filament is running on.
* <p>
*
* @see SwapChain
* @see Renderer
*/
public class Engine {
private long mNativeObject;
@NonNull private final TransformManager mTransformManager;
@NonNull private final LightManager mLightManager;
@NonNull private final RenderableManager mRenderableManager;
/**
* Denotes a backend
*/
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.
/**
* Automatically selects an appropriate driver for the platform.
*/
DEFAULT,
/**
* Selects the OpenGL driver (which supports OpenGL ES as well).
*/
OPENGL,
/**
* Selects the Vulkan driver if the platform supports it.
*/
VULKAN,
/**
* Selects the Metal driver if the platform supports it.
*/
METAL,
/**
* Selects the no-op driver for testing purposes.
*/
NOOP,
}
private Engine(long nativeEngine) {
@@ -40,6 +143,19 @@ public class Engine {
mRenderableManager = new RenderableManager(nGetRenderableManager(nativeEngine));
}
/**
* Creates an instance of Engine using the default {@link Backend}
* <p>
* This method is one of the few thread-safe methods.
*
* @return A newly created <code>Engine</code>, or <code>null</code> if the GPU driver couldn't
* be initialized, for instance if it doesn't support the right version of OpenGL or
* OpenGL ES.
*
* @exception IllegalStateException can be thrown if there isn't enough memory to
* allocate the command buffer.
*
*/
@NonNull
public static Engine create() {
long nativeEngine = nCreateEngine(0, 0);
@@ -47,6 +163,21 @@ public class Engine {
return new Engine(nativeEngine);
}
/**
* Creates an instance of Engine using the specified {@link Backend}
* <p>
* This method is one of the few thread-safe methods.
*
* @param backend driver backend to use
*
* @return A newly created <code>Engine</code>, or <code>null</code> if the GPU driver couldn't
* be initialized, for instance if it doesn't support the right version of OpenGL or
* OpenGL ES.
*
* @exception IllegalStateException can be thrown if there isn't enough memory to
* allocate the command buffer.
*
*/
@NonNull
public static Engine create(@NonNull Backend backend) {
long nativeEngine = nCreateEngine(backend.ordinal(), 0);
@@ -55,9 +186,21 @@ public class Engine {
}
/**
* Valid shared context:
* - Android: EGLContext
* - Other: none
* Creates an instance of Engine using the {@link Backend#OPENGL} and a shared OpenGL context.
* <p>
* This method is one of the few thread-safe methods.
*
* @param sharedContext A platform-dependant OpenGL context used as a shared context
* when creating filament's internal context. On Android this parameter
* <b>must be</b> an instance of {@link android.opengl.EGLContext}.
*
* @return A newly created <code>Engine</code>, or <code>null</code> if the GPU driver couldn't
* be initialized, for instance if it doesn't support the right version of OpenGL or
* OpenGL ES.
*
* @exception IllegalStateException can be thrown if there isn't enough memory to
* allocate the command buffer.
*
*/
@NonNull
public static Engine create(@NonNull Object sharedContext) {
@@ -70,15 +213,41 @@ public class Engine {
throw new IllegalArgumentException("Invalid shared context " + sharedContext);
}
/**
* @return <code>true</code> if this <code>Engine</code> is initialized properly.
*/
public boolean isValid() {
return mNativeObject != 0;
}
/**
* Destroy the <code>Engine</code> instance and all associated resources.
* <p>
* This method is one of the few thread-safe methods.
* <p>
* {@link Engine#destroy()} should be called last and after all other resources have been
* destroyed, it ensures all filament resources are freed.
* <p>
* <code>Destroy</code> performs the following tasks:
* <li>Destroy all internal software and hardware resources.</li>
* <li>Free all user allocated resources that are not already destroyed and logs a warning.
* <p>This indicates a "leak" in the user's code.</li>
* <li>Terminate the rendering engine's thread.</li>
*
* <pre>
* Engine engine = Engine.create();
* engine.destroy();
* </pre>
*/
public void destroy() {
nDestroyEngine(getNativeObject());
clearNativeObject();
}
/**
* @return the backend used by this <code>Engine</code>
*/
@NonNull
public Backend getBackend() {
return Backend.values()[(int) nGetBackend(getNativeObject())];
}
@@ -86,25 +255,36 @@ public class Engine {
// SwapChain
/**
* Valid surface types:
* - Android: Surface
* - Other: none
* Creates an opaque {@link SwapChain} from the given OS native window handle.
*
* @param surface on Android, <b>must be</b> an instance of {@link android.view.Surface}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the SwapChain couldn't be created
*/
@NonNull
public SwapChain createSwapChain(@NonNull Object surface) {
return createSwapChain(surface, SwapChain.CONFIG_DEFAULT);
}
/**
* Valid surface types:
* - Android: Surface
* - Other: none
* Creates a {@link SwapChain} from the given OS native window handle.
*
* Flags: see CONFIG flags in SwapChain.
* @param surface on Android, <b>must be</b> an instance of {@link android.view.Surface}
*
* @param flags configuration flags, see {@link SwapChain}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the SwapChain couldn't be created
*
* @see SwapChain#CONFIG_DEFAULT
* @see SwapChain#CONFIG_TRANSPARENT
* @see SwapChain#CONFIG_READABLE
*
*/
@NonNull
public SwapChain createSwapChain(@NonNull Object surface, long flags) {
if (Platform.get().validateSurface(surface)) {
long nativeSwapChain = nCreateSwapChain(getNativeObject(), surface, flags);
@@ -114,6 +294,44 @@ public class Engine {
throw new IllegalArgumentException("Invalid surface " + surface);
}
/**
* Creates a headless {@link SwapChain}
*
* @param width width of the rendering buffer
* @param height height of the rendering buffer
* @param flags configuration flags, see {@link SwapChain}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the SwapChain couldn't be created
*
* @see SwapChain#CONFIG_DEFAULT
* @see SwapChain#CONFIG_TRANSPARENT
* @see SwapChain#CONFIG_READABLE
*
*/
@NonNull
public SwapChain createSwapChain(int width, int height, long flags) {
if (width >= 0 && height >= 0) {
long nativeSwapChain = nCreateSwapChainHeadless(getNativeObject(), width, height, flags);
if (nativeSwapChain == 0) throw new IllegalStateException("Couldn't create SwapChain");
return new SwapChain(nativeSwapChain, null);
}
throw new IllegalArgumentException("Invalid parameters");
}
/**
* Creates a {@link SwapChain} from a {@link NativeSurface}.
*
* @param surface a properly initialized {@link NativeSurface}
*
* @param flags configuration flags, see {@link SwapChain}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the {@link SwapChain} couldn't be created
*/
@NonNull
public SwapChain createSwapChainFromNativeSurface(@NonNull NativeSurface surface, long flags) {
long nativeSwapChain =
nCreateSwapChainFromRawPointer(getNativeObject(), surface.getNativeObject(), flags);
@@ -121,6 +339,10 @@ public class Engine {
return new SwapChain(nativeSwapChain, surface);
}
/**
* Destroys a {@link SwapChain} and frees all its associated resources.
* @param swapChain the {@link SwapChain} to destroy
*/
public void destroySwapChain(@NonNull SwapChain swapChain) {
nDestroySwapChain(getNativeObject(), swapChain.getNativeObject());
swapChain.clearNativeObject();
@@ -128,6 +350,11 @@ public class Engine {
// View
/**
* Creates a {@link View}.
* @return a newly created {@link View}
* @exception IllegalStateException can be thrown if the {@link View} couldn't be created
*/
@NonNull
public View createView() {
long nativeView = nCreateView(getNativeObject());
@@ -135,6 +362,10 @@ public class Engine {
return new View(nativeView);
}
/**
* Destroys a {@link View} and frees all its associated resources.
* @param view the {@link View} to destroy
*/
public void destroyView(@NonNull View view) {
nDestroyView(getNativeObject(), view.getNativeObject());
view.clearNativeObject();
@@ -142,6 +373,11 @@ public class Engine {
// Renderer
/**
* Creates a {@link Renderer}.
* @return a newly created {@link Renderer}
* @exception IllegalStateException can be thrown if the {@link Renderer} couldn't be created
*/
@NonNull
public Renderer createRenderer() {
long nativeRenderer = nCreateRenderer(getNativeObject());
@@ -149,6 +385,10 @@ public class Engine {
return new Renderer(this, nativeRenderer);
}
/**
* Destroys a {@link Renderer} and frees all its associated resources.
* @param renderer the {@link Renderer} to destroy
*/
public void destroyRenderer(@NonNull Renderer renderer) {
nDestroyRenderer(getNativeObject(), renderer.getNativeObject());
renderer.clearNativeObject();
@@ -156,6 +396,12 @@ public class Engine {
// Camera
/**
* Creates a new <code>entity</code> and adds a {@link Camera} component to it.
*
* @return A newly created {@link Camera}
* @exception IllegalStateException can be thrown if the {@link Camera} couldn't be created
*/
@NonNull
public Camera createCamera() {
long nativeCamera = nCreateCamera(getNativeObject());
@@ -163,6 +409,13 @@ public class Engine {
return new Camera(nativeCamera);
}
/**
* Creates and adds a {@link Camera} component to a given <code>entity</code>.
*
* @param entity <code>entity</code> to add the camera component to
* @return A newly created {@link Camera}
* @exception IllegalStateException can be thrown if the {@link Camera} couldn't be created
*/
@NonNull
public Camera createCamera(@Entity int entity) {
long nativeCamera = nCreateCameraWithEntity(getNativeObject(), entity);
@@ -170,6 +423,10 @@ public class Engine {
return new Camera(nativeCamera);
}
/**
* Destroys a {@link Camera} component and frees all its associated resources.
* @param camera the {@link Camera} to destroy
*/
public void destroyCamera(@NonNull Camera camera) {
nDestroyCamera(getNativeObject(), camera.getNativeObject());
camera.clearNativeObject();
@@ -177,6 +434,11 @@ public class Engine {
// Scene
/**
* Creates a {@link Scene}.
* @return a newly created {@link Scene}
* @exception IllegalStateException can be thrown if the {@link Scene} couldn't be created
*/
@NonNull
public Scene createScene() {
long nativeScene = nCreateScene(getNativeObject());
@@ -184,6 +446,10 @@ public class Engine {
return new Scene(nativeScene);
}
/**
* Destroys a {@link Scene} and frees all its associated resources.
* @param scene the {@link Scene} to destroy
*/
public void destroyScene(@NonNull Scene scene) {
nDestroyScene(getNativeObject(), scene.getNativeObject());
scene.clearNativeObject();
@@ -191,6 +457,10 @@ public class Engine {
// Stream
/**
* Destroys a {@link Stream} and frees all its associated resources.
* @param stream the {@link Stream} to destroy
*/
public void destroyStream(@NonNull Stream stream) {
nDestroyStream(getNativeObject(), stream.getNativeObject());
stream.clearNativeObject();
@@ -198,13 +468,22 @@ public class Engine {
// Fence
/**
* Creates a {@link Fence}.
* @return a newly created {@link Fence}
* @exception IllegalStateException can be thrown if the {@link Fence} couldn't be created
*/
@NonNull
public Fence createFence(@NonNull Fence.Type type) {
long nativeFence = nCreateFence(getNativeObject(), type.ordinal());
public Fence createFence() {
long nativeFence = nCreateFence(getNativeObject());
if (nativeFence == 0) throw new IllegalStateException("Couldn't create Fence");
return new Fence(nativeFence);
}
/**
* Destroys a {@link Fence} and frees all its associated resources.
* @param fence the {@link Fence} to destroy
*/
public void destroyFence(@NonNull Fence fence) {
nDestroyFence(getNativeObject(), fence.getNativeObject());
fence.clearNativeObject();
@@ -212,69 +491,135 @@ public class Engine {
// others...
/**
* Destroys a {@link IndexBuffer} and frees all its associated resources.
* @param indexBuffer the {@link IndexBuffer} to destroy
*/
public void destroyIndexBuffer(@NonNull IndexBuffer indexBuffer) {
nDestroyIndexBuffer(getNativeObject(), indexBuffer.getNativeObject());
indexBuffer.clearNativeObject();
}
/**
* Destroys a {@link VertexBuffer} and frees all its associated resources.
* @param vertexBuffer the {@link VertexBuffer} to destroy
*/
public void destroyVertexBuffer(@NonNull VertexBuffer vertexBuffer) {
nDestroyVertexBuffer(getNativeObject(), vertexBuffer.getNativeObject());
vertexBuffer.clearNativeObject();
}
/**
* Destroys a {@link IndirectLight} and frees all its associated resources.
* @param ibl the {@link IndirectLight} to destroy
*/
public void destroyIndirectLight(@NonNull IndirectLight ibl) {
nDestroyIndirectLight(getNativeObject(), ibl.getNativeObject());
ibl.clearNativeObject();
}
/**
* Destroys a {@link Material} and frees all its associated resources.
* <p>
* All {@link MaterialInstance} of the specified {@link Material} must be destroyed before
* destroying it; if some {@link MaterialInstance} remain, this method fails silently.
*
* @param material the {@link Material} to destroy
*/
public void destroyMaterial(@NonNull Material material) {
nDestroyMaterial(getNativeObject(), material.getNativeObject());
material.clearNativeObject();
}
/**
* Destroys a {@link MaterialInstance} and frees all its associated resources.
* @param materialInstance the {@link MaterialInstance} to destroy
*/
public void destroyMaterialInstance(@NonNull MaterialInstance materialInstance) {
nDestroyMaterialInstance(getNativeObject(), materialInstance.getNativeObject());
materialInstance.clearNativeObject();
}
/**
* Destroys a {@link Skybox} and frees all its associated resources.
* @param skybox the {@link Skybox} to destroy
*/
public void destroySkybox(@NonNull Skybox skybox) {
nDestroySkybox(getNativeObject(), skybox.getNativeObject());
skybox.clearNativeObject();
}
/**
* Destroys a {@link Texture} and frees all its associated resources.
* @param texture the {@link Texture} to destroy
*/
public void destroyTexture(@NonNull Texture texture) {
nDestroyTexture(getNativeObject(), texture.getNativeObject());
texture.clearNativeObject();
}
/**
* Destroys a {@link RenderTarget} and frees all its associated resources.
* @param target the {@link RenderTarget} to destroy
*/
public void destroyRenderTarget(@NonNull RenderTarget target) {
nDestroyRenderTarget(getNativeObject(), target.getNativeObject());
target.clearNativeObject();
}
/**
* Destroys an <code>entity</code> and all its components.
* <p>
* It is recommended to destroy components individually before destroying their
* <code>entity</code>, this gives more control as to when the destruction really happens.
* Otherwise, orphaned components are garbage collected, which can happen at a later time.
* Even when component are garbage collected, the destruction of their <code>entity</code>
* terminates their participation immediately.
*
* @param entity the <code>entity</code> to destroy
*/
public void destroyEntity(@Entity int entity) {
nDestroyEntity(getNativeObject(), entity);
}
// Managers
/**
* @return the {@link TransformManager} used by this {@link Engine}
*/
@NonNull
public TransformManager getTransformManager() {
return mTransformManager;
}
/**
* @return the {@link LightManager} used by this {@link Engine}
*/
@NonNull
public LightManager getLightManager() {
return mLightManager;
}
/**
* @return the {@link RenderableManager} used by this {@link Engine}
*/
@NonNull
public RenderableManager getRenderableManager() {
return mRenderableManager;
}
/**
* Kicks the hardware thread (e.g.: the OpenGL, Vulkan or Metal thread) and blocks until
* all commands to this point are executed. Note that this doesn't guarantee that the
* hardware is actually finished.
*
* <p>This is typically used right after destroying the <code>SwapChain</code>,
* in cases where a guarantee about the SwapChain destruction is needed in a timely fashion,
* such as when responding to Android's
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.</p>
*/
public void flushAndWait() {
Fence.waitAndDestroy(createFence(Fence.Type.HARD), Fence.Mode.FLUSH);
nFlushAndWait(getNativeObject());
}
@UsedByReflection("TextureHelper.java")
@@ -293,6 +638,7 @@ public class Engine {
private static native void nDestroyEngine(long nativeEngine);
private static native long nGetBackend(long nativeEngine);
private static native long nCreateSwapChain(long nativeEngine, Object nativeWindow, long flags);
private static native long nCreateSwapChainHeadless(long nativeEngine, int width, int height, long flags);
private static native long nCreateSwapChainFromRawPointer(long nativeEngine, long pointer, long flags);
private static native void nDestroySwapChain(long nativeEngine, long nativeSwapChain);
private static native long nCreateView(long nativeEngine);
@@ -304,7 +650,7 @@ public class Engine {
private static native void nDestroyCamera(long nativeEngine, long nativeCamera);
private static native long nCreateScene(long nativeEngine);
private static native void nDestroyScene(long nativeEngine, long nativeScene);
private static native long nCreateFence(long nativeEngine, int fenceType);
private static native long nCreateFence(long nativeEngine);
private static native void nDestroyFence(long nativeEngine, long nativeFence);
private static native void nDestroyStream(long nativeEngine, long nativeStream);
private static native void nDestroyIndexBuffer(long nativeEngine, long nativeIndexBuffer);
@@ -316,6 +662,7 @@ public class Engine {
private static native void nDestroyTexture(long nativeEngine, long nativeTexture);
private static native void nDestroyRenderTarget(long nativeEngine, long nativeTarget);
private static native void nDestroyEntity(long nativeEngine, int entity);
private static native void nFlushAndWait(long nativeEngine);
private static native long nGetTransformManager(long nativeEngine);
private static native long nGetLightManager(long nativeEngine);
private static native long nGetRenderableManager(long nativeEngine);

View File

@@ -16,10 +16,10 @@
package com.google.android.filament;
import com.google.android.filament.proguard.UsedByReflection;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
public class EntityManager {
private long mNativeObject = nGetEntityManager();

View File

@@ -15,7 +15,7 @@ package com.google.android.filament;
* limitations under the License.
*/
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
public class Fence {
private long mNativeObject;
@@ -26,11 +26,6 @@ public class Fence {
public static final long WAIT_FOR_EVER = -1;
public enum Type {
SOFT,
HARD
}
public enum Mode {
FLUSH,
DONT_FLUSH
@@ -42,6 +37,9 @@ public class Fence {
TIMEOUT_EXPIRED
}
/**
* Blocks the current thread until the Fence signals.
*/
public FenceStatus wait(@NonNull Mode mode, long timeoutNanoSeconds) {
int nativeResult = nWait(getNativeObject(), mode.ordinal(), timeoutNanoSeconds);
switch (nativeResult) {

View File

@@ -16,13 +16,24 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
/**
* A buffer containing vertex indices into a <code>VertexBuffer</code>. Indices can be 16 or 32 bit.
* The buffer itself is a GPU resource, therefore mutating the data can be relatively slow.
* Typically these buffers are constant.
*
* It is possible, and even encouraged, to use a single index buffer for several
* <code>Renderables</code>.
*
* @see VertexBuffer
* @see RenderableManager
*/
public class IndexBuffer {
private long mNativeObject;
@@ -36,8 +47,14 @@ public class IndexBuffer {
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
/**
* Type of the index buffer.
*/
public enum IndexType {
/** 16-bit indices */
USHORT,
/** 32-bit indices */
UINT,
}
@@ -46,18 +63,45 @@ public class IndexBuffer {
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Size of the index buffer in elements.
*
* @param indexCount number of indices the <code>IndexBuffer</code> can hold
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder indexCount(@IntRange(from = 1) int indexCount) {
nBuilderIndexCount(mNativeBuilder, indexCount);
return this;
}
/**
* Type of the index buffer, 16-bit or 32-bit.
*
* @param indexType type of indices stored in the <code>IndexBuffer</code>
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder bufferType(@NonNull IndexType indexType) {
nBuilderBufferType(mNativeBuilder, indexType.ordinal());
return this;
}
/**
* Creates and returns the <code>IndexBuffer</code> object. After creation, the index buffer
* is uninitialized. Use {@link #setBuffer} to initialized the <code>IndexBuffer</code>.
*
* @param engine reference to the {@link Engine} to associate this <code>IndexBuffer</code>
* with
*
* @return the newly created <code>IndexBuffer</code> object
*
* @exception IllegalStateException if the IndexBuffer could not be created
*
* @see #setBuffer
*/
@NonNull
public IndexBuffer build(@NonNull Engine engine) {
long nativeIndexBuffer = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -85,24 +129,69 @@ public class IndexBuffer {
}
}
/**
* Returns the size of this <code>IndexBuffer</code> in elements.
*
* @return the number of indices the <code>IndexBuffer</code> holds
*/
@IntRange(from = 0)
public int getIndexCount() {
return nGetIndexCount(getNativeObject());
}
/**
* Asynchronously copy-initializes this <code>IndexBuffer</code> from the data provided.
*
* @param engine reference to the {@link Engine} to associate this
* <code>IndexBuffer</code> with
* @param buffer a CPU-side {@link Buffer} with the data used to initialize the
* <code>IndexBuffer</code>. <code>buffer</code> should contain raw,
* untyped data that will be interpreted as either 16-bit or 32-bits
* indices based on the <code>IndexType</code> of this
* <code>IndexBuffer</code>.
*/
public void setBuffer(@NonNull Engine engine, @NonNull Buffer buffer) {
setBuffer(engine, buffer, 0, 0, null, null);
}
/**
* Asynchronously copy-initializes a region of this <code>IndexBuffer</code> from the data
* provided.
*
* @param engine reference to the {@link Engine} to associate this
* <code>IndexBuffer</code> with
* @param buffer a CPU-side {@link Buffer} with the data used to initialize the
* <code>IndexBuffer</code>. <code>buffer</code> should contain raw,
* untyped data that will be interpreted as either 16-bit or 32-bits
* indices based on the <code>IndexType</code> of this
* <code>IndexBuffer</code>.
* @param destOffsetInBytes offset in <i>bytes</i> into the <code>IndexBuffer</code>
* @param count number of buffer elements to consume, defaults to
* <code>buffer.remaining()</code>
*/
public void setBuffer(@NonNull Engine engine, @NonNull Buffer buffer,
@IntRange(from = 0) int destOffsetInBytes, @IntRange(from = 0) int count) {
setBuffer(engine, buffer, destOffsetInBytes, count, null, null);
}
/**
* Valid handler types:
* - Android: Handler, Executor
* - Other: Executor
* Asynchronously copy-initializes a region of this <code>IndexBuffer</code> from the data
* provided.
*
* @param engine reference to the {@link Engine} to associate this
* <code>IndexBuffer</code> with
* @param buffer a CPU-side {@link Buffer} with the data used to initialize the
* <code>IndexBuffer</code>. <code>buffer</code> should contain raw,
* untyped data that will be interpreted as either 16-bit or 32-bits
* indices based on the <code>IndexType</code> of this
* <code>IndexBuffer</code>.
* @param destOffsetInBytes offset in <i>bytes</i> into the <code>IndexBuffer</code>
* @param count number of buffer elements to consume, defaults to
* <code>buffer.remaining()</code>
* @param handler an {@link java.util.concurrent.Executor Executor}. On Android this
* can also be a {@link android.os.Handler Handler}.
* @param callback a callback executed by <code>handler</code> when <code>buffer</code>
* is no longer needed.
*/
public void setBuffer(@NonNull Engine engine, @NonNull Buffer buffer,
@IntRange(from = 0) int destOffsetInBytes, @IntRange(from = 0) int count,

View File

@@ -16,37 +16,171 @@
package com.google.android.filament;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import com.google.android.filament.proguard.UsedByReflection;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
/**
* <code>IndirectLight</code> is used to simulate environment lighting, a form of global illumination.
*
* <p>Environment lighting has a two components:</p>
* <ol>
* <li>irradiance</li>
* <li>reflections (specular component)</li>
* </ol>
*
* <p>Environments are usually captured as high-resolution HDR equirectangular images and processed
* by the <b>cmgen</b> tool to generate the data needed by {@link IndirectLight}.</p>
*
* <p>Currently {@link IndirectLight} is intended to be used for "distant probes", that is, to represent
* global illumination from a distant (i.e. at infinity) environment, such as the sky or distant
* mountains. Only a single {@link IndirectLight} can be used in a {@link Scene}.
* This limitation will be lifted in the future.</p>
*
*
* <h1>Creation and destruction</h1>
*
* <p>An {@link IndirectLight} object is created using the {@link IndirectLight.Builder} and
* destroyed by calling {@link Engine#destroyIndirectLight}.</p>
*
* <pre>
* Engine engine = Engine.create();
*
* Scene scene = engine.createScene();
*
* IndirectLight environment = new IndirectLight.Builder()
* .reflections(cubemap)
* .irradiance(numBands, sphericalHarmonicsCoefficients)
* .build(engine);
*
* scene.setIndirectLight(environment);
* </pre>
*
*
* <h1>Irradiance</h1>
*
* <p>The irradiance represents the light that comes from the environment and shines an
* object's surface.
* The irradiance is calculated automatically from the Reflections (see below), and generally
* doesn't need to be provided explicitly. However, it can be provided separately from the
* Reflections as
* <a href="https://en.wikipedia.org/wiki/Spherical_harmonics">Spherical Harmonics</a> (SH) of 1, 2 or
* 3 bands, respectively 1, 4 or 9 coefficients.</p>
*
* <p>Use the <b>cmgen</b> tool to generate the Spherical Harmonics for a given environment.</p>
*
*
* <h1>Reflections</h1>
*
* <p>The reflections on object surfaces (specular component) is calculated from a specially
* filtered cubemap pyramid generated by the <b>cmgen</b> tool.</p>
*
* @see Scene
* @see LightManager
* @see Texture
* @see Skybox
*/
public class IndirectLight {
long mNativeObject;
@UsedByReflection("KtxLoader.java")
IndirectLight(long indirectLight) {
public IndirectLight(long indirectLight) {
mNativeObject = indirectLight;
}
/**
* Use <code>Builder</code> to construct an <code>IndirectLight</code> object instance.
*/
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
/**
* Use <code>Builder</code> to construct an <code>IndirectLight</code> object instance.
*/
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Set the reflections cubemap mipmap chain.
*
* @param cubemap A mip-mapped cubemap generated by <b>cmgen</b>. Each cubemap level
* encodes the irradiance for a roughness level.
*
* @return This Builder, for chaining calls.
*
*/
@NonNull
public Builder reflections(@NonNull Texture cubemap) {
nBuilderReflections(mNativeBuilder, cubemap.getNativeObject());
return this;
}
/**
* Sets the irradiance as Spherical Harmonics.
*
* <p>The irradiance coefficients must be pre-convolved by <code>&lt n &sdot l &gt</code> and
* pre-multiplied by the Lambertian diffuse BRDF <code>1/&pi</code> and
* specified as Spherical Harmonics coefficients.</p>
*
* <p>Additionally, these Spherical Harmonics coefficients must be pre-scaled by the
* reconstruction factors A<sup>l,m</sup>.</p>
*
* <p>The final coefficients can be generated using the <code>cmgen</code> tool.</p>
*
* <p>The index in the <code>sh</code> array is given by:
* <br><code>index(l, m) = 3 &times (l * (l + 1) + m)</code>
* <br><code>sh[index(l,m) + 0] = L<sub>R</sub><sup>l,m</sup>
* &times 1/&pi
* &times A<sup>l,m</sup>
* &times C<sup>l</sup> </code>
* <br><code>sh[index(l,m) + 1] = L<sub>G</sub><sup>l,m</sup>
* &times 1/&pi
* &times A<sup>l,m</sup>
* &times C<sup>l</sup> </code>
* <br><code>sh[index(l,m) + 2] = L<sub>B</sub><sup>l,m</sup>
* &times 1/&pi
* &times A<sup>l,m</sup>
* &times C<sup>l</sup> </code>
* </p>
*
* <center>
* <table border="1" cellpadding="3">
* <tr><th> index </th><th> l </th><th> m </th><th> A<sup>l,m</sup> </th><th> C<sup>l</sup> </th>
* <th> 1/&pi &times A<sup>l,m</sup> &times C<sup>l</sup></th></tr>
* <tr align="right"><td>0</td><td>0</td><td> 0</td><td> 0.282095</td><td>3.1415926</td><td> 0.282095</td></tr>
* <tr align="right"><td>1</td><td>1</td><td>-1</td><td>-0.488602</td><td>2.0943951</td><td>-0.325735</td></tr>
* <tr align="right"><td>2</td><td>1</td><td> 0</td><td> 0.488602</td><td>2.0943951</td><td> 0.325735</td></tr>
* <tr align="right"><td>3</td><td>1</td><td> 1</td><td>-0.488602</td><td>2.0943951</td><td>-0.325735</td></tr>
* <tr align="right"><td>4</td><td>2</td><td>-2</td><td> 1.092548</td><td>0.785398 </td><td> 0.273137</td></tr>
* <tr align="right"><td>5</td><td>2</td><td>-1</td><td>-1.092548</td><td>0.785398 </td><td>-0.273137</td></tr>
* <tr align="right"><td>6</td><td>2</td><td> 0</td><td> 0.315392</td><td>0.785398 </td><td> 0.078848</td></tr>
* <tr align="right"><td>7</td><td>2</td><td> 1</td><td>-1.092548</td><td>0.785398 </td><td>-0.273137</td></tr>
* <tr align="right"><td>8</td><td>2</td><td> 2</td><td> 0.546274</td><td>0.785398 </td><td> 0.136569</td></tr>
* </table>
* </center>
*
*
* <p>Only 1, 2 or 3 bands are allowed.</p>
*
* <p>Because the coefficients are pre-scaled, <code>sh[0]</code> is the environment's
* average irradiance.</p>
*
* @param bands Number of spherical harmonics bands. Must be 1, 2 or 3.
* @param sh Array containing the spherical harmonics coefficients.
* The size of the array must be <code>3 &times bands<sup>2</sup></code>
* (i.e. 1, 4 or 9 <code>float3</code> coefficients respectively).
*
* @return This Builder, for chaining calls.
*
* @exception ArrayIndexOutOfBoundsException if the <code>sh</code> array length is smaller
* than 3 &times bands<sup>2</sup>
*/
@NonNull
public Builder irradiance(@IntRange(from=1, to=3) int bands, @NonNull float[] sh) {
switch (bands) {
@@ -65,6 +199,44 @@ public class IndirectLight {
return this;
}
/**
* Sets the irradiance from the radiance expressed as Spherical Harmonics.
*
* <p>The radiance must be specified as Spherical Harmonics coefficients L<sup>l,m</sup>, where
* each coefficient is comprised of three floats for red, green and blue components, respectively</p>
*
* <p>The index in the <code>sh</code> array is given by:
* <br><code>index(l, m) = 3 &times (l * (l + 1) + m)</code>
* <br><code>sh[index(l,m) + 0] = L<sub>R</sub><sup>l,m</sup></code>
* <br><code>sh[index(l,m) + 1] = L<sub>G</sub><sup>l,m</sup></code>
* <br><code>sh[index(l,m) + 2] = L<sub>B</sub><sup>l,m</sup></code>
* </p>
*
* <center>
* <table border="1" cellpadding="3">
* <tr><th> index </th><th> l </th><th> m </th>
* <tr align="right"><td>0</td><td>0</td><td> 0</td>
* <tr align="right"><td>1</td><td>1</td><td>-1</td>
* <tr align="right"><td>2</td><td>1</td><td> 0</td>
* <tr align="right"><td>3</td><td>1</td><td> 1</td>
* <tr align="right"><td>4</td><td>2</td><td>-2</td>
* <tr align="right"><td>5</td><td>2</td><td>-1</td>
* <tr align="right"><td>6</td><td>2</td><td> 0</td>
* <tr align="right"><td>7</td><td>2</td><td> 1</td>
* <tr align="right"><td>8</td><td>2</td><td> 2</td>
* </table>
* </center>
*
* @param bands Number of spherical harmonics bands. Must be 1, 2 or 3.
* @param sh Array containing the spherical harmonics coefficients.
* The size of the array must be 3 &times <code>bands<sup>2</sup></code>
* (i.e. 1, 4 or 9 <code>float3</code> coefficients respectively).
*
* @return This Builder, for chaining calls.
*
* @exception ArrayIndexOutOfBoundsException if the <code>sh</code> array length is smaller
* than 3 &times bands<sup>2</sup>
*/
@NonNull
public Builder radiance(@IntRange(from=1, to=3) int bands, @NonNull float[] sh) {
switch (bands) {
@@ -83,18 +255,52 @@ public class IndirectLight {
return this;
}
/**
* Sets the irradiance as a cubemap.
* <p></p>
* The irradiance can alternatively be specified as a cubemap instead of Spherical
* Harmonics coefficients. It may or may not be more efficient, depending on your
* hardware (essentially, it's trading ALU for bandwidth).
* <p></p>
* This irradiance cubemap can be generated with the <code>cmgen</code> tool.
*
* @param cubemap Cubemap representing the Irradiance pre-convolved by
* <code>&lt n &sdot l &gt</code>.
*
* @return This Builder, for chaining calls.
*
* @see #irradiance(int bands, float[] sh)
*/
@NonNull
public Builder irradiance(@NonNull Texture cubemap) {
nIrradianceAsTexture(mNativeBuilder, cubemap.getNativeObject());
return this;
}
/**
* Environment intensity (optional).
*
* <p>Because the environment is encoded usually relative to some reference, the
* range can be adjusted with this method.</p>
*
* @param envIntensity Scale factor applied to the environment and irradiance such that
* the result is in cd/m^2 (lux) units (default = 30000)
*
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder intensity(float envIntensity) {
nIntensity(mNativeBuilder, envIntensity);
return this;
}
/**
* Specifies the rigid-body transformation to apply to the IBL.
*
* @param rotation 3x3 rotation matrix. Must be a rigid-body transform.
*
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder rotation(@NonNull @Size(min = 9) float[] rotation) {
nRotation(mNativeBuilder,
@@ -104,6 +310,15 @@ public class IndirectLight {
return this;
}
/**
* Creates the IndirectLight object and returns a pointer to it.
*
* @param engine The {@link Engine} to associate this <code>IndirectLight</code> with.
*
* @return A newly created <code>IndirectLight</code>
*
* @exception IllegalStateException if a parameter to a builder function was invalid.
*/
@NonNull
public IndirectLight build(@NonNull Engine engine) {
long nativeIndirectLight = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -128,14 +343,31 @@ public class IndirectLight {
}
}
/**
* Sets the environment's intensity.
*
* <p>Because the environment is encoded usually relative to some reference, the
* range can be adjusted with this method.</p>
*
* @param intensity Scale factor applied to the environment and irradiance such that
* the result is in cd/m^2 units (default = 30000)
*/
public void setIntensity(float intensity) {
nSetIntensity(getNativeObject(), intensity);
}
/**
* Returns the environment's intensity in cd/m<sup>2</sup>.
*/
public float getIntensity() {
return nGetIntensity(getNativeObject());
}
/**
* Sets the rigid-body transformation to apply to the IBL.
*
* @param rotation 3x3 rotation matrix. Must be a rigid-body transform.
*/
public void setRotation(@NonNull @Size(min = 9) float[] rotation) {
Asserts.assertMat3fIn(rotation);
nSetRotation(getNativeObject(),
@@ -144,6 +376,14 @@ public class IndirectLight {
rotation[6], rotation[7], rotation[8]);
}
/**
* Returns the rigid-body transformation applied to the IBL.
*
* @param rotation an array of 9 floats to receive the rigid-body transformation applied to
* the IBL or <code>null</code>
* @return the <code>rotation</code> paramter if it was provided, or a newly allocated float
* array containing the rigid-body transformation applied to the IBL
*/
@NonNull @Size(min = 9)
public float[] getRotation(@Nullable @Size(min = 9) float[] rotation) {
rotation = Asserts.assertMat3f(rotation);
@@ -151,6 +391,41 @@ public class IndirectLight {
return rotation;
}
/**
* Helper to estimate the direction of the dominant light in the environment.
*
* <p>This assumes that there is only a single dominant light (such as the sun in outdoors
* environments), if it's not the case the direction returned will be an average of the
* various lights based on their intensity.</p>
*
* <p>If there are no clear dominant light, as is often the case with low dynamic range (LDR)
* environments, this method may return a wrong or unexpected direction.</p>
*
* <p>The dominant light direction can be used to set a directional light's direction,
* for instance to produce shadows that match the environment.</p>
*
* @param sh pre-scaled 3-bands spherical harmonics
* @param direction an array of 3 floats to receive a unit vector representing the direction of
* the dominant light or <code>null</code>
* @return the <code>direction</code> paramter if it was provided, or a newly allocated float
* array containing a unit vector representing the direction of the dominant light
*
* @see LightManager.Builder#direction
* @see #getColorEstimate
*/
@NonNull @Size(min = 3)
public static float[] getDirectionEstimate(@NonNull float[] sh, @Nullable @Size(min = 3) float[] direction) {
if (sh.length < 9 * 3) {
throw new ArrayIndexOutOfBoundsException(
"3 bands SH required, array must be at least 9 x float3");
}
direction = Asserts.assertFloat3(direction);
nGetDirectionEstimateStatic(sh, direction);
return direction;
}
/** @deprecated */
@NonNull @Size(min = 3)
public float[] getDirectionEstimate(@Nullable @Size(min = 3) float[] direction) {
direction = Asserts.assertFloat3(direction);
@@ -158,6 +433,41 @@ public class IndirectLight {
return direction;
}
/**
* Helper to estimate the color and relative intensity of the environment in a given direction.
*
* <p>This can be used to set the color and intensity of a directional light. In this case
* make sure to multiply this relative intensity by the the intensity of this indirect light.</p>
*
* @param colorIntensity an array of 4 floats to receive the result or <code>null</code>
* @param sh pre-scaled 3-bands spherical harmonics
* @param x the x coordinate of a unit vector representing the direction of the light
* @param y the x coordinate of a unit vector representing the direction of the light
* @param z the x coordinate of a unit vector representing the direction of the light
*
* @return A vector of 4 floats where the first 3 components represent the linear color and
* the 4th component represents the intensity of the dominant light
*
* @see LightManager.Builder#color
* @see LightManager.Builder#intensity
* @see #getDirectionEstimate
* @see #getIntensity
* @see #setIntensity
*/
@NonNull @Size(min = 4)
public static float[] getColorEstimate(@Nullable @Size(min = 4) float[] colorIntensity, @NonNull float[] sh, float x, float y, float z) {
if (sh.length < 9 * 3) {
throw new ArrayIndexOutOfBoundsException(
"3 bands SH required, array must be at least 9 x float3");
}
colorIntensity = Asserts.assertFloat4(colorIntensity);
nGetColorEstimateStatic(colorIntensity, sh, x, y, z);
return colorIntensity;
}
/** @deprecated */
@NonNull @Size(min = 4)
public float[] getColorEstimate(@Nullable @Size(min = 4) float[] colorIntensity, float x, float y, float z) {
colorIntensity = Asserts.assertFloat4(colorIntensity);
@@ -193,4 +503,7 @@ public class IndirectLight {
private static native void nGetRotation(long nativeIndirectLight, float[] outRotation);
private static native void nGetDirectionEstimate(long nativeIndirectLight, float[] outDirection);
private static native void nGetColorEstimate(long nativeIndirectLight, float[] outColor, float x, float y, float z);
private static native void nGetDirectionEstimateStatic(float[] sh, float[] direction);
private static native void nGetColorEstimateStatic(float[] colorIntensity, float[] sh, float x, float y, float z);
}

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
public class LightManager {
private long mNativeObject;
@@ -56,6 +56,9 @@ public class LightManager {
public float shadowNearHint = 1.0f;
public float shadowFarHint = 100.0f;
public boolean stable = true;
public boolean screenSpaceContactShadows = false;
public int stepCount = 8;
public float maxShadowDistance = 0.3f;
}
public static final float EFFICIENCY_INCANDESCENT = 0.0220f;
@@ -83,7 +86,8 @@ public class LightManager {
public Builder shadowOptions(@NonNull ShadowOptions options) {
nBuilderShadowOptions(mNativeBuilder,
options.mapSize, options.constantBias, options.normalBias, options.shadowFar,
options.shadowNearHint, options.shadowFarHint, options.stable);
options.shadowNearHint, options.shadowFarHint, options.stable,
options.screenSpaceContactShadows, options.stepCount, options.maxShadowDistance);
return this;
}
@@ -282,7 +286,7 @@ public class LightManager {
private static native void nDestroyBuilder(long nativeBuilder);
private static native boolean nBuilderBuild(long nativeBuilder, long nativeEngine, int entity);
private static native void nBuilderCastShadows(long nativeBuilder, boolean enable);
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable);
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable, boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance);
private static native void nBuilderCastLight(long nativeBuilder, boolean enabled);
private static native void nBuilderPosition(long nativeBuilder, float x, float y, float z);
private static native void nBuilderDirection(long nativeBuilder, float x, float y, float z);

View File

@@ -16,9 +16,10 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
import com.google.android.filament.proguard.UsedByNative;
import java.nio.Buffer;
@@ -28,45 +29,182 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Set;
/**
* A Filament Material defines the visual appearance of an object. Materials function as a
* templates from which {@link MaterialInstance}s can be spawned. Use {@link Builder} to construct
* a Material object.
*
* @see <a href="https://google.github.io/filament/Materials.html">Filament Materials Guide</a>
*/
public class Material {
private long mNativeObject;
private final MaterialInstance mDefaultInstance;
private Set<VertexBuffer.VertexAttribute> mRequiredAttributes;
/** Supported shading models */
public enum Shading {
/**
* No lighting applied, emissive possible
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialmodels/unlitmodel">
* Unlit model</a>
*/
UNLIT,
/**
* Default, standard lighting
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialmodels/litmodel">
* Lit model</a>
*/
LIT,
/**
* Subsurface lighting model
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialmodels/subsurfacemodel">
* Subsurface model</a>
*/
SUBSURFACE,
/**
* Cloth lighting model
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialmodels/clothmodel">
* Cloth model</a>
*/
CLOTH,
/**
* Legacy lighting model
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialmodels/specularglossiness">
* Specular glossiness</a>
*/
SPECULAR_GLOSSINESS
}
/**
* Attribute interpolation types in the fragment shader
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:interpolation">
* Vertex and attributes: interpolation</a>
*/
public enum Interpolation {
/** Default, smooth interpolation */
SMOOTH,
/** Flat interpolation */
FLAT
}
/**
* Supported blending modes
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:blending">
* Blending and transparency: blending</a>
*/
public enum BlendingMode {
/** Material is opaque. */
OPAQUE,
/**
* Material is transparent and color is alpha-pre-multiplied.
* Affects diffuse lighting only.
*/
TRANSPARENT,
/** Material is additive (e.g.: hologram). */
ADD,
MODULATE,
/** Material is masked (i.e. alpha tested). */
MASKED,
FADE
/**
* Material is transparent and color is alpha-pre-multiplied.
* Affects specular lighting.
*/
FADE,
/** Material darkens what's behind it. */
MULTIPLY,
/** Material brightens what's behind it. */
SCREEN,
}
/**
* Supported refraction modes
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refraction">
* Blending and transparency: refractionMode</a>
*/
public enum RefractionMode {
NONE,
CUBEMAP,
SCREEN_SPACE
}
/**
* Supported refraction types
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refractiontype">
* Blending and transparency: refractionType</a>
*/
public enum RefractionType {
SOLID,
THIN
}
/**
* Supported types of vertex domains
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:vertexdomain">
* Vertex and attributes: vertexDomain</a>
*/
public enum VertexDomain {
/** Vertices are in object space, default. */
OBJECT,
/** Vertices are in world space. */
WORLD,
/** Vertices are in view space. */
VIEW,
/** Vertices are in normalized device space. */
DEVICE
}
/**
* Face culling Mode
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
* Rasterization: culling</a>
*/
public enum CullingMode {
/** No culling. Front and back faces are visible. */
NONE,
/** Front face culling. Only back faces are visible. */
FRONT,
/** Back face culling. Only front faces are visible. */
BACK,
/** Front and back culling. Geometry is not visible. */
FRONT_AND_BACK
}
@@ -144,6 +282,13 @@ public class Material {
private Buffer mBuffer;
private int mSize;
/**
* Specifies the material data. The material data is a binary blob produced by
* libfilamat or by matc.
*
* @param buffer buffer containing material data
* @param size size of the material data in bytes
*/
@NonNull
public Builder payload(@NonNull Buffer buffer, @IntRange(from = 0) int size) {
mBuffer = buffer;
@@ -151,6 +296,15 @@ public class Material {
return this;
}
/**
* Creates and returns the Material object.
*
* @param engine reference to the Engine instance to associate this Material with
*
* @return the newly created object
*
* @exception IllegalStateException if the material could not be created
*/
@NonNull
public Material build(@NonNull Engine engine) {
long nativeMaterial = nBuilderBuild(engine.getNativeObject(), mBuffer, mSize);
@@ -159,6 +313,12 @@ public class Material {
}
}
/**
* Creates a new instance of this material. Material instances should be freed using
* {@link Engine#destroyMaterialInstance(MaterialInstance)}.
*
* @return the new instance
*/
@NonNull
public MaterialInstance createInstance() {
long nativeInstance = nCreateInstance(getNativeObject());
@@ -166,63 +326,185 @@ public class Material {
return new MaterialInstance(this, nativeInstance);
}
/** Returns the material's default instance. */
@NonNull
public MaterialInstance getDefaultInstance() {
return mDefaultInstance;
}
/**
* Returns the name of this material. The material name is used for debugging purposes.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/general:name">
* General: name</a>
*/
public String getName() {
return nGetName(getNativeObject());
}
/**
* Returns the shading model of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialmodels">
* Material Models</a>
*/
public Shading getShading() {
return Shading.values()[nGetShading(getNativeObject())];
}
/**
* Returns the interpolation mode of this material. This affects how variables are interpolated.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:interpolation">
* Vertex and attributes: interpolation</a>
*/
public Interpolation getInterpolation() {
return Interpolation.values()[nGetInterpolation(getNativeObject())];
}
/**
* Returns the blending mode of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:blending">
* Blending and transparency: blending</a>
*/
public BlendingMode getBlendingMode() {
return BlendingMode.values()[nGetBlendingMode(getNativeObject())];
}
/**
* Returns the refraction mode of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refraction">
* Blending and transparency: refraction</a>
*/
public RefractionMode getRefractionMode() {
return RefractionMode.values()[nGetRefractionMode(getNativeObject())];
}
/**
* Returns the refraction type of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:refractiontype">
* Blending and transparency: refractionType</a>
*/
public RefractionType getRefractionType() {
return RefractionType.values()[nGetRefractionType(getNativeObject())];
}
/**
* Returns the vertex domain of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:vertexdomain">
* Vertex and attributes: vertexDomain</a>
*/
public VertexDomain getVertexDomain() {
return VertexDomain.values()[nGetVertexDomain(getNativeObject())];
}
/**
* Returns the default culling mode of this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
* Rasterization: culling</a>
*/
public CullingMode getCullingMode() {
return CullingMode.values()[nGetCullingMode(getNativeObject())];
}
/**
* Indicates whether instances of this material will, by default, write to the color buffer.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:colorwrite">
* Rasterization: colorWrite</a>
*/
public boolean isColorWriteEnabled() {
return nIsColorWriteEnabled(getNativeObject());
}
/**
* Indicates whether instances of this material will, by default, write to the depth buffer.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:depthwrite">
* Rasterization: depthWrite</a>
*/
public boolean isDepthWriteEnabled() {
return nIsDepthWriteEnabled(getNativeObject());
}
/**
* Indicates whether instances of this material will, by default, use depth testing.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:depthculling">
* Rasterization: depthCulling</a>
*/
public boolean isDepthCullingEnabled() {
return nIsDepthCullingEnabled(getNativeObject());
}
/**
* Indicates whether this material is double-sided.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:doublesided">
* Rasterization: doubleSided</a>
*/
public boolean isDoubleSided() {
return nIsDoubleSided(getNativeObject());
}
/**
* Returns the alpha mask threshold used when the blending mode is set to masked.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:maskthreshold">
* Blending and transparency: maskThreshold</a>
*/
public float getMaskThreshold() {
return nGetMaskThreshold(getNativeObject());
}
/**
* Returns the screen-space variance for specular-antialiasing. This value is between 0 and 1.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">
* Anti-aliasing: specularAntiAliasingVariance</a>
*/
public float getSpecularAntiAliasingVariance() {
return nGetSpecularAntiAliasingVariance(getNativeObject());
}
/**
* Returns the clamping threshold for specular-antialiasing. This value is between 0 and 1.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">
* Anti-aliasing: specularAntiAliasingThreshold</a>
*/
public float getSpecularAntiAliasingThreshold() {
return nGetSpecularAntiAliasingThreshold(getNativeObject());
}
/**
* Returns a set of {@link VertexBuffer.VertexAttribute}s that are required by this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:requires">
* Vertex and attributes: requires</a>
*/
public Set<VertexBuffer.VertexAttribute> getRequiredAttributes() {
if (mRequiredAttributes == null) {
int bitSet = nGetRequiredAttributes(getNativeObject());
@@ -238,14 +520,38 @@ public class Material {
return mRequiredAttributes;
}
/**
* Returns a bit set representing the set of {@link VertexBuffer.VertexAttribute}s that are
* required by this material. Use {@link #getRequiredAttributes()} to get these as a Set object.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:requires">
* Vertex and attributes: requires</a>
*/
int getRequiredAttributesAsInt() {
return nGetRequiredAttributes(getNativeObject());
}
/**
* Returns the number of parameters declared by this material.
* The returned value can be 0.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/general:parameters">
* General: parameters</a>
*/
public int getParameterCount() {
return nGetParameterCount(getNativeObject());
}
/**
* Returns a list of Parameter objects representing this material's parameters.
* The list may be empty if the material has no declared parameters.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/general:parameters">
* General: parameters</a>
*/
public List<Parameter> getParameters() {
int count = getParameterCount();
List<Parameter> parameters = new ArrayList<>(count);
@@ -253,86 +559,308 @@ public class Material {
return parameters;
}
/**
* Indicates whether a parameter of the given name exists on this material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/general:parameters">
* General: parameters</a>
*/
public boolean hasParameter(@NonNull String name) {
return nHasParameter(getNativeObject(), name);
}
/**
* Sets the value of a bool parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the material parameter
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, boolean x) {
mDefaultInstance.setParameter(name, x);
}
/**
* Sets the value of a float parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the material parameter
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, float x) {
mDefaultInstance.setParameter(name, x);
}
/**
* Sets the value of an int parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the material parameter
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, int x) {
mDefaultInstance.setParameter(name, x);
}
/**
* Sets the value of a bool2 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, boolean x, boolean y) {
mDefaultInstance.setParameter(name, x, y);
}
/**
* Sets the value of a float2 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, float x, float y) {
mDefaultInstance.setParameter(name, x, y);
}
/**
* Sets the value of an int2 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, int x, int y) {
mDefaultInstance.setParameter(name, x, y);
}
/**
* Sets the value of a bool3 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, boolean x, boolean y, boolean z) {
mDefaultInstance.setParameter(name, x, y, z);
}
/**
* Sets the value of a float3 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, float x, float y, float z) {
mDefaultInstance.setParameter(name, x, y, z);
}
/**
* Sets the value of a int3 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, int x, int y, int z) {
mDefaultInstance.setParameter(name, x, y, z);
}
/**
* Sets the value of a bool4 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, boolean x, boolean y, boolean z, boolean w) {
mDefaultInstance.setParameter(name, x, y, z, w);
}
/**
* Sets the value of a float4 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, float x, float y, float z, float w) {
mDefaultInstance.setParameter(name, x, y, z, w);
}
/**
* Sets the value of a int4 parameter on this material's default instance.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, int x, int y, int z, int w) {
mDefaultInstance.setParameter(name, x, y, z, w);
}
/**
* Set a bool parameter array by name.
*
* @param name name of the parameter array as defined by this Material
* @param type the number of components for each individual parameter
* @param v array of values to set to the named parameter array
* @param offset the number of elements to skip
* @param count the number of elements in the parameter array to set
*
* <p>For example, to set a parameter array of 4 bool4s:
* <pre>{@code
* boolean[] a = new boolean[4 * 4];
* material.setDefaultParameter("param", MaterialInstance.BooleanElement.BOOL4, a, 0, 4);
* }</pre>
* To only set the last 3 elements, specify an offset of 1 and a count of 3:
* <pre>{@code
* boolean[] a = new boolean[4 * 3];
* material.setDefaultParameter("param", MaterialInstance.BooleanElement.BOOL4, a, 1, 3);
* }</pre>
* </p>
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name,
@NonNull MaterialInstance.BooleanElement type, @NonNull @Size(min = 1) boolean[] v,
@IntRange(from = 0) int offset, @IntRange(from = 1) int count) {
mDefaultInstance.setParameter(name, type, v, offset, count);
}
/**
* Set an int parameter array by name.
*
* @param name name of the parameter array as defined by this Material
* @param type the number of components for each individual parameter
* @param v array of values to set to the named parameter array
* @param offset the number of elements to skip
* @param count the number of elements in the parameter array to set
*
* <p>For example, to set a parameter array of 4 int4s:
* <pre>{@code
* int[] a = new int[4 * 4];
* material.setDefaultParameter("param", MaterialInstance.IntElement.INT4, a, 0, 4);
* }</pre>
* To only set the last 3 elements, specify an offset of 1 and a count of 3:
* <pre>{@code
* int[] a = new int[4 * 3];
* material.setDefaultParameter("param", MaterialInstance.IntElement.INT4, a, 1, 3);
* }</pre>
* </p>
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name,
@NonNull MaterialInstance.IntElement type, @NonNull @Size(min = 1) int[] v,
@IntRange(from = 0) int offset, @IntRange(from = 1) int count) {
mDefaultInstance.setParameter(name, type, v, offset, count);
}
/**
* Set a float parameter array by name.
*
* @param name name of the parameter array as defined by this Material
* @param type the number of components for each individual parameter
* @param v array of values to set to the named parameter array
* @param offset the number of elements to skip
* @param count the number of elements in the parameter array to set
*
* <p>For example, to set a parameter array of 4 float4s:
* <pre>{@code
* float[] a = new float[4 * 4];
* material.setDefaultParameter("param", MaterialInstance.FloatElement.FLOAT4, a, 0, 4);
* }</pre>
* To only set the last 3 elements, specify an offset of 1 and a count of 3:
* <pre>{@code
* float[] a = new float[4 * 3];
* material.setDefaultParameter("param", MaterialInstance.FloatElement.FLOAT4, a, 1, 3);
* }</pre>
* </p>
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name,
@NonNull MaterialInstance.FloatElement type, @NonNull @Size(min = 1) float[] v,
@IntRange(from = 0) int offset, @IntRange(from = 1) int count) {
mDefaultInstance.setParameter(name, type, v, offset, count);
}
/**
* Sets the color of the given parameter on this material's default instance.
*
* @param name the name of the material color parameter
* @param type whether the color is specified in the linear or sRGB space
* @param r red component
* @param g green component
* @param b blue component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, @NonNull Colors.RgbType type,
float r, float g, float b) {
mDefaultInstance.setParameter(name, type, r, g, b);
}
/**
* Sets the color of the given parameter on this material's default instance.
*
* @param name the name of the material color parameter
* @param type whether the color is specified in the linear or sRGB space
* @param r red component
* @param g green component
* @param b blue component
* @param a alpha component
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name, @NonNull Colors.RgbaType type,
float r, float g, float b, float a) {
mDefaultInstance.setParameter(name, type, r, g, b, a);
}
/**
* Sets a texture and sampler parameter on this material's default instance.
*
* @param name The name of the material texture parameter
* @param texture The texture to set as parameter
* @param sampler The sampler to be used with this texture
*
* @see Material#getDefaultInstance()
*/
public void setDefaultParameter(@NonNull String name,
@NonNull Texture texture, @NonNull TextureSampler sampler) {
mDefaultInstance.setParameter(name, texture, sampler);
@@ -366,6 +894,9 @@ public class Material {
private static native float nGetMaskThreshold(long nativeMaterial);
private static native float nGetSpecularAntiAliasingVariance(long nativeMaterial);
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterial);
private static native int nGetRefractionMode(long nativeMaterial);
private static native int nGetRefractionType(long nativeMaterial);
private static native int nGetParameterCount(long nativeMaterial);
private static native void nGetParameters(long nativeMaterial,

View File

@@ -16,9 +16,9 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
public class MaterialInstance {
private Material mMaterial;
@@ -58,6 +58,7 @@ public class MaterialInstance {
mNativeObject = nativeMaterialInstance;
}
/** @return the {@link Material} associated with this instance */
@NonNull
public Material getMaterial() {
if (mMaterial == null) {
@@ -66,118 +67,402 @@ public class MaterialInstance {
return mMaterial;
}
/**
* Sets the value of a bool parameter.
*
* @param name the name of the material parameter
* @param x the value of the material parameter
*/
public void setParameter(@NonNull String name, boolean x) {
nSetParameterBool(getNativeObject(), name, x);
}
/**
* Sets the value of a float parameter.
*
* @param name the name of the material parameter
* @param x the value of the material parameter
*/
public void setParameter(@NonNull String name, float x) {
nSetParameterFloat(getNativeObject(), name, x);
}
/**
* Sets the value of an int parameter.
*
* @param name the name of the material parameter
* @param x the value of the material parameter
*/
public void setParameter(@NonNull String name, int x) {
nSetParameterInt(getNativeObject(), name, x);
}
/**
* Sets the value of a bool2 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
*/
public void setParameter(@NonNull String name, boolean x, boolean y) {
nSetParameterBool2(getNativeObject(), name, x, y);
}
/**
* Sets the value of a float2 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
*/
public void setParameter(@NonNull String name, float x, float y) {
nSetParameterFloat2(getNativeObject(), name, x, y);
}
/**
* Sets the value of an int2 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
*/
public void setParameter(@NonNull String name, int x, int y) {
nSetParameterInt2(getNativeObject(), name, x, y);
}
/**
* Sets the value of a bool3 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
*/
public void setParameter(@NonNull String name, boolean x, boolean y, boolean z) {
nSetParameterBool3(getNativeObject(), name, x, y, z);
}
/**
* Sets the value of a float3 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
*/
public void setParameter(@NonNull String name, float x, float y, float z) {
nSetParameterFloat3(getNativeObject(), name, x, y, z);
}
/**
* Sets the value of a int3 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
*/
public void setParameter(@NonNull String name, int x, int y, int z) {
nSetParameterInt3(getNativeObject(), name, x, y, z);
}
/**
* Sets the value of a bool4 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
*/
public void setParameter(@NonNull String name, boolean x, boolean y, boolean z, boolean w) {
nSetParameterBool4(getNativeObject(), name, x, y, z, w);
}
/**
* Sets the value of a float4 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
*/
public void setParameter(@NonNull String name, float x, float y, float z, float w) {
nSetParameterFloat4(getNativeObject(), name, x, y, z, w);
}
/**
* Sets the value of a int4 parameter.
*
* @param name the name of the material parameter
* @param x the value of the first component
* @param y the value of the second component
* @param z the value of the third component
* @param w the value of the fourth component
*/
public void setParameter(@NonNull String name, int x, int y, int z, int w) {
nSetParameterInt4(getNativeObject(), name, x, y, z, w);
}
/**
* Sets a texture and sampler parameter on this material's default instance.
*
* @param name The name of the material texture parameter
* @param texture The texture to set as parameter
* @param sampler The sampler to be used with this texture
*/
public void setParameter(@NonNull String name,
@NonNull Texture texture, @NonNull TextureSampler sampler) {
nSetParameterTexture(getNativeObject(), name, texture.getNativeObject(), sampler.mSampler);
}
/**
* Set a bool parameter array by name.
*
* @param name name of the parameter array as defined by this Material
* @param type the number of components for each individual parameter
* @param v array of values to set to the named parameter array
* @param offset the number of elements to skip
* @param count the number of elements in the parameter array to set
*
* <p>For example, to set a parameter array of 4 bool4s:
* <pre>{@code
* boolean[] a = new boolean[4 * 4];
* instance.setParameter("param", MaterialInstance.BooleanElement.BOOL4, a, 0, 4);
* }</pre>
* To only set the last 3 elements, specify an offset of 1 and a count of 3:
* <pre>{@code
* boolean[] a = new boolean[4 * 3];
* instance.setParameter("param", MaterialInstance.BooleanElement.BOOL4, a, 1, 3);
* }</pre>
* </p>
*/
public void setParameter(@NonNull String name,
@NonNull BooleanElement type, @NonNull boolean[] v,
@IntRange(from = 0) int offset, @IntRange(from = 1) int count) {
nSetBooleanParameterArray(getNativeObject(), name, type.ordinal(), v, offset, count);
}
/**
* Set an int parameter array by name.
*
* @param name name of the parameter array as defined by this Material
* @param type the number of components for each individual parameter
* @param v array of values to set to the named parameter array
* @param offset the number of elements to skip
* @param count the number of elements in the parameter array to set
*
* <p>For example, to set a parameter array of 4 int4s:
* <pre>{@code
* int[] a = new int[4 * 4];
* instance.setParameter("param", MaterialInstance.IntElement.INT4, a, 0, 4);
* }</pre>
* To only set the last 3 elements, specify an offset of 1 and a count of 3:
* <pre>{@code
* int[] a = new int[4 * 3];
* instance.setParameter("param", MaterialInstance.IntElement.INT4, a, 1, 3);
* }</pre>
* </p>
*/
public void setParameter(@NonNull String name,
@NonNull IntElement type, @NonNull int[] v,
@IntRange(from = 0) int offset, @IntRange(from = 1) int count) {
nSetIntParameterArray(getNativeObject(), name, type.ordinal(), v, offset, count);
}
/**
* Set a float parameter array by name.
*
* @param name name of the parameter array as defined by this Material
* @param type the number of components for each individual parameter
* @param v array of values to set to the named parameter array
* @param offset the number of elements to skip
* @param count the number of elements in the parameter array to set
*
* <p>For example, to set a parameter array of 4 float4s:
* <pre>{@code
* float[] a = new float[4 * 4];
* material.setDefaultParameter("param", MaterialInstance.FloatElement.FLOAT4, a, 0, 4);
* }</pre>
* To only set the last 3 elements, specify an offset of 1 and a count of 3:
* <pre>{@code
* float[] a = new float[4 * 3];
* material.setDefaultParameter("param", MaterialInstance.FloatElement.FLOAT4, a, 1, 3);
* }</pre>
* </p>
*/
public void setParameter(@NonNull String name,
@NonNull FloatElement type, @NonNull float[] v,
@IntRange(from = 0) int offset, @IntRange(from = 1) int count) {
nSetFloatParameterArray(getNativeObject(), name, type.ordinal(), v, offset, count);
}
/**
* Sets the color of the given parameter on this material's default instance.
*
* @param name the name of the material color parameter
* @param type whether the color is specified in the linear or sRGB space
* @param r red component
* @param g green component
* @param b blue component
*/
public void setParameter(@NonNull String name, @NonNull Colors.RgbType type,
float r, float g, float b) {
float[] color = Colors.toLinear(type, r, g, b);
nSetParameterFloat3(getNativeObject(), name, color[0], color[1], color[2]);
}
/**
* Sets the color of the given parameter on this material's default instance.
*
* @param name the name of the material color parameter
* @param type whether the color is specified in the linear or sRGB space
* @param r red component
* @param g green component
* @param b blue component
* @param a alpha component
*/
public void setParameter(@NonNull String name, @NonNull Colors.RgbaType type,
float r, float g, float b, float a) {
float[] color = Colors.toLinear(type, r, g, b, a);
nSetParameterFloat4(getNativeObject(), name, color[0], color[1], color[2], color[3]);
}
/**
* Set up a custom scissor rectangle; by default this encompasses the View.
*
* @param left left coordinate of the scissor box
* @param bottom bottom coordinate of the scissor box
* @param width width of the scissor box
* @param height height of the scissor box
*/
public void setScissor(@IntRange(from = 0) int left, @IntRange(from = 0) int bottom,
@IntRange(from = 0) int width, @IntRange(from = 0) int height) {
nSetScissor(getNativeObject(), left, bottom, width, height);
}
/** Returns the scissor rectangle to its default setting, which encompasses the View. */
public void unsetScissor() {
nUnsetScissor(getNativeObject());
}
/**
* Sets a polygon offset that will be applied to all renderables drawn with this material
* instance.
*
* The value of the offset is scale * dz + r * constant, where dz is the change in depth
* relative to the screen area of the triangle, and r is the smallest value that is guaranteed
* to produce a resolvable offset for a given implementation. This offset is added before the
* depth test.
*
* Warning: using a polygon offset other than zero has a significant negative performance
* impact, as most implementations have to disable early depth culling. DO NOT USE unless
* absolutely necessary.
*
* @param scale scale factor used to create a variable depth offset for each triangle
* @param constant scale factor used to create a constant depth offset for each triangle
*/
public void setPolygonOffset(float scale, float constant) {
nSetPolygonOffset(getNativeObject(), scale, constant);
}
/**
* Overrides the minimum alpha value a fragment must have to not be discarded when the blend
* mode is MASKED. Defaults to 0.4 if it has not been set in the parent Material. The specified
* value should be between 0 and 1 and will be clamped if necessary.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/blendingandtransparency:maskthreshold">
* Blending and transparency: maskThreshold</a>
*/
public void setMaskThreshold(float threshold) {
nSetMaskThreshold(getNativeObject(), threshold);
}
/**
* Sets the screen space variance of the filter kernel used when applying specular
* anti-aliasing. The default value is set to 0.15. The specified value should be between
* 0 and 1 and will be clamped if necessary.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">
* Anti-aliasing: specularAntiAliasingVariance</a>
*/
public void setSpecularAntiAliasingVariance(float variance) {
nSetSpecularAntiAliasingVariance(getNativeObject(), variance);
}
/**
* Sets the clamping threshold used to suppress estimation errors when applying specular
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0
* and 1 and will be clamped if necessary.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">
* Anti-aliasing: specularAntiAliasingThreshold</a>
*/
public void setSpecularAntiAliasingThreshold(float threshold) {
nSetSpecularAntiAliasingThreshold(getNativeObject(), threshold);
}
/**
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
* automatically disabled.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:doublesided">
* Rasterization: doubleSided</a>
*/
public void setDoubleSided(boolean doubleSided) {
nSetDoubleSided(getNativeObject(), doubleSided);
}
/**
* Overrides the default triangle culling state that was set on the material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
* Rasterization: culling</a>
*/
public void setCullingMode(Material.CullingMode mode) {
nSetCullingMode(getNativeObject(), mode.ordinal());
}
/**
* Overrides the default color-buffer write state that was set on the material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:colorWrite">
* Rasterization: colorWrite</a>
*/
void setColorWrite(boolean enable) {
nSetColorWrite(getNativeObject(), enable);
}
/**
* Overrides the default depth-buffer write state that was set on the material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:depthWrite">
* Rasterization: depthWrite</a>
*/
void setDepthWrite(boolean enable) {
nSetDepthWrite(getNativeObject(), enable);
}
/**
* Overrides the default depth testing state that was set on the material.
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:depthCulling">
* Rasterization: depthCulling</a>
*/
void setDepthCulling(boolean enable) {
nSetDepthCulling(getNativeObject(), enable);
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed MaterialInstance");
@@ -247,4 +532,8 @@ public class MaterialInstance {
float threshold);
private static native void nSetDoubleSided(long nativeMaterialInstance, boolean doubleSided);
private static native void nSetCullingMode(long nativeMaterialInstance, long mode);
private static native void nSetColorWrite(long nativeMaterialInstance, boolean enable);
private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable);
private static native void nSetDepthCulling(long nativeMaterialInstance, boolean enable);
}

View File

@@ -16,13 +16,36 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Size;
public final class MathUtils {
private MathUtils() { }
/**
* Packs the tangent frame represented by the specified tangent, bitangent, and normal into a
* quaternion.
*
* <p>
* Reflection is preserved by encoding it as the sign of the w component in the resulting
* quaternion. Since -0 cannot always be represented on the GPU, this function computes a bias
* to ensure values are always either positive or negative, never 0. The bias is computed based
* on a per-element storage size of 2 bytes, making the resulting quaternion suitable for
* storage into an SNORM16 vector.
* </p>
*
* @param tangentX the X component of the tangent
* @param tangentY the Y component of the tangent
* @param tangentZ the Z component of the tangent
* @param bitangentX the X component of the bitangent
* @param bitangentY the Y component of the bitangent
* @param bitangentZ the Z component of the bitangent
* @param normalX the X component of the normal
* @param normalY the Y component of the normal
* @param normalZ the Z component of the normal
* @param quaternion a float array of at least size 4 for the quaternion result to be stored
*/
public static void packTangentFrame(
float tangentX, float tangentY, float tangentZ,
float bitangentX, float bitangentY, float bitangentZ,
@@ -34,6 +57,30 @@ public final class MathUtils {
normalX, normalY, normalZ, quaternion, 0);
}
/**
* Packs the tangent frame represented by the specified tangent, bitangent, and normal into a
* quaternion.
*
* <p>
* Reflection is preserved by encoding it as the sign of the w component in the resulting
* quaternion. Since -0 cannot always be represented on the GPU, this function computes a bias
* to ensure values are always either positive or negative, never 0. The bias is computed based
* on a per-element storage size of 2 bytes, making the resulting quaternion suitable for
* storage into an SNORM16 vector.
* </p>
*
* @param tangentX the X component of the tangent
* @param tangentY the Y component of the tangent
* @param tangentZ the Z component of the tangent
* @param bitangentX the X component of the bitangent
* @param bitangentY the Y component of the bitangent
* @param bitangentZ the Z component of the bitangent
* @param normalX the X component of the normal
* @param normalY the Y component of the normal
* @param normalZ the Z component of the normal
* @param quaternion a float array of at least size 4 for the quaternion result to be stored
* @param offset offset, in elements, into the quaternion array to store the results
*/
public static void packTangentFrame(
float tangentX, float tangentY, float tangentZ,
float bitangentX, float bitangentY, float bitangentZ,

View File

@@ -16,7 +16,8 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByNative;
import java.nio.Buffer;

View File

@@ -16,7 +16,7 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
abstract class Platform {
private static Platform mCurrentPlatform = null;

View File

@@ -16,13 +16,20 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* An offscreen render target that can be associated with a {@link View} and contains
* weak references to a set of attached {@link Texture} objects.
*
* <p>
* Clients are responsible for the lifetime of all associated <code>Texture</code> attachments.
* </p>
*
* @see View
*/
public class RenderTarget {
private long mNativeObject;
private final Texture[] mTextures = new Texture[2];
@@ -40,11 +47,17 @@ public class RenderTarget {
return mNativeObject;
}
/**
* An attachment point is a slot that can be assigned to a {@link Texture}.
*/
public enum AttachmentPoint {
COLOR,
DEPTH,
}
/**
* Constructs <code>RenderTarget</code> objects using a builder pattern.
*/
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
private final BuilderFinalizer mFinalizer;
@@ -56,6 +69,15 @@ public class RenderTarget {
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Sets a texture to a given attachment point.
*
* <p>All RenderTargets must have a non-null <code>COLOR</code> attachment.</p>
*
* @param attachment The attachment point of the texture.
* @param texture The associated texture object.
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder texture(@NonNull AttachmentPoint attachment, @Nullable Texture texture) {
mTextures[attachment.ordinal()] = texture;
@@ -63,24 +85,51 @@ public class RenderTarget {
return this;
}
/**
* Sets the mipmap level for a given attachment point.
*
* @param attachment The attachment point of the texture.
* @param level The associated mipmap level, 0 by default.
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder mipLevel(@NonNull AttachmentPoint attachment, @IntRange(from = 0) int level) {
nBuilderMipLevel(mNativeBuilder, attachment.ordinal(), level);
return this;
}
/**
* Sets the cubemap face for a given attachment point.
*
* @param attachment The attachment point.
* @param face The associated cubemap face.
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder face(@NonNull AttachmentPoint attachment, Texture.CubemapFace face) {
nBuilderFace(mNativeBuilder, attachment.ordinal(), face.ordinal());
return this;
}
/**
* Sets the layer for a given attachment point (for 3D textures).
*
* @param attachment The attachment point.
* @param layer The associated cubemap layer.
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder layer(@NonNull AttachmentPoint attachment, @IntRange(from = 0) int layer) {
nBuilderLayer(mNativeBuilder, attachment.ordinal(), layer);
return this;
}
/**
* Creates the RenderTarget object and returns a pointer to it.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*/
@NonNull
public RenderTarget build(@NonNull Engine engine) {
long nativeRenderTarget = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -108,20 +157,45 @@ public class RenderTarget {
}
}
/**
* Gets the texture set on the given attachment point.
*
* @param attachment Attachment point
* @return A Texture object or nullptr if no texture is set for this attachment point
*/
@Nullable
public Texture getTexture(@NonNull AttachmentPoint attachment) {
return mTextures[attachment.ordinal()];
}
/**
* Returns the mipmap level set on the given attachment point.
*
* @param attachment Attachment point
* @return the mipmap level set on the given attachment point
*/
@IntRange(from = 0)
public int getMipLevel(@NonNull AttachmentPoint attachment) {
return nGetMipLevel(getNativeObject(), attachment.ordinal());
}
/**
* Returns the face of a cubemap set on the given attachment point.
*
* @param attachment Attachment point
* @return A cubemap face identifier. This is only relevant if the attachment's texture is
* a cubemap.
*/
public Texture.CubemapFace getFace(AttachmentPoint attachment) {
return Texture.CubemapFace.values()[nGetFace(getNativeObject(), attachment.ordinal())];
}
/**
* Returns the texture-layer set on the given attachment point.
*
* @param attachment Attachment point
* @return A texture layer. This is only relevant if the attachment's texture is a 3D texture.
*/
@IntRange(from = 0)
public int getLayer(@NonNull AttachmentPoint attachment) {
return nGetLayer(getNativeObject(), attachment.ordinal());
@@ -132,11 +206,11 @@ public class RenderTarget {
}
private static native long nCreateBuilder();
private static native long nDestroyBuilder(long nativeBuilder);
private static native long nBuilderTexture(long nativeBuilder, int attachment, long nativeTexture);
private static native long nBuilderMipLevel(long nativeBuilder, int attachment, int level);
private static native long nBuilderFace(long nativeBuilder, int attachment, int face);
private static native long nBuilderLayer(long nativeBuilder, int attachment, int layer);
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderTexture(long nativeBuilder, int attachment, long nativeTexture);
private static native void nBuilderMipLevel(long nativeBuilder, int attachment, int level);
private static native void nBuilderFace(long nativeBuilder, int attachment, int face);
private static native void nBuilderLayer(long nativeBuilder, int attachment, int layer);
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native int nGetMipLevel(long nativeRenderTarget, int attachment);

View File

@@ -16,19 +16,58 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.ReadOnlyBufferException;
/**
* A <code>Renderer</code> instance represents an operating system's window.
*
* <p>
* Typically, applications create a <code>Renderer</code> per window. The <code>Renderer</code> generates
* drawing commands for the render thread and manages frame latency.
* <br>
* A Renderer generates drawing commands from a View, itself containing a Scene description.
* </p>
*
* <h1>Creation and Destruction</h1>
*
* <p>A <code>Renderer</code> is created using {@link Engine#createRenderer} and destroyed
* using {@link Engine#destroyRenderer}.</p>
*
* @see Engine
* @see View
*/
public class Renderer {
private final Engine mEngine;
private long mNativeObject;
/**
* Indicates that the <code>dstSwapChain</code> passed into {@link #copyFrame} should be
* committed after the frame has been copied.
*
* @see #copyFrame
*/
public static final int MIRROR_FRAME_FLAG_COMMIT = 0x1;
/**
* Indicates that the presentation time should be set on the <code>dstSwapChain</code>
* passed into {@link #copyFrame} to the monotonic clock time when the frame is
* copied.
*
* @see #copyFrame
*/
public static final int MIRROR_FRAME_FLAG_SET_PRESENTATION_TIME = 0x2;
/**
* Indicates that the <code>dstSwapChain</code> passed into {@link #copyFrame} should be
* cleared to black before the frame is copied into the specified viewport.
*
* @see #copyFrame
*/
public static final int MIRROR_FRAME_FLAG_CLEAR = 0x4;
Renderer(@NonNull Engine engine, long nativeRenderer) {
@@ -36,25 +75,128 @@ public class Renderer {
mNativeObject = nativeRenderer;
}
/**
* Gets the {@link Engine} that created this <code>Renderer</code>.
*
* @return {@link Engine} instance this <code>Renderer</code> is associated to.
*/
@NonNull
public Engine getEngine() {
return mEngine;
}
/**
* Sets up a frame for this <code>Renderer</code>.
* <p><code>beginFrame</code> manages frame pacing, and returns whether or not a frame should be
* drawn. The goal of this is to skip frames when the GPU falls behind in order to keep the frame
* latency low.</p>
*
* <p>If a given frame takes too much time in the GPU, the CPU will get ahead of the GPU. The
* display will draw the same frame twice producing a stutter. At this point, the CPU is
* ahead of the GPU and depending on how many frames are buffered, latency increases.
* beginFrame() attempts to detect this situation and returns <code>false</code> in that case,
* indicating to the caller to skip the current frame.</p>
*
* <p>All calls to render() must happen <b>after</b> beginFrame().</p>
*
* @param swapChain the {@link SwapChain} instance to use
*
* @return <code>false</code> if the current frame must be skipped<br>
* When skipping a frame, the whole frame is canceled, and {@link #endFrame} must not
* be called.
*
* @see #endFrame
* @see #render
*/
public boolean beginFrame(@NonNull SwapChain swapChain) {
return nBeginFrame(getNativeObject(), swapChain.getNativeObject());
}
/**
* Finishes the current frame and schedules it for display.
* <p>
* <code>endFrame()</code> schedules the current frame to be displayed on the
* <code>Renderer</code>'s window.
* </p>
*
* <br><p>All calls to render() must happen <b>before</b> endFrame().</p>
*
* @see #beginFrame
* @see #render
*/
public void endFrame() {
nEndFrame(getNativeObject());
}
/**
* Renders a {@link View} into this <code>Renderer</code>'s window.
*
* <p>
* This is filament's main rendering method, most of the CPU-side heavy lifting is performed
* here. The purpose of the <code>render()</code> function is to generate render commands which
* are asynchronously executed by the {@link Engine}'s render thread.
* </p>
*
* <p><code>render()</code> generates commands for each of the following stages:</p>
* <ul>
* <li>Shadow map pass, if needed (currently only a single shadow map is supported)</li>
* <li>Depth pre-pass</li>
* <li>SSAO pass, if enabled</li>
* <li>Color pass</li>
* <li>Post-processing pass</li>
* </ul>
*
* A typical render loop looks like this:
*
* <pre>
* void renderLoop(Renderer renderer, SwapChain swapChain) {
* do {
* // typically we wait for VSYNC and user input events
* if (renderer.beginFrame(swapChain)) {
* renderer.render(mView);
* renderer.endFrame();
* }
* } while (!quit());
* }
* </pre>
*
* <ul>
*<li><code>render()</code> must be called <b>after</b> {@link #beginFrame} and <b>before</b>
*{@link #endFrame}.</li>
*
*<li><code>render()</code> must be called from the {@link Engine}'s main thread
*(or external synchronization must be provided). In particular, calls to <code>render()</code>
*on different <code>Renderer</code> instances <b>must</b> be synchronized.</li>
*
*<li><code>render()</code> performs potentially heavy computations and cannot be multi-threaded.
*However, internally, it is highly multi-threaded to both improve performance and mitigate
*the call's latency.</li>
*
*<li><code>render()</code> is typically called once per frame (but not necessarily).</li>
* </ul>
*
* @param view the {@link View} to render
*
* @see #beginFrame
* @see #endFrame
* @see View
*
*/
public void render(@NonNull View view) {
nRender(getNativeObject(), view.getNativeObject());
}
/**
* This method MUST be called before endFrame.
* Copies the currently rendered {@link View} to the indicated {@link SwapChain}, using the
* indicated source and destination rectangle.
*
* <p><code>copyFrame()</code> should be called after a frame is rendered using {@link #render}
* but before {@link #endFrame} is called.</p>
*
* @param dstSwapChain the {@link SwapChain} into which the frame should be copied
* @param dstViewport the destination rectangle in which to draw the view
* @param srcViewport the source rectangle to be copied
* @param flags one or more <code>CopyFrameFlag</code> behavior configuration flags
*/
public void copyFrame(
@NonNull SwapChain dstSwapChain, @NonNull Viewport dstViewport,
@@ -73,7 +215,68 @@ public class Renderer {
}
/**
* This method MUST be called before endFrame.
* Reads back the content of the {@link SwapChain} associated with this <code>Renderer</code>.
*
*<pre>
*
* Framebuffer as seen on User buffer (PixelBufferDescriptor)
* screen
* +--------------------+
* | | .stride .alignment
* | | ----------------------->-->
* | | O----------------------+--+ low addresses
* | | | | | |
* | w | | | .top | |
* | <---------> | | V | |
* | +---------+ | | +---------+ | |
* | | ^ | | ======> | | | | |
* | x | h| | | |.left| | | |
* +------>| v | | +---->| | | |
* | +.........+ | | +.........+ | |
* | ^ | | | |
* | y | | +----------------------+--+ high addresses
* O------------+-------+
*
*</pre>
*
*
* <p>Typically <code>readPixels</code> will be called after {@link #render} and before
* {@link #endFrame}.</p>
* <br>
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link #beginFrame},
* {@link #render}, {@link #endFrame}.</p>
* <br>
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* @param xoffset left offset of the sub-region to read back
* @param yoffset bottom offset of the sub-region to read back
* @param width width of the sub-region to read back
* @param height height of the sub-region to read back
* @param buffer client-side buffer where the read-back will be written
*
* <p>
* The following format are always supported:
* <li>{@link Texture.Format#RGBA}</li>
* <li>{@link Texture.Format#RGBA_INTEGER}</li>
* </p>
*
* <p>
* The following types are always supported:
* <li>{@link Texture.Type#UBYTE}</li>
* <li>{@link Texture.Type#UINT}</li>
* <li>{@link Texture.Type#INT}</li>
* <li>{@link Texture.Type#FLOAT}</li>
* </p>
*
* <p>Other combination of format/type may be supported. If a combination is
* not supported, this operation may fail silently. Use a DEBUG build
* to get some logs about the failure.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*/
public void readPixels(
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
@@ -96,11 +299,155 @@ public class Renderer {
}
}
double getUserTime() {
/**
* Reads back the content of a specified {@link RenderTarget}.
*
*<pre>
*
* Framebuffer as seen on User buffer (PixelBufferDescriptor)
* screen
* +--------------------+
* | | .stride .alignment
* | | ----------------------->-->
* | | O----------------------+--+ low addresses
* | | | | | |
* | w | | | .top | |
* | <---------> | | V | |
* | +---------+ | | +---------+ | |
* | | ^ | | ======> | | | | |
* | x | h| | | |.left| | | |
* +------>| v | | +---->| | | |
* | +.........+ | | +.........+ | |
* | ^ | | | |
* | y | | +----------------------+--+ high addresses
* O------------+-------+
*
*</pre>
*
*
* <p>Typically <code>readPixels</code> will be called after {@link #render} and before
* {@link #endFrame}.</p>
* <br>
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link #beginFrame},
* {@link #render}, {@link #endFrame}.</p>
* <br>
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* @param renderTarget {@link RenderTarget} to read back from
* @param xoffset left offset of the sub-region to read back
* @param yoffset bottom offset of the sub-region to read back
* @param width width of the sub-region to read back
* @param height height of the sub-region to read back
* @param buffer client-side buffer where the read-back will be written
*
* <p>
* The following format are always supported:
* <li>{@link Texture.Format#RGBA}</li>
* <li>{@link Texture.Format#RGBA_INTEGER}</li>
* </p>
*
* <p>
* The following types are always supported:
* <li>{@link Texture.Type#UBYTE}</li>
* <li>{@link Texture.Type#UINT}</li>
* <li>{@link Texture.Type#INT}</li>
* <li>{@link Texture.Type#FLOAT}</li>
* </p>
*
* <p>Other combination of format/type may be supported. If a combination is
* not supported, this operation may fail silently. Use a DEBUG build
* to get some logs about the failure.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*/
public void readPixels(
@NonNull RenderTarget renderTarget,
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
@IntRange(from = 0) int width, @IntRange(from = 0) int height,
@NonNull Texture.PixelBufferDescriptor buffer) {
if (buffer.storage.isReadOnly()) {
throw new ReadOnlyBufferException();
}
int result = nReadPixelsEx(getNativeObject(), mEngine.getNativeObject(),
renderTarget.getNativeObject(),
xoffset, yoffset, width, height,
buffer.storage, buffer.storage.remaining(),
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
buffer.stride, buffer.format.ordinal(),
buffer.handler, buffer.callback);
if (result < 0) {
throw new BufferOverflowException();
}
}
/**
* Returns a timestamp (in seconds) for the last call to {@link #beginFrame}. This value is
* constant for all {@link View views} rendered during a frame. The epoch is set with
* {@link #resetUserTime}.
* <br>
* <p>In materials, this value can be queried using <code>vec4 getUserTime()</code>. The value
* returned is a <code>highp vec4</code> encoded as follows:</p>
* <pre>
* time.x = (float)Renderer.getUserTime();
* time.y = Renderer.getUserTime() - time.x;
* </pre>
*
* It follows that the following invariants are true:
* <pre>
* (double)time.x + (double)time.y == Renderer.getUserTime()
* time.x == (float)Renderer.getUserTime()
* </pre>
*
* This encoding allows the shader code to perform high precision (i.e. double) time
* calculations when needed despite the lack of double precision in the shader, e.g.:
* <br>
* To compute <code>(double)time * vertex</code> in the material, use the following construct:
* <pre>
* vec3 result = time.x * vertex + time.y * vertex;
* </pre>
*
* Most of the time, high precision computations are not required, but be aware that the
* precision of <code>time.x</code> rapidly diminishes as time passes:
*
* <center>
* <table border="1">
* <tr align="center"><th> time </th><th> precision </th></tr>
* <tr align="center"><td> 16.7s </td><td> us </td></tr>
* <tr align="center"><td> 4h39.7s </td><td> ms </td></tr>
* <tr align="center"><td> 77h </td><td> 1/60s </td></tr>
* </table>
* </center>
* <p>
*
* In other words, it is only possible to get microsecond accuracy for about 16s or millisecond
* accuracy for just under 5h. This problem can be mitigated by calling {@link #resetUserTime},
* or using high precision time as described above.
*
* @return the time in seconds since {@link #resetUserTime} was last called
*
* @see #resetUserTime
*/
public double getUserTime() {
return nGetUserTime(getNativeObject());
}
void resetUserTime() {
/**
* Sets the user time epoch to now, i.e. resets the user time to zero.
* <br>
* <p>Use this method used to keep the precision of time high in materials, in practice it should
* be called at least when the application is paused, e.g.
* <code>Activity.onPause</code> in Android.</p>
*
* @see #getUserTime
*/
public void resetUserTime() {
nResetUserTime(getNativeObject());
}
@@ -127,6 +474,12 @@ public class Renderer {
Buffer storage, int remaining,
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
private static native int nReadPixelsEx(long nativeRenderer, long nativeEngine,
long nativeRenderTarget,
int xoffset, int yoffset, int width, int height,
Buffer storage, int remaining,
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
private static native double nGetUserTime(long nativeRenderer);
private static native void nResetUserTime(long nativeRenderer);
}

View File

@@ -16,8 +16,30 @@
package com.google.android.filament;
import android.support.annotation.Nullable;
import androidx.annotation.Nullable;
/**
* A <code>Scene</code> is a flat container of {@link RenderableManager} and {@link LightManager}
* components.
* <br>
* <p>A <code>Scene</code> doesn't provide a hierarchy of objects, i.e.: it's not a scene-graph.
* However, it manages the list of objects to render and the list of lights. These can
* be added or removed from a <code>Scene</code> at any time.
* Moreover clients can use {@link TransformManager} to create a graph of transforms.</p>
* <br>
* <p>A {@link RenderableManager} component <b>must</b> be added to a <code>Scene</code> in order
* to be rendered, and the <code>Scene</code> must be provided to a {@link View}.</p>
*
* <h1>Creation and Destruction</h1>
*
* A <code>Scene</code> is created using {@link Engine#createScene} and destroyed using
* {@link Engine#destroyScene(Scene)}.
*
* @see View
* @see LightManager
* @see RenderableManager
* @see TransformManager
*/
public class Scene {
private long mNativeObject;
private @Nullable Skybox mSkybox;
@@ -27,35 +49,78 @@ public class Scene {
mNativeObject = nativeScene;
}
/**
* @return the {@link Skybox} or <code>null</code> if none is set
* @see #setSkybox(Skybox)
*/
@Nullable
public Skybox getSkybox() {
return mSkybox;
}
/**
* Sets the {@link Skybox}.
*
* The {@link Skybox} is drawn last and covers all pixels not touched by geometry.
*
* @param skybox the {@link Skybox} to use to fill untouched pixels,
* or <code>null</code> to unset the {@link Skybox}.
*/
public void setSkybox(@Nullable Skybox skybox) {
mSkybox = skybox;
nSetSkybox(getNativeObject(), mSkybox != null ? mSkybox.getNativeObject() : 0);
}
/**
* @return the {@link IndirectLight} or <code>null</code> if none is set
* @see #setIndirectLight(IndirectLight)
*/
@Nullable
public IndirectLight getIndirectLight() {
return mIndirectLight;
}
/**
* Sets the {@link IndirectLight} to use when rendering the <code>Scene</code>.
*
* Currently, a <code>Scene</code> may only have a single {@link IndirectLight}.
* This call replaces the current {@link IndirectLight}.
*
* @param ibl the {@link IndirectLight} to use when rendering the <code>Scene</code>
* or <code>null</code> to unset.
*/
public void setIndirectLight(@Nullable IndirectLight ibl) {
mIndirectLight = ibl;
nSetIndirectLight(getNativeObject(),
mIndirectLight != null ? mIndirectLight.getNativeObject() : 0);
}
/**
* Adds an {@link Entity} to the <code>Scene</code>.
*
* @param entity the entity is ignored if it doesn't have a {@link RenderableManager} component
* or {@link LightManager} component.<br>
* A given {@link Entity} object can only be added once to a <code>Scene</code>.
*/
public void addEntity(@Entity int entity) {
nAddEntity(getNativeObject(), entity);
}
/**
* Adds a list of entities to the <code>Scene</code>.
*
* @param entities array containing entities to add to the <code>Scene</code>.
*/
public void addEntities(@Entity int[] entities) {
nAddEntities(getNativeObject(), entities);
}
/**
* Removes an {@link Entity} from the <code>Scene</code>.
*
* @param entity the {@link Entity} to remove from the <code>Scene</code>. If the specified
* <code>entity</code> doesn't exist, this call is ignored.
*/
public void removeEntity(@Entity int entity) {
nRemove(getNativeObject(), entity);
}
@@ -67,10 +132,20 @@ public class Scene {
removeEntity(entity);
}
/**
* Returns the number of {@link RenderableManager} components in the <code>Scene</code>.
*
* @return number of {@link RenderableManager} components in the <code>Scene</code>..
*/
public int getRenderableCount() {
return nGetRenderableCount(getNativeObject());
}
/**
* Returns the number of {@link LightManager} components in the <code>Scene</code>.
*
* @return number of {@link LightManager} components in the <code>Scene</code>..
*/
public int getLightCount() {
return nGetLightCount(getNativeObject());
}

View File

@@ -16,41 +16,125 @@
package com.google.android.filament;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
/**
* Skybox
* <p>When added to a {@link Scene}, the <code>Skybox</code> fills all untouched pixels.</p>
*
* <h1>Creation and destruction</h1>
*
* A <code>Skybox</code> object is created using the {@link Skybox.Builder} and destroyed by calling
* {@link Engine#destroySkybox}.<br>
* <pre>
* Engine engine = Engine.create();
*
* Scene scene = engine.createScene();
*
* Skybox skybox = new Skybox.Builder()
* .environment(cubemap)
* .build(engine);
*
* scene.setSkybox(skybox);
* </pre>
*
* Currently only {@link Texture} based sky boxes are supported.
*
* @see Scene
* @see IndirectLight
*/
public class Skybox {
private long mNativeObject;
@UsedByReflection("KtxLoader.java")
Skybox(long nativeSkybox) {
public Skybox(long nativeSkybox) {
mNativeObject = nativeSkybox;
}
/**
* Use <code>Builder</code> to construct a <code>Skybox</code> object instance.
*/
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
/**
* Use <code>Builder</code> to construct a <code>Skybox</code> object instance.
*/
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Set the environment map (i.e. the skybox content).
*
* <p>The <code>Skybox</code> is rendered as though it were an infinitely large cube with the
* camera inside it. This means that the cubemap which is mapped onto the cube's exterior
* will appear mirrored. This follows the OpenGL conventions.</p>
*
* <p>The <code>cmgen</code> tool generates reflection maps by default which are therefore
* ideal to use as skyboxes.</p>
*
* @param cubemap A cubemap {@link Texture}
*
* @return This Builder, for chaining calls.
*
* @see Texture
*/
@NonNull
public Builder environment(@NonNull Texture texture) {
nBuilderEnvironment(mNativeBuilder, texture.getNativeObject());
public Builder environment(@NonNull Texture cubemap) {
nBuilderEnvironment(mNativeBuilder, cubemap.getNativeObject());
return this;
}
/**
* Indicates whether the sun should be rendered. The sun can only be
* rendered if there is at least one light of type {@link LightManager.Type#SUN} in
* the {@link Scene}. The default value is <code>false</code>.
*
* @param show <code>true</code> if the sun should be rendered, <code>false</code> otherwise
*
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder showSun(boolean show) {
nBuilderShowSun(mNativeBuilder, show);
return this;
}
/**
* Sets the <code>Skybox</code> intensity when no {@link IndirectLight} is set
*
* <p>This call is ignored when an {@link IndirectLight} is set, otherwise it is used in
* its place.</p>
*
* @param envIntensity Scale factor applied to the skybox texel values such that
* the result is in cd/m<sup>2</sup> (lux) units (default = 30000)
*
* @return This Builder, for chaining calls.
*
* @see IndirectLight.Builder#intensity
*/
@NonNull
public Builder intensity(float envIntensity) {
nBuilderIntensity(mNativeBuilder, envIntensity);
return this;
}
/**
* Creates a <code>Skybox</code> object
*
* @param engine the {@link Engine} to associate this <code>Skybox</code> with.
*
* @return A newly created <code>Skybox</code>object
*
* @exception IllegalStateException can be thrown if the <code>Skybox</code> couldn't be created
*/
@NonNull
public Skybox build(@NonNull Engine engine) {
long nativeSkybox = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -75,14 +159,35 @@ public class Skybox {
}
}
public void setLayerMask(@IntRange(from = 0, to = 255) int select, @IntRange(from = 0, to = 255) int value) {
nSetLayerMask(getNativeObject(), select & 0xff, value & 0xff);
/**
* Sets bits in a visibility mask. By default, this is <code>0x1</code>.
* <p>This provides a simple mechanism for hiding or showing this <code>Skybox</code> in a
* {@link Scene}.</p>
*
* <p>For example, to set bit 1 and reset bits 0 and 2 while leaving all other bits unaffected,
* call: <code>setLayerMask(7, 2)</code>.</p>
*
* @param select the set of bits to affect
* @param values the replacement values for the affected bits
*
* @see View#setVisibleLayers
*/
public void setLayerMask(@IntRange(from = 0, to = 255) int select, @IntRange(from = 0, to = 255) int values) {
nSetLayerMask(getNativeObject(), select & 0xff, values & 0xff);
}
/**
* @return the visibility mask bits
*/
public int getLayerMask() {
return nGetLayerMask(getNativeObject());
}
/**
* Returns the <code>Skybox</code>'s intensity in cd/m<sup>2</sup>.
*/
public float getIntensity() { return nGetIntensity(getNativeObject()); }
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Skybox");
@@ -98,7 +203,9 @@ public class Skybox {
private static native void nDestroyBuilder(long nativeSkyboxBuilder);
private static native void nBuilderEnvironment(long nativeSkyboxBuilder, long nativeTexture);
private static native void nBuilderShowSun(long nativeSkyboxBuilder, boolean show);
private static native void nBuilderIntensity(long nativeSkyboxBuilder, float intensity);
private static native long nBuilderBuild(long nativeSkyboxBuilder, long nativeEngine);
private static native void nSetLayerMask(long nativeSkybox, int select, int value);
private static native int nGetLayerMask(long nativeSkybox);
private static native float nGetIntensity(long nativeSkybox);
}

View File

@@ -16,36 +16,73 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.ReadOnlyBufferException;
/**
* <code>Stream</code> is used to attach a native video stream to a filament {@link Texture}.
*
* @see Texture#setExternalStream
* @see Engine#destroyStream
*/
public class Stream {
private long mNativeObject;
private long mNativeEngine;
/**
* Represents the immutable stream type.
*/
public enum StreamType {
/** Not synchronized but copy-free. Good for video. */
NATIVE,
/** Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26. */
TEXTURE_ID,
/** Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+. */
ACQUIRED,
};
Stream(long nativeStream, Engine engine) {
mNativeObject = nativeStream;
mNativeEngine = engine.getNativeObject();
}
/**
* Use <code>Builder</code> to construct an Stream object instance.
*
* By default, Stream objects are {@link StreamType#ACQUIRED ACQUIRED} and must have external images pushed to them via
* {@link #setAcquiredImage}.
*
* To create a {@link StreamType#NATIVE NATIVE} or {@link StreamType#TEXTURE_ID TEXTURE_ID} stream, call one of the <pre>stream</pre> methods
* on the builder.
*/
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
/**
* Use <code>Builder</code> to construct an Stream object instance.
*/
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Accepted types for the stream source:
* - Android: SurfaceView
* - Other: none
* Creates a {@link StreamType#NATIVE NATIVE} stream. Native streams can sample data
* directly from an opaque platform object such as a {@link android.graphics.SurfaceTexture SurfaceTexture}
* on Android.
*
* @param streamSource an opaque native stream handle, e.g.: on Android this must be a
* {@link android.graphics.SurfaceTexture SurfaceTexture} object
* @return This Builder, for chaining calls.
* @see Texture#setExternalStream
*/
@NonNull
public Builder stream(@NonNull Object streamSource) {
@@ -56,24 +93,57 @@ public class Stream {
throw new IllegalArgumentException("Invalid stream source: " + streamSource);
}
/**
* Creates a {@link StreamType#TEXTURE_ID TEXTURE_ID} stream. A copy stream will sample data from the supplied
* external texture and copy it into an internal private texture.
*
* <p>Currently only OpenGL external texture ids are supported.</p>
*
* @param externalTextureId An opaque texture id (typically a GLuint created with
* <code>glGenTextures()</code>) in a context shared with
* filament -- in that case this texture's target must be
* <code>GL_TEXTURE_EXTERNAL_OES.</code>
* @return This Builder, for chaining calls.
* @see Texture#setExternalStream
*/
@NonNull
public Builder stream(long externalTextureId) {
nBuilderStream(mNativeBuilder, externalTextureId);
return this;
}
/**
* @param width initial width of the incoming stream. Whether this value is used is
* stream dependent. On Android, it must be set when using
* {@link #stream(long)}
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder width(int width) {
nBuilderWidth(mNativeBuilder, width);
return this;
}
/**
* @param height initial height of the incoming stream. Whether this value is used is
* stream dependent. On Android, it must be set when using
* {@link #stream(long)}
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder height(int height) {
nBuilderHeight(mNativeBuilder, height);
return this;
}
/**
* Creates a new <code>Stream</code> object instance.
*
* @param engine {@link Engine} instance to associate this <code>Stream</code> with.
*
* @return newly created <code>Stream</code> object
* @exception IllegalStateException if the <code>Stream</code> couldn't be created
*/
@NonNull
public Stream build(@NonNull Engine engine) {
long nativeStream = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -99,14 +169,104 @@ public class Stream {
}
}
public boolean isNative() {
return nIsNative(getNativeObject());
/**
* Indicates whether this <code>Stream</code> is NATIVE, TEXTURE_ID, or ACQUIRED.
*/
public StreamType getStreamType() {
return StreamType.values()[nGetStreamType(getNativeObject())];
}
/**
* Updates an <pre>ACQUIRED</pre> stream with an image that is guaranteed to be used in the next frame.
*
* This method should be called on the same thread that calls {#link Renderer#beginFrame}, which is
* also where the callback is invoked.
*
* @param hwbuffer {@link android.hardware.HardwareBuffer HardwareBuffer} (requires API level 26)
* @param handler {@link java.util.concurrent.Executor Executor} or {@link android.os.Handler Handler}.
* @param callback a callback invoked by <code>handler</code> when the <code>hwbuffer</code> can be released.
*/
public void setAcquiredImage(Object hwbuffer, Object handler, Runnable callback) {
nSetAcquiredImage(getNativeObject(), mNativeEngine, hwbuffer, handler, callback);
}
/**
* Updates the size of the incoming stream. Whether this value is used is
* stream dependent. On Android, it must be set when using
* {@link Builder#stream(long)}
*
* @param width new width of the incoming stream
* @param height new height of the incoming stream
*/
public void setDimensions(@IntRange(from = 0) int width, @IntRange(from = 0) int height) {
nSetDimensions(getNativeObject(), width, height);
}
/**
* Reads back the content of the last frame of a <code>Stream</code> since the last call to
* {@link Renderer#beginFrame}.
*
* <p>The Stream must be a copy stream, which can be checked with {@link #getStreamType()}.
* This function is a no-op otherwise.</p>
*
* <pre>
*
* Stream buffer User buffer (PixelBufferDescriptor)
* +--------------------+
* | | .stride .alignment
* | | ----------------------->-->
* | | O----------------------+--+ low addresses
* | | | | | |
* | w | | | .top | |
* | <---------> | | V | |
* | +---------+ | | +---------+ | |
* | | ^ | | ======> | | | | |
* | x | h| | | |.left| | | |
* +------>| v | | +---->| | | |
* | +.........+ | | +.........+ | |
* | ^ | | | |
* | y | | +----------------------+--+ high addresses
* O------------+-------+
*
* </pre>
*
* <p>Typically readPixels() will be called after {@link Renderer#beginFrame}.</p>
*
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link Renderer#beginFrame},
* {@link Renderer#render}, {@link Renderer#endFrame}.</p>
*
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* @param xoffset left offset of the sub-region to read back
* @param yoffset bottom offset of the sub-region to read back
* @param width width of the sub-region to read back
* @param height height of the sub-region to read back
* @param buffer client-side buffer where the read-back will be written
*
* <p>
* The following format are always supported:
* <li>{@link Texture.Format#RGBA}</li>
* <li>{@link Texture.Format#RGBA_INTEGER}</li>
* </p>
*
* <p>
* The following types are always supported:
* <li>{@link Texture.Type#UBYTE}</li>
* <li>{@link Texture.Type#UINT}</li>
* <li>{@link Texture.Type#INT}</li>
* <li>{@link Texture.Type#FLOAT}</li>
* </p>
*
* <p>Other combination of format/type may be supported. If a combination is
* not supported, this operation may fail silently. Use a DEBUG build
* to get some logs about the failure.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*/
public void readPixels(
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
@IntRange(from = 0) int width, @IntRange(from = 0) int height,
@@ -128,6 +288,13 @@ public class Stream {
}
}
/**
* Returns the presentation time of the currently displayed frame in nanosecond.
*
* This value can change at any time.
*
* @return timestamp in nanosecond.
*/
public long getTimestamp() {
return nGetTimestamp(getNativeObject());
}
@@ -151,6 +318,7 @@ public class Stream {
private static native void nBuilderHeight(long nativeStreamBuilder, int height);
private static native long nBuilderBuild(long nativeStreamBuilder, long nativeEngine);
private static native int nGetStreamType(long nativeStream);
private static native void nSetDimensions(long nativeStream, int width, int height);
private static native int nReadPixels(long nativeStream, long nativeEngine,
int xoffset, int yoffset, int width, int height,
@@ -158,6 +326,6 @@ public class Stream {
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
private static native long nGetTimestamp(long nativeStream);
private static native boolean nIsNative(long nativeStream);
private static native void nSetAcquiredImage(long nativeStream, long nativeEngine,
Object hwbuffer, Object handler, Runnable callback);
}

View File

@@ -0,0 +1,225 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import java.nio.Buffer;
/**
* Helper used to populate <code>TANGENTS</code> buffers.
*/
public class SurfaceOrientation {
private long mNativeObject;
private SurfaceOrientation(long nativeSurfaceOrientation) {
mNativeObject = nativeSurfaceOrientation;
}
/**
* Constructs an immutable surface orientation helper.
*
* At a minimum, clients must supply a vertex count.
* They can supply data in any of the following combinations:
*
* <ol>
* <li>normals only (not recommended)</li>
* <li>normals + tangents (sign of W determines bitangent orientation)</li>
* <li>normals + uvs + positions + indices</li>
* <li>positions + indices</li>
* </ol>
*
* Additionally, the client-side data has the following type constraints:
*
* <ol>
* <li>Normals must be float3</li>
* <li>Tangents must be float4</li>
* <li>UVs must be float2</li>
* <li>Positions must be float3</li>
* <li>Triangles must be uint3 or ushort3</li>
* </ol>
*/
public static class Builder {
private int mVertexCount;
private int mTriangleCount;
private Buffer mNormals;
private int mNormalsStride;
private Buffer mTangents;
private int mTangentsStride;
private Buffer mTexCoords;
private int mTexCoordsStride;
private Buffer mPositions;
private int mPositionsStride;
private Buffer mTrianglesUint16;
private Buffer mTrianglesUint32;
@NonNull
public Builder vertexCount(@IntRange(from = 1) int vertexCount) {
mVertexCount = vertexCount;
return this;
}
@NonNull
public Builder normals(@NonNull Buffer buffer) {
mNormals = buffer;
mNormalsStride = 0;
return this;
}
@NonNull
public Builder tangents(@NonNull Buffer buffer) {
mTangents = buffer;
mTangentsStride = 0;
return this;
}
@NonNull
public Builder uvs(@NonNull Buffer buffer) {
mTexCoords = buffer;
mTexCoordsStride = 0;
return this;
}
@NonNull
public Builder positions(@NonNull Buffer buffer) {
mPositions = buffer;
mPositionsStride = 0;
return this;
}
@NonNull
public Builder triangleCount(int triangleCount) {
mTriangleCount = triangleCount;
return this;
}
@NonNull
public Builder triangles_uint16(@NonNull Buffer buffer) {
mTrianglesUint16 = buffer;
return this;
}
@NonNull
public Builder triangles_uint32(@NonNull Buffer buffer) {
mTrianglesUint32 = buffer;
return this;
}
/**
* Consumes the input data, produces quaternions, and destroys the native builder.
*/
@NonNull
public SurfaceOrientation build() {
// The C++ Builder API specifies that the pointers are consumed during build(), not
// during the individual daisy-chain methods. Therefore we need to retain the Java
// buffers until this point in the code.
long builder = nCreateBuilder();
nBuilderVertexCount(builder, mVertexCount);
nBuilderTriangleCount(builder, mTriangleCount);
if (mNormals != null) {
nBuilderNormals(builder, mNormals, mNormals.remaining(), mNormalsStride);
}
if (mTangents != null) {
nBuilderTangents(builder, mTangents, mTangents.remaining(), mTangentsStride);
}
if (mTexCoords != null) {
nBuilderUVs(builder, mTexCoords, mTexCoords.remaining(), mTexCoordsStride);
}
if (mPositions != null) {
nBuilderPositions(builder, mPositions, mPositions.remaining(), mPositionsStride);
}
if (mTrianglesUint16 != null) {
nBuilderTriangles16(builder, mTrianglesUint16, mTrianglesUint16.remaining());
}
if (mTrianglesUint32 != null) {
nBuilderTriangles32(builder, mTrianglesUint32, mTrianglesUint32.remaining());
}
long nativeSurfaceOrientation = nBuilderBuild(builder);
nDestroyBuilder(builder);
if (nativeSurfaceOrientation == 0) {
throw new IllegalStateException("Could not create SurfaceOrientation");
}
return new SurfaceOrientation(nativeSurfaceOrientation);
}
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed SurfaceOrientation");
}
return mNativeObject;
}
@IntRange(from = 0)
public int getVertexCount() {
return nGetVertexCount(mNativeObject);
}
@NonNull
public void getQuatsAsFloat(@NonNull Buffer buffer) {
nGetQuatsAsFloat(mNativeObject, buffer, buffer.remaining());
}
@NonNull
public void getQuatsAsHalf(@NonNull Buffer buffer) {
nGetQuatsAsHalf(mNativeObject, buffer, buffer.remaining());
}
@NonNull
public void getQuatsAsShort(@NonNull Buffer buffer) {
nGetQuatsAsShort(mNativeObject, buffer, buffer.remaining());
}
public void destroy() {
nDestroy(mNativeObject);
mNativeObject = 0;
}
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderVertexCount(long nativeBuilder, int vertexCount);
private static native void nBuilderNormals(long nativeBuilder, Buffer buffer, int remaining, int stride);
private static native void nBuilderTangents(long nativeBuilder, Buffer buffer, int remaining, int stride);
private static native void nBuilderUVs(long nativeBuilder, Buffer buffer, int remaining, int stride);
private static native void nBuilderPositions(long nativeBuilder, Buffer buffer, int remaining, int stride);
private static native void nBuilderTriangleCount(long nativeBuilder, int triangleCount);
private static native void nBuilderTriangles16(long nativeBuilder, Buffer buffer, int remaining);
private static native void nBuilderTriangles32(long nativeBuilder, Buffer buffer, int remaining);
private static native long nBuilderBuild(long nativeBuilder);
private static native int nGetVertexCount(long nativeSurfaceOrientation);
private static native void nGetQuatsAsFloat(long nativeSurfaceOrientation, Buffer buffer, int remaining);
private static native void nGetQuatsAsHalf(long nativeSurfaceOrientation, Buffer buffer, int remaining);
private static native void nGetQuatsAsShort(long nativeSurfaceOrientation, Buffer buffer, int remaining);
private static native void nDestroy(long nativeSurfaceOrientation);
}

View File

@@ -16,22 +16,84 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
/**
* A <code>SwapChain</code> represents an Operating System's <b>native</b> renderable surface.
*
* <p>Typically it's a native window or a view. Because a <code>SwapChain</code> is initialized
* from a native object, it is given to filament as an <code>Object</code>, which must be of the
* proper type for each platform filament is running on.</p>
*
* <code>
* SwapChain swapChain = engine.createSwapChain(nativeWindow);
* </code>
*
* <p>The <code>nativeWindow</code> parameter above must be of type:</p>
*
* <center>
* <table border="1">
* <tr><th> Platform </th><th> nativeWindow type </th></tr>
* <tr><td> Android </td><td>{@link android.view.Surface Surface}</td></tr>
* </table>
* </center>
* <p>
*
* <h1>Examples</h1>
*
* <h2>Android</h2>
*
*
* <p>A {@link android.view.Surface Surface} can be retrieved from a
* {@link android.view.SurfaceView SurfaceView} or {@link android.view.SurfaceHolder SurfaceHolder}
* easily using {@link android.view.SurfaceHolder#getSurface SurfaceHolder.getSurface()} and/or
* {@link android.view.SurfaceView#getHolder SurfaceView.getHolder()}.</p>
*
* <p>To use a {@link android.view.TextureView Textureview} as a <code>SwapChain</code>, it is
* necessary to first get its {@link android.graphics.SurfaceTexture SurfaceTexture},
* for instance using {@link android.view.TextureView.SurfaceTextureListener SurfaceTextureListener}
* and then create a {@link android.view.Surface Surface}:</p>
*
* <pre>
* // using a TextureView.SurfaceTextureListener:
* public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
* mSurface = new Surface(surfaceTexture);
* // mSurface can now be used with Engine.createSwapChain()
* }
* </pre>
*
* @see Engine
*/
public class SwapChain {
private final Object mSurface;
private long mNativeObject;
public static final long CONFIG_DEFAULT = 0x0;
/**
* This flag indicates that the <code>SwapChain</code> must be allocated with an
* alpha-channel.
*/
public static final long CONFIG_TRANSPARENT = 0x1;
/**
* This flag indicates that the <code>SwapChain</code> may be used as a source surface
* for reading back render results. This config must be set when creating
* any <code>SwapChain</code> that will be used as the source for a blit operation.
*
* @see Renderer#copyFrame
*/
public static final long CONFIG_READABLE = 0x2;
SwapChain(long nativeSwapChain, @NonNull Object surface) {
SwapChain(long nativeSwapChain, Object surface) {
mNativeObject = nativeSwapChain;
mSurface = surface;
}
@NonNull
/**
* @return the native <code>Object</code> this <code>SwapChain</code> was created from or null
* for a headless SwapChain.
*/
public Object getNativeWindow() {
return mSurface;
}

View File

@@ -16,12 +16,12 @@
package com.google.android.filament;
import com.google.android.filament.proguard.UsedByReflection;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import com.google.android.filament.proguard.UsedByReflection;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
@@ -29,20 +29,145 @@ import java.nio.ByteBuffer;
import static com.google.android.filament.Texture.Type.COMPRESSED;
/**
* Texture
* <p>The <code>Texture</code> class supports:</p>
* <ul>
* <li>2D textures</li>
* <li>3D textures</li>
* <li>Cube maps</li>
* <li>mip mapping</li>
* </ul>
*
*
* <h1>Usage example</h1>
*
* A <code>Texture</code> object is created using the {@link Texture.Builder} and destroyed by
* calling {@link Engine#destroyTexture}. They're bound using {@link MaterialInstance#setParameter}.
*
* <pre>
* Engine engine = Engine.create();
*
* Material material = new Material.Builder()
* .payload( ... )
* .build(ending);
*
* MaterialInstance mi = material.getDefaultInstance();
*
* Texture texture = new Texture.Builder()
* .width(64)
* .height(64)
* .build(engine);
*
*
* texture.setImage(engine, 0,
* new Texture.PixelBufferDescriptor( ... ));
*
* mi.setParameter("parameterName", texture, new TextureSampler());
* </pre>
*
* @see #setImage
* @see PixelBufferDescriptor
* @see MaterialInstance#setParameter(String, Texture, TextureSampler)
*/
public class Texture {
private long mNativeObject;
@UsedByReflection("KtxLoader.java")
Texture(long nativeTexture) {
public Texture(long nativeTexture) {
mNativeObject = nativeTexture;
}
/**
* Type of sampler
*/
public enum Sampler {
/** 2D sampler */
SAMPLER_2D,
/** 2D array sampler */
SAMPLER_2D_ARRAY,
/** Cubemap sampler */
SAMPLER_CUBEMAP,
/** External texture sampler */
SAMPLER_EXTERNAL
}
/**
* Internal texel formats
*
* <p>These formats are used to specify a texture's internal storage format.</p>
*
* <h1>Enumerants syntax format</h1>
*
* <code>[components][size][type]</code>
* <br><code>components</code> : List of stored components by this format
* <br><code>size</code> : Size in bit of each component
* <br><code>type</code> : Type this format is stored as
*
* <center>
* <table border="1">
* <tr><th> Name </th><th> Component </th></tr>
* <tr><td> R </td><td> Linear Red </td></tr>
* <tr><td> RG </td><td> Linear Red, Green </td></tr>
* <tr><td> RGB </td><td> Linear Red, Green, Blue </td></tr>
* <tr><td> RGBA </td><td> Linear Red, Green Blue, Alpha </td></tr>
* <tr><td> SRGB </td><td> sRGB encoded Red, Green, Blue </td></tr>
* <tr><td> DEPTH </td><td> Depth </td></tr>
* <tr><td> STENCIL </td><td> Stencil </td></tr>
* </table>
* </center>
* <br>
*
* <center>
* <table border="1">
* <tr><th> Name </th><th> Type </th></tr>
* <tr><td> (none) </td><td> Unsigned Normalized Integer [0, 1] </th></tr>
* <tr><td> _SNORM </td><td> Signed Normalized Integer [-1, 1] </td></tr>
* <tr><td> UI </td><td> Unsigned Integer [0, 2<sup>size</sup>] </td></tr>
* <tr><td> I </td><td> Signed Integer [-2<sup>size-1</sup>, 2<sup>size-1</sup>-1] </td></tr>
* <tr><td> F </td><td> Floating-point </td></tr>
* </table>
* </center>
* <br>
*
* <h1>Special color formats</h1>
*
* There are a few special color formats that don't follow the convention above:
*
* <center>
* <table border="1">
* <tr><th> Name </th><th> Format </th></tr>
* <tr><td> RGB565 </td><td> 5-bits for R and B, 6-bits for G. </td></tr>
* <tr><td> RGB5_A1 </td><td> 5-bits for R, G and B, 1-bit for A. </td></tr>
* <tr><td> RGB10_A2 </td><td> 10-bits for R, G and B, 2-bits for A. </td></tr>
* <tr><td> RGB9_E5 </td><td> <b>Unsigned</b> floating point. 9-bits mantissa for RGB, 5-bits shared exponent </td></tr>
* <tr><td> R11F_G11F_B10F </td><td> <b>Unsigned</b> floating point. 6-bits mantissa, for R and G, 5-bits for B. 5-bits exponent. </td></tr>
* <tr><td> SRGB8_A8 </td><td> sRGB 8-bits with linear 8-bits alpha. </td></tr>
* <tr><td> DEPTH24_STENCIL8 </td><td> 24-bits unsigned normalized integer depth, 8-bits stencil. </td></tr>
* </table>
* </center>
* <br>
*
* <h1>Compressed texture formats</h1>
*
* Many compressed texture formats are supported as well, which include (but are not limited to)
* the following list:
*
* <center>
* <table border="1">
* <tr><th> Name </th><th> Format </th></tr>
* <tr><td> EAC_R11 </td><td> Compresses R11UI </td></tr>
* <tr><td> EAC_R11_SIGNED </td><td> Compresses R11I </td></tr>
* <tr><td> EAC_RG11 </td><td> Compresses RG11UI </td></tr>
* <tr><td> EAC_RG11_SIGNED </td><td> Compresses RG11I </td></tr>
* <tr><td> ETC2_RGB8 </td><td> Compresses RGB8 </td></tr>
* <tr><td> ETC2_SRGB8 </td><td> compresses SRGB8 </td></tr>
* <tr><td> ETC2_EAC_RGBA8 </td><td> Compresses RGBA8 </td></tr>
* <tr><td> ETC2_EAC_SRGBA8 </td><td> Compresses SRGB8_A8 </td></tr>
* <tr><td> ETC2_RGB8_A1 </td><td> Compresses RGB8 with 1-bit alpha </td></tr>
* <tr><td> ETC2_SRGB8_A1 </td><td> Compresses sRGB8 with 1-bit alpha </td></tr>
* </table>
* </center>
*/
public enum InternalFormat {
// 8-bits per element
R8, R8_SNORM, R8UI, R8I, STENCIL8,
@@ -92,6 +217,10 @@ public class Texture {
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA
}
/**
* Compressed data types for use with {@link PixelBufferDescriptor}
* @see InternalFormat
*/
public enum CompressedFormat {
// Mandatory in GLES 3.0 and GL 4.3
EAC_R11, EAC_R11_SIGNED, EAC_RG11, EAC_RG11_SIGNED,
@@ -103,15 +232,27 @@ public class Texture {
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA
}
/**
* Cubemap faces
*/
public enum CubemapFace {
/** +x face */
POSITIVE_X,
/** -x face */
NEGATIVE_X,
/** +y face */
POSITIVE_Y,
/** -y face */
NEGATIVE_Y,
/** +z face */
POSITIVE_Z,
/** -z face */
NEGATIVE_Z
}
/**
* Pixel color format
*/
public enum Format {
R,
R_INTEGER,
@@ -128,19 +269,43 @@ public class Texture {
ALPHA
}
/**
* Pixel data type
*/
public enum Type {
/** unsigned byte, 8-bits */
UBYTE,
/** signed byte, 8-bits */
BYTE,
/** unsigned short, 16-bits */
USHORT,
/** signed short, 16-bits */
SHORT,
/** unsigned int, 32-bits */
UINT,
/** signed int, 32-bits */
INT,
/** half-float, 16-bits float with 10 bits mantissa */
HALF,
/** float, 32-bits float, with 24 bits mantissa */
FLOAT,
/** a compessed type */
COMPRESSED,
/** unsigned 5.6 (5.5 for blue) float packed in 32-bits */
UINT_10F_11F_11F_REV
}
/**
* A descriptor to an image in main memory, typically used to transfer image data from the CPU
* to the GPU.
* <p>A <code>PixelBufferDescriptor</code> owns the memory buffer it references,
* therefore <code>PixelBufferDescriptor</code> cannot be copied, but can be moved.</p>
*
* <code>PixelBufferDescriptor</code> releases ownership of the memory-buffer when it's
* destroyed.
*
* @see #setImage
*/
public static class PixelBufferDescriptor {
public Buffer storage;
@@ -158,12 +323,39 @@ public class Texture {
public CompressedFormat compressedFormat;
@Nullable public Object handler;
@Nullable public Runnable callback;
/**
* Valid handler types:
* - Android: Handler, Executor
* - Other: Executor
* Callback used to destroy the buffer data.
* <p>
* Guarantees:
* <ul>
* <li>Called on the main filament thread.</li>
* </ul>
* </p>
*
* <p>
* Limitations:
* <ul>
* <li>Must be lightweight.</li>
* <li>Must not call filament APIs.</li>
* </ul>
* </p>
*/
@Nullable public Runnable callback;
/**
* Creates a <code>PixelBufferDescriptor</code>
*
* @param storage CPU-side buffer containing the image data to upload into the texture
* @param format Pixel {@link Format format} of the CPU-side image
* @param type Pixel data {@link Type type} of the CPU-side image
* @param alignment Row-alignment in bytes of the CPU-side image (1 to 8 bytes)
* @param left Left coordinate in pixels of the CPU-side image
* @param top Top coordinate in pixels of the CPU-side image
* @param stride Stride in pixels of the CPU-side image (i.e. distance in pixels to the next row)
* @param handler An {@link java.util.concurrent.Executor Executor}. On Android this can also be a {@link android.os.Handler Handler}.
* @param callback A callback executed by <code>handler</code> when <code>storage</code> is no longer needed.
*/
public PixelBufferDescriptor(@NonNull Buffer storage,
@NonNull Format format, @NonNull Type type,
@@ -182,17 +374,48 @@ public class Texture {
this.callback = callback;
}
/**
* Creates a <code>PixelBufferDescriptor</code> with some default values and no callback.
*
* @param storage CPU-side buffer containing the image data to upload into the texture
* @param format Pixel {@link Format format} of the CPU-side image
* @param type Pixel data {@link Type type} of the CPU-side image
*
* @see #setCallback
*/
public PixelBufferDescriptor(@NonNull Buffer storage,
@NonNull Format format, @NonNull Type type) {
this(storage, format, type, 1, 0, 0, 0, null, null);
}
/**
* Creates a <code>PixelBufferDescriptor</code> with some default values and no callback.
*
* @param storage CPU-side buffer containing the image data to upload into the texture
* @param format Pixel {@link Format format} of the CPU-side image
* @param type Pixel data {@link Type type} of the CPU-side image
* @param alignment Row-alignment in bytes of the CPU-side image (1 to 8 bytes)
*
* @see #setCallback
*/
public PixelBufferDescriptor(@NonNull Buffer storage,
@NonNull Format format, @NonNull Type type,
@IntRange(from = 1, to = 8) int alignment) {
this(storage, format, type, alignment, 0, 0, 0, null, null);
}
/**
* Creates a <code>PixelBufferDescriptor</code> with some default values and no callback.
*
* @param storage CPU-side buffer containing the image data to upload into the texture
* @param format Pixel {@link Format format} of the CPU-side image
* @param type Pixel data {@link Type type} of the CPU-side image
* @param alignment Row-alignment in bytes of the CPU-side image (1 to 8 bytes)
* @param left Left coordinate in pixels of the CPU-side image
* @param top Top coordinate in pixels of the CPU-side image
*
* @see #setCallback
*/
public PixelBufferDescriptor(@NonNull Buffer storage,
@NonNull Format format, @NonNull Type type,
@IntRange(from = 1, to = 8) int alignment,
@@ -200,6 +423,14 @@ public class Texture {
this(storage, format, type, alignment, left, top, 0, null, null);
}
/**
*
* @param storage CPU-side buffer containing the image data to upload into the texture
* @param format Compressed pixel {@link CompressedFormat format} of the CPU-side image
* @param compressedSizeInBytes Size of the compressed data in bytes
*
* @see #setCallback
*/
public PixelBufferDescriptor(@NonNull ByteBuffer storage,
@NonNull CompressedFormat format,
@IntRange(from = 0) int compressedSizeInBytes) {
@@ -211,9 +442,10 @@ public class Texture {
}
/**
* Valid handler types:
* - Android: Handler, Executor
* - Other: Executor
* Set or replace the callback called when the CPU-side data is no longer needed.
*
* @param handler An {@link java.util.concurrent.Executor Executor}. On Android this can also be a {@link android.os.Handler Handler}.
* @param callback A callback executed by <code>handler</code> when <code>storage</code> is no longer needed.
*/
public void setCallback(@Nullable Object handler, @Nullable Runnable callback) {
this.handler = handler;
@@ -288,57 +520,113 @@ public class Texture {
}
}
/**
* Options of {@link #generatePrefilterMipmap}
*/
public static class PrefilterOptions {
/** number of samples for roughness pre-filtering */
public int sampleCount = 8;
/** whether to generate a reflection map (mirror) */
public boolean mirror = true;
}
/**
* Checks whether a given format is supported for texturing in this {@link Engine}.
* This depends on the selected backend.
*
* @param engine {@link Engine} to test the {@link InternalFormat InternalFormat} against
* @param format format to check
* @return <code>true</code> if this format is supported for texturing.
*/
public static boolean isTextureFormatSupported(@NonNull Engine engine,
@NonNull InternalFormat format) {
return nIsTextureFormatSupported(engine.getNativeObject(), format.ordinal());
}
/**
* Use <code>Builder</code> to construct a <code>Texture</code> object instance.
*/
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
// Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
/**
* Use <code>Builder</code> to construct a <code>Texture</code> object instance.
*/
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Specifies the width of the texture in texels.
* @param width texture width in texels, must be at least 1. Default is 1.
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder width(@IntRange(from = 1) int width) {
nBuilderWidth(mNativeBuilder, width);
return this;
}
/**
* Specifies the height of the texture in texels.
* @param height texture height in texels, must be at least 1. Default is 1.
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder height(@IntRange(from = 1) int height) {
nBuilderHeight(mNativeBuilder, height);
return this;
}
/**
* Specifies the texture's number of layers. Values greater than 1 create a 3D texture.
*
* <p>This <code>Texture</code> instance must use
* {@link Sampler#SAMPLER_2D_ARRAY SAMPLER_2D_ARRAY} or it has no effect.</p>
*
* @param depth texture number of layers. Default is 1.
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder depth(@IntRange(from = 1) int depth) {
nBuilderDepth(mNativeBuilder, depth);
return this;
}
/**
* Specifies the number of mipmap levels
* @param levels must be at least 1 and less or equal to <code>floor(log<sub>2</sub>(max(width, height))) + 1</code>. Default is 1.
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder levels(@IntRange(from = 1) int levels) {
nBuilderLevels(mNativeBuilder, levels);
return this;
}
/**
* Specifies the type of sampler to use.
* @param target {@link Sampler Sampler} type
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder sampler(@NonNull Sampler target) {
nBuilderSampler(mNativeBuilder, target.ordinal());
return this;
}
/**
* Specifies the texture's internal format.
* <p>The internal format specifies how texels are stored (which may be different from how
* they're specified in {@link #setImage}). {@link InternalFormat InternalFormat} specifies
* both the color components and the data type used.</p>
* @param format texture's {@link InternalFormat internal format}.
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder format(@NonNull InternalFormat format) {
nBuilderFormat(mNativeBuilder, format.ordinal());
@@ -356,6 +644,13 @@ public class Texture {
return this;
}
/**
* Creates a new <code>Texture</code> instance.
* @param engine The {@link Engine} to associate this <code>Texture</code> with.
* @return A newly created <code>Texture</code>
* @exception IllegalStateException if a parameter to a builder function was invalid.
* A mode detailed message about the error is output in the system log.
*/
@NonNull
public Texture build(@NonNull Engine engine) {
long nativeTexture = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -382,38 +677,71 @@ public class Texture {
}
}
/**
* A bitmask to specify how the texture will be used.
*/
public static class Usage {
/** The texture will be used as a color attachment */
public static final int COLOR_ATTACHMENT = 0x1;
/** The texture will be used as a depth attachment */
public static final int DEPTH_ATTACHMENT = 0x2;
/** The texture will be used as a stencil attachment */
public static final int STENCIL_ATTACHMENT = 0x4;
/** The texture content can be set with {@link #setImage} */
public static final int UPLOADABLE = 0x8;
/** The texture can be read from a shader or blitted from */
public static final int SAMPLEABLE = 0x10;
/** by default textures are <code>UPLOADABLE</code> and <code>SAMPLEABLE</code>*/
public static final int DEFAULT = UPLOADABLE | SAMPLEABLE;
}
public static final int BASE_LEVEL = 0;
/**
* Queries the width of a given level of this texture.
* @param level to query the with of. Must be between 0 and {@link #getLevels}
* @return The width in texel of the given level
*/
public int getWidth(@IntRange(from = 0) int level) {
return nGetWidth(getNativeObject(), level);
}
/**
* Queries the height of a given level of this texture.
* @param level to query the height of. Must be between 0 and {@link #getLevels}
* @return The height in texel of the given level
*/
public int getHeight(@IntRange(from = 0) int level) {
return nGetHeight(getNativeObject(), level);
}
/**
* Queries the number of layers of given level of this texture has.
* @param level to query the number of layers of. Must be between 0 and {@link #getLevels}
* @return The number of layers of the given level
*/
public int getDepth(@IntRange(from = 0) int level) {
return nGetDepth(getNativeObject(), level);
}
/**
* @return the number of mipmap levels of this texture
*/
public int getLevels() {
return nGetLevels(getNativeObject());
}
/**
* @return This texture {@link Sampler Sampler} type.
*/
@NonNull
public Sampler getTarget() {
return Sampler.values()[nGetTarget(getNativeObject())];
}
/**
* @return This texture's {@link InternalFormat InternalFormat}.
*/
@NonNull
public InternalFormat getFormat() {
return InternalFormat.values()[nGetInternalFormat(getNativeObject())];
@@ -421,12 +749,65 @@ public class Texture {
// TODO: add a setImage() version that takes an android Bitmap
/**
* <code>setImage</code> is used to modify the whole content of the texure from a CPU-buffer.
*
* <p>This <code>Texture</code> instance must use {@link Sampler#SAMPLER_2D SAMPLER_2D} or
* {@link Sampler#SAMPLER_EXTERNAL SAMPLER_EXTERNAL}. If the later is specified
* and external textures are supported by the driver implementation,
* this method will have no effect, otherwise it will behave as if the
* texture was specified with {@link Sampler#SAMPLER_2D SAMPLER_2D}.</p>
*
* This is equivalent to calling: <br>
*
* <code>setImage(engine, level, 0, 0, getWidth(level), getHeight(level), buffer)</code>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param level Level to set the image for. Must be less than {@link #getLevels()}.
* @param buffer Client-side buffer containing the image to set.
* <code>buffer</code>'s {@link Format format} must match that
* of {@link #getFormat()}
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*
* @see Builder#sampler
* @see PixelBufferDescriptor
*/
public void setImage(@NonNull Engine engine,
@IntRange(from = 0) int level,
@NonNull PixelBufferDescriptor buffer) {
setImage(engine, level, 0, 0, getWidth(level), getHeight(level), buffer);
}
/**
* <code>setImage</code> is used to modify a sub-region of the texure from a CPU-buffer.
*
* <p>This <code>Texture</code> instance must use {@link Sampler#SAMPLER_2D SAMPLER_2D} or
* {@link Sampler#SAMPLER_EXTERNAL SAMPLER_EXTERNAL}. If the later is specified
* and external textures are supported by the driver implementation,
* this method will have no effect, otherwise it will behave as if the
* texture was specified with {@link Sampler#SAMPLER_2D SAMPLER_2D}.</p>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param level Level to set the image for. Must be less than {@link #getLevels()}.
* @param xoffset x-offset in texel of the region to modify
* @param yoffset y-offset in texel of the region to modify
* @param width width in texel of the region to modify
* @param height height in texel of the region to modify
* @param buffer Client-side buffer containing the image to set.
* <code>buffer</code>'s {@link Format format} must match that
* of {@link #getFormat()}
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*
* @see Builder#sampler
* @see PixelBufferDescriptor
*/
public void setImage(@NonNull Engine engine,
@IntRange(from = 0) int level,
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
@@ -453,9 +834,33 @@ public class Texture {
}
}
// note: faceOffsetsInBytes are offsets in byte in the buffer relative to the current position()
// note: use Texture CubemapFace to index the faceOffsetsInBytes array
// note: we assume all 6 faces are tightly packed
/**
* <code>setImage</code> is used to specify all six images of a cubemap level and
* follows exactly the OpenGL conventions
*
* <p>This <code>Texture</code> instance must use
* {@link Sampler#SAMPLER_CUBEMAP SAMPLER_CUBEMAP}.</p>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param level Level to set the image for. Must be less than {@link #getLevels()}.
* @param buffer Client-side buffer containing the image to set.
* <code>buffer</code>'s {@link Format format} must match that
* of {@link #getFormat()}
* @param faceOffsetsInBytes Offsets in bytes into <code>buffer</code> for all six images.
* The offsets are specified in the following order:
* +x, -x, +y, -y, +z, -z.
*
* <p><code>faceOffsetsInBytes</code> are offsets in byte in the <code>buffer</code> relative
* to the current {@link Buffer#position()}. Use {@link CubemapFace} to index the
* <code>faceOffsetsInBytes</code> array. All six faces must be tightly packed.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*
* @see Builder#sampler
* @see PixelBufferDescriptor
*/
public void setImage(@NonNull Engine engine, @IntRange(from = 0) int level,
@NonNull PixelBufferDescriptor buffer,
@NonNull @Size(min = 6) int[] faceOffsetsInBytes) {
@@ -478,10 +883,60 @@ public class Texture {
}
}
/**
* Specifies the external image to associate with this <code>Texture</code>.
*
* <p>This <code>Texture</code> instance must use
* {@link Sampler#SAMPLER_EXTERNAL SAMPLER_EXTERNAL}.</p>
* <p>Typically the external image is OS specific, and can be a video or camera frame.
* There are many restrictions when using an external image as a texture, such as:</p>
* <ul>
* <li> only the level of detail (LOD) 0 can be specified</li>
* <li> only {@link TextureSampler.MagFilter#NEAREST NEAREST} or
* {@link TextureSampler.MagFilter#LINEAR LINEAR} filtering is supported</li>
* <li> the size and format of the texture is defined by the external image</li>
* </ul>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param eglImage An opaque handle to a platform specific image. Supported types are
* <code>eglImageOES</code> on Android and <code>CVPixelBufferRef</code> on iOS.
* <p>On iOS the following pixel formats are supported: <ul>
* <li><code>kCVPixelFormatType_32BGRA</code></li>
* <li><code>kCVPixelFormatType_420YpCbCr8BiPlanarFullRange</code></li>
* </ul></p>
*
* @see Builder#sampler
*/
public void setExternalImage(@NonNull Engine engine, long eglImage) {
nSetExternalImage(getNativeObject(), engine.getNativeObject(), eglImage);
}
/**
* Specifies the external stream to associate with this <code>Texture</code>.
*
* <p>This <code>Texture</code> instance must use
* {@link Sampler#SAMPLER_EXTERNAL SAMPLER_EXTERNAL}.</p>
* <p>Typically the external image is OS specific, and can be a video or camera frame.
* There are many restrictions when using an external image as a texture, such as:</p>
* <ul>
* <li> only the level of detail (LOD) 0 can be specified</li>
* <li> only {@link TextureSampler.MagFilter#NEAREST NEAREST} or
* {@link TextureSampler.MagFilter#LINEAR LINEAR} filtering is supported</li>
* <li> the size and format of the texture is defined by the external image</li>
* </ul>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param stream A {@link Stream} object
*
* @exception IllegalStateException if the sampler type is not
* {@link Sampler#SAMPLER_EXTERNAL SAMPLER_EXTERNAL}
*
* @see Stream
* @see Builder#sampler
*
*/
public void setExternalStream(@NonNull Engine engine, @NonNull Stream stream) {
long nativeObject = getNativeObject();
long streamNativeObject = stream.getNativeObject();
@@ -492,10 +947,68 @@ public class Texture {
nSetExternalStream(nativeObject, engine.getNativeObject(), streamNativeObject);
}
/**
* Generates all the mipmap levels automatically. This requires the texture to have a
* color-renderable format.
*
* <p>This <code>Texture</code> instance must <b>not</b> use
* {@link Sampler#SAMPLER_CUBEMAP SAMPLER_CUBEMAP}, or it has no effect.</p>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
*/
public void generateMipmaps(@NonNull Engine engine) {
nGenerateMipmaps(getNativeObject(), engine.getNativeObject());
}
/**
* Creates a reflection map from an environment map.
*
* <p>This is a utility function that replaces calls to {@link #setImage}.
* The provided environment map is processed and all mipmap levels are populated. The
* processing is similar to the offline tool <code>cmgen</code> at a lower quality setting.</p>
*
* <p>This function is intended to be used when the environment cannot be processed offline,
* for instance if it's generated at runtime.</p>
*
* <p>The source data must obey to some constraints:</p>
* <ul>
* <li>the data {@link Format format} must be {@link Format#RGB}</li>
* <li>the data {@link Type type} must be one of
* <ul>
* <li>{@link Type#FLOAT}</li>
* <li>{@link Type#HALF}</li>
* </ul>
* </li>
* </ul>
*
* <p>The current texture must be a cubemap.</p>
*
* <p>The reflections cubemap's {@link InternalFormat internal format} cannot be a compressed format.</p>
*
* <p>The reflections cubemap's dimension must be a power-of-two.</p>
*
* <p>This operation is computationally intensive, especially with large environments and
* is currently <b>synchronous</b>. Expect about 1ms for a 16 &times 16 cubemap.</p>
*
* @param engine {@link Engine} this texture is associated to. Must be the
* instance passed to {@link Builder#build Builder.build()}.
* @param buffer Client-side buffer containing the image to set.
* <code>buffer</code>'s {@link Format format} and {@link Type type} must match
* the constraints above.
* @param faceOffsetsInBytes Offsets in bytes into <code>buffer</code> for all six images.
* The offsets are specified in the following order:
* +x, -x, +y, -y, +z, -z.
*
* @param options Optional parameter to control user-specified quality and options.
*
* <p><code>faceOffsetsInBytes</code> are offsets in byte in the <code>buffer</code> relative
* to the current {@link Buffer#position()}. Use {@link CubemapFace} to index the
* <code>faceOffsetsInBytes</code> array. All six faces must be tightly packed.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*/
public void generatePrefilterMipmap(@NonNull Engine engine,
@NonNull PixelBufferDescriptor buffer, @NonNull @Size(min = 6) int[] faceOffsetsInBytes,
PrefilterOptions options) {

View File

@@ -16,26 +16,62 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
/**
* <code>TextureSampler</code> defines how a texture is accessed.
*/
public class TextureSampler {
public enum WrapMode {
/**
* The edge of the texture extends to infinity.
*/
CLAMP_TO_EDGE,
/**
* The texture infinitely repeats in the wrap direction.
*/
REPEAT,
/**
* The texture infinitely repeats and mirrors in the wrap direction.
*/
MIRRORED_REPEAT
}
public enum MinFilter {
/**
* No filtering. Nearest neighbor is used.
*/
NEAREST,
/**
* Box filtering. Weighted average of 4 neighbors is used.
*/
LINEAR,
/**
* Mip-mapping is activated. But no filtering occurs.
*/
NEAREST_MIPMAP_NEAREST,
/**
* Box filtering within a mip-map level.
*/
LINEAR_MIPMAP_NEAREST,
/**
* Mip-map levels are interpolated, but no other filtering occurs.
*/
NEAREST_MIPMAP_LINEAR,
/**
* Both interpolated Mip-mapping and linear filtering are used.
*/
LINEAR_MIPMAP_LINEAR,
}
public enum MagFilter {
/**
* No filtering. Nearest neighbor is used.
*/
NEAREST,
/**
* Box filtering. Weighted average of 4 neighbors is used.
*/
LINEAR
}
@@ -44,114 +80,246 @@ public class TextureSampler {
COMPARE_TO_TEXTURE
}
/**
* Comparison functions for the depth sampler.
*/
public enum CompareFunction {
/**
* Less or equal
*/
LESS_EQUAL,
/**
* Greater or equal
*/
GREATER_EQUAL,
/**
* Strictly less than
*/
LESS,
/**
* Strictly greater than
*/
GREATER,
/**
* Equal
*/
EQUAL,
/**
* Not equal
*/
NOT_EQUAL,
/**
* Always. Depth testing is deactivated.
*/
ALWAYS,
/**
* Never. The depth test always fails.
*/
NEVER
}
int mSampler = 0; // bit field used by native
/**
* Min filter: LINEAR_MIPMAP_LINEAR
* Mag filter: LINEAR
* Wrap mode: REPEAT
* Initializes the <code>TextureSampler</code> with default values.
* <br>Minification filter: {@link MinFilter#LINEAR_MIPMAP_LINEAR}
* <br>Magnification filter: {@link MagFilter#LINEAR}
* <br>Wrap modes: {@link WrapMode#REPEAT}
*/
public TextureSampler() {
this(MinFilter.LINEAR_MIPMAP_LINEAR, MagFilter.LINEAR, WrapMode.REPEAT);
}
/**
* Initializes the <code>TextureSampler</code> with default values, but specifying the
* minification and magnification filters.
*
* @param minMag {@link MagFilter magnification filter},
* the minification filter will be set to the same value.
*/
public TextureSampler(@NonNull MagFilter minMag) {
this(minMag, WrapMode.CLAMP_TO_EDGE);
}
/**
* Initializes the <code>TextureSampler</code> with user specified values.
*
* @param minMag {@link MagFilter magnification filter},
* the minification filter will be set to the same value.
* @param wrap {@link WrapMode wrapping mode} for all directions
*/
public TextureSampler(@NonNull MagFilter minMag, @NonNull WrapMode wrap) {
this(minFilterFromMagFilter(minMag), minMag, wrap);
}
/**
* Initializes the <code>TextureSampler</code> with user specified values.
*
* @param min {@link MagFilter magnification filter}
* @param mag {@link MinFilter minification filter}
* @param wrap {@link WrapMode wrapping mode} for all directions
*/
public TextureSampler(@NonNull MinFilter min, @NonNull MagFilter mag, @NonNull WrapMode wrap) {
this(min, mag, wrap, wrap, wrap);
}
/**
* Initializes the <code>TextureSampler</code> with user specified values.
*
* @param min {@link MagFilter magnification filter}
* @param mag {@link MinFilter minification filter}
* @param s {@link WrapMode wrapping mode} for the s (horizontal) direction
* @param t {@link WrapMode wrapping mode} for the t (vertical) direction
* @param r {@link WrapMode wrapping mode} fot the r (depth) direction
*/
public TextureSampler(@NonNull MinFilter min, @NonNull MagFilter mag,
@NonNull WrapMode s, @NonNull WrapMode t, @NonNull WrapMode r) {
mSampler = nCreateSampler(min.ordinal(), mag.ordinal(),
s.ordinal(), t.ordinal(), r.ordinal());
}
/**
* Initializes the <code>TextureSampler</code> with user specified comparison mode. The
* comparison fonction is set to {@link CompareFunction#LESS_EQUAL}.
*
* @param mode {@link CompareMode comparison mode}
*/
public TextureSampler(@NonNull CompareMode mode) {
this(mode, CompareFunction.LESS_EQUAL);
}
/**
* Initializes the <code>TextureSampler</code> with user specified comparison mode and function.
*
* @param mode {@link CompareMode comparison mode}
* @param function {@link CompareFunction comparison function}
*/
public TextureSampler(@NonNull CompareMode mode, @NonNull CompareFunction function) {
mSampler = nCreateCompareSampler(mode.ordinal(), function.ordinal());
}
/**
* @return the minification filter
*/
public MinFilter getMinFilter() {
return MinFilter.values()[nGetMinFilter(mSampler)];
}
/**
* Sets the minification filter.
*
* @param filter minification filter
*/
public void setMinFilter(MinFilter filter) {
mSampler = nSetMinFilter(mSampler, filter.ordinal());
}
/**
* @return the magnification filter
*/
public MagFilter getMagFilter() {
return MagFilter.values()[nGetMagFilter(mSampler)];
}
/**
* Sets the magnification filter.
*
* @param filter magnification filter
*/
public void setMagFilter(MagFilter filter) {
mSampler = nSetMagFilter(mSampler, filter.ordinal());
}
/**
* @return the wrapping mode in the s (horizontal) direction
*/
public WrapMode getWrapModeS() {
return WrapMode.values()[nGetWrapModeS(mSampler)];
}
/**
* Sets the wrapping mode in the s (horizontal) direction.
* @param mode wrapping mode
*/
public void setWrapModeS(WrapMode mode) {
mSampler = nSetWrapModeS(mSampler, mode.ordinal());
}
/**
* @return the wrapping mode in the t (vertical) direction
*/
public WrapMode getWrapModeT() {
return WrapMode.values()[nGetWrapModeT(mSampler)];
}
/**
* Sets the wrapping mode in the t (vertical) direction.
* @param mode wrapping mode
*/
public void setWrapModeT(WrapMode mode) {
mSampler = nSetWrapModeT(mSampler, mode.ordinal());
}
/**
* @return the wrapping mode in the r (depth) direction
*/
public WrapMode getWrapModeR() {
return WrapMode.values()[nGetWrapModeR(mSampler)];
}
/**
* Sets the wrapping mode in the t (depth) direction.
* @param mode wrapping mode
*/
public void setWrapModeR(WrapMode mode) {
mSampler = nSetWrapModeR(mSampler, mode.ordinal());
}
/**
* @return the anisotropy value
* @see #setAnisotropy
*/
public float getAnisotropy() {
return nGetAnisotropy(mSampler);
}
/**
* This controls anisotropic filtering.
*
* @param anisotropy Amount of anisotropy, should be a power-of-two. The default is 0.
* The maximum permissible value is 7.
*/
public void setAnisotropy(float anisotropy) {
mSampler = nSetAnisotropy(mSampler, anisotropy);
}
/**
* @return the comparison mode
*/
public CompareMode getCompareMode() {
return CompareMode.values()[nGetCompareMode(mSampler)];
}
/**
* Sets the comparison mode.
*
* @param mode comparison mode
*/
public void setCompareMode(CompareMode mode) {
mSampler = nSetCompareMode(mSampler, mode.ordinal());
}
/**
* @return the comparison function
*/
public CompareFunction getCompareFunction() {
return CompareFunction.values()[nGetCompareFunction(mSampler)];
}
/**
* Sets the comparison function.
* @param function the comparison function
*/
public void setCompareFunction(CompareFunction function) {
mSampler = nSetCompareFunction(mSampler, function.ordinal());
}

View File

@@ -16,51 +16,158 @@
package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
public class TransformManager {
/**
* <code>TransformManager</code> is used to add transform components to entities.
*
* <p>A transform component gives an entity a position and orientation in space in the coordinate
* space of its parent transform. The <code>TransformManager</code> takes care of computing the
* world-space transform of each component (i.e. its transform relative to the root).</p>
*
* <h1>Creation and destruction</h1>
*
* A transform component is created using {@link TransformManager#create} and destroyed by calling
* {@link TransformManager#destroy}.
*
* <pre>
* Engine engine = Engine.create();
* EntityManager entityManager = EntityManager().get();
* int object = entityManager.create();
*
* TransformManager tcm = engine.getTransformManager();
*
* // create the transform component
* tcm.create(object);
*
* // set its transform
* float[] transform = ...; // transform to set
* EntityInstance i = tcm.getInstance(object);
* tcm.setTransform(i, transform));
*
* // destroy the transform component
* tcm.destroy(object);
* </pre>
*
*/public class TransformManager {
private long mNativeObject;
TransformManager(long nativeTransformManager) {
mNativeObject = nativeTransformManager;
}
/**
* Returns whether a particular {@link Entity} is associated with a component of this
* <code>TransformManager</code>
*
* @param entity an {@link Entity}
* @return true if this {@link Entity} has a component associated with this manager
*/
public boolean hasComponent(@Entity int entity) {
return nHasComponent(mNativeObject, entity);
}
/**
* Gets an {@link EntityInstance} representing the transform component associated with the
* given {@link Entity}.
*
* @param entity an {@link Entity}
* @return an {@link EntityInstance}, which represents the transform component associated with
* the {@link Entity} <code>entity</code>
* @see #hasComponent
*/
@EntityInstance
public int getInstance(@Entity int entity) {
return nGetInstance(mNativeObject, entity);
}
/**
* Creates a transform component and associates it with the given entity. The component is
* initialized with the identity transform.
* If this component already exists on the given entity, it is first
* destroyed as if {@link #destroy} was called.
*
* @param entity an {@link Entity} to associate a transform component to.
* @see #destroy
*/
@EntityInstance
public int create(@Entity int entity) {
return nCreate(mNativeObject, entity);
}
/**
* Creates a transform component with a parent and associates it with the given entity.
* If this component already exists on the given entity, it is first
* destroyed as if {@link #destroy} was called.
*
* @param entity an {@link Entity} to associate a transform component to.
* @param parent the {@link EntityInstance} of the parent transform
* @param localTransform the transform, relative to the parent, to initialize the transform
* component with.
* @see #destroy
*/
@EntityInstance
public int create(@Entity int entity, @EntityInstance int parent,
@Nullable @Size(min = 16) float[] localTransform) {
return nCreateArray(mNativeObject, entity, parent, localTransform);
}
/**
* Destroys this component from the given entity, children are orphaned.
*
* @param entity an {@link Entity}.
* If this transform had children, these are orphaned, which means their local
* transform becomes a world transform. Usually it's nonsensical.
* It's recommended to make sure that a destroyed transform doesn't have children.
* @see #create
*/
public void destroy(@Entity int entity) {
nDestroy(mNativeObject, entity);
}
/**
* Re-parents an entity to a new one.
*
* @param i the {@link EntityInstance} of the transform component to re-parent
* @param newParent the {@link EntityInstance} of the new parent transform.
* It is an error to re-parent an entity to a descendant and will cause
* undefined behaviour.
* @see #getInstance
*/
public void setParent(@EntityInstance int i, @EntityInstance int newParent) {
nSetParent(mNativeObject, i, newParent);
}
/**
* Sets a local transform of a transform component.
* <p>This operation can be slow if the hierarchy of transform is too deep, and this
* will be particularly bad when updating a lot of transforms. In that case,
* consider using {@link #openLocalTransformTransaction} / {@link #commitLocalTransformTransaction}.</p>
*
* @param i the {@link EntityInstance} of the transform component to set the local
* transform to.
* @param localTransform the local transform (i.e. relative to the parent).
* @see #getTransform
*/
public void setTransform(@EntityInstance int i,
@NonNull @Size(min = 16) float[] localTransform) {
Asserts.assertMat4fIn(localTransform);
nSetTransform(mNativeObject, i, localTransform);
}
/**
* Returns the local transform of a transform component.
*
* @param i the {@link EntityInstance} of the transform component to query the
* local transform from.
* @param outLocalTransform a 16 <code>float</code> array to receive the result.
* If <code>null</code> is given, a new suitable array is allocated.
* @return the local transform of the component (i.e. relative to the parent). This always
* returns the value set by setTransform().
* @see #setTransform
*/
@NonNull
@Size(min = 16)
public float[] getTransform(@EntityInstance int i,
@@ -70,6 +177,17 @@ public class TransformManager {
return outLocalTransform;
}
/**
* Returns the world transform of a transform component.
*
* @param i the {@link EntityInstance} of the transform component to query the
* world transform from.
* @param outWorldTransform a 16 <code>float</code> array to receive the result.
* If <code>null</code> is given, a new suitable array is allocated
* @return The world transform of the component (i.e. relative to the root). This is the
* composition of this component's local transform with its parent's world transform.
* @see #setTransform
*/
@NonNull
@Size(min = 16)
public float[] getWorldTransform(@EntityInstance int i,
@@ -79,10 +197,36 @@ public class TransformManager {
return outWorldTransform;
}
/**
* Opens a local transform transaction. During a transaction, {@link #getWorldTransform} can
* return an invalid transform until {@link #commitLocalTransformTransaction} is called.
* However, {@link #setTransform} will perform significantly better and in constant time.
*
* <p>This is useful when updating many transforms and the transform hierarchy is deep (say more
* than 4 or 5 levels).</p>
*
* <p>If the local transform transaction is already open, this is a no-op.</p>
*
* @see #commitLocalTransformTransaction
* @see #setTransform
*/
public void openLocalTransformTransaction() {
nOpenLocalTransformTransaction(mNativeObject);
}
/**
* Commits the currently open local transform transaction. When this returns, calls
* to {@link #getWorldTransform} will return the proper value.
*
* <p>Failing to call this method when done updating the local transform will cause
* a lot of rendering problems. The system never closes the transaction
* automatically.</p>
*
* <p>If the local transform transaction is not open, this is a no-op.</p>
*
* @see #openLocalTransformTransaction
* @see #setTransform
*/
public void commitLocalTransformTransaction() {
nCommitLocalTransformTransaction(mNativeObject);
}

View File

@@ -16,13 +16,40 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
/**
* Holds a set of buffers that define the geometry of a <code>Renderable</code>.
*
* <p>
* The geometry of the <code>Renderable</code> itself is defined by a set of vertex attributes such as
* position, color, normals, tangents, etc...
* </p>
*
* <p>
* There is no need to have a 1-to-1 mapping between attributes and buffer. A buffer can hold the
* data of several attributes -- attributes are then referred as being "interleaved".
* </p>
*
* <p>
* The buffers themselves are GPU resources, therefore mutating their data can be relatively slow.
* For this reason, it is best to separate the constant data from the dynamic data into multiple
* buffers.
* </p>
*
* <p>
* It is possible, and even encouraged, to use a single vertex buffer for several
* <code>Renderable</code>s.
* </p>
*
* @see IndexBuffer
* @see RenderableManager
*/
public class VertexBuffer {
private long mNativeObject;
@@ -31,13 +58,22 @@ public class VertexBuffer {
}
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)
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)
BONE_WEIGHTS, // weights of the 4 bones (normalized float4)
UNUSED, // reserved for future use
CUSTOM0, // custom or MORPH_POSITION_0
CUSTOM1, // custom or MORPH_POSITION_1
CUSTOM2, // custom or MORPH_POSITION_2
CUSTOM3, // custom or MORPH_POSITION_3
CUSTOM4, // custom or MORPH_TANGENTS_0
CUSTOM5, // custom or MORPH_TANGENTS_1
CUSTOM6, // custom or MORPH_TANGENTS_2
CUSTOM7 // custom or MORPH_TANGENTS_3
}
public enum AttributeType {
@@ -68,22 +104,47 @@ public class VertexBuffer {
HALF3,
HALF4,
}
/**
* Specifies the quaternion type for the {@link #populateTangentQuaternions} utility.
*/
public enum QuatType {
HALF4, // 2 bytes per component as half-floats (8 bytes per quat)
SHORT4, // 2 bytes per component as normalized integers (8 bytes per quat)
FLOAT4, // 4 bytes per component as floats (16 bytes per quat)
/** 2 bytes per component as half-floats (8 bytes per quat) */
HALF4,
/** 2 bytes per component as normalized integers (8 bytes per quat) */
SHORT4,
/** 4 bytes per component as floats (16 bytes per quat) */
FLOAT4,
}
/**
* Specifies the parameters for the {@link #populateTangentQuaternions} utility.
*/
public static class QuatTangentContext {
public QuatType quatType; // desired quaternion type (required)
public int quatCount; // number of quaternions (required)
public Buffer outBuffer; // pre-allocated output buffer (required)
public int outStride; // desired stride in bytes (optional)
public Buffer normals; // source normals (required)
public int normalsStride; // normals stride in bytes (optional)
public Buffer tangents; // source tangents (optional)
public int tangentsStride; // tangents stride in bytes (optional)
/** desired quaternion type (required) */
public QuatType quatType;
/** number of quaternions (required) */
public int quatCount;
/** pre-allocated output buffer (required) */
public Buffer outBuffer;
/** desired stride in bytes (optional) */
public int outStride;
/** source normals (required) */
public Buffer normals;
/** normals stride in bytes (optional) */
public int normalsStride;
/** source tangents (optional) */
public Buffer tangents;
/** tangents stride in bytes (optional) */
public int tangentsStride;
}
public static class Builder {
@@ -96,18 +157,64 @@ public class VertexBuffer {
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Size of each buffer in this set, expressed in in number of vertices.
*
* @param vertexCount number of vertices in each buffer in this set
*
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder vertexCount(@IntRange(from = 1) int vertexCount) {
nBuilderVertexCount(mNativeBuilder, vertexCount);
return this;
}
/**
* Defines how many buffers will be created in this vertex buffer set. These buffers are
* later referenced by index from 0 to <code>bufferCount</code> - 1.
*
* This call is mandatory. The default is 0.
*
* @param bufferCount number of buffers in this vertex buffer set. The maximum value is 8.
*
* @return this <code>Builder</code> for chaining calls
*/
@NonNull
public Builder bufferCount(@IntRange(from = 1) int bufferCount) {
nBuilderBufferCount(mNativeBuilder, bufferCount);
return this;
}
/**
* Sets up an attribute for this vertex buffer set.
*
* Using <code>byteOffset</code> and <code>byteStride</code>, attributes can be interleaved
* in the same buffer.
*
* <p>
* This is a no-op if the <code>attribute</code> is an invalid enum.
* This is a no-op if the <code>bufferIndex</code> is out of bounds.
* </p>
*
* <p>
* Warning: <code>VertexAttribute.TANGENTS</code> must be specified as a quaternion and is
* how normals are specified.
* </p>
*
* @param attribute the attribute to set up
* @param bufferIndex the index of the buffer containing the data for this attribute. Must
* be between 0 and bufferCount() - 1.
* @param attributeType the type of the attribute data (e.g. byte, float3, etc...)
* @param byteOffset offset in <i>bytes</i> into the buffer <code>bufferIndex</code>
* @param byteStride stride in <i>bytes</i> to the next element of this attribute. When
* set to zero the attribute size, as defined by
* <code>attributeType</code> is used.
*
* @return A reference to this <code>Builder</code> for chaining calls.
*
* @see VertexAttribute
*/
@NonNull
public Builder attribute(@NonNull VertexAttribute attribute,
@IntRange(from = 0) int bufferIndex, @NonNull AttributeType attributeType,
@@ -117,24 +224,82 @@ public class VertexBuffer {
return this;
}
/**
* Sets up an attribute for this vertex buffer set.
*
* Using <code>byteOffset</code> and <code>byteStride</code>, attributes can be interleaved
* in the same buffer.
*
* <p>
* This is a no-op if the <code>attribute</code> is an invalid enum.
* This is a no-op if the <code>bufferIndex</code> is out of bounds.
* </p>
*
* <p>
* Warning: <code>VertexAttribute.TANGENTS</code> must be specified as a quaternion and is
* how normals are specified.
* </p>
*
* @param attribute the attribute to set up
* @param bufferIndex the index of the buffer containing the data for this attribute. Must
* be between 0 and bufferCount() - 1.
* @param attributeType the type of the attribute data (e.g. byte, float3, etc...)
*
* @return A reference to this <code>Builder</code> for chaining calls.
*
* @see VertexAttribute
*/
@NonNull
public Builder attribute(@NonNull VertexAttribute attribute,
@IntRange(from = 0) int bufferIndex, @NonNull AttributeType attributeType) {
return attribute(attribute, bufferIndex, attributeType, 0, 0 );
}
/**
* Sets whether a given attribute should be normalized. By default attributes are not
* normalized. A normalized attribute is mapped between 0 and 1 in the shader. This applies
* only to integer types.
*
* @param attribute enum of the attribute to set the normalization flag to
*
* @return this <code>Builder</code> object for chaining calls.
*
* This is a no-op if the <code>attribute</code> is an invalid enum.
*/
@NonNull
public Builder normalized(@NonNull VertexAttribute attribute) {
nBuilderNormalized(mNativeBuilder, attribute.ordinal(), true);
return this;
}
/**
* Sets whether a given attribute should be normalized. By default attributes are not
* normalized. A normalized attribute is mapped between 0 and 1 in the shader. This applies
* only to integer types.
*
* @param attribute enum of the attribute to set the normalization flag to
* @param enabled true to automatically normalize the given attribute
*
* @return this <code>Builder</code> object for chaining calls.
*
* This is a no-op if the <code>attribute</code> is an invalid enum.
*/
@NonNull
public Builder normalized(@NonNull VertexAttribute attribute, boolean enabled) {
nBuilderNormalized(mNativeBuilder, attribute.ordinal(), enabled);
return this;
}
/**
* Creates the <code>VertexBuffer</code> object and returns a pointer to it.
*
* @param engine reference to the {@link Engine} to associate this <code>VertexBuffer</code>
* with
*
* @return the newly created <code>VertexBuffer</code> object
*
* @exception IllegalStateException if the VertexBuffer could not be created
*/
@NonNull
public VertexBuffer build(@NonNull Engine engine) {
long nativeVertexBuffer = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
@@ -159,24 +324,68 @@ public class VertexBuffer {
}
}
/**
* Returns the vertex count.
*
* @return number of vertices in this vertex buffer set
*/
@IntRange(from = 0)
public int getVertexCount() {
return nGetVertexCount(getNativeObject());
}
/**
* Asynchronously copy-initializes the specified buffer from the given buffer data.
*
* @param engine reference to the {@link Engine} to associate this
* <code>VertexBuffer</code> with
* @param bufferIndex index of the buffer to initialize. Must be between 0 and
* bufferCount() - 1.
* @param buffer a CPU-side {@link Buffer} representing the data used to initialize
* the <code>VertexBuffer</code> at index <code>bufferIndex</code>.
* <code>buffer</code> should contain raw, untyped data that will
* be copied as-is into the buffer.
*/
public void setBufferAt(@NonNull Engine engine, int bufferIndex, @NonNull Buffer buffer) {
setBufferAt(engine, bufferIndex, buffer, 0, 0, null, null);
}
/**
* Asynchronously copy-initializes a region of the specified buffer from the given buffer data.
*
* @param engine reference to the {@link Engine} to associate this
* <code>VertexBuffer</code> with
* @param bufferIndex index of the buffer to initialize. Must be between 0 and
* bufferCount() - 1.
* @param buffer a CPU-side {@link Buffer} representing the data used to initialize
* the <code>VertexBuffer</code> at index <code>bufferIndex</code>.
* <code>buffer</code> should contain raw, untyped data that will
* be copied as-is into the buffer.
* @param destOffsetInBytes offset in <i>bytes</i> into the buffer at index
* <code>bufferIndex</code> of this vertex buffer set.
*/
public void setBufferAt(@NonNull Engine engine, int bufferIndex, @NonNull Buffer buffer,
@IntRange(from = 0) int destOffsetInBytes, @IntRange(from = 0) int count) {
setBufferAt(engine, bufferIndex, buffer, destOffsetInBytes, count, null, null);
}
/**
* Valid handler types:
* - Android: Handler, Executor
* - Other: Executor
* Asynchronously copy-initializes a region of the specified buffer from the given buffer data.
*
* @param engine reference to the {@link Engine} to associate this
* <code>VertexBuffer</code> with
* @param bufferIndex index of the buffer to initialize. Must be between 0 and
* bufferCount() - 1.
* @param buffer a CPU-side {@link Buffer} representing the data used to initialize
* the <code>VertexBuffer</code> at index <code>bufferIndex</code>.
* <code>buffer</code> should contain raw, untyped data that will
* be copied as-is into the buffer.
* @param destOffsetInBytes offset in <i>bytes</i> into the buffer at index
* <code>bufferIndex</code> of this vertex buffer set.
* @param handler an {@link java.util.concurrent.Executor Executor}. On Android this
* can also be a {@link android.os.Handler Handler}.
* @param callback a callback executed by <code>handler</code> when <code>buffer</code>
* is no longer needed.
*/
public void setBufferAt(@NonNull Engine engine, int bufferIndex, @NonNull Buffer buffer,
@IntRange(from = 0) int destOffsetInBytes, @IntRange(from = 0) int count,
@@ -188,7 +397,30 @@ public class VertexBuffer {
throw new BufferOverflowException();
}
}
/**
* Convenience function that consumes normal vectors (and, optionally, tangent vectors) and
* produces quaternions that can be passed into a TANGENTS buffer.
*
* <p>
* The given output buffer must be preallocated with at least quatCount * outStride bytes.
* <p>
*
* <p>
* Normals are required but tangents are optional, in which case this function tries to generate
* reasonable tangents. The given normals should be unit length.
* </p>
*
* <p>
* If supplied, the tangent vectors should be unit length and should be orthogonal to the
* normals. The w component of the tangent is a sign (-1 or +1) indicating handedness of the
* basis.
* </p>
*
* @deprecated Instead please use SurfaceOrientation since it has additional capabilities and a
* builder-style API.
*
* @param context an initialized QuatTangentContext object
*/
public static void populateTangentQuaternions(@NonNull QuatTangentContext context) {
nPopulateTangentQuaternions(context.quatType.ordinal(), context.quatCount,
context.outBuffer, context.outBuffer.remaining(), context.outStride,

View File

@@ -16,13 +16,44 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import static com.google.android.filament.Colors.*;
import static com.google.android.filament.Colors.LinearColor;
/**
* Encompasses all the state needed for rendering a {@link Scene}.
*
* <p>
* {@link Renderer#render} operates on <code>View</code> objects. These <code>View</code> objects
* specify important parameters such as:
* </p>
*
* <ul>
* <li>The Scene</li>
* <li>The Camera</li>
* <li>The Viewport</li>
* <li>Some rendering parameters</li>
* </ul>
*
* <p>
* <code>View</code> instances are heavy objects that internally cache a lot of data needed for
* rendering. It is not advised for an application to use many View objects.
* </p>
*
* <p>
* For example, in a game, a <code>View</code> could be used for the main scene and another one for
* the game's user interface. More <code>View</code> instances could be used for creating special
* effects (e.g. a <code>View</code> is akin to a rendering pass).
* </p>
*
* @see Renderer
* @see Scene
* @see Camera
* @see RenderTarget
*/
public class View {
private long mNativeObject;
private String mName;
@@ -31,28 +62,14 @@ public class View {
private Viewport mViewport = new Viewport(0, 0, 0, 0);
private DynamicResolutionOptions mDynamicResolution;
private RenderQuality mRenderQuality;
private DepthPrepass mDepthPrepass = DepthPrepass.DEFAULT;
private AmbientOcclusionOptions mAmbientOcclusionOptions;
private BloomOptions mBloomOptions;
private FogOptions mFogOptions;
private RenderTarget mRenderTarget;
public static class DynamicResolutionOptions {
public boolean enabled = false;
public boolean homogeneousScaling = false;
public float targetFrameTimeMilli = 1000.0f / 60.0f;
public float headRoomRatio = 0.0f;
public float scaleRate = 0.125f;
public float minScale = 0.5f;
public float maxScale = 1.0f;
public int history = 9;
}
public static class AmbientOcclusionOptions {
public float radius = 0.3f;
public float bias = 0.005f;
public float power = 0.0f;
public float resolution = 0.5f;
}
/**
* Generic Quality Level
*/
public enum QualityLevel {
LOW,
MEDIUM,
@@ -60,92 +77,459 @@ public class View {
ULTRA
}
/**
* Dynamic resolution can be used to either reach a desired target frame rate by lowering the
* resolution of a <code>View</code>, or to increase the quality when the rendering is faster
* than the target frame rate.
*
* <p>
* This structure can be used to specify the minimum scale factor used when lowering the
* resolution of a <code>View</code>, and the maximum scale factor used when increasing the
* resolution for higher quality rendering. The scale factors can be controlled on each X and Y
* axis independently. By default, all scale factors are set to 1.0.
* </p>
*
* <p>
* Dynamic resolution is only supported on platforms where the time to render a frame can be
* measured accurately. Dynamic resolution is currently only supported on Android.
* </p>
*/
public static class DynamicResolutionOptions {
/**
* Enables or disables dynamic resolution on a View.
*/
public boolean enabled = false;
/**
* If false, the system scales the major axis first.
*/
public boolean homogeneousScaling = false;
/**
* Desired frame time in milliseconds.
*/
public float targetFrameTimeMilli = 1000.0f / 60.0f;
/**
* Additional headroom for the GPU as a ratio of the targetFrameTime.
*/
public float headRoomRatio = 0.0f;
/**
* Rate at which the scale will change to reach the target frame rate.
*/
public float scaleRate = 0.125f;
/**
* The minimum scale in X and Y this View should use.
*/
public float minScale = 0.5f;
/**
* The maximum scale in X and Y this View should use.
*/
public float maxScale = 1.0f;
/**
* History size. higher values, tend to filter more (clamped to 30).
*/
public int history = 9;
/**
* Upscaling quality. LOW: 1 bilinear taps, MEDIUM: 4 bilinear taps, HIGH: 9 bilinear taps.
* If minScale needs to be very low, it might help to use MEDIUM or HIGH here.
* The default upsacling quality is set to LOW.
*/
@NonNull
public QualityLevel quality = QualityLevel.LOW;
}
/**
* Options for Ambient Occlusion
* @see #setAmbientOcclusion
*/
public static class AmbientOcclusionOptions {
/**
* Ambient Occlusion radius in meters, between 0 and ~10.
*/
public float radius = 0.3f;
/**
* Self-occlusion bias in meters. Use to avoid self-occlusion. Between 0 and a few mm.
*/
public float bias = 0.0005f;
/**
* Controls ambient occlusion's contrast. Must be positive. Default is 1.
* Good values are between 0.5 and 3.
*/
public float power = 1.0f;
/**
* How each dimension of the AO buffer is scaled. Must be positive and <= 1.
*/
public float resolution = 0.5f;
/**
* Strength of the Ambient Occlusion effect. Must be positive.
*/
public float intensity = 1.0f;
/**
* The quality setting controls the number of samples used for evaluating Ambient
* occlusion. The default is QualityLevel.LOW which is sufficient for most mobile
* applications.
*/
@NonNull
public QualityLevel quality = QualityLevel.LOW;
}
/**
* Options for controlling the Bloom effect
*
* enabled: Enable or disable the bloom post-processing effect. Disabled by default.
* levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
* maximum is 12. This value together with resolution influences the spread of the
* blur effect. This value can be silently reduced to accommodate the original
* image size.
* resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
* the maximum is lower of the original resolution and 4096. This parameter is
* silently clamped to the minimum and maximum.
* It is highly recommended that this value be smaller than the target resolution
* after dynamic resolution is applied (horizontally and vertically).
* strength: how much of the bloom is added to the original image. Between 0 and 1.
* blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
* image (true).
* anamorphism: Bloom's aspect ratio (x/y), for artistic purposes.
* threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
* useful for artistic reasons and is usually needed when a dirt texture is used.
* dirt: A dirt/scratch/smudges texture (that can be RGB), which gets added to the
* bloom effect. Smudges are visible where bloom occurs. Threshold must be
* enabled for the dirt effect to work properly.
* dirtStrength: Strength of the dirt texture.
*
* @see setBloomOptions
*/
public static class BloomOptions {
public enum BlendingMode {
ADD,
INTERPOLATE
}
/**
* User provided dirt texture
*/
@Nullable
public Texture dirt = null;
/**
* strength of the dirt texture
*/
public float dirtStrength = 0.2f;
/**
* Strength of the bloom effect, between 0.0 and 1.0
*/
public float strength = 0.10f;
/**
* Resolution of minor axis (2^levels to 4096)
*/
public int resolution = 360;
/**
* Bloom x/y aspect-ratio (1/32 to 32)
*/
public float anamorphism = 1.0f;
/**
* Number of blur levels (3 to 12)
*/
public int levels = 6;
/**
* How the bloom effect is applied
*/
public BlendingMode blendingMode = BlendingMode.ADD;
/**
* Whether to threshold the source
*/
public boolean threshold = true;
/**
* enable or disable bloom
*/
public boolean enabled = false;
}
/**
* Options to control fog in the scene
*
* @see setFogOptions
*/
public static class FogOptions {
/**
* distance in world units from the camera where the fog starts ( >= 0.0 )
*/
public float distance = 0.0f;
/**
* fog's maximum opacity between 0 and 1
*/
public float maximumOpacity = 1.0f;
/**
* fog's floor in world units
*/
public float height = 0.0f;
/**
* how fast fog dissipates with altitude
*/
public float heightFalloff = 1.0f;
/**
* fog's color (linear)
*/
@NonNull
public float[] color = { 0.5f, 0.5f, 0.5f };
/**
* fog's density at altitude given by 'height'
*/
public float density = 0.1f;
/**
* distance in world units from the camera where in-scattering starts
*/
public float inScatteringStart = 0.0f;
/**
* size of in-scattering (>=0 to activate). Good values are >> 1 (e.g. ~10 - 100)
*/
public float inScatteringSize = 0.0f;
/**
* fog color will be modulated by the IBL color in the view direction
*/
public boolean fogColorFromIbl = false;
/**
* enable or disable fog
*/
public boolean enabled = false;
}
/**
* Structure used to set the color precision for the rendering of a <code>View</code>.
*
* <p>
* This structure offers separate quality settings for different parts of the rendering
* pipeline.
* </p>
*
* @see #setRenderQuality
* @see #getRenderQuality
*/
public static class RenderQuality {
/**
* <p>
* A quality of <code>HIGH</code> or <code>ULTRA</code> means using an RGB16F or RGBA16F color
* buffer. This means colors in the LDR range (0..1) have 10 bit precision. A quality of
* <code>LOW</code> or <code>MEDIUM</code> means using an R11G11B10F opaque color buffer or an
* RGBA16F transparent color buffer. With R11G11B10F colors in the LDR range have a precision of
* either 6 bits (red and green channels) or 5 bits (blue channel).
* </p>
*/
public QualityLevel hdrColorBuffer = QualityLevel.HIGH;
}
/**
* List of available ambient occlusion techniques.
*
* @see #setAmbientOcclusion
*/
public enum AmbientOcclusion {
NONE,
SSAO
}
/**
* List of available post-processing anti-aliasing techniques.
*
* @see #setAntiAliasing
* @see #getAntiAliasing
*/
public enum AntiAliasing {
/**
* No anti aliasing performed as part of post-processing.
*/
NONE,
/**
* FXAA is a low-quality but very efficient type of anti-aliasing. (default).
*/
FXAA
}
/**
* List of available tone-mapping operators
*/
public enum ToneMapping {
/**
* Equivalent to disabling tone-mapping.
*/
LINEAR,
/**
* The Academy Color Encoding System (ACES).
*/
ACES
}
/**
* List of available post-processing dithering techniques.
*/
public enum Dithering {
NONE,
TEMPORAL
}
public enum DepthPrepass {
DEFAULT(-1),
DISABLED(0),
ENABLED(1);
final int value;
DepthPrepass(int value) {
this.value = value;
}
};
View(long nativeView) {
mNativeObject = nativeView;
}
/**
* Sets the View's name. Only useful for debugging.
*/
public void setName(@NonNull String name) {
mName = name;
nSetName(getNativeObject(), name);
}
/**
* Returns the View's name.
*/
@Nullable
public String getName() {
return mName;
}
/**
* Sets this View instance's Scene.
*
* <p>
* This method associates the specified Scene with this View. Note that a particular scene can
* be associated with several View instances. To remove an existing association, simply pass
* null.
* </p>
*
* <p>
* The View does not take ownership of the Scene pointer. Before destroying a Scene, be sure
* to remove it from all assoicated Views.
* </p>
*
* @see #getScene
*/
public void setScene(@Nullable Scene scene) {
mScene = scene;
nSetScene(getNativeObject(), scene == null ? 0 : scene.getNativeObject());
}
/**
* Gets this View's associated Scene, or null if none has been assigned.
*
* @see #setScene
*/
@Nullable
public Scene getScene() {
return mScene;
}
/**
* Sets this View's Camera.
*
* <p>
* This method associates the specified Camera with this View. A Camera can be associated with
* several View instances. To remove an existing association, simply pass
* null.
* </p>
*
* <p>
* The View does not take ownership of the Scene pointer. Before destroying a Camera, be sure
* to remove it from all assoicated Views.
* </p>
*
* @see #getCamera
*/
public void setCamera(@Nullable Camera camera) {
mCamera = camera;
nSetCamera(getNativeObject(), camera == null ? 0 : camera.getNativeObject());
}
/**
* Gets this View's associated Camera, or null if none has been assigned.
*
* @see #setCamera
*/
@Nullable
public Camera getCamera() {
return mCamera;
}
/**
* Specifies the rectangular rendering area.
*
* <p>
* The viewport specifies where the content of the View (i.e. the Scene) is rendered in
* the render target. The render target is automatically clipped to the Viewport.
* </p>
*
* <p>
* If you wish subsequent changes to take effect please call this method again in order to
* propagate the changes down to the native layer.
* </p>
*
* @param viewport The Viewport to render the Scene into.
*/
public void setViewport(@NonNull Viewport viewport) {
mViewport = viewport;
nSetViewport(getNativeObject(),
mViewport.left, mViewport.bottom, mViewport.width, mViewport.height);
}
/**
* Returns the rectangular rendering area.
*
* @see #setViewport
*/
@NonNull
public Viewport getViewport() {
return mViewport;
}
/**
* Sets the color used to clear the Viewport when rendering this View.
*
* <p>This is ignored if a {@link Skybox} is present or if clearing has been disabled
* via {@link #setClearTargets}. Defaults to black.</p>
*
* @see #getClearColor
*/
public void setClearColor(
@LinearColor float r, @LinearColor float g, @LinearColor float b, float a) {
nSetClearColor(getNativeObject(), r, g, b, a);
}
/**
* Returns the View clear color in a provided 4-tuple.
*
* @return A reference to the passed-in array.
*
* @see #setClearColor
*/
@NonNull @Size(min = 4)
public float[] getClearColor(@NonNull @Size(min = 4) float[] out) {
out = Asserts.assertFloat4(out);
@@ -153,65 +537,178 @@ public class View {
return out;
}
/**
* Sets which targets to clear (default: true, true, false)
*
* @see #setClearColor
*/
public void setClearTargets(boolean color, boolean depth, boolean stencil) {
nSetClearTargets(getNativeObject(), color, depth, stencil);
}
/**
* Sets which layers are visible.
*
* <p>
* Renderable objects can have one or several layers associated to them. Layers are
* represented with an 8-bits bitmask, where each bit corresponds to a layer.
* By default all layers are visible.
* </p>
*
* @see RenderableManager#setLayerMask
*
* @param select a bitmask specifying which layer to set or clear using <code>values</code>.
* @param values a bitmask where each bit sets the visibility of the corresponding layer
* (1: visible, 0: invisible), only layers in <code>select</code> are affected.
*/
public void setVisibleLayers(
@IntRange(from = 0, to = 255) int select,
@IntRange(from = 0, to = 255) int values) {
nSetVisibleLayers(getNativeObject(), select & 0xFF, values & 0xFF);
}
/**
* Enables or disables shadow mapping. Enabled by default.
*
* @see LightManager.Builder#castShadows
* @see RenderableManager.Builder#receiveShadows
* @see RenderableManager.Builder#castShadows
*/
public void setShadowsEnabled(boolean enabled) {
nSetShadowsEnabled(getNativeObject(), enabled);
}
/**
* Specifies an offscreen render target to render into.
*
* <p>
* By default, the view's associated render target is null, which corresponds to the
* SwapChain associated with the engine.
* </p>
*
* @param target render target associated with view, or null for the swap chain
*/
public void setRenderTarget(@Nullable RenderTarget target) {
mRenderTarget = target;
nSetRenderTarget(getNativeObject(), target != null ? target.getNativeObject() : 0);
}
/**
* Gets the offscreen render target associated with this view.
*
* Returns null if the render target is the swap chain (which is default).
*
* @see #setRenderTarget
*/
@Nullable
public RenderTarget getRenderTarget() {
return mRenderTarget;
}
/**
* Sets how many samples are to be used for MSAA in the post-process stage.
* Default is 1 and disables MSAA.
*
* <p>
* Note that anti-aliasing can also be performed in the post-processing stage, generally at
* lower cost. See the FXAA option in {@link #setAntiAliasing}.
* </p>
*
* @param count number of samples to use for multi-sampled anti-aliasing.
*/
public void setSampleCount(int count) {
nSetSampleCount(getNativeObject(), count);
}
/**
* Returns the effective MSAA sample count.
*
* <p>
* A value of 0 or 1 means MSAA is disabled.
* </p>
*
* @return value set by {@link #setSampleCount}
*/
public int getSampleCount() {
return nGetSampleCount(getNativeObject());
}
/**
* Enables or disables anti-aliasing in the post-processing stage. Enabled by default.
*
* <p>
* For MSAA anti-aliasing, see {@link #setSampleCount}.
* </p>
*
* @param type FXAA for enabling, NONE for disabling anti-aliasing.
*/
public void setAntiAliasing(@NonNull AntiAliasing type) {
nSetAntiAliasing(getNativeObject(), type.ordinal());
}
/**
* Queries whether anti-aliasing is enabled during the post-processing stage. To query
* whether MSAA is enabled, see {@link #getSampleCount}.
*
* @return The post-processing anti-aliasing method.
*/
@NonNull
public AntiAliasing getAntiAliasing() {
return AntiAliasing.values()[nGetAntiAliasing(getNativeObject())];
}
/**
* Enables or disables tone-mapping in the post-processing stage. Enabled by default.
*
* @param type Tone-mapping function.
*/
public void setToneMapping(@NonNull ToneMapping type) {
nSetToneMapping(getNativeObject(), type.ordinal());
}
/**
* Returns the tone-mapping function.
* @return tone-mapping function.
*/
@NonNull
public ToneMapping getToneMapping() {
return ToneMapping.values()[nGetToneMapping(getNativeObject())];
}
/**
* Enables or disables dithering in the post-processing stage. Enabled by default.
*
* @param dithering dithering type
*/
public void setDithering(@NonNull Dithering dithering) {
nSetDithering(getNativeObject(), dithering.ordinal());
}
/**
* Queries whether dithering is enabled during the post-processing stage.
*
* @return the current dithering type for this view.
*/
@NonNull
public Dithering getDithering() {
return Dithering.values()[nGetDithering(getNativeObject())];
}
/**
* Sets the dynamic resolution options for this view.
*
* <p>
* Dynamic resolution options controls whether dynamic resolution is enabled, and if it is,
* how it behaves.
* </p>
*
* <p>
* If you wish subsequent changes to take effect please call this method again in order to
* propagate the changes down to the native layer.
* </p>
*
* @param options The dynamic resolution options to use on this view
*/
public void setDynamicResolutionOptions(@NonNull DynamicResolutionOptions options) {
mDynamicResolution = options;
nSetDynamicResolutionOptions(getNativeObject(),
@@ -222,9 +719,14 @@ public class View {
options.scaleRate,
options.minScale,
options.maxScale,
options.history);
options.history,
options.quality.ordinal());
}
/**
* Returns the dynamic resolution options associated with this view.
* @return value set by {@link #setDynamicResolutionOptions}.
*/
@NonNull
public DynamicResolutionOptions getDynamicResolutionOptions() {
if (mDynamicResolution == null) {
@@ -233,11 +735,20 @@ public class View {
return mDynamicResolution;
}
/**
* Sets the rendering quality for this view (e.g. color precision).
*
* @param renderQuality The render quality to use on this view
*/
public void setRenderQuality(@NonNull RenderQuality renderQuality) {
mRenderQuality = renderQuality;
nSetRenderQuality(getNativeObject(), renderQuality.hdrColorBuffer.ordinal());
}
/**
* Returns the render quality used by this view.
* @return value set by {@link #setRenderQuality}.
*/
@NonNull
public RenderQuality getRenderQuality() {
if (mRenderQuality == null) {
@@ -246,50 +757,129 @@ public class View {
return mRenderQuality;
}
@NonNull
public DepthPrepass getDepthPrepass() {
return mDepthPrepass;
}
public void setDepthPrepass(@NonNull DepthPrepass depthPrepass) {
mDepthPrepass = depthPrepass;
nSetDepthPrepass(getNativeObject(), depthPrepass.value);
}
/**
* Returns true if post-processing is enabled.
*
* @see #setPostProcessingEnabled
*/
public boolean isPostProcessingEnabled() {
return nIsPostProcessingEnabled(getNativeObject());
}
/**
* Enables or disables post processing. Enabled by default.
*
* <p>Post-processing includes:</p>
* <ul>
* <li>Tone-mapping & gamma encoding</li>
* <li>Dithering</li>
* <li>MSAA</li>
* <li>FXAA</li>
* <li>Dynamic scaling</li>
* </ul>
*
* <p>
* Disabling post-processing forgoes color correctness as well as anti-aliasing and
* should only be used experimentally (e.g., for UI overlays).
* </p>
*
* @param enabled true enables post processing, false disables it
*
* @see #setToneMapping
* @see #setAntiAliasing
* @see #setDithering
* @see #setSampleCount
*/
public void setPostProcessingEnabled(boolean enabled) {
nSetPostProcessingEnabled(getNativeObject(), enabled);
}
/**
* Returns true if post-processing is enabled.
*
* @see #setPostProcessingEnabled
*/
public boolean isFrontFaceWindingInverted() {
return nIsFrontFaceWindingInverted(getNativeObject());
}
/**
* Inverts the winding order of front faces. By default front faces use a counter-clockwise
* winding order. When the winding order is inverted, front faces are faces with a clockwise
* winding order.
*
* Changing the winding order will directly affect the culling mode in materials
* (see Material#getCullingMode).
*
* Inverting the winding order of front faces is useful when rendering mirrored reflections
* (water, mirror surfaces, front camera in AR, etc.).
*
* @param inverted True to invert front faces, false otherwise.
*/
public void setFrontFaceWindingInverted(boolean inverted) {
nSetFrontFaceWindingInverted(getNativeObject(), inverted);
}
/**
* Sets options relative to dynamic lighting for this view.
*
* <p>
* Together <code>zLightNear</code> and <code>zLightFar</code> must be chosen so that the
* visible influence of lights is spread between these two values.
* </p>
*
* @param zLightNear Distance from the camera where the lights are expected to shine.
* This parameter can affect performance and is useful because depending
* on the scene, lights that shine close to the camera may not be
* visible -- in this case, using a larger value can improve performance.
* e.g. when standing and looking straight, several meters of the ground
* isn't visible and if lights are expected to shine there, there is no
* point using a short zLightNear. (Default 5m).
*
* @param zLightFar Distance from the camera after which lights are not expected to be visible.
* Similarly to zLightNear, setting this value properly can improve
* performance. (Default 100m).
*
*/
public void setDynamicLightingOptions(float zLightNear, float zLightFar) {
nSetDynamicLightingOptions(getNativeObject(), zLightNear, zLightFar);
}
/**
* Activates or deactivates ambient occlusion.
*
* @param ao Type of ambient occlusion to use.
*/
public void setAmbientOcclusion(@NonNull AmbientOcclusion ao) {
nSetAmbientOcclusion(getNativeObject(), ao.ordinal());
}
/**
* Queries the type of ambient occlusion active for this View.
*
* @return ambient occlusion type.
*/
@NonNull
public AmbientOcclusion getAmbientOcclusion() {
return AmbientOcclusion.values()[nGetAmbientOcclusion(getNativeObject())];
}
/**
* Sets ambient occlusion options.
*
* @param options Options for ambient occlusion.
*/
public void setAmbientOcclusionOptions(@NonNull AmbientOcclusionOptions options) {
mAmbientOcclusionOptions = options;
nSetAmbientOcclusionOptions(getNativeObject(), options.radius, options.bias, options.power, options.resolution);
nSetAmbientOcclusionOptions(getNativeObject(), options.radius, options.bias, options.power,
options.resolution, options.intensity, options.quality.ordinal());
}
/**
* Gets the ambient occlusion options.
*
* @return ambient occlusion options currently set.
*/
@NonNull
public AmbientOcclusionOptions getAmbientOcclusionOptions() {
if (mAmbientOcclusionOptions == null) {
@@ -298,6 +888,46 @@ public class View {
return mAmbientOcclusionOptions;
}
/**
* Sets bloom options.
*
* @param options Options for bloom.
*/
public void setBloomOptions(@NonNull BloomOptions options) {
mBloomOptions = options;
nSetBloomOptions(getNativeObject(), options.dirt != null ? options.dirt.getNativeObject() : 0,
options.dirtStrength, options.strength, options.resolution,
options.anamorphism, options.levels, options.blendingMode.ordinal(),
options.threshold, options.enabled);
}
/**
* Sets fog options.
*
* @param options Options for fog.
*/
public void setFogOptions(@NonNull FogOptions options) {
mFogOptions = options;
nSetFogOptions(getNativeObject(), options.distance, options.maximumOpacity, options.height,
options.heightFalloff, options.color[0], options.color[1], options.color[2],
options.density, options.inScatteringStart, options.inScatteringSize,
options.fogColorFromIbl,
options.enabled);
}
/**
* Gets the bloom options
*
* @return bloom options currently set.
*/
@NonNull
public BloomOptions getBloomOptions() {
if (mBloomOptions == null) {
mBloomOptions = new BloomOptions();
}
return mBloomOptions;
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed View");
@@ -330,15 +960,17 @@ public class View {
private static native void nSetDynamicResolutionOptions(long nativeView,
boolean enabled, boolean homogeneousScaling,
float targetFrameTimeMilli, float headRoomRatio, float scaleRate,
float minScale, float maxScale, int history);
float minScale, float maxScale, int history, int quality);
private static native void nSetRenderQuality(long nativeView, int hdrColorBufferQuality);
private static native void nSetDynamicLightingOptions(long nativeView, float zLightNear, float zLightFar);
private static native void nSetDepthPrepass(long nativeView, int value);
private static native void nSetPostProcessingEnabled(long nativeView, boolean enabled);
private static native boolean nIsPostProcessingEnabled(long nativeView);
private static native void nSetFrontFaceWindingInverted(long nativeView, boolean inverted);
private static native boolean nIsFrontFaceWindingInverted(long nativeView);
private static native void nSetAmbientOcclusion(long nativeView, int ordinal);
private static native int nGetAmbientOcclusion(long nativeView);
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution);
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution, float intensity, int quality);
private static native void nSetBloomOptions(long nativeView, long dirtNativeObject, float dirtStrength, float strength, int resolution, float anamorphism, int levels, int blendMode, boolean threshold, boolean enabled);
private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, boolean enabled);
}

View File

@@ -16,8 +16,18 @@
package com.google.android.filament;
import android.support.annotation.IntRange;
import androidx.annotation.IntRange;
/**
* Specifies a rectangular region within a render target in terms of pixel coordinates.
*
* <p>
* The rectangle spans from <code>(left,bottom)</code> to <code>(left+width-1, top+height-1)</code>,
* inclusive. Width and height must be non-negative.
* </p>
*
* @see View#setViewport
*/
public class Viewport {
public Viewport(int left, int bottom, @IntRange(from = 0) int width, @IntRange(from = 0) int height) {
this.left = left;

View File

@@ -17,8 +17,8 @@
package com.google.android.filament.android;
import android.graphics.Bitmap;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.google.android.filament.Engine;
import com.google.android.filament.Texture;
@@ -34,21 +34,6 @@ public final class TextureHelper {
private static final int BITMAP_CONFIG_RGBA_F16 = 4;
private static final int BITMAP_CONFIG_HARDWARE = 5;
private static Method sEngineGetNativeObject;
private static Method sTextureGetNativeObject;
static {
try {
sEngineGetNativeObject = Engine.class.getDeclaredMethod("getNativeObject");
sTextureGetNativeObject = Texture.class.getDeclaredMethod("getNativeObject");
sEngineGetNativeObject.setAccessible(true);
sTextureGetNativeObject.setAccessible(true);
} catch (NoSuchMethodException e) {
// Cannot happen
}
}
private TextureHelper() {
}
@@ -69,14 +54,10 @@ public final class TextureHelper {
throw new IllegalArgumentException("Unsupported config: ARGB_4444 or HARDWARE");
}
try {
long nativeTexture = (Long) sTextureGetNativeObject.invoke(texture);
long nativeEngine = (Long) sEngineGetNativeObject.invoke(engine);
nSetBitmap(nativeTexture, nativeEngine, level, xoffset, yoffset, width, height,
bitmap, format);
} catch (Exception e) {
// Ignored
}
long nativeTexture = texture.getNativeObject();
long nativeEngine = engine.getNativeObject();
nSetBitmap(nativeTexture, nativeEngine, level, xoffset, yoffset, width, height,
bitmap, format);
}
private static int toNativeFormat(Bitmap.Config config) {

View File

@@ -18,15 +18,15 @@ package com.google.android.filament.android;
import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import com.google.android.filament.SwapChain;
/**
@@ -99,10 +99,6 @@ import com.google.android.filament.SwapChain;
* // 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();
* }
*
@@ -135,6 +131,7 @@ public class UiHelper {
private RenderSurface mRenderSurface;
private boolean mOpaque = true;
private boolean mOverlay = false;
/**
* Enum used to decide whether UiHelper should perform extra error checking.
@@ -177,7 +174,7 @@ public class UiHelper {
void detach();
}
private class SurfaceViewHandler implements RenderSurface {
private static class SurfaceViewHandler implements RenderSurface {
private SurfaceView mSurfaceView;
SurfaceViewHandler(SurfaceView surface) {
@@ -327,6 +324,30 @@ public class UiHelper {
mOpaque = opaque;
}
/**
* Returns true if the SurfaceView used as a render target should be positioned above
* other surfaces but below the activity's surface. False by default.
*/
public boolean isMediaOverlay() {
return mOverlay;
}
/**
* Controls whether the surface of the SurfaceView used as a render target should be
* positioned above other surfaces but below the activity's surface. This property
* only has an effect when used in combination with {@link #setOpaque(boolean) setOpaque(false)}
* and does not affect TextureView targets.
*
* Must be called before calling {@link #attachTo(SurfaceView)}
* or {@link #attachTo(TextureView)}.
*
* @param overlay Indicates whether the render target should be rendered below the activity's
* surface when transparent.
*/
public void setMediaOverlay(boolean overlay) {
mOverlay = overlay;
}
/**
* Returns the flags to pass to
* {@link com.google.android.filament.Engine#createSwapChain(Object, long)} to honor all
@@ -344,11 +365,18 @@ public class UiHelper {
*/
public void attachTo(@NonNull SurfaceView view) {
if (attach(view)) {
if (!isOpaque()) {
view.setZOrderOnTop(true);
view.getHolder().setFormat(PixelFormat.TRANSLUCENT);
boolean translucent = !isOpaque();
// setZOrderOnTop() and setZOrderMediaOverlay() override each other,
// we must only call one of them
if (isMediaOverlay()) {
view.setZOrderMediaOverlay(translucent);
} else {
view.setZOrderOnTop(translucent);
}
int format = isOpaque() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
view.getHolder().setFormat(format);
mRenderSurface = new SurfaceViewHandler(view);
final SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
@@ -381,7 +409,6 @@ public class UiHelper {
final Surface surface = holder.getSurface();
if (surface != null && surface.isValid()) {
callback.surfaceCreated(holder);
int format = isOpaque() ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
callback.surfaceChanged(holder, format,
holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
}

View File

@@ -26,16 +26,14 @@ import java.lang.annotation.Target;
*
* Note that adding this annotation to a method is not enough to guarantee that
* it is kept - either its class must be referenced elsewhere in the program, or
* the class must be annotated with this as well.
* the class must be annotated with this as well. Usage example:
* <pre>
*
* Usage example:<br />
* {@code
* @UsedByNative("NativeCrashHandler.cpp")
public static void reportCrash(int signal, int code, int address) {
...
}
}
* &commat;UsedByNative("NativeCrashHandler.cpp")
* public static void reportCrash(int signal, int code, int address) {
* ...
* }
* </pre>
*/
@Target({
ElementType.METHOD,

View File

@@ -26,16 +26,14 @@ import java.lang.annotation.Target;
*
* Note that adding this annotation to a method is not enough to guarantee that
* it is kept - either its class must be referenced elsewhere in the program, or
* the class must be annotated with this as well.
* the class must be annotated with this as well. Usage example:
* <pre>
*
* Usage example:<br />
* {@code
* @UsedByReflection("PeopleListItemView.java")
public PeopleListItemViewV11(Context context) {
super(context);
}
}
* &commat;UsedByReflection("PeopleListItemView.java")
* public PeopleListItemViewV11(Context context) {
* super(context);
* }
* </pre>
*/
@Target({
ElementType.METHOD,

Some files were not shown because too many files have changed in this diff Show More