Compare commits

...

731 Commits

Author SHA1 Message Date
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
prideout
dc062305b9 Bump to 1.3.2 2019-08-26 14:07:14 -07:00
Philip Rideout
bc94269e73 matdbg: fix a warning when building civetweb. 2019-08-26 12:37:38 -07:00
Philip Rideout
876534330a matdbg: add more info to the details panel. 2019-08-23 16:43:16 -07:00
Philip Rideout
2af8ef81b3 matdbg: add required attributes. 2019-08-23 16:43:16 -07:00
Philip Rideout
8da553db58 matdbg: fix active shader highlight. 2019-08-23 16:43:16 -07:00
Philip Rideout
83e9857b30 matdbg: remove bogus hrefs from anchors. 2019-08-23 16:43:16 -07:00
Philip Rideout
088ed2d472 matdbg: make mat list and shader list scrollable. 2019-08-23 16:43:16 -07:00
Ben Doherty
c826b03411 Break driver dependency on Texture.h (#1549) 2019-08-23 16:13:24 -07:00
Benjamin Doherty
f1257994d1 Disable DirIncluder tests 2019-08-23 13:31:20 -07:00
Benjamin Doherty
efb9e005b2 Fix build due to DirIncluder test 2019-08-23 12:40:47 -07:00
Romain Guy
6f30ff31c8 Fix warnings 2019-08-23 11:55:06 -07:00
Romain Guy
d0f38c2d5d Update Gradle, AGP and Kotlin 2019-08-23 11:52:30 -07:00
Ben Doherty
d4943cc70b Add #include preprocessing to filamat and matc (#1541)
* Add #include preprocessing to filamat and matc

* Update RELEASE_NOTES

* Fix RELEASE_NOTES

* Use final instead of virtual / override

* Clarify comments

* Use pure virtual for includer functions

* Use a callback instead of an interface

* Rename Includer.h to IncludeCallback.h

* Update comment
2019-08-23 11:10:36 -07:00
Ben Doherty
9a47ea1ef0 Fix Tungsten build (#1548) 2019-08-23 11:08:27 -07:00
Romain Guy
ac33331fd6 Update documentation to fix typos 2019-08-23 10:58:08 -07:00
Philip Rideout
a65998bbc1 Fix Linux build, hopefully. 2019-08-23 10:16:22 -07:00
Philip Rideout
5120c18977 Update third_party/cgltf to latest. 2019-08-23 09:50:08 -07:00
Philip Rideout
21347eaa88 Fix build break, re-enable DebugServer. 2019-08-23 09:49:57 -07:00
Philip Rideout
a191cc8171 Fix build break. 2019-08-22 17:07:34 -07:00
Philip Rideout
ad3d823fa3 matdbg: Use Variant enum. 2019-08-22 16:12:20 -07:00
Philip Rideout
8d7c00b0d9 matdbg: add DebugServer class.
matdbg is now linked into the Filament Engine in debug config (allowing
live inspection of GLSL / SPIRV) and into the matinfo tool (to support
the --web-server option).

In both cases, the library spins up a small web server that listens to
http://localhost:8080. You can run any Filament app and attach to it.

The web client caches all material information. This allows the user to
close an atttached Filament app, and the web app will continue to
function properly (useful for crash diagnosis). Moreover the user can
launch a second Filament app and the web client will add its materials
to the existing list (useful when comparing two Filament apps).

For now this only supports inspection, not editing. Some of the material
info such as required attributes is not yet displayed but this will be
easy to flesh out in a subsequent PR.
2019-08-22 16:12:20 -07:00
Ben Doherty
99d9ea73ac Fix potential Metal memory leak (#1542) 2019-08-22 14:15:39 -07:00
Philip Rideout
c4b0edbfe3 Introduce matdbg library, simplify matinfo.
This moves some of the matinfo functionality into a library which will
soon have an embedded web server.
2019-08-22 08:11:06 -07:00
Philip Rideout
6d74d31ecd Add civetweb to third_party (MIT).
This is a dependency of our upcoming web-based material debugger. This
CL also includes `tnt/CMakeLists.txt`, which builds a static lib in a
minimal configuration that enables WebSocket support. The entire library
is built from only 4 files:

    ${PUBLIC_HDR_DIR}/CivetServer.h
    ${PUBLIC_HDR_DIR}/civetweb.h
    ${SRC_DIR}/civetweb.c
    ${SRC_DIR}/CivetServer.cpp
2019-08-21 17:45:37 -07:00
Ben Doherty
bd22bed2fb Fix Windows test cases (#1537) 2019-08-20 15:36:22 -07:00
Ben Doherty
f8aa17c245 Preallocate uniform buffers in Metal (#1528)
* Preallocate uniform buffers in Metal

* Allocate empty uniform at draw time

* Remove unnecessary return
2019-08-19 15:37:13 -07:00
Ben Doherty
6ba20f29d4 Fix normal mapping with skinning or morphing in Metal (#1530) 2019-08-16 17:24:01 -07:00
Philip Rideout
95ef8d85db Minor fixup to suzanne Vulkan demo. 2019-08-16 17:04:32 -07:00
Mathias Agopian
eca381a5be Rename fg::Resource to fg::TextureResource 2019-08-15 16:58:58 -07:00
Mathias Agopian
ea47f0bd87 simplify how we determine if a resource is sample-able 2019-08-15 16:58:58 -07:00
Mathias Agopian
b849008ce5 rename useRenderTarget to createRenderTarget 2019-08-15 16:58:58 -07:00
Mathias Agopian
5389ac963f framegraph: useRenderTarget() doesn't set access anymore
access to resources now needs to be done explicitly before calling
useRenderTarget(). This simplifies things and is needed for more
simplifications to come.
2019-08-15 16:58:58 -07:00
Mathias Agopian
0fd16d760a refactor/cleanup of FrameGraph code
this change mostly puts all internal classes into their own file,
making FrameGraph.cpp much smaller and easier to deal with
2019-08-15 16:58:58 -07:00
Philip Rideout
6754e80c75 gltfio: Minor cleanup. 2019-08-15 14:29:07 -07:00
Benjamin Doherty
fb95d8e7a4 debug 2019-08-14 18:13:57 -07:00
Benjamin Doherty
40efd5fd23 More debug 2019-08-14 18:13:57 -07:00
Benjamin Doherty
d440775775 debug 2019-08-14 18:13:57 -07:00
Benjamin Doherty
e1d9f26dbd Try keyserver 2019-08-14 18:13:57 -07:00
Benjamin Doherty
ee048d259f Try to fix broken Linux and Android CI 2019-08-14 18:13:57 -07:00
Philip Rideout
d7e5f2c26b Web: remove more &free callbacks.
It is not safe to take the address of a stdlib function with emscripten,
this causes an intermittent crash in the WebGL backend.
2019-08-14 15:14:49 -07:00
Philip Rideout
c11a61aa15 Web: add setBoolParameter, fixes #1499. 2019-08-14 13:05:17 -07:00
Philip Rideout
b859b57797 matc, matinfo et al: improve diagnostic output
This enhances the exisiting matc option "--debug" so that it includes
debug information in the resulting SPIR-V.

Previously we tied this to the build configuration which isn't very
flexible. Moreover this needs to be orthogonal to shader opts, because
we often need to debug problems that arise from optimization.

This CL also gives meaningful names to the ubershader materials and
fixes up the new matinfo analysis so that it prints the entire SPIRV
chunk that corresponds to each potentially problematic GLSL codeline.

Motivated by #1516.
2019-08-14 13:01:43 -07:00
Mathias Agopian
76cca21c65 most StructureOfArray<> methods cannot be constexpr
This is because we can't create a constexpr SoA in the first place,
and it wouldn't be very useful if we could.

This change ripples into users of SoA.
2019-08-13 18:29:15 -07:00
Philip Rideout
a09c3b154a Fix paths in android glTF demo. 2019-08-13 12:47:08 -07:00
Philip Rideout
2460f9e721 Better Adreno workaround for #1096.
This is an improved workaround for a known limitation with Vulkan
drivers on Android P. The offending SPIR-V sequence was introduced
during shader optimization and can be avoided by using full precision
for certain variables.
2019-08-13 11:36:59 -07:00
Mathias Agopian
d30429e891 make getNativeObject() public
this allows mixed java/native apps to use filament objects on both
sides more easily
2019-08-12 21:56:49 -07:00
Ben Doherty
c23c3d48b2 Remove unusued function (#1508) 2019-08-12 15:17:05 -07:00
Philip Rideout
046809cee0 Use --quiet when invoking cmgen in build. 2019-08-12 14:59:46 -07:00
Philip Rideout
c9750dd633 Fix gradle bug that created junk folder. 2019-08-12 13:41:52 -07:00
Philip Rideout
18a0bd70fb Restore accidental removal of Adreno workaround. 2019-08-12 11:42:16 -07:00
Philip Rideout
38955a91e5 matinfo: fix ordering of analyze-spirv output. 2019-08-12 11:40:36 -07:00
Mathias Agopian
eac2ad7e05 fix some lint warnings in Hash.h 2019-08-12 11:09:24 -07:00
Philip Rideout
5df53f733e Add error message to matinfo. 2019-08-12 10:45:44 -07:00
Romain Guy
50abcf6bfa Don't check for NDK side-by-side if ndk bundle is found 2019-08-12 10:22:06 -07:00
Philip Rideout
4d41b83448 Minor fixups in TypeScript annotations. 2019-08-12 09:13:46 -07:00
Philip Rideout
d2324d253c filamat: when building debug, use verbose SPIR-V. 2019-08-12 09:12:59 -07:00
Philip Rideout
cf9e87a892 matinfo: add SPIR-V analysis functionality
This adds a new option to matinfo that does some very dumb regex-based
analysis on the disassembled SPIR-V, then dumps out transpiled GLSL
that has annotations added to the end of some codelines. For example:

```glsl
float luminance(vec3 linear) // POTENTIAL MIXED PRECISION %49 = OpDot %float %linear %48; relaxed = %49 %linear
{
    return dot(linear, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
}
```

The code currently tries to find potential mixed precision but does not
do the right thing yet for pointers and structs. This is just a starting
point to help diagnose problem areas in our generated SPIR-V.
2019-08-12 09:12:59 -07:00
Romain Guy
829db244f2 Add support for side-by-side NDK (#1505) 2019-08-11 17:36:49 -07:00
Gregory Popovitch
772af1e897 More fixes for building with vs2019/msvc (#1500)
* Update Froxelizer.h

Fix this error when building with msvc from vs2019
error C2926:  'filament::details::Froxelizer::FroxelEntry::<unnamed-tag>::offset': a default member initializer is not allowed for a member of an anonymous struct within a union

* Fix some compilation issues with vs2019/msvc

Program.cpp:
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): error C2610:  'filament::backend::Program::Program(void) noexcept': is not a special member function or comparison operator which can be defaulted
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): message :  exception specification does not match the implicitly declared specification.

GLUtils.h: __PRETTY_FUNCTION__ macro is clang specific. Use MSVC equivalent

Color.h: fix warning

* #1493 - inline constructor in definition as requested by @romainguy

* #1493  "move this #define inside the #else below" as requested

* #1493 revert last change which causes compilation failures on other platforms.

provide empty implementation of Program::Program() in Program.cpp

* More fixes for building with vs2019/msvc

* #1500 use consistent macro definition syntax (@bejado)

* #1500 simplify DEBUG_COMMAND macro as requested by @pixelflinger

* #1500 use `{ 0 }` which is accepted by Visual Studio  (` = 0 ` is not accepted)

* #1500 remove incorrect UTILS_RESTRICT alltogether
2019-08-09 16:38:31 -07:00
Romain Guy
52a8f50539 Fix backface issue in lit-cube sample 2019-08-09 16:10:12 -07:00
Mathias Agopian
9f1cadf77a remplace multimap by a vector for the framegraph texture cache
because we don't expect many items in the cache, using a linear
search is not a problem -- multimap generates tons of code 
by comparison.
2019-08-09 15:36:40 -07:00
Mathias Agopian
308935d706 fix framegraph test 2019-08-09 15:36:40 -07:00
Mathias Agopian
67f75f0ecf reformatting 2019-08-09 15:07:12 -07:00
Mathias Agopian
f728776714 better normal transforms
We use the cofactors to transform normals, which preserves its
direction, unlike of the inverse-transpose method.
2019-08-09 15:07:12 -07:00
Mathias Agopian
10259f80f4 Add support for det() and cof()
Respectively computing the determinant and cofactors of a matrix.
2019-08-09 15:07:12 -07:00
Mathias Agopian
c65239aec2 Implement a basic Texture cache for the framegraph
We're only caching textures (not render targets yet), and we're
evicting cache entries older than 30 allocations.

This should cut down on texture allocation / gl calls.

The cache should get in a stable state very quickly (less than half
second).
2019-08-09 15:01:04 -07:00
Philip Rideout
0bd9515b3d Add getWorldOffset() shader API, enhance docs.
This allows advanced shader authors like myself to get coordinates
in the API level world space.

Fixes #1485.
2019-08-09 08:28:28 -07:00
Ben Doherty
442315aaa8 Silence Metal shader compilation warnings (#1496) 2019-08-08 18:07:01 -07:00
Gregory Popovitch
614a7d6de8 Fix some compilation issues with vs2019/msvc (#1493)
* Update Froxelizer.h

Fix this error when building with msvc from vs2019
error C2926:  'filament::details::Froxelizer::FroxelEntry::<unnamed-tag>::offset': a default member initializer is not allowed for a member of an anonymous struct within a union

* Fix some compilation issues with vs2019/msvc

Program.cpp:
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): error C2610:  'filament::backend::Program::Program(void) noexcept': is not a special member function or comparison operator which can be defaulted
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): message :  exception specification does not match the implicitly declared specification.

GLUtils.h: __PRETTY_FUNCTION__ macro is clang specific. Use MSVC equivalent

Color.h: fix warning

* #1493 - inline constructor in definition as requested by @romainguy

* #1493  "move this #define inside the #else below" as requested

* #1493 revert last change which causes compilation failures on other platforms.

provide empty implementation of Program::Program() in Program.cpp
2019-08-08 17:03:26 -07:00
Philip Rideout
d28189c173 Repaired broken npm package. 2019-08-08 13:27:52 -07:00
Ben Doherty
dc75c10014 Update Xcode projects for KTX build step (#1495) 2019-08-08 11:39:13 -07:00
Philip Rideout
91ff1d87eb Replace prebuilt KTX with a build step.
This removes the samples/envs folder and replaces these KTX files with a
build step that is driven by CMake / gradle / bash, depending on
platform.

This makes it easier to use IBL files that are generated by the latest
and greatest version of cmake.
2019-08-08 10:41:13 -07:00
Ben Doherty
6b415273ba Add isTextureFormatMipmappable driver query (#1491) 2019-08-08 09:54:03 -07:00
Philip Rideout
4ce2a03f64 Update release notes before v1.3.1 2019-08-08 09:44:19 -07:00
Philip Rideout
f67a71d849 Fix web build, third attempt. 2019-08-08 09:22:05 -07:00
Gregory Popovitch
55d8d93be9 Update Froxelizer.h (#1489)
Fix this error when building with msvc from vs2019
error C2926:  'filament::details::Froxelizer::FroxelEntry::<unnamed-tag>::offset': a default member initializer is not allowed for a member of an anonymous struct within a union
2019-08-07 17:44:39 -07:00
Romain Guy
5d57dee18d Add API to enable/disable shadows on a light (#1492) 2019-08-07 17:39:33 -07:00
Philip Rideout
1d1a0c16ba Quick fix for web build, second attempt. 2019-08-07 16:11:40 -07:00
Philip Rideout
71e2434717 Fix web builds on Kokoro. 2019-08-07 15:11:00 -07:00
Benjamin Doherty
f876e6165f Assert that Metal textures are created 2019-08-07 09:51:50 -07:00
Benjamin Doherty
54e224e9fa Label Metal command queue 2019-08-07 09:51:50 -07:00
Philip Rideout
8e76259bac Fix web builds on Kokoro. 2019-08-07 07:40:19 -07:00
Mathias Agopian
13224d9c6e laying the foundations for a rendertarget cache
Some drivers have performance issues when repeatedly (once per frame)
allocating and destroying render targets, so we will
re-introduce a cache for that.

this just adds the hooks for the cache.
2019-08-06 18:17:08 -07:00
Philip Rideout
34ef2a871f Stop using compressed IBL's in more places.
We use R11F_G11F_B10F for HDR so we should stop checking for compressed
IBL files.

Also, make the glTF sample on web more consistent with the default
settings used by gltf_viewer on native and use venetian_crossroads
instead of syferfontein.
2019-08-06 16:18:51 -07:00
Philip Rideout
6f143b1b54 Fix wasm by avoiding the "&free" trick.
We should not use the address of a stdlib function for BufferDescriptor
callbacks. With emcc this compiles without warnings or errors, but
produces incorrect code that causes intermittent out-of-memory errors at
run time.
2019-08-06 15:03:48 -07:00
Philip Rideout
46e85804b1 Disable jsdocs to fix Kokoro. 2019-08-06 13:28:49 -07:00
Philip Rideout
0fe8035309 gltfio: allow names to be queried.
Fixes #1425.
2019-08-06 12:54:29 -07:00
Philip Rideout
b3feafe320 Enable shadows in helmet demo. 2019-08-06 11:28:00 -07:00
Philip Rideout
ec623e7c1b Add IndirectLight queries to JavaScript / TypeScript. 2019-08-06 09:14:28 -07:00
Mathias Agopian
a38f2754ce Add children iterators to TransformManager (C++ only) 2019-08-04 23:16:54 -07:00
Mathias Agopian
932d2746f3 fix typo 2019-08-04 23:16:34 -07:00
Mathias Agopian
e176dea383 Add API to extract the color/intensity of the IBL dominant light 2019-08-04 23:16:34 -07:00
Hendrik Wagenaar
8f15964ee6 Use GL_EXTENSION for GL_OES_EGL_image_external_essl3 (#1471)
* Use GL_EXTENSION for GL_OES_EGL_image_external_essl3

A prior change that reworked some code incorrectly attempted to
use the existing EGL extensions to set a GL extension boolean.

Added additional GL extension code.

* Fix typo

* Fix typo
2019-08-01 17:17:36 -07:00
Romain Guy
53a12c3f01 Add flower_road envmap with the sun removed 2019-08-01 16:37:06 -07:00
Romain Guy
2c953b9f08 Add the sun instead of blending it (#1470) 2019-08-01 15:19:18 -07:00
Mathias Agopian
b1cdd5452f API to query the direction of the IBL
Initialized the directional light direction to the
IBL direction in material_sandbox and gltf_viewer.
2019-08-01 12:49:40 -07:00
Hendrik Wagenaar
cb66324095 OpenGL: Avoid unresolves on render pass (#1469)
Avoid enabling scissors when the viewport is the same size as the
buffer. On Adreno devices, running clearWithGeometryPipe adds
three additional unresolves for each bin.
2019-08-01 10:26:27 -07:00
prideout
b16dc443ff Do not bind materials outside of a render pass. (affects GL) 2019-07-31 16:35:55 -07:00
Mathias Agopian
8798d367c5 fix some doxygen comments 2019-07-31 15:47:30 -07:00
prideout
c9921cac3d Vulkan: fix issue with mipmapped render targets.
VkFramebuffer requires its attachments to have only one miplevel each,
but our VulkanRenderTarget wrapper was sharing the VkImageView that
associated with the underlying texture object.

This fixes up VulkanRenderTarget so that it owns a unique VkImageView
that is pinned to a specific miplevel.
2019-07-31 15:18:04 -07:00
prideout
485711f7c6 gltfio now uses FADE when the asset is BLEND.
Fixes #1461
2019-07-31 12:36:11 -07:00
prideout
81df9dd705 Desktop samples should not link Embree.
We now build three gltfio libraries:

 - gltfio_core ....... lightweight library with ubershaders
 - gltfio ............ uses filamat to generate materials at runtime
 - gltfio_pipeline ... depends on path tracer functionality
2019-07-31 12:05:22 -07:00
@roxlu ☾
0faa391470 Copy GLXFBConfig from shared context. (#1456)
* Copy GLXFBConfig from shared context.

* Style fixes
2019-07-31 09:30:45 -07:00
prideout
cd59d6cd23 Fix VulkanDriver query for the DEPTH24 format.
This fixes one of the bugs seen with `gltf-bloom` on Android.

We already dynamically map Filament's DEPTH24 format to either
VK_FORMAT_D32_SFLOAT or VK_FORMAT_X8_D24_UNORM_PACK32, depending on
the platform. Therefore we should return `true` when asked if the
backend supports DEPTH24. Otherwise the client will not be able to
create a depth texture.
2019-07-30 14:32:37 -07:00
prideout
d46ba48293 Build tweaks for Android.
(1) Sometimes (but not always!) gltfio-android was failing to build due
to two missing ANativeWindow functions. Linking in "android" seems to
fix this, and is consistent with libfilament-jni.

(2) Improve our "build.sh -c" utility by clobbering some additional
Android build directories. This is especially useful after
adding "-Pextra_cmake_args=-DFILAMENT_SUPPORTS_VULKAN=ON", otherwise
Gradle will try to use a cached CMake configuration.
2019-07-30 10:53:17 -07:00
Romain Guy
7d84f97dc1 Add function to compute the Fresnel Lazanyi term 2019-07-30 10:38:42 -07:00
Philip Rideout
3263c46355 Add morphing support to gltfio.
Issue #1149, #1417
2019-07-30 10:20:50 -07:00
prideout
44c7d3ac34 Add workaround for Adreno Vulkan shader bug.
Fixes #1096.
2019-07-30 10:20:21 -07:00
prideout
7dad09dbc4 Fix VulkanRenderTarget attachment ref counts.
By design, VulkanRenderTarget has weak references to its attachments and
does not manage any hardware resources. Therefore, when we start
rendering to a particular render target, we need to inform
VulkanDisposer that the command buffer has acquired a reference to the
underlying textures. This prevents the possibility of the texture being
destroyed while still in use.

This fixes #1450 although we should also add a render target pool for
best performance.
2019-07-29 14:39:57 -07:00
prideout
401bc4b486 Fix warning. 2019-07-29 11:10:21 -07:00
Philip Rideout
2b1f9290a4 Fix skinning regression (uninitialized bytes in UBO).
Fix #1440.
2019-07-29 13:37:46 -04:00
Philip Rideout
90c17ccbad Filament now supports GPU vertex morphing.
This works by aliasing CUSTOM0 - CUSTOM7 to morphing attributes, and by
extending our existing skinning variant.

This PR was tested against some upcoming changes to gltfio.

Issue #1149, #1417
2019-07-26 17:53:46 -04:00
Ben Doherty
f8f947addb Handle missing vertex attributes in Metal backend (#1442) 2019-07-26 14:44:34 -07:00
Romain Guy
85449a08fb Give specular-color the ability to compute f82 (or other angles) (#1443) 2019-07-26 08:56:24 -10:00
Ben Doherty
115ce0cb42 Delete empty file 2019-07-25 17:56:56 -07:00
Romain Guy
edc2b49196 Add Mathematica notebook for an improved Fresnel term 2019-07-25 16:28:31 -07:00
Ben Doherty
a47b5c21cf Update SPIRV-Cross (#1439) 2019-07-24 16:26:24 -07:00
Ben Doherty
ada148b819 Add OpenGL scheme to hello-ar (#1437) 2019-07-24 15:49:31 -07:00
Romain Guy
5d5d9af4df Remove trailing semi-colon 2019-07-23 21:20:56 -07:00
Mathias Agopian
064441732e Add support for RGBA buffer formats in Texture::generatePrefilterMipmap 2019-07-23 16:01:57 -07:00
Romain Guy
7b80b31365 Remove unused parameter 2019-07-23 10:04:18 -07:00
Ben Doherty
b439ddc5f4 Implement external images for iOS / OpenGL (#1391) 2019-07-23 09:52:24 -07:00
Ben Doherty
5b9351354a Ensure structs used as Metal state keys have no compiler-generated padding (#1433) 2019-07-23 09:49:00 -07:00
Pixelflinger
9bcf10cf44 fix thread count initialization
if hw thread count was 1, we'd end-up with 32 threads
2019-07-22 13:01:53 -07:00
Ben Doherty
ff72598b7d Update Material class to handle both surface and post-process materials (#1410) 2019-07-19 12:24:18 -07:00
Pixelflinger
79aeaf3250 added an option to turn of pre-filtering in cmgen
When processing very high dynamic range environments, the importance
sampling code falls appart, it becomes a user choice to decide if
prefilter importance sampling is better or worse than just regular
importance sampling -- both are usually bad.

--ibl-no-prefilter gives the user this choice.
2019-07-19 10:57:48 -07:00
Pixelflinger
261dafa924 Fix a possible infinite loop
In the case where we have 2 cores, we would spawn only one thread in
the thread pool. If that thread got to try to steal() from another
thread before the main thread was adopted, it would end-up always
trying to steal from itself and enter an infinite loop.

This seems to happen during windows builds.
2019-07-19 10:56:41 -07:00
Philip Rideout
90792e7032 Fix upper limit on vertex attributes.
This combines two constants into one, and changes it into a value that
is actually correct.  :)

Technically the movement of the CUSTOM attributes will change the layout
qualifier and therefore merits a materials version bump, however custom
attributes were only recently introduced so this seems unnecessary.

Did some quick testing with 3 samples: gltf_viewer, lucy_bloom, and
point_sprites.
2019-07-18 17:10:16 -07:00
Mathias Agopian
6e375b1bba Automatic SH windowing
Clamping is now disabled by default in cmgen, there is a new option
to enable it "--clamp". 

Automatic SH windowing is also enabled by default and can be controled
with the "--sh-window" option. Accepted parameters are "no" to disable
windowing, "auto" for automatic windowing or a number to specify the
cutoff band.

auto windowing only works for 1, 2, and 3 bands.
2019-07-18 17:04:14 -07:00
Mathias Agopian
4d7ab6547c cmgen: tonemap images instead of clamping
Currently we're arbitrarily clamping environments to 16384 because both
the pre-filtering and SH algorithms can't handle very larger dynamic 
ranges.  Instead of clamping, we now tonemap, which is a little bit better.
2019-07-18 17:04:14 -07:00
Mathias Agopian
58b7084c8b make libmath much more constexpr friendly
It turns out that most of libmath couldn't be used in constexpr
expression due to our use of union{}. The C++ standard requires that
all accesses to a union{} in a constexpr expression be the same
element.

Also because libm and cmath are not constexpr some functions such
as length() or normalize() can't be constexpr. The same is true for
anything needing things like sqrt, cos, sin, ceil, floor.

This change mainly does the following:
- replace all accesses to vector elements by operator[]
  (this ensure all of libmath uses the same union element)

- avoid use of std::min / std::max / std::abs

- avoid uninitialized variables, which can't be constexpr

- remove 'constexpr' keyword on functions that can never be

It is now possible to write things like:

    constexpr mat4f I = inverse(
            transpose(mat4f::translation(float3{ 1, 2, 3 }) 
                 * mat4f::scaling(4)));
2019-07-18 16:48:37 -07:00
Philip Rideout
d313fe13fb Add deps to gltfio-android when Vulkan is enabled.
Note that these are SHARED rather than STATIC dependencies.

Issue #1414.
2019-07-17 12:57:55 -07:00
Ben Doherty
4d41c9bde3 Update MaterialBuilder to handle post-process materials correctly (#1408) 2019-07-15 10:56:00 -07:00
Philip Rideout
6c4157767f Restore shadows to helmet web demo. 2019-07-15 09:43:01 -07:00
Ben Doherty
5cceda4155 Pass material domain, variant to ShaderGenerator (#1402) 2019-07-12 13:20:00 -07:00
Philip Rideout
8f45f4ec35 gltfio: Fix skinning offset.
Thanks @iamjinge for the fix.

Fixes #1405.
2019-07-12 09:34:52 -07:00
Mathias Agopian
f3e5b46bf9 highlight negative values in SH debug files 2019-07-11 22:45:49 -07:00
Mathias Agopian
497c544f33 fix sh generation when -d is used
When -d was used, the radiance and irradiance ended-up being
swapped in the final file.

Also rename g_coefficients to g_sh_coefficients.
2019-07-11 22:45:49 -07:00
Mathias Agopian
2e4a825fec clamp correctly when converting to RGB_11_11_10
This avoids artifacts with unclipped HDR environments.
2019-07-11 22:45:49 -07:00
Philip Rideout
244c83a77c gltfio JavaScript: add basePath argument to loadResources.
Fixes #1392
2019-07-11 17:52:02 -07:00
Philip Rideout
41e5bb4f78 Add demo for point sprites and custom attribs. 2019-07-11 14:59:16 -07:00
Philip Rideout
2265eca82d Update cgltf. 2019-07-11 14:52:48 -07:00
Ben Doherty
82c7e4d988 Add new post-process functions (#1400) 2019-07-11 14:06:26 -07:00
Philip Rideout
793198f96a Expose setSampleCount to JavaScript. 2019-07-11 12:18:32 -07:00
Philip Rideout
f139589423 Update WebGL demos and docs on site. 2019-07-11 12:04:43 -07:00
Mathias Agopian
f929b6cee7 New experimental filtering options to cmgen
--sh-window=band, -w band : this low-pass-filters the environment
such that bands above 'band' are zero. This can be used to reduce ringing
when the source environment has high frequencies

--noclamp : turns off clamping before processing the cube map


This is still work in progress.
2019-07-11 11:55:59 -07:00
Pixelflinger
4d6f8c281a fix IndirectLight::radiance()
The conversion factors from radiance to irradiance where wrong.

The bug above was found while refactoring the code to be clearer. Now
the method that computes the coefficients for the shader calls the
regular SH code and applies all the appropriate factors on that.

With this change the options "--sh-shader" and "-sh=3 -i" won't
produce the same result because --sh-shader includes the lambertian
diffuse. "--sh" now always produces actual SH coefficients.
2019-07-11 11:52:33 -07:00
Ben Doherty
943af435aa Handle GL_PROGRAM_POINT_SIZE correctly (#1396) 2019-07-11 10:51:50 -07:00
Ben Doherty
f028af3186 Don't build all variants for Windows CI (#1394) 2019-07-11 10:49:51 -07:00
Ben Doherty
b15abe9e5e Rename post-process generator functions (#1395) 2019-07-11 10:44:46 -07:00
Philip Rideout
5281f2a511 Enumerate all 8 custom vertex attribs. 2019-07-11 09:00:10 -07:00
Philip Rideout
c2c546d671 Add support for custom vertex attributes.
This is a prep step for the upcoming morph feature and does not require
a bump to our material version number.

Stay tuned for a new sample app that demonstrates this feature.
2019-07-11 09:00:10 -07:00
Ben Doherty
6fc10c1dda Fix matc bug when compiling for multiple APIs (#1393) 2019-07-10 17:06:28 -07:00
Ben Doherty
80f3afaac6 Manually define PI to fix MSVC issue (#1388) 2019-07-10 16:23:26 -07:00
Ben Doherty
725c978545 Remove yOffset uniform (#1382) 2019-07-10 15:30:00 -07:00
Philip Rideout
a9091570b7 OpenGL driver: allow point sprites on desktop.
I noticed that point sprites were working on mobile and web but not
desktop.  This is why.  :)
2019-07-10 12:39:01 -07:00
Philip Rideout
4e8dac2680 Re-enable shadows in helmet demo. 2019-07-10 09:13:03 -07:00
Ben Doherty
da81e857a0 Correct spherical harmonics comments (#1375) 2019-07-09 16:16:30 -07:00
Mathias Agopian
111b3320c0 make sure we never execute a job smaller than requested 2019-07-09 16:12:15 -07:00
Mathias Agopian
665703dbd8 parallel_for now creates jobs in reverse order
this is because the JobSystem's queue works as a LIFO, by creating
jobs in reverse (memory) order, we attempt to help streaming to
the d-cache on that threads -- until the point where
jobs are stolen. 

we also execute the last job immediately instead of creating a job
for it -- since we're already in a job.
2019-07-09 16:12:15 -07:00
Pixelflinger
8170ca7cd1 improve JobSystem::parallel_for + minor optimizations
- parallel_for doesn't use recursion anymore to create the "leaf"
jobs, this is now done linearly on N thread (one thread per CPU).
This uses less stack space, and reduces miss-predicted branches.

- remove almost all SYSTRACE calls because they have a huge impact
on things like parallel_for() and are misleading. They can be
enabled again by setting HEAVY_SYSTRACE to true.
2019-07-09 16:12:15 -07:00
Mathias Agopian
2df639133b improvements to JobSystem
- we simplify the waiting code by using only a single
condition variable instead of two.

- wait() now behaves just like a looper, it will process jobs until
the one it's waiting for finishes -- before it could just sit there
(the idea was that the job would finish quickly, but that's not always
the case).

- we also make sure to never call notify_n() when it's not needed.
We track how many waiters we have and use that to decide if we need
to notify().

notify is pretty slow on all architectures, even on linux it's always
a syscall, so it's better to avoid it.

- don't use stand-alone fences, makes things ugly for no real benefit

- refactored the code a bit, hopefully it's more clear.
2019-07-09 16:12:15 -07:00
Mathias Agopian
fc1d39334f separate SpinLock out of Allocator.h 2019-07-09 16:12:15 -07:00
Mathias Agopian
af16e43830 add notify_n(int) to our condition variable
notify_n() wakes up n waiters, this is more fine grained than
notify_one() / notify_all(), and the implementation costs nothing.
2019-07-09 16:12:15 -07:00
Mathias Agopian
801c5b57a5 math::half is an arithmetic type even on msvc 2019-07-09 15:45:18 -07:00
Philip Rideout
19d7a3d21f Stop using DXT5 in web samples for the IBL.
Filament no longer decodes RGBM, so it's better to use a
floating-point format such as R11F_G11F_B10F.
2019-07-09 14:23:14 -07:00
Ben Doherty
6af77db79d Fix Android Toolchain issue on Windows (#1383) 2019-07-09 11:57:29 -07:00
Ben Doherty
efb2f9a1d8 Fix windows build (#1384) 2019-07-09 11:56:36 -07:00
Romain Guy
3b3f52f48c Add Engine::destroy(Engine*) to match other APIs (#1377) 2019-07-08 14:22:13 -07:00
Ben Doherty
ba5b9c733d Add shadow plane to hello-ar iOS sample (#1372) 2019-07-07 21:55:45 -07:00
Philip Rideout
e009dbbf96 Minor updates to the webpack sample. 2019-07-03 15:32:01 -07:00
prideout
073a6c7696 Prepare for a new npm release. 2019-07-03 11:26:49 -07:00
Philip Rideout
b30f6e5332 gltfio: JavaScript friendly error message for glb files. 2019-07-03 10:20:17 -07:00
Philip Rideout
384651e21a gltfio: fix JavaScript utility for glb files. 2019-07-03 10:20:17 -07:00
Philip Rideout
22dcdc770f gltfio: fix issue with bounding box computation.
If the client opts in to "recomputeBoundingBoxes", then we manually
compute a bounding box that ignores the glTF min / max annotations.

This computation was erroneously including the transform of the injected
root node, which is not part of the model.

This could cause a problem when creating the asset, then immediately
positioning it with its injected root node before the ResourceLoader
is done downloading vertex buffers.
2019-07-03 10:20:17 -07:00
Philip Rideout
fd4d6c0d44 Use std::move in MeshAssimp.
Tested this via material_sandbox, seems to be fine.

Fixes #1366.
2019-07-02 14:20:55 -07:00
Philip Rideout
ca5b52b2ce Add JavaScript / TypeScript support for RenderTarget. 2019-07-02 13:26:56 -07:00
Ben Doherty
cc4e9db81b Fix spherical harmonics parsing (#1370) 2019-07-02 12:54:52 -07:00
Ben Doherty
2bfea16459 Update usage of KtxUtility in iOS projects (#1371) 2019-07-02 12:33:55 -07:00
Philip Rideout
927662ea4d Add JNI for KTX, simplify the bloom Android demo. 2019-07-02 11:02:45 -07:00
Ben Doherty
5b2dc1d3de Link against IBL library in iOS projects, update README (#1369) 2019-07-02 10:43:54 -07:00
Ben Doherty
097feb0372 Delete accidentally committed file (#1368) 2019-07-02 09:58:48 -07:00
Romain Guy
9cd2971b65 Fix typo in documentation 2019-07-01 17:58:03 -07:00
Ben Doherty
fb16516480 Post-process materials: add post-process variant enum, split writeChunks function (#1365) 2019-07-01 12:57:41 -10:00
Mathias Agopian
76027cab85 fix a JobSystem bug in waitAndRelease()
We were not checking for jobs to execute during waitAndRelease(), so
this thread would essentially not participate to the work pool.
2019-07-01 14:25:26 -07:00
Mathias Agopian
64c95c615a Fix a theoretical wrapping around issue in WSDQ
The Work-stealing dequeue indices could wrap around after ~2 billion
calls to steal(). This could probably be achieved in a few hours.
By using 64-bits indices, we avoid the problem entirely.
2019-07-01 14:25:26 -07:00
Mathias Agopian
31745f6025 fix benchamrk JobSystem de-initialization
JobSystem's API requires to call emancipate() for each adopt() before
destroying the JobSystem.
2019-07-01 14:25:26 -07:00
Ben Doherty
2a8f04c791 Limit material compilation to supported backends (#1359) 2019-07-01 10:05:00 -10:00
Philip Rideout
3fdecfdefa gltf_viewer should not crash when there is no IBL. 2019-06-28 15:40:43 -07:00
Philip Rideout
26cbef7452 Fix intermittent cmgen crash. 2019-06-28 14:49:40 -07:00
Romain Guy
571a9b1ff3 Update README 2019-06-28 13:52:52 -07:00
Romain Guy
b84117eb92 Update READMEs 2019-06-28 13:51:57 -07:00
Romain Guy
6af0c72d0d Add missing getter in IndirectLight (#1356)
This change also factors a bunch of assert methods in a single place
which should slightly decrease binary size.
2019-06-28 13:38:51 -07:00
Mathias Agopian
12fde30f31 better comments and potential fix for work-stealing dequeue
It's better to use std::memory_order_seq_cst in pop() and
steal() because we rely on ordering of access to
mTop and mBottom members.
2019-06-28 13:08:56 -07:00
Philip Rideout
56c2d6338e Add spherical harmonics parser, reduce code duplication.
This uses strtof rather than stringstream and provides a common location
that can be leveraged by the upcoming JNI bindings.

Note that this new method lives in KtxBundle rather than KtxUtility. The
latter creates Filament textures and therefore does not get built into
libimage.
2019-06-28 11:10:04 -07:00
Romain Guy
10c8ff352d Try with clang 7.0.1 on Windows 2019-06-27 10:52:48 -07:00
Romain Guy
53ea1a00ec Fix warnings 2019-06-27 10:46:52 -07:00
Romain Guy
62a458099a Fix more warnings 2019-06-27 09:56:43 -07:00
Romain Guy
826d52bca2 Fix Windows build and warnings 2019-06-27 09:18:31 -07:00
Romain Guy
299a600377 Add CMake to PATH during install 2019-06-26 19:02:21 -07:00
Romain Guy
a4ebf23baa Update PATH 2019-06-26 18:53:05 -07:00
Romain Guy
d23a703ca5 Echo on again 2019-06-26 18:45:47 -07:00
Romain Guy
2beb9c5588 Don't update PATH 2019-06-26 18:40:43 -07:00
Romain Guy
a7fc4d8fbb Update PATH 2019-06-26 18:28:48 -07:00
Romain Guy
a5dc89b071 Don't use refreshenv 2019-06-26 18:18:16 -07:00
Philip Rideout
2bfec9f4af gltfio: Disable file formats that we do not need.
This only removes 40k but at least it is easy.
2019-06-26 18:15:02 -07:00
Romain Guy
1aa7fac8c2 Remove ci-common 2019-06-26 18:03:58 -07:00
Romain Guy
c01107fd52 Exit from the if statement to see what's going on 2019-06-26 17:55:43 -07:00
Romain Guy
5b27361ef0 Try with LLVM 6 2019-06-26 17:47:41 -07:00
Romain Guy
494ddc10e4 More logging 2019-06-26 17:36:24 -07:00
Mathias Agopian
6151f78d28 Update RELEASE_NOTES.md 2019-06-26 17:29:46 -07:00
Romain Guy
46c67632c7 Add logging to test Windows build 2019-06-26 17:28:33 -07:00
Philip Rideout
3f7cf2f971 Increase epsilon in test_cmgen. 2019-06-26 16:46:57 -07:00
Mathias Agopian
84cc8ff9c8 update release notes 2019-06-26 16:05:30 -07:00
Mathias Agopian
921c2bcd61 mitigate overhead of jobsystem
For jobs with that do very little work, the jobsystem can introduce
a lot of overhead, we mitigate this by:

- don't wake-up worker threads when scheduling several very small jobs,
like when scheduling the per-face jobs. 

- don't wait for per-face jobs to finish -- we only did that to avoid
a copy of the job's data.

- don't use multi-threading at all if the job has too little work. We
evaluate the work using the scanline length and number of samples.
2019-06-26 16:05:30 -07:00
Mathias Agopian
6ea8ed07ed a few libibl optimizations 2019-06-26 16:05:30 -07:00
Mathias Agopian
a5addd2257 convert libibl from double to float
since libibl is now used online, it makes more sense to do all the
math in float instead of double. It doesn't seem to impact quality.
2019-06-26 16:05:30 -07:00
Mathias Agopian
8b1d4ee06a a way to fold mirroring with prefiltering 2019-06-26 16:05:30 -07:00
Mathias Agopian
3e23d9742b fixup: remove code that wasn't supposed to be comited 2019-06-26 16:05:30 -07:00
Romain Guy
847d7dd71a Fix various errors discovered by clang-tidy (#1351)
- Move the static function declared in MaterialVariants.h to the .cpp
- Fix several use-after-move that were horribly wrong
2019-06-26 15:25:58 -07:00
Philip Rideout
10dc3a24e8 Add Kotlin sample for gltfio and custom render targets. 2019-06-26 13:55:23 -07:00
Romain Guy
c6c1cfef3c Small cleanups 2019-06-26 12:43:37 -07:00
Romain Guy
cc8a2f736b Fix progress bars display in cmgen 2019-06-26 12:43:37 -07:00
Philip Rideout
7fcd3e1a4f Java clients can now get material instances from renderables.
Discussed this feature with Mathias, we decided to create
MaterialInstance Java wrappers on the fly, and create Material Java
wrappers lazily. This is simple and avoids caching the wrapper objects,
which might otherwise lead to complexity and bugs.

Note that gltfio creates material instances behind the scenes, so this
feature is particularly useful for gltfio clients.
2019-06-25 19:47:49 -07:00
Philip Rideout
481fe5a087 Fix build break of gltfio-android. 2019-06-25 16:31:30 -07:00
Philip Rideout
2d690ac585 Add View::getRenderTarget to JNI. 2019-06-25 16:31:25 -07:00
Philip Rideout
a118299cfb Fix JNI for parameter arrays in MaterialInstance.
Previously we used the <T=float> template instantiation of setParameter
when the client specified FLOAT4. This resulted in the lower layer
adding needless padding, thus causing a buffer overflow.

Moreover the JNI code for this was somewhat cryptic because it casted an
enum value to an int, then added 1 to compute the size. We now use
a switch statement to improve readability.

This issue was discovered (and the fix was verified) with the upcoming
Android port of the bloom demo.
2019-06-25 15:32:30 -07:00
Mathias Agopian
bc01475920 optimize libibl for smaller workloads
We now never process mirroring or mipmaping with multithreading
it's just not worth it given the overhead of the jobsystem.

We also require 64 lines per job, below that, we only multithread per
face (6 threads). This should probably depends on the sample count,
but we don't have this facility yet.

Special case downsampling for mipmaping.

This alone improves performance by 2x for small cubemaps (e.g. 16x16).
2019-06-25 15:08:15 -07:00
Mathias Agopian
56e9d8eda5 Utility to prefilter an environment at runtime
This adds a utility function on IndirectLight populate the reflection
map from an environment at runtime. This performs some processing
similar to cmgen, albeit at a reduced quality.
2019-06-25 15:08:15 -07:00
Mathias Agopian
902e7021fd libibl doesn't use its own JobSystem instance 2019-06-25 15:08:15 -07:00
Adrian Perez
1773c42398 Comment fixes (#1346) 2019-06-25 13:42:52 -07:00
Philip Rideout
ae88536f0c Fix GL_INVALID_OPERATION in the default IBL.
In commit d955e73 we changed the default IBL from RGBM to RGB, but we
kept its internal format of RGBA8. Since the internal format is not
compatible with the data format, we see GL_INVALID_OPERATION during the
texture upload.

This is a single-pixel black texture, so the format does not really
matter, but this clears up a GL error seen on some platforms.
2019-06-24 13:22:34 -07:00
Philip Rideout
b4d6583901 Fix up WebGL bindings after RGBM removal. 2019-06-24 13:22:34 -07:00
Philip Rideout
b31e420064 Fix GL_INVALID_OPERATION in the default IBL.
In commit d955e73 we changed the default IBL from RGBM to RGB, but we
kept its internal format of RGBA8. Since the internal format is not
compatible with the data format, we see GL_INVALID_OPERATION during the
texture upload.

This is a single-pixel black texture, so the format does not really
matter, but this clears up a GL error seen on some platforms.
2019-06-24 13:21:45 -07:00
Philip Rideout
e4e439e2bf Fix build break. 2019-06-21 18:48:40 -07:00
Philip Rideout
a79a83d6da gltfio: gracefully error when mesh uses draco. 2019-06-21 16:12:59 -07:00
Philip Rideout
50d4dc6499 Update cgltf. 2019-06-21 14:51:41 -07:00
Philip Rideout
cbc662085e cgltf: expose extension lists 2019-06-21 14:51:41 -07:00
Philip Rideout
02a5541fed gltfio: minor improvements to error handling. 2019-06-21 10:09:57 -07:00
Romain Guy
14248621fe Workaround for a Mali driver bug (#1337)
Fixes #1320
2019-06-21 09:57:50 -07:00
Romain Guy
8c299d7b0b Update documentation to fix #1336 2019-06-21 09:29:49 -07:00
Ben Doherty
57d6bdff1b Allow mutliple API flags in matc (#1327) 2019-06-21 09:27:49 -07:00
Romain Guy
957ec9be60 Use R11G11B10F instead of RGBM in Android sample apps (#1333) 2019-06-20 16:31:17 -07:00
Philip Rideout
76147a7231 gltfio: fix bug with colliding TANGENT buffers.
ResourceLoader was mistakenly assuming that all primitives in the
entire model have TANGENTS in the same slot index.

Fixes #1326.
2019-06-20 16:29:22 -07:00
Philip Rideout
eff3d1a09b gltfio: show warning for missing normals. 2019-06-20 16:29:22 -07:00
Mathias Agopian
5f6d7a279c fix some warnings 2019-06-20 16:19:02 -07:00
Mathias Agopian
9bce361b3e Remove RGBM support entirely from filament.
⚠️ this break c++ and java source compatibility
2019-06-20 16:17:27 -07:00
Mathias Agopian
925e414e7b fix cmgen test 2019-06-20 15:19:59 -07:00
Mathias Agopian
aeec6f2df5 skygen handles rgb_11_11_10 2019-06-20 14:36:37 -07:00
Mathias Agopian
9358650bd4 remove generated test ibls
we're not using them in the build and they can easily get out of date.
2019-06-20 14:36:37 -07:00
Mathias Agopian
54d44a76a7 fix linux builds 2019-06-20 14:36:37 -07:00
Mathias Agopian
cc22183f20 update samples/envs 2019-06-20 14:36:37 -07:00
Mathias Agopian
2ded1c955f cmgen and filament now support RGB_10_11_11_REV
- RGB_11_11_10 is exported in a RGBA PNG file where the 4 channels are
  used as a uint32 storing a RGB_10_11_11_REV pixel.
  We use the .rgb32f extension, and those PNG files contain garbage 
  when seen in a PNG viewer.

- This is now the default for the -x option.

- compressed KTX files don't encode RGBM, which means they can't
  support HDR, unless an HDR compression scheme is used.
2019-06-20 14:36:37 -07:00
Mathias Agopian
d955e733bf remove RGBM support for skybox and ibl cubemap 2019-06-20 14:36:37 -07:00
Mathias Agopian
99a501f0c3 fix s3tc compression with HDR input
HDR input where producing garbage pixels, instead we saturate.
2019-06-20 14:36:37 -07:00
Ben Doherty
cdb2b47e0f Add material domains boilerplate (#1305) 2019-06-20 08:53:36 -07:00
joetoth
366e20cbe8 Compile gltfio with -fPIC 2019-06-19 19:34:25 -07:00
Philip Rideout
d5179bd9ed Fix JsonishParser to handle parameter arrays. 2019-06-19 15:32:40 -07:00
Philip Rideout
12506784da Expose texture usage flags to Java / Kotlin. 2019-06-19 15:32:26 -07:00
Romain Guy
4fee4d8da2 Don't use clear coat roughness as base roughness if clear coat is 0 (#1323)
This change finds the max of the clear coat and base layer roughness
then lerps the base layer roughness according to the amount of clear
coat.
2019-06-19 15:22:09 -07:00
Romain Guy
b1242163f7 Make CMake 3.10 the minimum version, add LTO option (#1316)
* Make CMake 3.10 the minimum version, add LTO option

* Install a newer CMake on Linux CI builds

* Update LLVM and Cmake on Windows CI

* Update build/windows/ci-common.bat

Co-Authored-By: Ben Doherty <benjdoherty15@gmail.com>

* Update formatting

* Apply suggestions from code review

* Update build/windows/ci-common.bat

* Update CMake

* Switch Android projects back to CMake 3.6
2019-06-19 12:53:03 -07:00
Mathias Agopian
8cd44fb2e8 rework math::half to be more generic
We introduce a templated fp<> class that can represent any float
format and convert to/from float32.
2019-06-19 12:22:01 -07:00
Romain Guy
33a8c9da7e Don't enable specularAO and multiBounceAO by default on mobile (#1319) 2019-06-19 11:04:40 -07:00
Pixelflinger
37facf7f7b fix build breakage on OpenGL ES targets 2019-06-19 01:25:37 -07:00
Mathias Agopian
1d20973363 IBL cubemaps can now be any size.
⚠️ breaks materials

There used to be a constraint that ibl cubemap needed to be
256x256. This constraint is now relaxed. IBL cubemaps can be any size.

We also add 16 float4 of padding to the frameUniform, which brings
its size to 1 KiB, the idea is to prevent more breakages in the
future.
2019-06-18 18:39:06 -07:00
Ben Doherty
0cb08cd114 Add mipmap level selection to Metal render targets (#1310) 2019-06-18 16:13:04 -07:00
Philip Rideout
c97ba45eed Fix several bugs in the gltfio JNI build. 2019-06-18 13:53:45 -07:00
Philip Rideout
74fcc456dc gltfio-android code review changes. 2019-06-18 13:53:45 -07:00
Philip Rideout
b17d606ed2 Introduce JNI bindings for gltfio.
For now this uses gltfio in the ubershader configuration in order
to avoid the filamat dependency. Note that we have not yet done a size
analysis of the `gltfio_core` library.

New Kotlin-based sample app is forthcoming.
2019-06-18 13:53:45 -07:00
Philip Rideout
3e97ac5268 Add Scene::getEntities to JNI. 2019-06-17 15:17:37 -07:00
Philip Rideout
a7ab0d98fa gltfio: allow clients to pass in EntityManager.
NOTE: Should we expose Engine::getEntityManager() to help with issues
like this? e.g. it would allow gltfio to extract it from the engine
rather than consuming an additional argument.

This fixes an entity id collision that I saw when building gltfio into
its own DSO (e.g. on Android). Since it is a separate executable it has
its own EntityManager singleton. This id collision was causing unwanted
entities to be added to the scene.
2019-06-17 11:11:06 -07:00
Philip Rideout
94b4f92bc5 Android: move JNI C++ utils into a common folder.
No need for a proper library, this is just a common location to simplify
JNI bindings in other projects like filamat and gltfio.

There is no need to move the one Java source file (`NioUtils.java`)
since downstream libraries will have a dependency on Filament, and
FindClass should work fine.
2019-06-17 08:47:27 -07:00
Romain Guy
77d058cf76 Fix MaterialInstance Java color bindings (#1308)
This changes addresses issue #1307. We recently fixed the way we support arrays
of parameters to allow arrays of 1 element. Previously single elements (e.g. float)
were treated as an array of 1 element and the other way around. Unfortunately our
Java bindings relied on this behavior to set colors. This change simply directly
calls the float3 and float4 variants of setParameter() when setting a color.
2019-06-16 19:15:18 -07:00
Mathias Agopian
52f815e240 Properly inverse the projection matrix for the shader
Some projections matrices were incorrectly inverted. 
This also fix #1281, fortunately, the incorrect matrix wasn't used
in that case.

Camera::inverseProjection only handles projection matrices it
created (as opposed to custom ones, which is what the shadowmap
code uses)
2019-06-14 16:59:05 -07:00
Philip Rideout
83b329c123 Fix incomplete FBO when rendering to cubemap.
The bug was reproduced and the fix was verified by making the following
changes to the lucy_bloom demo.

Fixes #1300.

diff --git a/samples/lucy_bloom.cpp b/samples/lucy_bloom.cpp
index c3a887ca..98f19c53 100644
--- a/samples/lucy_bloom.cpp
+++ b/samples/lucy_bloom.cpp
@@ -87,6 +87,7 @@ static void setup(LucyApp& app, Engine* engine, View* finalView, Scene* finalSce

     app.reflection.color = Texture::Builder()
         .width(FBO_WIDTH).height(FBO_HEIGHT).levels(1)
+        .sampler(Texture::Sampler::SAMPLER_CUBEMAP)
         .usage(Texture::Usage::COLOR_ATTACHMENT | Texture::Usage::SAMPLEABLE)
         .format(Texture::InternalFormat::RGBA8).build(*engine);
     app.reflection.depth = Texture::Builder()
@@ -96,6 +97,7 @@ static void setup(LucyApp& app, Engine* engine, View* finalView, Scene* finalSce
     app.reflection.target = RenderTarget::Builder()
         .texture(RenderTarget::COLOR, app.reflection.color)
         .texture(RenderTarget::DEPTH, app.reflection.depth)
+        .face(RenderTarget::COLOR, RenderTarget::CubemapFace::POSITIVE_Y)
         .build(*engine);

     app.primary.color = Texture::Builder()
diff --git a/samples/lucy_utils.cpp b/samples/lucy_utils.cpp
index 647a97f2..59a0135b 100644
--- a/samples/lucy_utils.cpp
+++ b/samples/lucy_utils.cpp
@@ -300,7 +300,8 @@ Entity createDisk(Engine* engine, Texture* reflection) {
                 material.ambientOcclusion = texture(materialParams_ao, getUV0()).r;

                 float2 uv = gl_FragCoord.xy * getResolution().zw; uv.y = 1.0 - uv.y;
-                vec3 reflection = texture(materialParams_reflection, uv).xyz;
+                float3 dir = float3(uv.x * 2.0 - 1.0, 1.0, uv.y * 2.0 - 1.0); // select POSITIVE_Y
+                vec3 reflection = texture(materialParams_reflection, dir).xyz;

                 // HACK: blend the reflection with the baseColor.
                 material.baseColor.rgb = mix(reflection, material.baseColor.rgb, 0.75);
@@ -311,7 +312,7 @@ Entity createDisk(Engine* engine, Texture* reflection) {
         .parameter(filamat::MaterialBuilder::SamplerType::SAMPLER_2D, "color")
         .parameter(filamat::MaterialBuilder::SamplerType::SAMPLER_2D, "roughness")
         .parameter(filamat::MaterialBuilder::SamplerType::SAMPLER_2D, "ao")
-        .parameter(filamat::MaterialBuilder::SamplerType::SAMPLER_2D, "reflection")
+        .parameter(filamat::MaterialBuilder::SamplerType::SAMPLER_CUBEMAP, "reflection")
         .targetApi(filamat::MaterialBuilder::TargetApi::OPENGL)
         .specularAntiAliasing(true)
         .shading(Shading::LIT)
2019-06-14 15:14:34 -07:00
Philip Rideout
909806b8ce API comments should not refer to backend types. 2019-06-14 15:14:13 -07:00
Mathias Agopian
d67d5cc267 Fix #1288, a division-by-zero in the SAO shader 2019-06-14 14:47:39 -07:00
Mathias Agopian
0b95f61549 Fix #477, add a way to set the intensity of the skybox
When there is no indirect light it wasn't possible to control the
skybox's intensity. Now the skybox has its own intensity that
is used in that case.
2019-06-14 14:47:15 -07:00
Mathias Agopian
6620edebb3 Add IndirectLight::radiance()
This allows to specify the irradiance by providing only the radiance
as SH, which might be easier in some case.
2019-06-13 13:23:56 -07:00
Mathias Agopian
4e4f7fd4ac improve IndirectLight::irradiance() documentation 2019-06-13 13:23:56 -07:00
Philip Rideout
f3769d8e86 lucy_bloom: minor fixups.
Tangents are required on the disk, not the quads...
2019-06-13 12:29:52 -07:00
Ben Doherty
5caf9b9575 SPIRV-cross update (#1295) 2019-06-13 12:15:37 -07:00
Philip Rideout
6d927f61aa lucy_bloom: use LINEAR to reduce texture lookups.
Many thanks to Dr. Rajan Srinivasan, who helped me with the math for this.
2019-06-13 12:10:53 -07:00
Philip Rideout
65a20df7c1 lucy_bloom: improve blur quality by not skipping texels 2019-06-13 12:10:53 -07:00
Philip Rideout
8ba0849bcf lucy_bloom: improve code comments 2019-06-13 12:10:53 -07:00
Philip Rideout
55abd67e81 lucy_bloom: do not dither intermediate framebuffers 2019-06-13 12:10:53 -07:00
Mathias Agopian
8cb38344ae remove float3 specialization 2019-06-12 18:31:24 -07:00
Mathias Agopian
d90d30d10b Fix #1270 Inconsistent setParameter behavior for arrays
Arrays in unform buffers are stored in std140, i.e. they have an
alignment of float4. This wasn't taken into account when setting
arrays (other than mat3)
2019-06-12 18:31:24 -07:00
Philip Rideout
709c5884ea geometry: tweak provided tangents to enforce orthonormality.
Fixes #1291.
2019-06-12 16:44:18 -07:00
Ben Doherty
5795bef02a Split runStaticCodeAnalysis into separate methods (#1287) 2019-06-12 13:42:18 -07:00
Philip Rideout
1f72b3ac24 gltfio: improve robustness for missing attributes.
The bistro model has some UV-free primitives associated with textured
materials. This caused Filament to emit warnings like:

[entity=445, primitive @ 0] missing required attributes (0xb), declared=0x3

We now catch these in gltfio, which enables a friendlier warning so that
the artist can go make a fix:

Missing UV0 data in Bistro_Research_Exterior_Paris_Building_01_paris_building_01_bottom_4669
2019-06-12 11:22:18 -07:00
Philip Rideout
0949e0a6f3 gltfio: fix bad color in ubershader mode. 2019-06-12 11:22:18 -07:00
Philip Rideout
1139209551 Add JNI bindings for RenderTarget.
New Kotlin sample app is forthcoming.
2019-06-12 10:18:30 -07:00
Philip Rideout
9c4fecb5c6 RenderTarget API now has per-attachment config, etc. 2019-06-11 15:56:24 -07:00
Philip Rideout
8142ffdfb7 Add bloom demo and release notes for #119. 2019-06-11 15:56:24 -07:00
Philip Rideout
961ad36443 Add View::setRenderTarget() for #119. 2019-06-11 15:56:24 -07:00
Philip Rideout
11309a8cf2 Introduce RenderTarget API for #119. 2019-06-11 15:56:24 -07:00
Romain Guy
7fadc438ec Add Filmic ALU tone mapping operator (#1286)
This change also cleans up tone mapping and transfer functions by
getting rid of unused code paths
2019-06-11 12:15:44 -07:00
Romain Guy
7388aeff55 Add Filmic ALU tone mapping operator (#1285) 2019-06-11 11:20:01 -07:00
Mathias Agopian
c886d5bcfd rename mirrorFrame() to copyFrame()
"mirror" was misleading, like it would apply a symmetry to the frame.
mirrorFrame() is just a blit from a swapchain to another, so it's a
copy.

The Java language API is kept for compatibility.
2019-06-10 23:45:38 -07:00
Mathias Agopian
58187f5c2c better command queue flushing
Instead of flushing the driver and command queue in RenderPass, we now
do that in the framegraph.

We flush the command queue after each pass -- which reduces memory
pressure on the command queue and improves parallel execution
with the backend thread. We flush the driver only after the last
pass -- maybe we could improve this in the future as the framegraph
gain more knowledge about what's going on.
2019-06-10 23:43:45 -07:00
Ben Doherty
6129930fb0 Show missing required attribute warning in release builds (#1278) 2019-06-10 21:48:52 -07:00
Romain Guy
505bb391c6 Remove file that shouldn't have been checked in 2019-06-10 18:13:55 -07:00
Mathias Agopian
3483eed412 address PR comments.
Typo, comments, unneeded code.
2019-06-10 15:45:32 -07:00
Mathias Agopian
aee938b51e Added resolution quality setting for SSAO 2019-06-10 15:45:32 -07:00
Mathias Agopian
ba95e522c4 Added SAO "reference" mode for debugging & comments
Reference mode allows to set an arbitrary
number of samples, which are computed in the 
shader.
2019-06-10 15:45:32 -07:00
Mathias Agopian
4c4303eacf Don't use derivative for computing normals
derivative-based normals are essentially
half-resolution, which creates artifacts around
geometry edges.
2019-06-10 15:45:32 -07:00
Mathias Agopian
6a7b1e8cb0 Tweak blur pass trying to improve perfs 2019-06-10 15:45:32 -07:00
Mathias Agopian
62cab7710c Add blur pass to SSAO 2019-06-10 15:45:32 -07:00
Mathias Agopian
96d34349ec encapsulate material data for postprocessing 2019-06-10 15:45:32 -07:00
Mathias Agopian
e4c6dcf3bc more efficient depth mipmaping
We simply pick one of the 4 depth texel based on its screen
space offset. Literature showed it doesn't impact AO
significantly.
2019-06-10 15:45:32 -07:00
Romain Guy
0f23633809 Fix warning in OpenGLDriver in release builds 2019-06-10 14:37:19 -07:00
Jeff McGlynn
53adfedc83 Fix msan use-of-uninitialized-value in destroyVertexBuffer (#1277)
GLVertexBuffer.gl.buffers is a std::array which is not
default-initialized, and createVertexBuffer only initializes the first
bufferCount fields of the array.

When destructing, destroyVertexBuffer iterated over all buffers to unset
bindings, but it was erroneously iterating over the entire array instead
of the initialized values.  Update the loop to only iterate over known
initialized values.
2019-06-10 13:38:00 -07:00
Romain Guy
2f736bee19 Update README.md 2019-06-09 21:43:59 -07:00
Ben Doherty
ae37ace15b Refactor MaterialBuilder, remove code duplication (#1269) 2019-06-09 18:58:35 -07:00
Romain Guy
1aed2379b9 Use a 32 bit index buffer when necessary (#1273)
Fixes #1272
2019-06-08 17:44:49 -07:00
Philip Rideout
f93046308c gltf_baker: improve error handling throughout. 2019-06-05 15:25:47 -07:00
Philip Rideout
1d514e6bf6 gltf_baker: allow re-baking after tweaking options. 2019-06-05 15:25:47 -07:00
Ben Doherty
62e51649fa Refactor MaterialBuilder chunks, findProperties (#1254) 2019-06-05 15:08:00 -07:00
Mathias Agopian
edb1beac3d give internet permission to ibl sample
this allows us to use snapdragon profiler
2019-06-05 14:34:58 -07:00
Romain Guy
f441e4ec4e Switch desktop to interleaved RGB noise (#1263)
This eliminates the flicker caused by triangle noise based dithering
when FXAA is turned on. This will require further investigation to
see if we can use triangle noise with FXAA without such artifacts.
2019-06-05 10:45:04 -07:00
Philip Rideout
70d569029b gltf_baker: allow adjustment to seed iterations. 2019-06-05 10:11:23 -07:00
Ben Doherty
018d6461f5 Update README with CoreVideo flag (#1266) 2019-06-04 21:15:42 -07:00
Romain Guy
413ce37681 Code formatting cleanup (#1264) 2019-06-04 21:11:00 -07:00
Romain Guy
9d31b7c008 Formatting of shaders 2019-06-04 16:23:20 -07:00
Philip Rideout
fb004a1990 AssetPipeline: fix crash with meshes that already have TEXCOORD_4.
Fixes #1256.
2019-06-04 15:48:54 -07:00
Philip Rideout
0262a38c7e gltf_baker: fix radio button numbering 2019-06-04 15:48:54 -07:00
Philip Rideout
d3f784d4f9 gltf_baker: add vertex normals visualization 2019-06-04 14:36:03 -07:00
Philip Rideout
475cd80faf gltfio: consolidate buffer slots.
Instead of using the actual glTF attribute indices, we now pack them
so that unused indices do not take up any VertexBuffer slots.

Fixes #1256.
2019-06-04 14:35:51 -07:00
Philip Rideout
37ff2d903f Additional validation in VertexBuffer::Builder::build.
If a client asks for more than 8 buffers in a VertexBuffer, they will
either crash (release) or hit an assert in OpenGLDriver (debug). It's
better to catch this earlier.

This was noticed while investigating #1256.
2019-06-04 13:23:07 -07:00
Philip Rideout
a900851abc gltfio: add optional diagnostic shading. 2019-06-03 17:30:56 -07:00
Romain Guy
3ae91957be Reorder shader 2019-06-03 17:24:00 -07:00
Philip Rideout
be11944f99 gltf_baker: AssetPipeline now has an options struct. 2019-06-03 13:03:14 -07:00
Philip Rideout
f3a70d82cd gltf_baker: make denoise optional. 2019-06-03 13:03:14 -07:00
Philip Rideout
61423f6900 gltf_baker: dilate charts for bent normals. 2019-06-03 13:03:14 -07:00
Philip Rideout
29d2f51fca gltf_baker: make chart dilation optional. 2019-06-03 13:03:14 -07:00
Philip Rideout
bfaa2bdd4e gltf_baker: allow 3D visualization of mesh normals. 2019-06-03 13:03:14 -07:00
Philip Rideout
ce4a3edf7b gltf_baker: visualizers now use fp32 textures.
This allows us to skip the CPU-side vector-to-color conversion that
occured at the end, and makes the real-time visualization consistent
with the final visualization.
2019-06-03 13:03:14 -07:00
Philip Rideout
6c153b046f gltf_baker: allow visualization of mesh normals. 2019-06-03 13:03:14 -07:00
Philip Rideout
7a732eb9c4 gltf_baker: show the bounds of the asset
Parameterization can run into problems for very large, very small, or
off-center assets. Showingthe min/max helps users diagnose these issues.
2019-06-03 13:03:14 -07:00
Philip Rideout
fdfb8862eb gltf_baker: allow tmin adjustment. 2019-06-03 13:03:14 -07:00
Philip Rideout
8df3253955 Resurrect the denoiser.
This follows the convention of providing our own CMake files in the tnt
folder(s) and successfully builds with the -i option (install).
2019-06-03 10:39:56 -07:00
Philip Rideout
78ec315b69 Overhaul the gltf_baker UI.
As per the design doc, this makes the app somewhat usable by eliminating
hardcoded filenames, the hidden state machine, etc.
2019-06-03 08:32:48 -07:00
Philip Rideout
13fc64470a Add shader_ball in glTF 2.0 format. 2019-05-31 15:02:35 -07:00
Philip Rideout
97b5d43bd5 AssetPipeline: renormalize after baking transforms. 2019-05-30 16:03:13 -07:00
Philip Rideout
c2fcb39336 resgen: remove unused flag. 2019-05-30 16:02:55 -07:00
Mathias Agopian
4e718f592c fix typo in ashmem fallback code
There was typo that prevented the ashmem fallback code to work.
This became briefly a problem on Android Q before we fixed our
use of private APIs.
2019-05-30 13:39:09 -07:00
Romain Guy
d780e8b2a0 Add link_library(libc++.a) (#1245)
* Add link_library(libc++.a)

* Always link statically against libc++ and libc++abi on Linux
2019-05-30 11:49:03 -07:00
Romain Guy
e1b773958f Add screen and multiply blending modes (#1241)
* Add screen and multiply blending modes

This change also fixes a sorting issue: different sorting modes
were sorted in different buckets which is incorrect. We want
to sort only by distance.

* Update release notes and Java API

* Fix build error
2019-05-30 10:17:16 -07:00
Ben Doherty
326a67acdb Fix iOS README formatting 2019-05-30 10:01:56 -07:00
Ben Doherty
2c36d0aaae Add gLTF iOS sample (#1236) 2019-05-30 10:00:21 -07:00
Jack Diver
1b45f253eb Removed unnecessary nullptr guard from MeshReader::MaterialRegistry destructor. 2019-05-30 09:54:37 -07:00
nitronoid
7a2b5125ed Moved back to [] syntax, works for exisitng string keys now. 2019-05-30 09:54:37 -07:00
nitronoid
da39dbcb57 Fixed move constructors for MeshReader::MaterialRegistry 2019-05-30 09:54:37 -07:00
Philip Rideout
fab70e878a Repair redball tutorial.
Our GitHub Pages site is currently using an older version of the
filament wasm file so we should avoid using the new API here.
2019-05-30 09:34:08 -07:00
Jack Diver
0d2fe62d68 Fixed enum scoping in DriverEnums.h to allow compilation with gcc (#1244) 2019-05-30 09:05:18 -07:00
Philip Rideout
bafa62cdec Repair the install target, disable denoise.
This rolls back denoise functionality to repair install builds.
Will investigate a proper fix by authoring a tnt/CMakeLists.
2019-05-29 15:41:34 -07:00
Ben Doherty
fd318826c5 Update spirv-cross (#1238) 2019-05-29 15:16:02 -07:00
Mathias Agopian
5403a19076 compute the projection scale properly.
It used to be hard-coded, which meant the size SAO radius changed with
the screen resolution.
2019-05-29 13:08:41 -07:00
Ben Doherty
89c4647c3c Expose gltfio library so it can be used by third_parties (#1230) 2019-05-28 14:50:38 -07:00
Mathias Agopian
9befaeb3ae SAO now uses a hierarchical depth to improve performance
- we generate LODs for the depth map using the framegraph
- these LODs are used in the SAO shader to improve data access locality
2019-05-28 13:09:11 -07:00
Philip Rideout
122eb8c82e gltf_baker: add UV visualization option 2019-05-28 11:44:04 -07:00
Philip Rideout
81b3f1b244 Build OpenImageDenoise only if TBB is available. 2019-05-28 11:43:50 -07:00
Philip Rideout
cc89b6ad1e PathTracer now applies OpenImageDenoise. 2019-05-28 11:43:50 -07:00
Philip Rideout
0f7aa70f2d Add OpenImageDenoise. 2019-05-28 11:43:50 -07:00
François Guthmann
b7304084d9 Corrected minor LaTeX typo (#1234)
The Jacobian formula display was broken in the cloth IBL section.
2019-05-25 13:14:35 -07:00
Romain Guy
a99d3b613f Remove unnecessary variants 2019-05-24 18:27:39 -07:00
Romain Guy
e896ed9d87 Add support for Parallax Occlusion Mapping in the PBR demo 2019-05-24 17:45:26 -07:00
Romain Guy
975395ce98 Simplify duplicate code 2019-05-24 17:01:57 -07:00
Philip Rideout
761b407159 AssetPipeline now has replaceOcclusion function.
This preserve original materials and substitutes the occlusion texture
with the generated AO.
2019-05-24 14:59:10 -07:00
Philip Rideout
5bdbf63ff6 gltf_baker now has an export modal. 2019-05-24 14:59:10 -07:00
Mathias Agopian
d3753ca463 fix framegraph test 2019-05-24 11:10:18 -07:00
Mathias Agopian
ca20ae3851 handle levels of textures in the framegraph
- it's now possible to use a level of a texture as an attachment of
  a rendertarget in the framegraph, by simply setting the desired level
  when specifying an attachment.

- for now, removed the (never used) feature where the framegraph could
  resize a resource under-the-hood.

- when requesting the physical renderder target by calling
  getRenderTarget(), we now must specify the same level that was used
  when the rendertarget was created. This is not ideal, and we hope
  to fix that in the future, but it'll require some serious internal
  changes (and maybe API changes)
2019-05-24 10:22:23 -07:00
Mathias Agopian
ea6d8dd212 Simplify useRenderTarget() helper and update accesses
- useRenderTarget() has a helper for simple cases, make it even more
easy to use. It assumes a single color attachment w/ WRITE access,
which is a common case.

- update all useRenderTarget() access flags
2019-05-24 10:22:23 -07:00
Mathias Agopian
92dfeb63dc Fix wrong assert in createRenderTarget()
- we were not taking the attachment's level into account.
2019-05-24 10:22:23 -07:00
Ben Doherty
68d6b5718e Unbind textures / sampler groups in Metal backend when destroyed, add SSAO workaround (#1222) 2019-05-24 09:14:25 -07:00
Philip Rideout
8f1d4ffa4d gltf_baker now parameterizes in a background thread. 2019-05-23 22:06:43 -07:00
Philip Rideout
3b2d75e129 gltf_baker now has adjustable resolution. 2019-05-23 22:06:43 -07:00
Mathias Agopian
2d2be0a214 update min/max LOD when using a texture as attachment
This fixes a problem where the min lod of a texture would be set
incorrectly when first drawing into the base level (common case) and
then creating a mipmap chain from it using blits.
Because drawing into the texture doesn't set the base level, after the
blit, the min level would be set to 1 instead of 0.

In fact, there was no way to set the level of a texture by drawing into
it, the only ways were by blitting or uploading data.


This change updates the min/max LOD when a texture level is attached to 
a rendertarget, regardless of whether we read or write -- assuming that
we will write to it. The problem is that at that stage we don't know
if we will read or write. That said, if the user attaches an uninitialized
level to read from it, who cares what really happens
2019-05-23 21:47:05 -07:00
Mathias Agopian
1716f9e7cd fix our ostream << hex << char
Even when hex modifier is used, 'char' should be printed as characters,
this is particularly relevant with 0.
e.g. out << (char)0, should write a nul terminator, not "0".
2019-05-23 21:46:28 -07:00
Mathias Agopian
da0d94caf2 promote uint8_t (i.e. uchar) to printable ints
An easy way to do this is to prepend a "+" to the variable.
2019-05-23 21:46:03 -07:00
Pixelflinger
1b41ef78cd Use depth culling when computing SSAO
Since we have a depth buffer, we might as well use it for depth-culling,
this automatically discards the skybox's fragments -- which we can
assume won't participate in SSAO.
2019-05-23 16:35:16 -07:00
Mathias Agopian
83c523256d fix debug builds 2019-05-23 13:09:11 -07:00
Pixelflinger
507aeb1e34 ssao is now done in quarter resolution
- this means that we cannot share the depth pass between ssao and color
passes, so all this code is removed, which simplify things a lot.

- the depth pass code is moved into the ssao codepath since they're now
intimately linked.

- and finals ssao shader can't rely on frameUniform which is set up with
the main buffer's size (instead of 1/4 res).
2019-05-23 12:59:22 -07:00
Romain Guy
43115e1f3b Update release notes 2019-05-23 12:56:56 -07:00
Romain Guy
0a5c068cb6 Switch specular AA to Tokuyoshi and Kaplanyan (#1218)
This replaces the previous "curvature to roughness" method. Both are related
and rely on the screen space variance of geometric normals but this new
solution offers more control (the screen space variance and the clamping
threshold can be controlled).
2019-05-23 12:56:26 -07:00
Ben Doherty
af559a1344 Use correct iPhone SDK availability flag, remove iOS OpenGL warnings (#1214) 2019-05-23 10:48:43 -07:00
Pixelflinger
0f69dbb0cf FrameGraph RenderTarget can now control how they're accessed
It's now possible to set if a render target's attachment is accessed
for read and/or write -- instead of always being hardcoded to both.

We just add an "access" field to Attachment, which is still set to
RW by default, but can be set in useRenderTarget(). 

The access mode only affects building the graph -- in the end it's just
a regular render target.
2019-05-22 18:40:52 -07:00
Philip Rideout
d7778e29b0 Light maps are now dilated to remove seams. 2019-05-22 12:33:07 -07:00
Mathias Agopian
9388aab32e fix ssao issue and rework RenderPass commandTypeFlags
There are now only 2 main commandTypeFlags, COLOR and DEPTH,
indicating if we need to generate respectively COLOR and DEPTH commands.
The command generation code, only has 3 implementations: DEPTH, COLOR and
DEPTH + COLOR.

We also add "options" flags that get passed along, used to control what
goes into the the depth pass -- this because sometimes we don't want
translucent or alpha masked objects. e.g. when rendering the shadow pass,
we want the DEPTH + shadow casters regardless of if they're translucent.


With this, we can fix a SSAO problem where alpha-masked objects where
not participating when the depth pre-pass was used. Now, we add those
objects to the DEPTH if SSAO is active and MSAA is not.
2019-05-22 09:54:13 -07:00
Ben Doherty
6d3cbb8d32 Accept MSAA render targets in MetalBlitter (#1194) 2019-05-22 09:05:06 -07:00
Ben Doherty
dd0e0840b8 Fix Metal error when sampler has not been bound (#1210) 2019-05-22 08:56:09 -07:00
Philip Rideout
5a5b6720b0 Add distance field generator to libimage.
This adds some new functions to libimage for computing distance fields
and coordinate fields. This runs on the CPU but uses an efficient
algorithm. This will initially be leveraged by the baking pipeline to
dilate charts, but could be useful in other applications.
2019-05-21 20:21:41 -07:00
Romain Guy
a4a26ef528 Update RELEASE_NOTES 2019-05-21 19:27:58 -07:00
Jeff McGlynn
9fe60a6368 Add proguard annotations for code used by native/reflection (#1207)
Filament references a few classes from native code and by reflections,
so when proguarding binaries we typically had to add an exception for
filament to make it run:

-keep class com.google.android.filament.** {*;}

In a compiled .dex file, the filament namespace takes about 120kb
(before compression), even if the classes aren't used.

To enable proguarding and stripping out unused filament classes,
introduce a UsedByNative and UsedByReflection annotation to explicitly
mark classes that need to be kept in the dex, so that the rest can be
potentially stripped out.

In my testing, this reduces the filament namespace in the .dex from
120kb->40kb, which translates to about 30kb apk size savings after
compression.
2019-05-20 21:02:54 -07:00
Philip Rideout
e2c3dfd341 xatlas: do not remove small faces 2019-05-20 19:37:37 -07:00
Philip Rideout
2687bf99d6 xatlas: fix crash caused by faulty spatial hash.
If A and B are equal keys, then hash(A) and hash(B) should be equal, but
xatlas was violating this constraint.

This bug was not present in Thekla's original code, it was introduced
later by the xatlas project.
2019-05-20 19:37:37 -07:00
Romain Guy
3d39f64c0d Move comment 2019-05-20 14:56:00 -07:00
Romain Guy
60bc860e76 Move IOR code to common_lighting 2019-05-20 14:54:44 -07:00
Romain Guy
2377287890 Fix curvatureToRoughnes 2019-05-20 14:50:44 -07:00
Romain Guy
cabdc255f5 Shader code cleanup
roughness is now called perceptualRoughness and linearRoughness
is now called roughness. It better matches papers, etc.
2019-05-20 14:45:26 -07:00
Philip Rideout
ac11e2b79a cgltf_writer: fix inconsistent buffer size.
`extension_flags` was uninitialized, which caused intermittent junk in
the output.
2019-05-20 13:23:47 -07:00
Philip Rideout
8f0fcc4efd xatlas: fix read-from-freed.
This fix has also been been submitted to the upstream repo.
2019-05-20 13:23:47 -07:00
Ben Doherty
399f7c24ac Fix flaky sstream test (#1205) 2019-05-20 13:09:03 -06:00
Philip Rideout
fdefa16cae jsbindings: add setColor4Parameter and rename setColorParam.
JavaScript does not have overloading so we generally use a numeric
suffix to distinguish overloads.

Fixes #1202
2019-05-20 10:43:38 -07:00
Mathias Agopian
95b4cdf819 Fix SSAO and SAO on Mobile devices
The fragment shader didn't work because of the default mediump
precision for floats on mobile.
We had the highp precision qualifier where needed.
2019-05-19 23:25:28 -07:00
Mathias Agopian
517bfc54c5 Use SAO style ambient occlusion
Both SSAO and SAO are available, but currently only
SSAO can be used.
SAO is more correct and produces less "halos", but
SSAO is sometimes more pleasant.

Note that this doesn't implement all the SAO optimizations
yet.
2019-05-19 23:25:28 -07:00
Pixelflinger
e840e72755 improve depth test usage and tracking
We now disable the depth test entirely when possible. this should save
a few gl calls.
2019-05-19 23:24:45 -07:00
Philip Rideout
992e27c4e0 Update cgltf to fix unlit materials. 2019-05-18 20:43:31 -07:00
Philip Rideout
cfb6a1c917 gltf_baker: add diagnostics. 2019-05-18 20:43:31 -07:00
Romain Guy
0347fb0441 Add new material properties: specular/multiBounceAmbientOcclusion (#1198) 2019-05-18 14:30:08 -07:00
Philip Rideout
24a77023bd Add AssetPipeline::bakeAllOutputs for diagnostic purposes. 2019-05-17 10:01:26 -07:00
Philip Rideout
07be9d1721 PathTracer: add bent normals and diagnostic targets. 2019-05-17 10:01:26 -07:00
Ben Doherty
88f6f4827c Allow creating and using MSAA textures as render targets (#1186) 2019-05-16 16:44:38 -07:00
Philip Rideout
9a72831a33 AssetPipeline can now preview baked texture. 2019-05-16 15:53:20 -07:00
Philip Rideout
59f929c7d3 Fix "already freed" bug in gltf_baker. 2019-05-16 15:53:20 -07:00
Romain Guy
f0aab6e46a Add micro-shadowing feature (#1188)
* Add micro-shadowing based on ambient occlusion

* Prevent crash when IBL is turned off

* Apply micro-shadows to baked AO only

* Remove debug code

* Add opacity control

* Fix opacity term

* Switch to micro-shadowing from Chan 2018
2019-05-16 12:24:16 -07:00
Romain Guy
8d7d10ae81 Use 64x64 DFG LUT on mobile targets (#1191)
The size of the LUT is now configurable at build-time with
-DDFG_LUT_SIZE=XX. It is 128x128 on desktop, 64x64 on Android,
WebGL and iOS.
2019-05-16 11:35:49 -07:00
Philip Rideout
c112b3ce40 Introduce AssetPipeline::SCALE_TO_UNIT to boost bake quality. 2019-05-15 16:44:33 -07:00
Philip Rideout
affc947ce0 gltf_baker: improve error reporting. 2019-05-15 16:44:33 -07:00
Philip Rideout
cbfb364c41 Introduce libs/rays and implement AO baking.
The AO baking procedure consists of the following steps:

1. Flatten the glTF hierarchy.
2. Generate a single 2D parameterization for the entire scene.
3. Embree Pass 1: Create G-Buffer using the above UVs as vert positions.
4. Embree Pass 2: Cast rays from the positions embedded in the G-Buffer.

The `gltf_baker` tool is not ready for general use but already
produces reasonable results for certain well-formed models.
2019-05-15 13:10:56 -07:00
Philip Rideout
c84c60112e Implement the bake button, uses a "UV camera" to cast primary rays. 2019-05-15 13:10:56 -07:00
Romain Guy
a9ef45dc9a Remember the high intensity for directional lights (#1184)
Fixes #1183
2019-05-14 09:02:09 -07:00
Romain Guy
bdd3e343ba Add multi-bounce AO based on GTAO (#1180) 2019-05-14 08:58:49 -07:00
Philip Rideout
cd364b029c gltf_baker: fix needless reload for rendering. 2019-05-13 18:55:56 -07:00
Philip Rideout
3e1ed97187 Add QUIET to find_package with embree, etc. 2019-05-13 18:55:37 -07:00
Ben Doherty
daddc25de8 Remove std::sstream from filamat (#1176) 2019-05-13 13:56:15 -07:00
Philip Rideout
4237ff42c9 PathTracer now generates ambient occlusion.
For now this uses the geometric normals provided by embree rather than
the smooth normals that ship with the model, I will fix this next.
2019-05-13 10:25:12 -07:00
Philip Rideout
3291fb6a1b Introduce gltf_baker tool. 2019-05-13 10:25:12 -07:00
Philip Rideout
f5b47dc95e PathTracer should not exceed MAX_JOB_COUNT. 2019-05-10 14:40:17 -07:00
Mathias Agopian
4f6d15d849 Try to handle “bad” normals
Normals reconstructed from derivatives at an edge are invalid and 
Cause dark spots in the final AO. We try to detect this case and
Assume no AO, which could be wrong too, but looks better more often.

I don’t think it’ll have an impact on performance because the normals
for the whole quad should be wrong together.
2019-05-10 13:58:00 -07:00
Ben Doherty
c35c1b6426 Fix Metal warnings (#1175) 2019-05-10 09:33:47 -07:00
Philip Rideout
80f6f18e54 Introduce gltfio::PathTracer and baking API.
AssetPipeline now has a path tracer and optionally uses embree. For now,
the path tracer only sends out visibility rays and generates a simple
hit-or-miss monochrome bitmap. It splits the render target into tiles
and invokes a JobSystem task for each tile.

Filament developers can optionally install embree using homebrew or a
debian package. This avoids bloating third_party and increasing our
build time. If embree is not installed, a friendly run-time error will
occur when attempting to invoke the rendering functionality in
AssetPipeline.

The AO code is not yet implemented, but this PR sets up the
infrastructure, API, and camera rays.
2019-05-10 08:04:09 -07:00
Romain Guy
ac8f55099d Indent SSAO options 2019-05-09 17:18:37 -07:00
Adrian Perez
3987da830c Fix -Wconversion issue in public header (#1172) 2019-05-09 17:00:34 -07:00
Mathias Agopian
cbae6120e1 Ambient Occlusion APIs are more descriptive
Use “AmbientOcclusion” instead of SSAO in all APIs.
2019-05-09 16:36:18 -07:00
Mathias Agopian
011daa952e Add API for controlling SSAO 2019-05-09 16:36:18 -07:00
Philip Rideout
cb98b75400 Implement AssetPipeline::parameterize() using xatlas. (#1167)
This feature consumes a flattened glTF asset and produces a glTF asset
with new topology and an additional set of UV coordinates suitable for
baking light maps.

I verified with a couple glTF models that the generated assets are
visually equivalent to the source assets, even though the topology and
scene hierarchy is different.

The actual light baking is not yet implemented, but this is a major step
towards that goal.
2019-05-09 14:09:27 -07:00
Ben Doherty
9a87b05570 Add new filamat_lite target to filamat (#1168) 2019-05-08 14:04:00 -07:00
Mathias Agopian
725ea06400 Add a contrast control for SSAO
This approximates ao^n with 1 <= n <=2 and gives a little bit of
control over the ambient occlusion contrast.
2019-05-07 18:35:19 -07:00
Mathias Agopian
facaa3326b SSAO is now configurable through the debug manager 2019-05-07 18:35:19 -07:00
Mathias Agopian
062ec48ee6 Implement basic SSAO 2019-05-07 18:35:19 -07:00
Mathias Agopian
6e0dc1dd2c set-up framegraph for SSAO
wip: This is very early stage.
2019-05-07 18:35:19 -07:00
Mathias Agopian
64afe136f6 Fix linkage errors
FMaterialInstance::setParameter<> template needs to be accessible from
other modules.
2019-05-07 18:35:19 -07:00
Ben Doherty
e7749c59ce Implement Metal fences (#1162) 2019-05-07 10:16:20 -07:00
Romain Guy
841f76f510 Update roughness-prefilter 2019-05-03 12:01:31 -07:00
Philip Rideout
2e391b01fe Introduce AssetPipeline for performing glTF manipulations. (#1163)
* Introduce AssetPipeline for performing glTF manipulations.

AssetPipeline offers a place for doing things like scene flattening,
transform baking, and optimization of glTF assets. These types of scene
manipulations will allow us to tackle lightmap baking in the upcoming
atlasgen tool.

This initial PR includes support for scene flattening, which is fairly
non-trivial. Support for parameterization via xatlas will be added in a
subsequent PR.

In a glTF asset, a single mesh can be referenced by several nodes, and
each reference can have a unique transform. AssetPipeline can flatten
the asset such that each instanced mesh has its own vertex data, and the
node transform gets baked into the vertex data.

Recall that gltfio is composed of two libraries: the core library (no
filamat) and the full library. This adds to the size of the full library
but leaves the core library as is.

* Fix various Windows build issues.
2019-05-03 09:49:04 -07:00
Philip Rideout
57fffab7b6 Improve SurfaceOrientation robustness when using UVs. (#1161)
Fix #1158
2019-05-03 08:18:13 -07:00
Gareth Morgan
45636e5afe Correct JS bindings for (#1137)
* Correct bindings for TransformManager::create and VertexBuffer::Builder::attribute

* Correct types
2019-05-01 17:09:32 -07:00
Ben Doherty
843372ace3 Only use Depth24Stencil8 textures on supported devices (#1160) 2019-05-01 12:35:45 -07:00
Benjamin Doherty
511a11a573 Implement Metal blitting 2019-05-01 12:06:27 -07:00
Mathias Agopian
13ae670568 framegraph improvements
- can now return the name of a pass in setup or execute
- can easily retrieve a rsrc descriptor in setup
2019-04-30 22:28:52 -07:00
Romain Guy
97850c62c7 Cleanup of filamat (#1157)
* Cleanup of filamat

* Add missing include
2019-04-30 16:39:22 -07:00
Pixelflinger
5b4ec6fd7d break dependency of Platforms on their backend
Platform implementations shouldn't depend on the concrete implementation
of the driver. e.g. PlatfromEGL.h shouldn't include OpenglDriver.h,
there is no reason for it.

Instead, we now have a {OpenGL|Vulkan|Metal}DriverFactory.h which is
only responsible to instantiate the correct concrete implementation
of the driver and Platform implementation only depend on that.

This effectively completely isolate the backend's header, which should
be completely private, and now is.

One benefit is that the backend's header needs to include 
DriverAPI.inc which uses complex macros and this used to be expanded
multiple times, for each Platform. So this should help a bit with 
build times.

We also mark *all* methods of all backends as "ALWAYS_INLINE inline",
which save quite a bit of code, without it, the compiler had to
instantiate each method twice. This saves 12KB on the final, stripped
libfilament-jni.so
2019-04-30 14:37:04 -07:00
Mathias Agopian
e4107201a3 Size optimizations
Most time we use ALWAYS_INLINE, we also intent to use "inline", which
allows the compiler to not emit the inlined function at all.
2019-04-30 14:37:04 -07:00
Philip Rideout
b9879cf23b Repair Vulkan: addBlob should return an index. (#1156) 2019-04-30 14:08:39 -07:00
Philip Rideout
2bc0e49bc7 Vulkan support for new RenderTarget DriverAPI. (#1153) 2019-04-30 13:20:24 -07:00
Romain Guy
f6767b59f5 Remove use after moves (#1155)
* Remove use after moves

* Remove unnecessary dependency
2019-04-30 13:18:49 -07:00
Philip Rideout
5228aba5dd Add xatlas and cgltf_write to third_party. (#1154)
This preps for an upcoming AO baking tool.
2019-04-30 12:54:40 -07:00
Benjamin Doherty
9a69a755bc Add Metal support 2019-04-30 00:14:07 -07:00
Pixelflinger
c688874064 Explicit RenderBuffer in RenderTarget
RendeTargets are now created with explicit RenderBuffer (that is 
Texture object in filament vocabulary).
2019-04-30 00:14:07 -07:00
Mathias Agopian
9e6d5f7727 backend textures can now represent a renderbuffer
We have a new TextureUsage::SAMPLEABLE flag, that is the default,
used for "regular" textures that can be sampled.
When this flag is not set, a RenderBuffer (in GL parlance) is
created instead.

This will be needed in an upcoming PR for creating RenderTarget more
explicitly.
2019-04-30 00:14:07 -07:00
Philip Rideout
59f1fb8956 gltfio: fix file path bug. (#1151)
The cgltf "base path" that gets passed to cgltf_load_buffers should
actually be the path to original glTF file, otherwise bin filepaths
are resolved incorrectly.
2019-04-29 22:42:17 -07:00
Mathias Agopian
224faeacb6 update code style / formatting clion config files 2019-04-26 15:38:40 -07:00
Mathias Agopian
f0465e442f release notes file.
this is intended to help creating releases. this
file should be updated each time a commit is significant enough that it should be mentioned in
release notes.

when doing code reviews, reviewers should take this into account for approval.
2019-04-26 14:50:38 -07:00
Benjamin Doherty
849bc91506 Remove necessity for frames to render to the default render target 2019-04-26 12:39:12 -07:00
Benjamin Doherty
f15667838b Fix bug-prone shader text loading 2019-04-26 12:39:12 -07:00
Benjamin Doherty
9ae2fe84f4 Remove automatic depth buffer creation for Metal swap chains 2019-04-26 12:39:12 -07:00
Mathias Agopian
0398aa4c67 fix minor issues
- use the clear flags to skip the clear code earlier

- better detection of the msaa RenderTarger with non msaa attachments
2019-04-25 16:22:39 -07:00
Mathias Agopian
409f95b50a disable "reverse resolve" and add some asserts
"reverse resolve" is needed on desktop to emulate
EXT_multisampled_render_to_texture. However, it is not easily supported
on Metal or GLES. So for now we avoid relying on this.

This means that filament requirements are lower than what
EXT_multisampled_render_to_texture guarantees.

Essentially filament doesn't rely on being able to preserve the 
content of a non-ms texture attached to a ms RenderTarget.

Also don't rely on being able to resolve+resize/move, which is
not supported in GLES.
2019-04-25 15:27:33 -07:00
Mathias Agopian
510451a35e minor clean-up 2019-04-25 15:27:33 -07:00
Mathias Agopian
a781fb6f2b support compilers that don't have attribute(packed)
this fixes #1140
2019-04-24 22:08:14 -07:00
Mathias Agopian
a429f361b8 TargetBufferFlags is now more comfortable to use
Added BitmaskType requirements so that we can easily and
safely do bitmask operations on TargetBufferFlags.
2019-04-24 16:21:11 -07:00
Mathias Agopian
be5d06d3c8 Emulate better EXT_multisampled_render_to_texture
We need to load the content of the resolved texture at
beginRenderPass time.
2019-04-24 16:21:11 -07:00
Mathias Agopian
ce6baeb714 debug: clear discarded buffers in debug builds
We now always clear in red/green discarded start/end attachments.
This is to make sure to expose discard bugs.
2019-04-23 18:27:39 -07:00
Mathias Agopian
85122d3fa9 method to get the GLbitfield from TargetBufferFlags 2019-04-23 18:27:39 -07:00
Mathias Agopian
5255871f1a fix blit from multi-sample rendertarget
there was a case where blitting from a multisample target with
a mix of multisample and non multisample attachments wouldn't work,
only the resolved non-multisample texture could be blitted.

this fix assumes that resolving doesn't damage the multisample buffer,
which is NOT TRUE on android with the EXT_multisampled_render_to_texture
extension. this will be fixed later.
2019-04-23 18:27:39 -07:00
Mathias Agopian
bd145cf18b Fix a FrameGraph discard bug with imported rendertargets
Imported render target's discard flags (i.e. the imported flags)
were ignored, which means we were discarding the imported buffer
each time we were drawing into it, especially the 2nd time when
drawing the ImGUI.
2019-04-23 18:27:24 -07:00
Ben Doherty
04859da116 Add hello-ar iOS sample (#1124) 2019-04-23 18:11:22 -07:00
Ben Doherty
1b41a73eb0 Fix incorrect depth comparisons with floating point depth formats (#1129) 2019-04-23 18:10:47 -07:00
Philip Rideout
9081a0b657 Add another missing file to site. 2019-04-23 15:14:54 -07:00
Philip Rideout
d87714e4ef Add missing files to web site. 2019-04-23 15:13:24 -07:00
Philip Rideout
45fae716de Update WebGL docs. 2019-04-23 15:04:06 -07:00
3956 changed files with 486583 additions and 79538 deletions

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

@@ -0,0 +1,108 @@
name: Presubmit
on: [pull_request]
jobs:
build-desktop:
name: build-desktop
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
cd build/$WORKFLOW_OS && ./build.sh ${TARGET}
env:
TARGET: presubmit
build-windows:
name: build-windows
runs-on: windows-latest
steps:
- name: Checkout Filament
run: |
git version
git init %GITHUB_WORKSPACE%
cd %GITHUB_WORKSPACE%
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +%GITHUB_REF%:%GITHUB_REF:refs/=refs/remote/%
git checkout --progress --force %GITHUB_REF:refs/=refs/remote/%
shell: cmd
- name: Run build script
run: |
build\windows\build-github.bat
build-android:
name: build-android
runs-on: macos-latest
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- name: Run build script
run: |
cd build/android && ./build.sh ${TARGET}
env:
TARGET: presubmit
build-ios:
name: build-iOS
runs-on: macos-latest
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- name: Run build script
run: |
cd build/ios && ./build.sh ${TARGET}
env:
TARGET: presubmit
build-web:
name: build-web
runs-on: macos-latest
steps:
- name: Checkout Filament
run: |
git version
git init $GITHUB_WORKSPACE
cd $GITHUB_WORKSPACE
git remote add origin https://github.com/google/filament
git config gc.auto 0
git fetch --tags --prune --progress --no-recurse-submodules origin +${GITHUB_REF}:${GITHUB_REF/refs\//refs\/remote\/}
git checkout --progress --force ${GITHUB_REF/refs\//refs\/remote\/}
- name: Run build script
run: |
cd build/web && ./build.sh ${TARGET}
env:
TARGET: presubmit

6
.gitignore vendored
View File

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

View File

@@ -1,7 +1,7 @@
# ==================================================================================================
# CMake
# ==================================================================================================
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.10)
# ==================================================================================================
# Project declaration
@@ -18,6 +18,8 @@ option(USE_EXTERNAL_GLES3 "Experimental: Compile Filament against OpenGL ES 3" O
option(GENERATE_JS_DOCS "Build WebGL documentation and tutorials" OFF)
option(ENABLE_LTO "Enable link-time optimizations if supported by the compiler" OFF)
# ==================================================================================================
# OS specific
# ==================================================================================================
@@ -25,6 +27,10 @@ if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL)
set(LINUX TRUE)
endif()
if (ANDROID OR WEBGL OR IOS)
set(IS_MOBILE_TARGET TRUE)
endif()
if (WIN32)
# Link statically against c/c++ lib to avoid missing redistriburable such as
# "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
@@ -44,19 +50,46 @@ if (WIN32)
set(CRT_FLAGS_DEBUG "/MDd")
endif()
# TODO: Figure out why pdb generation messes with incremental compilaton.
# IN RELEASE_WITH_DEBUG_INFO, generate debug info in .obj, no in pdb.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
# TODO: Figure out why pdb generation messes with incremental compilaton.
# IN RELEASE_WITH_DEBUG_INFO, generate debug info in .obj, no in pdb.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CRT_FLAGS_RELEASE} /Z7")
# In DEBUG, avoid generating a PDB file which seems to mess with incremental compilation.
# Instead generate debug info directly inside obj files.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
endif()
# In RELEASE, also generate PDBs.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CRT_FLAGS_RELEASE} /Zi")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${CRT_FLAGS_RELEASE} /Zi")
# In DEBUG, avoid generating a PDB file which seems to mess with incremental compilation.
# Instead generate debug info directly inside obj files.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CRT_FLAGS_DEBUG} /Z7")
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 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)
message("Found TBB ${TBB_VERSION}")
add_definitions(-DFILAMENT_HAS_EMBREE)
set(DENOISE_LIBRARY OpenImageDenoise)
else()
message("TBB 2019 not found.")
endif()
else()
message("Embree not found, pipeline features are disabled.")
endif()
# ==================================================================================================
@@ -77,13 +110,13 @@ set(TOOLS ${CMAKE_CURRENT_SOURCE_DIR}/tools)
# ==================================================================================================
# Compiler check
# ==================================================================================================
set(MIN_CLANG_VERSION "5.0")
set(MIN_CLANG_VERSION "6.0")
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()
@@ -91,13 +124,31 @@ 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")
set(CLANG_CL true)
endif()
elseif (MSVC)
set(MSVC_NATIVE true)
endif()
# ==================================================================================================
# Link time optimizations (LTO)
# ==================================================================================================
if (ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORT)
if (IPO_SUPPORT)
message(STATUS "LTO support is enabled")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
# ==================================================================================================
@@ -108,7 +159,12 @@ 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_NATIVE)
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)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_EXTERNAL_GLES3")
@@ -120,25 +176,16 @@ endif()
if (LINUX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
if (FILAMENT_REQUIRES_CXXABI)
# Required in CI environment with custom libc++ and libc++abi
link_libraries(libc++abi.a)
endif()
# To distribute our binaries, we must remove the dependency on libc++ and libgcc.
if (CMAKE_BUILD_TYPE STREQUAL "Release")
link_libraries("-static-libgcc -static-libstdc++")
endif()
else()
if (FILAMENT_REQUIRES_CXXABI)
message("The option FILAMENT_REQUIRES_CXXABI is unsupported on this platform")
endif()
link_libraries("-static-libgcc -static-libstdc++")
link_libraries(libc++.a)
link_libraries(libc++abi.a)
endif()
if (CYGWIN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
endif()
if (CLANG_CL)
if (CLANG_CL OR 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")
@@ -154,7 +201,7 @@ endif()
# ==================================================================================================
# Release compiler flags
# ==================================================================================================
if (NOT CLANG_CL)
if (NOT CLANG_CL AND NOT MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ffunction-sections -fdata-sections")
endif()
@@ -172,7 +219,7 @@ endif()
# -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 CLANG_CL AND NOT MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
@@ -245,6 +292,36 @@ else()
option(FILAMENT_BUILD_FILAMAT "Build filamat and JNI buildings" OFF)
endif()
# ==================================================================================================
# Material compilation flags
# ==================================================================================================
# Target system.
if (IS_MOBILE_TARGET)
set(MATC_TARGET mobile)
else()
set(MATC_TARGET desktop)
endif()
set(MATC_API_FLAGS )
# TODO: Add a flag to build Filament without support for OpenGL.
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a opengl)
if (FILAMENT_SUPPORTS_VULKAN)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a vulkan)
endif()
if (FILAMENT_SUPPORTS_METAL)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a metal)
endif()
# Only optimize materials in Release mode (so error message lines match the source code)
if (NOT CMAKE_BUILD_TYPE MATCHES Release)
set(MATC_OPT_FLAGS -g)
endif()
set(MATC_BASE_FLAGS ${MATC_API_FLAGS} -p ${MATC_TARGET} ${MATC_OPT_FLAGS})
# ==================================================================================================
# Distribution
# ==================================================================================================
@@ -259,20 +336,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.
# ==================================================================================================
@@ -312,7 +416,9 @@ function(get_resgen_vars ARCHIVE_DIR ARCHIVE_NAME)
${ARCHIVE_DIR}/${ARCHIVE_NAME}.apple.S
${ARCHIVE_DIR}/${ARCHIVE_NAME}.h
)
set(ASM_ARCH_FLAG "-arch ${DIST_ARCH}")
if (IOS)
set(ASM_ARCH_FLAG "-arch ${DIST_ARCH}")
endif()
if (APPLE)
set(ASM_SUFFIX ".apple")
endif()
@@ -344,6 +450,7 @@ add_subdirectory(${LIBRARIES}/geometry)
add_subdirectory(${LIBRARIES}/gltfio)
add_subdirectory(${LIBRARIES}/ibl)
add_subdirectory(${LIBRARIES}/image)
add_subdirectory(${LIBRARIES}/rays)
add_subdirectory(${LIBRARIES}/math)
add_subdirectory(${LIBRARIES}/utils)
add_subdirectory(${FILAMENT}/filament)
@@ -353,7 +460,9 @@ add_subdirectory(${EXTERNAL}/smol-v/tnt)
add_subdirectory(${EXTERNAL}/benchmark/tnt)
add_subdirectory(${EXTERNAL}/meshoptimizer)
add_subdirectory(${EXTERNAL}/cgltf/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
@@ -390,14 +499,15 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
add_subdirectory(${LIBRARIES}/bluegl)
add_subdirectory(${LIBRARIES}/filagui)
add_subdirectory(${LIBRARIES}/imageio)
add_subdirectory(${LIBRARIES}/matdbg)
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)
@@ -417,6 +527,11 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS)
add_subdirectory(${TOOLS}/roughness-prefilter)
add_subdirectory(${TOOLS}/skygen)
add_subdirectory(${TOOLS}/specular-color)
if (DENOISE_LIBRARY)
add_subdirectory(${EXTERNAL}/OpenImageDenoise/tnt)
endif()
endif()
# Generate exported executables for cross-compiled builds (Android, WebGL, and iOS)

103
README.md
View File

@@ -43,13 +43,23 @@ 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)
![Chess set](docs/images/samples/chess1.jpg)
![Material 1](docs/images/samples/material_01.jpg)
![Material 2](docs/images/samples/material_02.jpg)
![Material 3](docs/images/samples/material_03.jpg)
![Material 6](docs/images/samples/material_06.jpg)
![Material 8](docs/images/samples/material_08.jpg)
## Applications
Here are a few screenshots of applications that use Filament in production:
### 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](docs/images/samples/app_google_3d_viewer.jpg)
## Features
### APIs
@@ -75,17 +85,18 @@ Here are a few sample materials rendered with Filament:
- Metallic workflow
- Clear coat
- Anisotropic lighting
- Approximated translucent (subsurface) materials (direct and indirect lighting)
- Approximated translucent (subsurface) materials
- Cloth shading
- Normal mapping & ambient occlusion mapping
- Image-based lighting
- Physically-based camera (shutter speed, sensitivity and aperture)
- Physical light units
- Point light, spot light and directional light
- SSAO
- ACES-like tone-mapping
- Temporal dithering
- FXAA or MSAA
- Dynamic resolution (on Android)
- FXAA, MSAA and specular anti-aliasing
- Dynamic resolution (on Android and iOS)
### Future
@@ -127,11 +138,13 @@ and tools.
- `filamat`: Material generation library
- `filameshio`: Tiny filamesh parsing library (see also `tools/filamesh`)
- `geometry`: Mesh-related utilities
- `gltfio`: Loader for glTF 2.0
- `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`
@@ -170,11 +183,16 @@ To build the Java based components of the project you can optionally install (re
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.3
- Android Studio 3.5
- Android SDK
- Android NDK 19 or higher
- Android NDK "side-by-side" 20 or higher
### Environment variables
@@ -231,14 +249,36 @@ $ ./build.sh -j release
If you use CMake directly instead of the build script, pass `-DENABLE_JAVA=OFF` to CMake instead.
### Filament-specific CMake Options
The following CMake options are boolean options specific to Filament:
- `ENABLE_JAVA`: Compile Java projects: requires a JDK and the JAVA_HOME env var
- `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
- `GENERATE_JS_DOCS`: Build WebGL documentation and tutorials
- `INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
- `USE_EXTERNAL_GLES3`: Experimental: Compile Filament against OpenGL ES 3
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`
- `clang-7` or higher
- `libglu1-mesa-dev`
- `libc++-7-dev` (`libcxx-devel` and `libcxx-static` on Fedora)
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora)
- `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`
@@ -254,13 +294,6 @@ $ cd out/cmake-release
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
```
If you experience link errors you must ensure that you are using `libc++abi` by passing this
extra parameter to `cmake`:
```
-DFILAMENT_REQUIRES_CXXABI=true
```
Your Linux distribution might default to `gcc` instead of `clang`, if that's the case invoke
`cmake` with the following command:
@@ -330,6 +363,33 @@ See [ios/samples/README.md](./ios/samples/README.md) for more information.
### Windows
#### Building on Windows with the Visual Studio 2019 compiler
Install the following components:
- [Visual Studio 2019](https://www.visualstudio.com/downloads)
- [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)
Open the `x64 Native Tools Command Prompt for VS 2019`.
Create a working directory, and run cmake in it:
```
> mkdir out
> cd out
> cmake ..
```
Then, you should be able to load the generated solution file `TNT.sln` in Visual Studio and build the `material_sandbox` project.
Run it from the `out` directory with:
```
> samples\Debug\material_sandbox.exe ..\assets\models\monkey\monkey.obj
```
#### Building on Windows with the Clang compiler
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.
@@ -706,8 +766,9 @@ 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 RGBM files
for the IBL. To generate an IBL simply use this command:
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
@@ -723,7 +784,7 @@ pre-filtered environment map (one file per cubemap face and per mip level), the
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.5`. The numerical
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

113
RELEASE_NOTES.md Normal file
View File

@@ -0,0 +1,113 @@
# Filament Release Notes log
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.
## 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.
## 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
- Unified Filament Sceneform and npm releases.
- Improved cmgen SH with HDR images.
- IndirectLight can now be queried for dominant direction and color.
- Added support for vertex morphing.
- Introduced custom attributes, accessible from the vertex shader.
- Added Java / Kotlin bindings for KtxLoader.
- Added JavaScript / Typescript bindings for the new `RenderTarget` class.
- Added base path to glTF loadResources method for JavaScript.
- Added support for iOS `CVPixelBuffer` external images with the OpenGL backend.
## sceneform-1.9pr4
- Added `gltf_bloom` Android sample to show gltfio and the `RenderTarget` API.
- Added `getMaterialInstanceAt` to the Java version of RenderableManager.
- Fix JNI bindings for setting values in parameter arrays.
- Added JNI bindings for the gltfio library.
- Fix support for parameter arrays in `.mat` files.
- Added support for `RGB_11_11_10`
- Removed support for `RGBM` (**warning:** source compatibility breakage)
- IBL cubemap can now be of any size
- `Texture::generatePrefilterMipmap` can be used for runtime generation of a reflection cubemap
## sceneform-1.9pr3
- Added `Scene.addEntities()` to the Java / Kotlin bindings.
- Improved robustness in the tangents utility for meshes that have tangents *and* normals.
- Introduced `RenderTarget` API that allows View to reference an offscreen render target.
- Added `lucy_bloom` sample to demonstrate the new `RenderTarget` API.
- Added Screen Space Ambient Occlusion support (SAO)
- New blending modes: `multiply` and `screen`
- Fixed an issue when sorting blended objects with different blending modes
- The material property `curvatureToRoughness` has been replaced with `specularAntiAliasing`.
This new specular anti-aliasing solution offers more control via two new properties:
`specularAntiAliasingVariance` and `specularAntiAliasingThreshold`. They can also be set on
material instances if needed
- Added specular ambient occlusion to compute a new AO term applied to specular reflections
(see `specularAmbientOcclusion` property in materials)
- Added multi-bounce ambient occlusion to brighten AO and preserve local color
(see `multiBounceAmbientOcclusion` property in materials)
- Micro-shadowing is now applied to material ambient occlusion
- Use a smaller 64x64 DFG LUT on mobile to reduce binary size
- Added a distance field generator to libimage.
- JavaScript MaterialInstance now supports vec4 colors.
- Further reduced `filamat` binary size by removing reliance on stdlib.
- Added a new, smaller, version of the `filamat` library, `filamat_lite`. Material optimization and
compiling for non-OpenGL backends have been removed in favor of a smaller binary size.
- Implemented hard fences for the Metal backend, enablying dynamic resolution support.
- Improved `SurfaceOrientation` robustness when using UVs to generate tangents.
- Created a `RELEASE_NOTES.md` file, to be updated with significant PRs.
## sceneform-1.9pr2

View File

@@ -33,6 +33,7 @@ List<File> getBinaries(String name, File toolsPath) {
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;
@@ -115,6 +116,7 @@ class MaterialCompiler extends DefaultTask {
// This task handles incremental builds
class IblGenerator extends DefaultTask {
File cmgenPath
String cmgenArgs = null;
@SuppressWarnings("GroovyUnusedDeclaration")
@InputFile
@@ -154,9 +156,13 @@ class IblGenerator extends DefaultTask {
project.exec {
standardOutput out
if (!cmgenArgs) {
cmgenArgs = '--format=rgb32f --extract-blur=0.08 --extract=' + outputDir.absolutePath
}
cmgenArgs = cmgenArgs + " " + file
errorOutput err
executable "${cmgenPath}"
args('--format=rgbm', '--extract-blur=0.08', "--extract=${outputDir.absolutePath}", file)
args(cmgenArgs.split())
}
}

View File

@@ -18,8 +18,8 @@
#include <jni.h>
#include "CallbackUtils.h"
#include "NioUtils.h"
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <filament/Engine.h>

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "NioUtils.h"
#include "common/NioUtils.h"
#include <algorithm>

View File

@@ -9,3 +9,4 @@
/build
/captures
.externalNativeBuild
/.cxx

View File

@@ -1,10 +1,15 @@
cmake_minimum_required(VERSION 3.4.1)
cmake_minimum_required(VERSION 3.6)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
add_library(filamat STATIC IMPORTED)
set_target_properties(filamat PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilamat.a)
set(FILAMAT_FLAVOR "filamat")
if(FILAMAT_LITE)
set(FILAMAT_FLAVOR "filamat_lite")
endif()
add_library(${FILAMAT_FLAVOR} STATIC IMPORTED)
set_target_properties(${FILAMAT_FLAVOR} PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/lib${FILAMAT_FLAVOR}.a)
add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
@@ -14,10 +19,6 @@ add_library(filabridge STATIC IMPORTED)
set_target_properties(filabridge PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilabridge.a)
add_library(backend STATIC IMPORTED)
set_target_properties(backend PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbackend.a)
add_library(smol-v STATIC IMPORTED)
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
@@ -44,9 +45,8 @@ add_library(filamat-jni SHARED
)
target_link_libraries(filamat-jni
filamat
${FILAMAT_FLAVOR}
filabridge
backend
shaders
utils
log

View File

@@ -13,7 +13,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
@@ -25,7 +25,7 @@ allprojects {
}
group = "com.google.android.filament"
version = "0.1"
version = "1.3"
apply plugin: 'com.android.library'
@@ -35,10 +35,10 @@ if (project.hasProperty("filament_dist_dir")) {
}
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
minSdkVersion 14
targetSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "1.0"
@@ -47,7 +47,7 @@ android {
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-21")
arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")
@@ -65,6 +65,23 @@ android {
}
}
flavorDimensions "functionality"
productFlavors {
full {
dimension "functionality"
}
lite {
dimension "functionality"
externalNativeBuild {
cmake {
arguments.add("-DFILAMAT_LITE=ON")
}
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"

View File

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

View File

@@ -226,17 +226,24 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderShadowM
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderCurvatureToRoughness(
JNIEnv*, jclass, jlong nativeBuilder, jboolean curvatureToRoughness) {
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderSpecularAntiAliasing(
JNIEnv*, jclass, jlong nativeBuilder, jboolean specularAntiAliasing) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->curvatureToRoughness(curvatureToRoughness);
builder->specularAntiAliasing(specularAntiAliasing);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderLimitOverInterpolation(
JNIEnv*, jclass, jlong nativeBuilder, jboolean limitOverInterpolation) {
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderSpecularAntiAliasingVariance(
JNIEnv*, jclass, jlong nativeBuilder, jfloat variance) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->limitOverInterpolation(limitOverInterpolation);
builder->specularAntiAliasingVariance(variance);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderSpecularAntiAliasingThreshold(
JNIEnv*, jclass, jlong nativeBuilder, jfloat threshold) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->specularAntiAliasingThreshold(threshold);
}
extern "C" JNIEXPORT void JNICALL
@@ -253,6 +260,20 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderFlipUV(
builder->flipUV(flipUV);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderMultiBounceAmbientOcclusion(
JNIEnv*, jclass, jlong nativeBuilder, jboolean multiBounceAO) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->multiBounceAmbientOcclusion(multiBounceAO);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderSpecularAmbientOcclusion(
JNIEnv*, jclass, jlong nativeBuilder, jboolean specularAO) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->specularAmbientOcclusion(specularAO);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderTransparencyMode(
JNIEnv* env, jclass, jlong nativeBuilder, jint mode) {

View File

@@ -98,7 +98,16 @@ public class MaterialBuilder {
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 BlendingMode {
@@ -107,8 +116,10 @@ public class MaterialBuilder {
// affects diffuse lighting only
ADD, // material is additive (e.g.: hologram)
MASKED, // material is masked (i.e. alpha tested)
FADE // material is transparent and color is alpha-pre-multiplied,
FADE, // material is transparent and color is alpha-pre-multiplied,
// affects specular lighting
MULTIPLY, // material darkens what's behind it
SCREN // material brightens what's behind it
}
public enum VertexDomain {
@@ -142,9 +153,16 @@ public class MaterialBuilder {
}
public enum TargetApi {
ALL,
OPENGL,
VULKAN,
OPENGL (0x1),
VULKAN (0x2),
METAL (0x4),
ALL (0x7);
final int number;
private TargetApi(int number) {
this.number = number;
}
}
public enum Optimization {
@@ -290,14 +308,20 @@ public class MaterialBuilder {
}
@NonNull
public MaterialBuilder curvatureToRoughness(boolean curvatureToRoughness) {
nMaterialBuilderCurvatureToRoughness(mNativeObject, curvatureToRoughness);
public MaterialBuilder specularAntiAliasing(boolean specularAntiAliasing) {
nMaterialBuilderSpecularAntiAliasing(mNativeObject, specularAntiAliasing);
return this;
}
@NonNull
public MaterialBuilder limitOverInterpolation(boolean limitOverInterpolation) {
nMaterialBuilderLimitOverInterpolation(mNativeObject, limitOverInterpolation);
public MaterialBuilder specularAntiAliasingVariance(float variance) {
nMaterialBuilderSpecularAntiAliasingVariance(mNativeObject, variance);
return this;
}
@NonNull
public MaterialBuilder specularAntiAliasingThreshold(float threshold) {
nMaterialBuilderSpecularAntiAliasingThreshold(mNativeObject, threshold);
return this;
}
@@ -313,6 +337,18 @@ public class MaterialBuilder {
return this;
}
@NonNull
public MaterialBuilder multiBounceAmbientOcclusion(boolean multiBounceAO) {
nMaterialBuilderMultiBounceAmbientOcclusion(mNativeObject, multiBounceAO);
return this;
}
@NonNull
public MaterialBuilder specularAmbientOcclusion(boolean specularAO) {
nMaterialBuilderSpecularAmbientOcclusion(mNativeObject, specularAO);
return this;
}
@NonNull
public MaterialBuilder transparencyMode(@NonNull TransparencyMode mode) {
nMaterialBuilderTransparencyMode(mNativeObject, mode.ordinal());
@@ -327,7 +363,7 @@ public class MaterialBuilder {
@NonNull
public MaterialBuilder targetApi(@NonNull TargetApi api) {
nMaterialBuilderTargetApi(mNativeObject, api.ordinal());
nMaterialBuilderTargetApi(mNativeObject, api.number);
return this;
}
@@ -408,13 +444,19 @@ public class MaterialBuilder {
private static native void nMaterialBuilderShadowMultiplier(long mNativeObject,
boolean shadowMultiplier);
private static native void nMaterialBuilderCurvatureToRoughness(long mNativeObject,
boolean curvatureToRoughness);
private static native void nMaterialBuilderLimitOverInterpolation(long mNativeObject,
boolean limitOverInterpolation);
private static native void nMaterialBuilderSpecularAntiAliasing(long mNativeObject,
boolean specularAntiAliasing);
private static native void nMaterialBuilderSpecularAntiAliasingVariance(long mNativeObject,
float variance);
private static native void nMaterialBuilderSpecularAntiAliasingThreshold(long mNativeObject,
float threshold);
private static native void nMaterialBuilderClearCoatIorChange(long mNativeObject,
boolean clearCoatIorChange);
private static native void nMaterialBuilderFlipUV(long nativeBuilder, boolean flipUV);
private static native void nMaterialBuilderMultiBounceAmbientOcclusion(long nativeBuilder,
boolean multiBounceAO);
private static native void nMaterialBuilderSpecularAmbientOcclusion(long nativeBuilder,
boolean specularAO);
private static native void nMaterialBuilderTransparencyMode(long nativeBuilder, int mode);
private static native void nMaterialBuilderPlatform(long nativeBuilder, int platform);
private static native void nMaterialBuilderTargetApi(long nativeBuilder, int api);

View File

@@ -9,3 +9,4 @@
/build
/captures
.externalNativeBuild
/.cxx

View File

@@ -1,29 +1,113 @@
<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>
<codeStyleSettings language="XML">
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,5 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Google Configuration Checker Style" />
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.4.1)
cmake_minimum_required(VERSION 3.6)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
@@ -14,6 +14,10 @@ add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
add_library(ibl STATIC IMPORTED)
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
add_library(filaflat STATIC IMPORTED)
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
@@ -35,7 +39,7 @@ set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
include_directories(${FILAMENT_DIR}/include)
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")
@@ -46,54 +50,66 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -ff
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")
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/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/CallbackUtils.cpp
src/main/cpp/Filament.cpp
src/main/cpp/NioUtils.cpp
add_library(filament-jni-obj OBJECT
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
)
target_link_libraries(filament-jni
filament
backend
filaflat
filabridge
geometry
utils
log
GLESv3
EGL
android
jnigraphics
)
if (NOT DISABLE_FILAMENT_JNI)
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-jni.map")
add_library(filament-jni SHARED
$<TARGET_OBJECTS:filament-jni-obj>
# Private utils
src/main/cpp/Filament.cpp
# Common utils
../common/CallbackUtils.cpp
../common/NioUtils.cpp
)
target_link_libraries(filament-jni
filament
backend
filaflat
filabridge
geometry
ibl
utils
log
GLESv3
EGL
android
jnigraphics
)
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
if (FILAMENT_SUPPORTS_VULKAN)
target_link_libraries(filament-jni bluevk smol-v)
endif()
if (FILAMENT_SUPPORTS_VULKAN)
target_link_libraries(filament-jni bluevk smol-v)
endif()

View File

@@ -13,7 +13,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
@@ -25,7 +25,7 @@ allprojects {
}
group = "com.google.android.filament"
version = "0.1"
version = "1.3"
apply plugin: 'com.android.library'
@@ -35,13 +35,13 @@ if (project.hasProperty("filament_dist_dir")) {
}
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
// Our minSdkVersion is actually 21, we lie and say 14 here so apps don't have
// 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 < 21.
// ensure they do not initialize Filament on API levels < 19.
minSdkVersion 14
targetSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "1.0"
@@ -50,7 +50,7 @@ android {
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-21")
arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")

View File

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

View File

@@ -5,17 +5,18 @@
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# 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.
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# Keep the annotations that proguard needs to process.
-keep class com.google.android.filament.proguard.UsedBy*
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# 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

@@ -154,9 +154,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
@@ -236,6 +236,14 @@ Java_com_google_android_filament_Engine_nDestroyTexture(JNIEnv*, jclass,
engine->destroy(texture);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyRenderTarget(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeTarget) {
Engine* engine = (Engine*) nativeEngine;
RenderTarget* target = (RenderTarget*) nativeTarget;
engine->destroy(target);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyEntity(JNIEnv*, jclass,
jlong nativeEngine, jint entity_) {
@@ -244,6 +252,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,8 +22,8 @@
#include <filament/IndexBuffer.h>
#include "CallbackUtils.h"
#include "NioUtils.h"
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace backend;

View File

@@ -17,6 +17,9 @@
#include <jni.h>
#include <filament/IndirectLight.h>
#include <filament/Texture.h>
#include <common/NioUtils.h>
#include <common/CallbackUtils.h>
using namespace filament;
@@ -57,6 +60,15 @@ Java_com_google_android_filament_IndirectLight_nIrradiance(JNIEnv* env, jclass,
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nRadiance(JNIEnv* env, jclass,
jlong nativeBuilder, jint bands, jfloatArray sh_) {
IndirectLight::Builder* builder = (IndirectLight::Builder*) nativeBuilder;
jfloat* sh = env->GetFloatArrayElements(sh_, NULL);
builder->radiance((uint8_t) bands, (const filament::math::float3*) sh);
env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nIrradianceAsTexture(JNIEnv*, jclass,
jlong nativeBuilder, jlong nativeTexture) {
@@ -80,8 +92,6 @@ Java_com_google_android_filament_IndirectLight_nRotation(JNIEnv *, jclass, jlong
builder->rotation(filament::math::mat3f{v0, v1, v2, v3, v4, v5, v6, v7, v8});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nSetIntensity(JNIEnv*, jclass,
jlong nativeIndirectLight, jfloat intensity) {
@@ -97,9 +107,38 @@ Java_com_google_android_filament_IndirectLight_nGetIntensity(JNIEnv*, jclass,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nSetRotation(JNIEnv *env, jclass type,
jlong nativeIndirectLight, jfloat v0, jfloat v1, jfloat v2, jfloat v3, jfloat v4, jfloat v5,
jfloat v6, jfloat v7, jfloat v8) {
Java_com_google_android_filament_IndirectLight_nSetRotation(JNIEnv*, jclass,
jlong nativeIndirectLight, jfloat v0, jfloat v1, jfloat v2,
jfloat v3, jfloat v4, jfloat v5, jfloat v6, jfloat v7, jfloat v8) {
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
indirectLight->setRotation(filament::math::mat3f{v0, v1, v2, v3, v4, v5, v6, v7, v8});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetRotation(JNIEnv* env, jclass,
jlong nativeIndirectLight, jfloatArray outRotation_) {
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
jfloat *outRotation = env->GetFloatArrayElements(outRotation_, NULL);
*reinterpret_cast<filament::math::mat3f*>(outRotation) = indirectLight->getRotation();
env->ReleaseFloatArrayElements(outRotation_, outRotation, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_IndirectLight_nGetDirectionEstimate(JNIEnv* env, jclass,
jlong nativeIndirectLight, jfloatArray outDirection_) {
IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight;
jfloat *outDirection = env->GetFloatArrayElements(outDirection_, NULL);
*reinterpret_cast<filament::math::float3*>(outDirection) = indirectLight->getDirectionEstimate();
env->ReleaseFloatArrayElements(outDirection_, outDirection, 0);
}
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) {
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);
}

View File

@@ -22,48 +22,47 @@ using namespace filament;
using namespace utils;
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_LightManager_nHasComponent(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nHasComponent(JNIEnv*, jclass,
jlong nativeLightManager, jint entity) {
LightManager *lm = (LightManager *) nativeLightManager;
return (jboolean) lm->hasComponent((Entity &) entity);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_LightManager_nGetInstance(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetInstance(JNIEnv*, jclass,
jlong nativeLightManager, jint entity) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->getInstance((Entity &) entity);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nDestroy(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nDestroy(JNIEnv*, jclass,
jlong nativeLightManager, jint entity) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->destroy((Entity &) entity);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_LightManager_nCreateBuilder(JNIEnv *env, jclass type,
jint lightType) {
Java_com_google_android_filament_LightManager_nCreateBuilder(JNIEnv*, jclass, jint lightType) {
return (jlong) new LightManager::Builder((LightManager::Type) lightType);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nDestroyBuilder(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nDestroyBuilder(JNIEnv*, jclass,
jlong nativeBuilder) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
delete builder;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderCastShadows(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderCastShadows(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enable) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->castShadows(enable);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv *env, jclass type,
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) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
@@ -78,84 +77,84 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv *env,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderCastLight(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderCastLight(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->castLight(enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderPosition(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderPosition(JNIEnv*, jclass,
jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->position({x, y, z});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderDirection(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderDirection(JNIEnv*, jclass,
jlong nativeBuilder, jfloat x, jfloat y, jfloat z) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->direction({x, y, z});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderColor(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderColor(JNIEnv*, jclass,
jlong nativeBuilder, jfloat linearR, jfloat linearG, jfloat linearB) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->color({linearR, linearG, linearB});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderIntensity__JF(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderIntensity__JF(JNIEnv*, jclass,
jlong nativeBuilder, jfloat intensity) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->intensity(intensity);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderIntensity__JFF(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderIntensity__JFF(JNIEnv*, jclass,
jlong nativeBuilder, jfloat watts, jfloat efficiency) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->intensity(watts, efficiency);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderFalloff(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderFalloff(JNIEnv*, jclass,
jlong nativeBuilder, jfloat radius) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->falloff(radius);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderSpotLightCone(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderSpotLightCone(JNIEnv*, jclass,
jlong nativeBuilder, jfloat inner, jfloat outer) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->spotLightCone(inner, outer);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderAngularRadius(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderAngularRadius(JNIEnv*, jclass,
jlong nativeBuilder, jfloat angularRadius) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->sunAngularRadius(angularRadius);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderHaloSize(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderHaloSize(JNIEnv*, jclass,
jlong nativeBuilder, jfloat haloSize) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->sunHaloSize(haloSize);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nBuilderHaloFalloff(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderHaloFalloff(JNIEnv*, jclass,
jlong nativeBuilder, jfloat haloFalloff) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
builder->sunHaloFalloff(haloFalloff);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_LightManager_nBuilderBuild(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nBuilderBuild(JNIEnv*, jclass,
jlong nativeBuilder, jlong nativeEngine, jint entity) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
@@ -170,133 +169,147 @@ Java_com_google_android_filament_LightManager_nGetType(JNIEnv* env,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetPosition(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetPosition(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat x, jfloat y, jfloat z) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setPosition((LightManager::Instance) i, {x, y, z});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nGetPosition(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetPosition(JNIEnv* env, jclass,
jlong nativeLightManager, jint i, jfloatArray out_) {
LightManager *lm = (LightManager *) nativeLightManager;
jfloat *out = env->GetFloatArrayElements(out_, NULL);
jfloat *out = env->GetFloatArrayElements(out_, nullptr);
*reinterpret_cast<filament::math::float3 *>(out) = lm->getPosition((LightManager::Instance) i);
env->ReleaseFloatArrayElements(out_, out, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetDirection(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetDirection(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat x, jfloat y, jfloat z) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setDirection((LightManager::Instance) i, {x, y, z});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nGetDirection(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetDirection(JNIEnv *env, jclass,
jlong nativeLightManager, jint i, jfloatArray out_) {
LightManager *lm = (LightManager *) nativeLightManager;
jfloat *out = env->GetFloatArrayElements(out_, NULL);
jfloat *out = env->GetFloatArrayElements(out_, nullptr);
*reinterpret_cast<filament::math::float3 *>(out) = lm->getDirection((LightManager::Instance) i);
env->ReleaseFloatArrayElements(out_, out, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetColor(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetColor(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat linearR, jfloat linearG, jfloat linearB) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setColor((LightManager::Instance) i, {linearR, linearG, linearB});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nGetColor(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetColor(JNIEnv *env, jclass,
jlong nativeLightManager, jint i, jfloatArray out_) {
LightManager *lm = (LightManager *) nativeLightManager;
jfloat *out = env->GetFloatArrayElements(out_, NULL);
jfloat *out = env->GetFloatArrayElements(out_, nullptr);
*reinterpret_cast<filament::math::float3 *>(out) = lm->getColor((LightManager::Instance) i);
env->ReleaseFloatArrayElements(out_, out, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetIntensity__JIF(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetIntensity__JIF(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat intensity) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setIntensity((LightManager::Instance) i, intensity);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetIntensity__JIFF(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetIntensity__JIFF(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat watts, jfloat efficiency) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setIntensity((LightManager::Instance) i, watts, efficiency);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetIntensity(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetIntensity(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->getIntensity((LightManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetFalloff(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetFalloff(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat falloff) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setFalloff((LightManager::Instance) i, falloff);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetFalloff(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetFalloff(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->getFalloff((LightManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetSpotLightCone(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetSpotLightCone(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat inner, jfloat outer) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setSpotLightCone((LightManager::Instance) i, inner, outer);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetSunAngularRadius(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetSunAngularRadius(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat angularRadius) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setSunAngularRadius((LightManager::Instance) i, angularRadius);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetSunAngularRadius(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetSunAngularRadius(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->getSunAngularRadius((LightManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetSunHaloSize(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetSunHaloSize(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat haloSize) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setSunHaloSize((LightManager::Instance) i, haloSize);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetHaloSize(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetHaloSize(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->getSunHaloSize((LightManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetSunHaloFalloff(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nSetSunHaloFalloff(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat haloFalloff) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setSunHaloFalloff((LightManager::Instance) i, haloFalloff);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetHaloFalloff(JNIEnv *env, jclass type,
Java_com_google_android_filament_LightManager_nGetHaloFalloff(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->getSunHaloFalloff((LightManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_LightManager_nSetShadowCaster(JNIEnv*, jclass,
jlong nativeLightManager, jint i, jfloat shadowCaster) {
LightManager *lm = (LightManager *) nativeLightManager;
lm->setShadowCaster((LightManager::Instance) i, shadowCaster);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_LightManager_nIsShadowCaster(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return lm->isShadowCaster((LightManager::Instance) i);
}

View File

@@ -18,7 +18,7 @@
#include <filament/Material.h>
#include "NioUtils.h"
#include "common/NioUtils.h"
using namespace filament;
@@ -140,6 +140,22 @@ Java_com_google_android_filament_Material_nGetMaskThreshold(JNIEnv*, jclass,
return material->getMaskThreshold();
}
extern "C"
JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_Material_nGetSpecularAntiAliasingVariance(JNIEnv*, jclass,
jlong nativeMaterial) {
Material* material = (Material*) nativeMaterial;
return material->getSpecularAntiAliasingVariance();
}
extern "C"
JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_Material_nGetSpecularAntiAliasingThreshold(JNIEnv*, jclass,
jlong nativeMaterial) {
Material* material = (Material*) nativeMaterial;
return material->getSpecularAntiAliasingThreshold();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_Material_nGetParameterCount(JNIEnv*, jclass,

View File

@@ -27,6 +27,30 @@
#include <math/vec4.h>
using namespace filament;
using namespace filament::math;
enum BooleanElement {
BOOL,
BOOL2,
BOOL3,
BOOL4
};
enum IntElement {
INT,
INT2,
INT3,
INT4
};
enum FloatElement {
FLOAT,
FLOAT2,
FLOAT3,
FLOAT4,
MAT3,
MAT4
};
template<typename T>
static void setParameter(JNIEnv* env, jlong nativeMaterialInstance, jstring name_, T v) {
@@ -47,14 +71,14 @@ extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterBool2(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_, jboolean x, jboolean y) {
setParameter(env, nativeMaterialInstance, name_, filament::math::bool2{x, y});
setParameter(env, nativeMaterialInstance, name_, bool2{x, y});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterBool3(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_, jboolean x, jboolean y, jboolean z) {
setParameter(env, nativeMaterialInstance, name_, filament::math::bool3{x, y, z});
setParameter(env, nativeMaterialInstance, name_, bool3{x, y, z});
}
extern "C"
@@ -62,7 +86,7 @@ JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterBool4(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_,
jboolean x, jboolean y, jboolean z, jboolean w) {
setParameter(env, nativeMaterialInstance, name_, filament::math::bool4{x, y, z, w});
setParameter(env, nativeMaterialInstance, name_, bool4{x, y, z, w});
}
extern "C"
@@ -76,14 +100,14 @@ extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterInt2(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_, jint x, jint y) {
setParameter(env, nativeMaterialInstance, name_, filament::math::int2{x, y});
setParameter(env, nativeMaterialInstance, name_, int2{x, y});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterInt3(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_, jint x, jint y, jint z) {
setParameter(env, nativeMaterialInstance, name_, filament::math::int3{x, y, z});
setParameter(env, nativeMaterialInstance, name_, int3{x, y, z});
}
extern "C"
@@ -91,7 +115,7 @@ JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterInt4(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_,
jint x, jint y, jint z, jint w) {
setParameter(env, nativeMaterialInstance, name_, filament::math::int4{x, y, z, w});
setParameter(env, nativeMaterialInstance, name_, int4{x, y, z, w});
}
extern "C"
@@ -105,14 +129,14 @@ extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterFloat2(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_, jfloat x, jfloat y) {
setParameter(env, nativeMaterialInstance, name_, filament::math::float2{x, y});
setParameter(env, nativeMaterialInstance, name_, float2{x, y});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterFloat3(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_, jfloat x, jfloat y, jfloat z) {
setParameter(env, nativeMaterialInstance, name_, filament::math::float3{x, y, z});
setParameter(env, nativeMaterialInstance, name_, float3{x, y, z});
}
extern "C"
@@ -120,7 +144,7 @@ JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterFloat4(JNIEnv *env, jclass,
jlong nativeMaterialInstance, jstring name_,
jfloat x, jfloat y, jfloat z, jfloat w) {
setParameter(env, nativeMaterialInstance, name_, filament::math::float4{x, y, z, w});
setParameter(env, nativeMaterialInstance, name_, float4{x, y, z, w});
}
extern "C"
@@ -131,9 +155,26 @@ Java_com_google_android_filament_MaterialInstance_nSetBooleanParameterArray(JNIE
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
const char* name = env->GetStringUTFChars(name_, 0);
size_t size = (size_t) element + 1;
jboolean* v = env->GetBooleanArrayElements(v_, NULL);
instance->setParameter(name, (bool*) (v + offset * size), (size_t) (count * size));
// NOTE: In C++, bool has an implementation-defined size. Here we assume
// it has the same size as jboolean, which is 1 byte.
switch ((BooleanElement) element) {
case BOOL:
instance->setParameter(name, ((const bool*) v) + offset, count);
break;
case BOOL2:
instance->setParameter(name, ((const bool2*) v) + offset, count);
break;
case BOOL3:
instance->setParameter(name, ((const bool3*) v) + offset, count);
break;
case BOOL4:
instance->setParameter(name, ((const bool4*) v) + offset, count);
break;
}
env->ReleaseBooleanArrayElements(v_, v, 0);
env->ReleaseStringUTFChars(name_, name);
@@ -147,10 +188,23 @@ Java_com_google_android_filament_MaterialInstance_nSetIntParameterArray(JNIEnv *
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
const char* name = env->GetStringUTFChars(name_, 0);
size_t size = (size_t) element + 1;
jint* v = env->GetIntArrayElements(v_, NULL);
instance->setParameter(name, reinterpret_cast<int32_t*>(v + offset * size),
(size_t) (count * size));
switch ((IntElement) element) {
case INT:
instance->setParameter(name, ((const int32_t*) v) + offset, count);
break;
case INT2:
instance->setParameter(name, ((const int2*) v) + offset, count);
break;
case INT3:
instance->setParameter(name, ((const int3*) v) + offset, count);
break;
case INT4:
instance->setParameter(name, ((const int4*) v) + offset, count);
break;
}
env->ReleaseIntArrayElements(v_, v, 0);
env->ReleaseStringUTFChars(name_, name);
@@ -164,16 +218,29 @@ Java_com_google_android_filament_MaterialInstance_nSetFloatParameterArray(JNIEnv
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
const char* name = env->GetStringUTFChars(name_, 0);
size_t size = (size_t) element + 1;
if (size == 5) {
// mat3
size = 9;
} else if (size == 6) {
// mat4
size = 16;
}
jfloat* v = env->GetFloatArrayElements(v_, NULL);
instance->setParameter(name, v + offset * size, (size_t) (count * size));
switch ((FloatElement) element) {
case FLOAT:
instance->setParameter(name, ((const float*) v) + offset, count);
break;
case FLOAT2:
instance->setParameter(name, ((const float2*) v) + offset, count);
break;
case FLOAT3:
instance->setParameter(name, ((const float3*) v) + offset, count);
break;
case FLOAT4:
instance->setParameter(name, ((const float4*) v) + offset, count);
break;
case MAT3:
instance->setParameter(name, ((const mat3f*) v) + offset, count);
break;
case MAT4:
instance->setParameter(name, ((const mat4f*) v) + offset, count);
break;
}
env->ReleaseFloatArrayElements(v_, v, 0);
env->ReleaseStringUTFChars(name_, name);
@@ -226,6 +293,22 @@ Java_com_google_android_filament_MaterialInstance_nSetMaskThreshold(JNIEnv*,
instance->setMaskThreshold(threshold);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetSpecularAntiAliasingVariance(JNIEnv*,
jclass, jlong nativeMaterialInstance, jfloat variance) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setSpecularAntiAliasingVariance(variance);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetSpecularAntiAliasingThreshold(JNIEnv*,
jclass, jlong nativeMaterialInstance, jfloat threshold) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setSpecularAntiAliasingThreshold(threshold);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetDoubleSided(JNIEnv*,
@@ -233,3 +316,11 @@ 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);
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <functional>
#include <stdlib.h>
#include <string.h>
#include <filament/RenderTarget.h>
using namespace filament;
using namespace backend;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_RenderTarget_nCreateBuilder(JNIEnv *env, jclass type) {
return (jlong) new RenderTarget::Builder();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nDestroyBuilder(JNIEnv *env, jclass type,
jlong nativeBuilder) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
delete builder;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderTexture(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong attachment, jlong nativeTexture) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
Texture* texture = (Texture*) nativeTexture;
builder->texture(RenderTarget::AttachmentPoint(attachment), texture);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderMipLevel(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong 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) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
RenderTarget::CubemapFace cubeface = (RenderTarget::CubemapFace) face;
builder->face(RenderTarget::AttachmentPoint(attachment), cubeface);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderLayer(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong attachment, jint layer) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
builder->layer(RenderTarget::AttachmentPoint(attachment), layer);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_RenderTarget_nBuilderBuild(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong nativeEngine) {
RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderTarget_nGetMipLevel(JNIEnv *env, jclass type,
jlong nativeTarget, jlong attachment) {
RenderTarget* target = (RenderTarget*) nativeTarget;
return (jint) target->getMipLevel(RenderTarget::AttachmentPoint(attachment));
}

View File

@@ -18,7 +18,7 @@
#include <jni.h>
#include <filament/RenderableManager.h>
#include "NioUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace utils;
@@ -182,6 +182,12 @@ Java_com_google_android_filament_RenderableManager_nBuilderSkinningBones(JNIEnv*
return 0;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderMorphing(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->morphing(enabled);
}
extern "C" JNIEXPORT jint JNICALL
@@ -218,6 +224,16 @@ Java_com_google_android_filament_RenderableManager_nSetBonesAsQuaternions(JNIEnv
return 0;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMorphWeights(JNIEnv* env, jclass,
jlong nativeRenderableManager, jint instance, jfloatArray weights) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
jfloat* vec = env->GetFloatArrayElements(weights, NULL);
math::float4 floatvec(vec[0], vec[1], vec[2], vec[3]);
env->ReleaseFloatArrayElements(weights, vec, JNI_ABORT);
rm->setMorphWeights((RenderableManager::Instance)instance, floatvec);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetAxisAlignedBoundingBox(JNIEnv*,
jclass, jlong nativeRenderableManager, jint i, jfloat cx, jfloat cy, jfloat cz,
@@ -299,6 +315,21 @@ Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv
materialInstance);
}
extern "C" JNIEXPORT long JNICALL
Java_com_google_android_filament_RenderableManager_nGetMaterialInstanceAt(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
return (long) rm->getMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
}
extern "C" JNIEXPORT long JNICALL
Java_com_google_android_filament_RenderableManager_nGetMaterialAt(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jint primitiveIndex) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
MaterialInstance *mi = rm->getMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex);
return (long) mi->getMaterial();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetGeometryAt__JIIIJJII(JNIEnv*,
jclass, jlong nativeRenderableManager, jint i, jint primitiveIndex, jint primitiveType,

View File

@@ -22,8 +22,8 @@
#include <filament/Viewport.h>
#include <backend/PixelBufferDescriptor.h>
#include "CallbackUtils.h"
#include "NioUtils.h"
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace backend;
@@ -51,7 +51,7 @@ Java_com_google_android_filament_Renderer_nRender(JNIEnv *, jclass, jlong native
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nMirrorFrame(JNIEnv *, jclass, jlong nativeRenderer,
Java_com_google_android_filament_Renderer_nCopyFrame(JNIEnv *, jclass, jlong nativeRenderer,
jlong nativeDstSwapChain,
jint dstLeft, jint dstBottom, jint dstWidth, jint dstHeight,
jint srcLeft, jint srcBottom, jint srcWidth, jint srcHeight,
@@ -60,7 +60,7 @@ Java_com_google_android_filament_Renderer_nMirrorFrame(JNIEnv *, jclass, jlong n
SwapChain *dstSwapChain = (SwapChain *) nativeDstSwapChain;
const filament::Viewport dstViewport {dstLeft, dstBottom, (uint32_t) dstWidth, (uint32_t) dstHeight};
const filament::Viewport srcViewport {srcLeft, srcBottom, (uint32_t) srcWidth, (uint32_t) srcHeight};
renderer->mirrorFrame(dstSwapChain, dstViewport, srcViewport, (uint32_t) flags);
renderer->copyFrame(dstSwapChain, dstViewport, srcViewport, (uint32_t) flags);
}
extern "C" JNIEXPORT jint JNICALL

View File

@@ -44,6 +44,15 @@ Java_com_google_android_filament_Scene_nAddEntity(JNIEnv *env, jclass type, jlon
scene->addEntity((Entity&) entity);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nAddEntities(JNIEnv *env, jclass type, jlong nativeScene,
jintArray entities) {
Scene* scene = (Scene*) nativeScene;
Entity* nativeEntities = (Entity*) env->GetIntArrayElements(entities, nullptr);
scene->addEntities(nativeEntities, env->GetArrayLength(entities));
env->ReleaseIntArrayElements(entities, (jint*) nativeEntities, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Scene_nRemove(JNIEnv *env, jclass type, jlong nativeScene,
jint entity) {

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

@@ -21,8 +21,8 @@
#include <filament/Stream.h>
#include <backend/PixelBufferDescriptor.h>
#include "NioUtils.h"
#include "CallbackUtils.h"
#include "common/NioUtils.h"
#include "common/CallbackUtils.h"
using namespace filament;
using namespace backend;

View File

@@ -28,8 +28,8 @@
#include <filament/Stream.h>
#include <filament/Texture.h>
#include "CallbackUtils.h"
#include "NioUtils.h"
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace backend;
@@ -107,10 +107,10 @@ Java_com_google_android_filament_Texture_nBuilderFormat(JNIEnv*, jclass,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Texture_nBuilderRgbm(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enable) {
Java_com_google_android_filament_Texture_nBuilderUsage(JNIEnv*, jclass,
jlong nativeBuilder, jint flags) {
Texture::Builder *builder = (Texture::Builder *) nativeBuilder;
builder->rgbm(enable);
builder->usage((Texture::Usage) flags);
}
extern "C" JNIEXPORT jlong JNICALL
@@ -163,12 +163,6 @@ Java_com_google_android_filament_Texture_nGetInternalFormat(JNIEnv*, jclass,
return (jint) texture->getFormat();
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Texture_nGetRgbm(JNIEnv*, jclass, jlong nativeTexture) {
Texture *texture = (Texture *) nativeTexture;
return static_cast<jboolean>(texture->isRgbm());
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong nativeTexture,
jlong nativeEngine, jint level, jint xoffset, jint yoffset, jint width, jint height,
@@ -183,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;
}
@@ -205,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;
@@ -214,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;
}
@@ -241,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);
@@ -250,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;
}
@@ -277,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);
@@ -285,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;
}
@@ -335,6 +328,49 @@ Java_com_google_android_filament_Texture_nIsStreamValidForTexture(JNIEnv*, jclas
return (jboolean) (texture->getTarget() == SamplerType::SAMPLER_EXTERNAL);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, jclass,
jlong nativeTexture, jlong nativeEngine, jint width, jint height,
jobject storage, jint remaining, jint left,
jint top, jint type, jint alignment, jint stride, jint format,
jintArray faceOffsetsInBytes_, jobject handler, jobject runnable, jint sampleCount,
jboolean mirror) {
Texture *texture = (Texture *) nativeTexture;
Engine *engine = (Engine *) nativeEngine;
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);
AutoBuffer nioBuffer(env, storage, 0);
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));
Texture::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);
Texture::PrefilterOptions options;
options.sampleCount = sampleCount;
options.mirror = mirror;
texture->generatePrefilterMipmap(*engine, std::move(desc), faceOffsets, &options);
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// ANDROID SPECIFIC BITS
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -24,8 +24,8 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include "CallbackUtils.h"
#include "NioUtils.h"
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace filament::math;

View File

@@ -94,6 +94,13 @@ Java_com_google_android_filament_View_nSetShadowsEnabled(JNIEnv*, jclass,
view->setShadowsEnabled(enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetRenderTarget(JNIEnv*, jclass,
jlong nativeView, jlong nativeTarget) {
View* view = (View*) nativeView;
view->setRenderTarget((RenderTarget*) nativeTarget);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetSampleCount(JNIEnv*, jclass,
jlong nativeView, jint count) {
@@ -219,3 +226,23 @@ Java_com_google_android_filament_View_nIsFrontFaceWindingInverted(JNIEnv*,
View* view = (View*) nativeView;
return static_cast<jboolean>(view->isFrontFaceWindingInverted());
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetAmbientOcclusion(JNIEnv*, jclass, jlong nativeView, jint ordinal) {
View* view = (View*) nativeView;
view->setAmbientOcclusion((View::AmbientOcclusion)ordinal);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_View_nGetAmbientOcclusion(JNIEnv*, jclass, jlong nativeView) {
View* view = (View*) nativeView;
return (jint)view->getAmbientOcclusion();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetAmbientOcclusionOptions(JNIEnv*, jclass,
jlong nativeView, jfloat radius, jfloat bias, jfloat power, jfloat resolution) {
View* view = (View*) nativeView;
View::AmbientOcclusionOptions options = { .radius = radius, .bias = bias, .power = power, .resolution = resolution};
view->setAmbientOcclusionOptions(options);
}

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

@@ -0,0 +1,89 @@
/*
* 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.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
final class Asserts {
private Asserts() {
}
@NonNull @Size(min = 9)
static float[] assertMat3f(@Nullable float[] out) {
if (out == null) out = new float[9];
else if (out.length < 9) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 9");
}
return out;
}
static void assertMat3fIn(@NonNull @Size(min = 9) float[] in) {
if (in.length < 9) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 9");
}
}
@NonNull @Size(min = 16)
static double[] assertMat4d(@Nullable double[] out) {
if (out == null) out = new double[16];
else if (out.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
return out;
}
static void assertMat4dIn(@NonNull @Size(min = 16) double[] in) {
if (in.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
}
@NonNull @Size(min = 16)
static float[] assertMat4f(@Nullable float[] out) {
if (out == null) out = new float[16];
else if (out.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
return out;
}
static void assertMat4fIn(@NonNull @Size(min = 16) float[] in) {
if (in.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
}
@NonNull @Size(min = 3)
static float[] assertFloat3(@Nullable float[] out) {
if (out == null) out = new float[3];
else if (out.length < 3) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 3");
}
return out;
}
@NonNull @Size(min = 4)
static float[] assertFloat4(@Nullable float[] out) {
if (out == null) out = new float[4];
else if (out.length < 4) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 4");
}
return out;
}
}

View File

@@ -19,12 +19,25 @@ package com.google.android.filament;
import android.support.annotation.NonNull;
import android.support.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

@@ -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 field-of-view in degrees from the camera center axis.
* 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,86 @@ public class Camera {
}
/**
* Sets the projection matrix from the focal length
*
* @param focalLength lense's focal length in millimeters. <code>focalLength</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);
}
/**
* 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) {
assertMat4dIn(inMatrix);
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[]) {
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 +313,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,13 +328,15 @@ 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[]) {
out = assertMat4d(out);
public double[] getProjectionMatrix(@Nullable @Size(min = 16) double[] out) {
out = Asserts.assertMat4d(out);
nGetProjectionMatrix(getNativeObject(), out);
return out;
}
@@ -281,13 +344,15 @@ 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[]) {
out = assertMat4f(out);
public float[] getModelMatrix(@Nullable @Size(min = 16) float[] out) {
out = Asserts.assertMat4f(out);
nGetModelMatrix(getNativeObject(), out);
return out;
}
@@ -297,24 +362,27 @@ 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[]) {
out = assertMat4f(out);
public float[] getViewMatrix(@Nullable @Size(min = 16) float[] out) {
out = Asserts.assertMat4f(out);
nGetViewMatrix(getNativeObject(), out);
return out;
}
/**
* 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[]) {
out = assertFloat3(out);
public float[] getPosition(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetPosition(getNativeObject(), out);
return out;
}
@@ -322,13 +390,15 @@ 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[]) {
out = assertFloat3(out);
public float[] getLeftVector(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetLeftVector(getNativeObject(), out);
return out;
}
@@ -336,13 +406,15 @@ 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[]) {
out = assertFloat3(out);
public float[] getUpVector(@Nullable @Size(min = 3) float[] out) {
out = Asserts.assertFloat3(out);
nGetUpVector(getNativeObject(), out);
return out;
}
@@ -350,52 +422,89 @@ 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[]) {
out = assertFloat3(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());
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Camera");
}
@@ -406,45 +515,6 @@ public class Camera {
mNativeObject = 0;
}
@NonNull @Size(min = 16)
private static double[] assertMat4d(@Nullable double[] out) {
if (out == null) out = new double[16];
else if (out.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
return out;
}
@NonNull @Size(min = 16)
private static float[] assertMat4f(@Nullable float[] out) {
if (out == null) out = new float[16];
else if (out.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
return out;
}
private static void assertMat4dIn(@NonNull @Size(min = 16) double[] in) {
if (in.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
}
private static void assertMat4fIn(@NonNull @Size(min = 16) float[] in) {
if (in.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
}
@NonNull @Size(min = 3)
private static float[] assertFloat3(@Nullable float[] out) {
if (out == null) out = new float[3];
else if (out.length < 3) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 3");
}
return out;
}
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);

View File

@@ -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

@@ -18,17 +18,118 @@ package com.google.android.filament;
import android.support.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
/**
* 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 ES driver.
*/
OPENGL,
/**
* Selects the experimental Vulkan driver.
*/
VULKAN,
/**
* Selects the no-op driver for testing purposes.
*/
NOOP,
}
private Engine(long nativeEngine) {
@@ -38,6 +139,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);
@@ -45,6 +159,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);
@@ -53,9 +182,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) {
@@ -68,15 +209,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())];
}
@@ -84,25 +251,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);
@@ -112,6 +290,18 @@ public class Engine {
throw new IllegalArgumentException("Invalid surface " + surface);
}
/**
* 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);
@@ -119,6 +309,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();
@@ -126,6 +320,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());
@@ -133,6 +332,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();
@@ -140,6 +343,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());
@@ -147,6 +355,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();
@@ -154,6 +366,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());
@@ -161,6 +379,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);
@@ -168,6 +393,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();
@@ -175,6 +404,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());
@@ -182,6 +416,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();
@@ -189,6 +427,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();
@@ -196,13 +438,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();
@@ -210,67 +461,139 @@ 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());
}
long getNativeObject() {
@UsedByReflection("TextureHelper.java")
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Engine");
}
@@ -296,7 +619,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);
@@ -306,7 +629,9 @@ public class Engine {
private static native void nDestroyMaterialInstance(long nativeEngine, long nativeMaterialInstance);
private static native void nDestroySkybox(long nativeEngine, long nativeSkybox);
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

@@ -19,6 +19,8 @@ package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
public class EntityManager {
private long mNativeObject = nGetEntityManager();
@@ -66,6 +68,11 @@ public class EntityManager {
return nIsAlive(mNativeObject, entity);
}
@UsedByReflection("AssetLoader.java")
public long getNativeObject() {
return mNativeObject;
}
private static native long nGetEntityManager();
private static native void nCreateArray(long nativeEntityManager, int n, int[] entities);
private static native int nCreate(long nativeEntityManager);

View File

@@ -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
@@ -70,7 +65,7 @@ public class Fence {
}
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Fence");
}

View File

@@ -23,6 +23,17 @@ import android.support.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;
@@ -30,21 +41,20 @@ public class IndexBuffer {
mNativeObject = nativeIndexBuffer;
}
long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed IndexBuffer");
}
return mNativeObject;
}
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
// Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
/**
* Type of the index buffer.
*/
public enum IndexType {
/** 16-bit indices */
USHORT,
/** 32-bit indices */
UINT,
}
@@ -53,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());
@@ -92,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,
@@ -121,6 +203,13 @@ public class IndexBuffer {
}
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed IndexBuffer");
}
return mNativeObject;
}
void clearNativeObject() {
mNativeObject = 0;
}

View File

@@ -18,31 +18,167 @@ 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 com.google.android.filament.proguard.UsedByReflection;
/**
* <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. It is represented 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;
private IndirectLight(long indirectLight) {
@UsedByReflection("KtxLoader.java")
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) {
@@ -61,20 +197,110 @@ 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) {
case 1: if (sh.length < 3)
throw new ArrayIndexOutOfBoundsException(
"1 band SH, array must be at least 1 x float3"); else break;
case 2: if (sh.length < 4 * 3)
throw new ArrayIndexOutOfBoundsException(
"2 bands SH, array must be at least 4 x float3"); else break;
case 3: if (sh.length < 9 * 3)
throw new ArrayIndexOutOfBoundsException(
"3 bands SH, array must be at least 9 x float3"); else break;
default: throw new IllegalArgumentException("bands must be 1, 2 or 3");
}
nRadiance(mNativeBuilder, bands, sh);
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[]) {
public Builder rotation(@NonNull @Size(min = 9) float[] rotation) {
nRotation(mNativeBuilder,
rotation[0], rotation[1], rotation[2],
rotation[3], rotation[4], rotation[5],
@@ -82,6 +308,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());
@@ -106,22 +341,110 @@ 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());
}
public void setRotation(@NonNull @Size(min = 9) float rotation[]) {
/**
* 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(),
rotation[0], rotation[1], rotation[2],
rotation[3], rotation[4], rotation[5],
rotation[6], rotation[7], rotation[8]);
}
long getNativeObject() {
/**
* 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);
nGetRotation(getNativeObject(), rotation);
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 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 float[] getDirectionEstimate(@Nullable @Size(min = 3) float[] direction) {
direction = Asserts.assertFloat3(direction);
nGetDirectionEstimate(getNativeObject(), direction);
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 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 float[] getColorEstimate(@Nullable @Size(min = 4) float[] colorIntensity, float x, float y, float z) {
colorIntensity = Asserts.assertFloat4(colorIntensity);
nGetColorEstimate(getNativeObject(), colorIntensity, x, y, z);
return colorIntensity;
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed IndirectLight");
}
@@ -138,6 +461,7 @@ public class IndirectLight {
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native void nBuilderReflections(long nativeBuilder, long nativeTexture);
private static native void nIrradiance(long nativeBuilder, int bands, float[] sh);
private static native void nRadiance(long nativeBuilder, int bands, float[] sh);
private static native void nIrradianceAsTexture(long nativeBuilder, long nativeTexture);
private static native void nIntensity(long nativeBuilder, float envIntensity);
private static native void nRotation(long nativeBuilder, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8) ;
@@ -145,5 +469,7 @@ public class IndirectLight {
private static native void nSetIntensity(long nativeIndirectLight, float intensity);
private static native float nGetIntensity(long nativeIndirectLight);
private static native void nSetRotation(long nativeIndirectLight, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8);
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);
}

View File

@@ -187,7 +187,7 @@ public class LightManager {
@NonNull
public float[] getPosition(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) {
out = assertFloat3(out);
out = Asserts.assertFloat3(out);
nGetPosition(mNativeObject, i, out);
return out;
}
@@ -198,7 +198,7 @@ public class LightManager {
@NonNull
public float[] getDirection(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) {
out = assertFloat3(out);
out = Asserts.assertFloat3(out);
nGetDirection(mNativeObject, i, out);
return out;
}
@@ -209,7 +209,7 @@ public class LightManager {
@NonNull
public float[] getColor(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) {
out = assertFloat3(out);
out = Asserts.assertFloat3(out);
nGetColor(mNativeObject, i, out);
return out;
}
@@ -262,13 +262,16 @@ public class LightManager {
return nGetSunHaloFalloff(mNativeObject, i);
}
@NonNull @Size(min = 3)
private static float[] assertFloat3(@Nullable float[] out) {
if (out == null) out = new float[3];
else if (out.length < 3) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 3");
}
return out;
public void setShadowCaster(@EntityInstance int i, boolean shadowCaster) {
nSetShadowCaster(mNativeObject, i, shadowCaster);
}
public boolean isShadowCaster(@EntityInstance int i) {
return nIsShadowCaster(mNativeObject, i);
}
public long getNativeObject() {
return mNativeObject;
}
private static native boolean nHasComponent(long nativeLightManager, int entity);
@@ -292,7 +295,6 @@ public class LightManager {
private static native void nBuilderHaloSize(long nativeBuilder, float haloSize);
private static native void nBuilderHaloFalloff(long nativeBuilder, float haloFalloff);
private static native int nGetType(long nativeLightManager, int i);
private static native void nSetPosition(long nativeLightManager, int i, float x, float y, float z);
private static native void nGetPosition(long nativeLightManager, int i, float[] out);
@@ -312,4 +314,6 @@ public class LightManager {
private static native float nGetSunHaloSize(long nativeLightManager, int i);
private static native void nSetSunHaloFalloff(long nativeLightManager, int i, float haloFalloff);
private static native float nGetSunHaloFalloff(long nativeLightManager, int i);
private static native void nSetShadowCaster(long nativeLightManager, int i, boolean shadowCaster);
private static native boolean nIsShadowCaster(long nativeLightManager, int i);
}

View File

@@ -20,6 +20,8 @@ import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Size;
import com.google.android.filament.proguard.UsedByNative;
import java.nio.Buffer;
import java.util.ArrayList;
import java.util.Collections;
@@ -27,48 +29,161 @@ 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 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
}
@UsedByNative("Material.cpp")
public static class Parameter {
public enum Type {
BOOL,
@@ -101,8 +216,8 @@ public class Material {
DEFAULT
}
// Used by native code
@SuppressWarnings("unused")
@UsedByNative("Material.cpp")
private static final int SAMPLER_OFFSET = Type.MAT4.ordinal() + 1;
@NonNull
@@ -122,8 +237,8 @@ public class Material {
this.count = count;
}
// Used by native code
@SuppressWarnings("unused")
@UsedByNative("Material.cpp")
private static void add(@NonNull List<Parameter> parameters, @NonNull String name,
@IntRange(from = 0) int type, @IntRange(from = 0) int precision,
@IntRange(from = 1) int count) {
@@ -132,8 +247,9 @@ public class Material {
}
}
private Material(long nativeMaterial, long nativeDefaultInstance) {
Material(long nativeMaterial) {
mNativeObject = nativeMaterial;
long nativeDefaultInstance = nGetDefaultInstance(nativeMaterial);
mDefaultInstance = new MaterialInstance(this, nativeDefaultInstance);
}
@@ -141,6 +257,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;
@@ -148,15 +271,29 @@ 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);
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
long nativeDefaultInstance = nGetDefaultInstance(nativeMaterial);
return new Material(nativeMaterial, nativeDefaultInstance);
return new Material(nativeMaterial);
}
}
/**
* 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());
@@ -164,55 +301,163 @@ 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 vertex domain of this material.
*
* @se
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/vertexandattributes:vertexdomain">
* Vertex and attributes: vertexDomain</a>
* @return
*/
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 this material will 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 this material will 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 this material will 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());
@@ -228,14 +473,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);
@@ -243,92 +512,314 @@ 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);
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Material");
}
@@ -354,6 +845,8 @@ public class Material {
private static native boolean nIsDepthCullingEnabled(long nativeMaterial);
private static native boolean nIsDoubleSided(long nativeMaterial);
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 nGetParameterCount(long nativeMaterial);
private static native void nGetParameters(long nativeMaterial,

View File

@@ -21,8 +21,9 @@ import android.support.annotation.NonNull;
import android.support.annotation.Size;
public class MaterialInstance {
private final Material mMaterial;
private Material mMaterial;
private long mNativeObject;
private long mNativeMaterial;
public enum BooleanElement {
BOOL,
@@ -52,114 +53,384 @@ public class MaterialInstance {
mNativeObject = nativeMaterialInstance;
}
MaterialInstance(long nativeMaterial, long nativeMaterialInstance) {
mNativeMaterial = nativeMaterial;
mNativeObject = nativeMaterialInstance;
}
/** @return the {@link Material} associated with this instance */
@NonNull
public Material getMaterial() {
if (mMaterial == null) {
mMaterial = new Material(mNativeMaterial);
}
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) {
setParameter(name, FloatElement.FLOAT3, Colors.toLinear(type, r, g, b), 0, 1);
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) {
setParameter(name, FloatElement.FLOAT4, Colors.toLinear(type, r, g, b, a), 0, 1);
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);
}
long getNativeObject() {
/**
* 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());
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed MaterialInstance");
}
@@ -218,9 +489,16 @@ public class MaterialInstance {
private static native void nUnsetScissor(long nativeMaterialInstance);
private static native void nSetPolygonOffset(long nativeMaterialInstance,
float scale, float constant);
float scale, float constant);
private static native void nSetMaskThreshold(long nativeMaterialInstance, float threshold);
private static native void nSetSpecularAntiAliasingVariance(long nativeMaterialInstance,
float variance);
private static native void nSetSpecularAntiAliasingThreshold(long nativeMaterialInstance,
float threshold);
private static native void nSetDoubleSided(long nativeMaterialInstance, boolean doubleSided);
private static native void nSetCullingMode(long nativeMaterialInstance, long mode);
}

View File

@@ -23,6 +23,29 @@ import android.support.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

@@ -18,6 +18,8 @@ package com.google.android.filament;
import android.support.annotation.NonNull;
import com.google.android.filament.proguard.UsedByNative;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
@@ -26,6 +28,7 @@ import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
@UsedByNative("NioUtils.cpp")
final class NioUtils {
enum BufferType {
@@ -41,18 +44,22 @@ final class NioUtils {
private NioUtils() {
}
@UsedByNative("NioUtils.cpp")
static long getBasePointer(@NonNull Buffer b, long address, int sizeShift) {
return address != 0 ? address + (b.position() << sizeShift) : 0;
}
@UsedByNative("NioUtils.cpp")
static Object getBaseArray(@NonNull Buffer b) {
return b.hasArray() ? b.array() : null;
}
@UsedByNative("NioUtils.cpp")
static int getBaseArrayOffset(@NonNull Buffer b, int sizeShift) {
return b.hasArray() ? ((b.arrayOffset() + b.position()) << sizeShift) : 0;
}
@UsedByNative("NioUtils.cpp")
static int getBufferType(@NonNull Buffer b) {
if (b instanceof ByteBuffer) {
return BufferType.BYTE.ordinal();

View File

@@ -0,0 +1,219 @@
/*
* 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.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.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];
private RenderTarget(long nativeRenderTarget, Builder builder) {
mNativeObject = nativeRenderTarget;
mTextures[0] = builder.mTextures[0];
mTextures[1] = builder.mTextures[1];
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed 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;
private final long mNativeBuilder;
private final Texture[] mTextures = new Texture[2];
public Builder() {
mNativeBuilder = nCreateBuilder();
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;
nBuilderTexture(mNativeBuilder, attachment.ordinal(), texture != null ? texture.getNativeObject() : 0);
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());
if (nativeRenderTarget == 0)
throw new IllegalStateException("Couldn't create RenderTarget");
return new RenderTarget(nativeRenderTarget, this);
}
private static class BuilderFinalizer {
private final long mNativeObject;
BuilderFinalizer(long nativeObject) {
mNativeObject = nativeObject;
}
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) { // Ignore
} finally {
nDestroyBuilder(mNativeObject);
}
}
}
}
/**
* 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());
}
void clearNativeObject() {
mNativeObject = 0;
}
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 long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native int nGetMipLevel(long nativeRenderTarget, int attachment);
private static native int nGetFace(long nativeRenderTarget, int attachment);
private static native int nGetLayer(long nativeRenderTarget, int attachment);
}

View File

@@ -23,12 +23,51 @@ 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,37 +75,208 @@ 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 mirrorFrame(
public void copyFrame(
@NonNull SwapChain dstSwapChain, @NonNull Viewport dstViewport,
@NonNull Viewport srcViewport, int flags) {
nMirrorFrame(getNativeObject(), dstSwapChain.getNativeObject(),
nCopyFrame(getNativeObject(), dstSwapChain.getNativeObject(),
dstViewport.left, dstViewport.bottom, dstViewport.width, dstViewport.height,
srcViewport.left, srcViewport.bottom, srcViewport.width, srcViewport.height,
flags);
}
@Deprecated
public void mirrorFrame(
@NonNull SwapChain dstSwapChain, @NonNull Viewport dstViewport,
@NonNull Viewport srcViewport, int flags) {
copyFrame(dstSwapChain, dstViewport, srcViewport, flags);
}
/**
* 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,
@@ -89,15 +299,71 @@ public class Renderer {
}
}
double getUserTime() {
/**
* 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.
* {@link android.app.Activity#onPause() Activity.onPause} in Android.</p>
*
* @see #getUserTime
*/
public void resetUserTime() {
nResetUserTime(getNativeObject());
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Renderer");
}
@@ -111,7 +377,7 @@ public class Renderer {
private static native boolean nBeginFrame(long nativeRenderer, long nativeSwapChain);
private static native void nEndFrame(long nativeRenderer);
private static native void nRender(long nativeRenderer, long nativeView);
private static native void nMirrorFrame(long nativeRenderer, long nativeDstSwapChain,
private static native void nCopyFrame(long nativeRenderer, long nativeDstSwapChain,
int dstLeft, int dstBottom, int dstWidth, int dstHeight,
int srcLeft, int srcBottom, int srcWidth, int srcHeight,
int flags);

View File

@@ -18,6 +18,28 @@ package com.google.android.filament;
import android.support.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,31 +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);
}
@@ -63,15 +132,25 @@ 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());
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Scene");
}
@@ -85,6 +164,7 @@ public class Scene {
private static native void nSetSkybox(long nativeScene, long nativeSkybox);
private static native void nSetIndirectLight(long nativeScene, long nativeIndirectLight);
private static native void nAddEntity(long nativeScene, int entity);
private static native void nAddEntities(long nativeScene, int[] entities);
private static native void nRemove(long nativeScene, int entity);
private static native int nGetRenderableCount(long nativeScene);
private static native int nGetLightCount(long nativeScene);

View File

@@ -19,35 +19,123 @@ package com.google.android.filament;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import com.google.android.filament.proguard.UsedByReflection;
/**
* 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;
private Skybox(long nativeSkybox) {
@UsedByReflection("KtxLoader.java")
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());
@@ -72,15 +160,36 @@ 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());
}
long 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");
}
@@ -95,7 +204,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

@@ -23,6 +23,12 @@ 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;
@@ -32,20 +38,31 @@ public class Stream {
mNativeEngine = engine.getNativeObject();
}
/**
* Use <code>Builder</code> to construct an Stream 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 Stream object instance.
*/
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Accepted types for the stream source:
* - Android: SurfaceView
* - Other: none
* Creates a 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 +73,57 @@ public class Stream {
throw new IllegalArgumentException("Invalid stream source: " + streamSource);
}
/**
* Creates a copy 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 +149,92 @@ public class Stream {
}
}
/**
* Indicates whether this <code>Stream</code> is a native stream or a copy stream.
*
* @return true if this is a native <code>Stream</code>, false otherwise.
*/
public boolean isNative() {
return nIsNative(getNativeObject());
}
/**
* 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 #isNative()}.
* 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,11 +256,18 @@ 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());
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Stream");
}

View File

@@ -18,12 +18,71 @@ package com.google.android.filament;
import android.support.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) {
@@ -31,12 +90,15 @@ public class SwapChain {
mSurface = surface;
}
/**
* @return the native <code>Object</code> this <code>SwapChain</code> was created from.
*/
@NonNull
public Object getNativeWindow() {
return mSurface;
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed SwapChain");
}

View File

@@ -21,25 +21,152 @@ 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;
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) {
mNativeObject = nativeTexture;
}
/**
* Type of sampler
*/
public enum Sampler {
/** 2D sampler */
SAMPLER_2D,
/** 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,
@@ -60,7 +187,7 @@ public class Texture {
RG16F, RG16UI, RG16I,
R11F_G11F_B10F,
RGBA8, SRGB8_A8, RGBA8_SNORM,
UNUSED, // The RGBM InternalFormat has been replaced with a flag (Texture.Builder.rgbm)
UNUSED, // used to be rgbm
RGB10_A2, RGBA8UI, RGBA8I,
DEPTH32F, DEPTH24_STENCIL8, DEPTH32F_STENCIL8,
@@ -89,6 +216,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,
@@ -100,15 +231,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,
@@ -118,25 +261,50 @@ public class Texture {
RGB_INTEGER,
RGBA,
RGBA_INTEGER,
RGBM,
UNUSED,
DEPTH_COMPONENT,
DEPTH_STENCIL,
STENCIL_INDEX,
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,
COMPRESSED
/** 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;
@@ -161,6 +329,20 @@ public class Texture {
* - Android: Handler, Executor
* - Other: Executor
*/
/**
* 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,
@IntRange(from = 1, to = 8) int alignment,
@@ -178,17 +360,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,
@@ -196,6 +409,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) {
@@ -207,9 +428,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;
@@ -252,7 +474,6 @@ public class Texture {
break;
case RGBA:
case RGBA_INTEGER:
case RGBM:
n = 4;
break;
}
@@ -273,6 +494,10 @@ public class Texture {
case FLOAT:
bpp *= 4;
break;
case UINT_10F_11F_11F_REV:
// Special case, format must be RGB and uses 4 bytes
bpp = 4;
break;
}
int bpr = bpp * stride;
@@ -281,64 +506,133 @@ 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. This creates a 3D texture.
* @param depth texture number of layer, must be at least 1. 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());
return this;
}
/**
* Sets the usage flags, which is necessary when attaching to {@link RenderTarget}.
*
* The flags argument much be a combination of {@link Usage} flags.
*/
@NonNull
public Builder rgbm(boolean enabled) {
nBuilderRgbm(mNativeBuilder, enabled);
public Builder usage(int flags) {
nBuilderUsage(mNativeBuilder, flags);
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());
@@ -365,29 +659,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())];
@@ -395,12 +731,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,
@@ -427,9 +816,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) {
@@ -452,10 +865,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();
@@ -466,11 +929,97 @@ 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());
}
long 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) {
int width = getWidth(0);
int height= getHeight(0);
int sampleCount = 8;
boolean mirror = true;
if (options != null) {
sampleCount = options.sampleCount;
mirror = options.mirror;
}
int result = nGeneratePrefilterMipmap(getNativeObject(), engine.getNativeObject(),
width, height,
buffer.storage, buffer.storage.remaining(),
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
buffer.stride, buffer.format.ordinal(), faceOffsetsInBytes,
buffer.handler, buffer.callback,
sampleCount, mirror);
if (result < 0) {
throw new BufferOverflowException();
}
}
@UsedByReflection("TextureHelper.java")
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Texture");
}
@@ -492,7 +1041,7 @@ public class Texture {
private static native void nBuilderLevels(long nativeBuilder, int levels);
private static native void nBuilderSampler(long nativeBuilder, int sampler);
private static native void nBuilderFormat(long nativeBuilder, int format);
private static native void nBuilderRgbm(long nativeBuilder, boolean enabled);
private static native void nBuilderUsage(long nativeBuilder, int flags);
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native int nGetWidth(long nativeTexture, int level);
@@ -533,4 +1082,9 @@ public class Texture {
private static native void nGenerateMipmaps(long nativeTexture, long nativeEngine);
private static native boolean nIsStreamValidForTexture(long nativeTexture, long nativeStream);
private static native int nGeneratePrefilterMipmap(long nativeIndirectLight, long nativeEngine,
int width, int height, Buffer storage, int remaining, int left, int top,
int type, int alignment, int stride, int format, int[] faceOffsetsInBytes,
Object handler, Runnable callback, int sampleCount, boolean mirror);
}

View File

@@ -18,24 +18,60 @@ package com.google.android.filament;
import android.support.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

@@ -20,82 +20,219 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.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) {
if (localTransform.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
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,
@Nullable @Size(min = 16) float[] outLocalTransform) {
outLocalTransform = assertMat4f(outLocalTransform);
outLocalTransform = Asserts.assertMat4f(outLocalTransform);
nGetTransform(mNativeObject, i, outLocalTransform);
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,
@Nullable @Size(min = 16) float[] outWorldTransform) {
outWorldTransform = assertMat4f(outWorldTransform);
outWorldTransform = Asserts.assertMat4f(outWorldTransform);
nGetWorldTransform(mNativeObject, i, outWorldTransform);
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);
}
@NonNull @Size(min = 16)
private static float[] assertMat4f(@Nullable float[] out) {
if (out == null) out = new float[16];
else if (out.length < 16) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 16");
}
return out;
public long getNativeObject() {
return mNativeObject;
}
private static native boolean nHasComponent(long nativeTransformManager, int entity);

View File

@@ -23,6 +23,33 @@ import android.support.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,27 @@ 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>
*
* @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,
@@ -197,7 +426,7 @@ public class VertexBuffer {
context.tangentsStride);
}
long getNativeObject() {
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed VertexBuffer");
}

View File

@@ -21,8 +21,39 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.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;
@@ -32,18 +63,105 @@ public class View {
private DynamicResolutionOptions mDynamicResolution;
private RenderQuality mRenderQuality;
private DepthPrepass mDepthPrepass = DepthPrepass.DEFAULT;
private AmbientOcclusionOptions mAmbientOcclusionOptions;
private RenderTarget mRenderTarget;
/**
* 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;
}
/**
* 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.005f;
/**
* Controls ambient occlusion's contrast. Between 0 (linear) and 1 (squared)
*/
public float power = 0.0f;
/**
* How each dimension of the AO buffer is scaled. Must be positive and <= 1.
*/
public float resolution = 0.5f;
}
/**
* Sets the quality of the HDR color buffer.
*
* <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 enum QualityLevel {
LOW,
MEDIUM,
@@ -51,25 +169,73 @@ public class View {
ULTRA
}
/**
* 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 {
public QualityLevel hdrColorBuffer = QualityLevel.HIGH;
}
public enum AntiAliasing {
/**
* 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
}
/** @see #setDepthPrepass */
public enum DepthPrepass {
DEFAULT(-1),
DISABLED(0),
@@ -86,108 +252,314 @@ public class View {
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 = assertFloat4(out);
out = Asserts.assertFloat4(out);
nGetClearColor(getNativeObject(), out);
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(),
@@ -201,6 +573,10 @@ public class View {
options.history);
}
/**
* Returns the dynamic resolution options associated with this view.
* @return value set by {@link #setDynamicResolutionOptions}.
*/
@NonNull
public DynamicResolutionOptions getDynamicResolutionOptions() {
if (mDynamicResolution == null) {
@@ -209,11 +585,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) {
@@ -222,37 +607,177 @@ public class View {
return mRenderQuality;
}
/**
* Checks if this view is rendered with a depth-only prepass.
*
* @return the value set by {@link #setDepthPrepass}.
*/
@NonNull
public DepthPrepass getDepthPrepass() {
return mDepthPrepass;
}
/**
* Sets whether this view is rendered with or without a depth pre-pass.
*
* <p>
* By default, the system picks the most appropriate strategy for your platform; this method
* lets you override that strategy.
* </p>
*
* <p>
* When the depth pre-pass is enabled, the renderer will first draw all objects in the
* depth buffer from front to back, and then draw the objects again but sorted to minimize
* state changes. With the depth pre-pass disabled, objects are drawn only once, but it may
* result in more state changes or more overdraw.
* </p>
*
* <p>
* The best strategy may depend on the scene and/or GPU.
* </p>
*
* <ul>
* <li>DepthPrepass::DEFAULT uses the most appropriate strategy</li>
* <li>DepthPrepass::DISABLED disables the depth pre-pass</li>
* <li>DepthPrepass::ENABLE enables the depth pre-pass</li>
* </ul>
*/
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);
}
long getNativeObject() {
/**
* 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);
}
/**
* Gets the ambient occlusion options.
*
* @return ambient occlusion options currently set.
*/
@NonNull
public AmbientOcclusionOptions getAmbientOcclusionOptions() {
if (mAmbientOcclusionOptions == null) {
mAmbientOcclusionOptions = new AmbientOcclusionOptions();
}
return mAmbientOcclusionOptions;
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed View");
}
@@ -263,15 +788,6 @@ public class View {
mNativeObject = 0;
}
@NonNull @Size(min = 4)
private static float[] assertFloat4(@Nullable float[] out) {
if (out == null) out = new float[4];
else if (out.length < 4) {
throw new ArrayIndexOutOfBoundsException("Array length must be at least 4");
}
return out;
}
private static native void nSetName(long nativeView, String name);
private static native void nSetScene(long nativeView, long nativeScene);
private static native void nSetCamera(long nativeView, long nativeCamera);
@@ -281,6 +797,7 @@ public class View {
private static native void nSetClearTargets(long nativeView, boolean color, boolean depth, boolean stencil);
private static native void nSetVisibleLayers(long nativeView, int select, int value);
private static native void nSetShadowsEnabled(long nativeView, boolean enabled);
private static native void nSetRenderTarget(long nativeView, long nativeRenderTarget);
private static native void nSetSampleCount(long nativeView, int count);
private static native int nGetSampleCount(long nativeView);
private static native void nSetAntiAliasing(long nativeView, int type);
@@ -300,4 +817,7 @@ public class View {
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);
}

View File

@@ -18,6 +18,16 @@ package com.google.android.filament;
import android.support.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

@@ -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,7 +18,6 @@ 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;
@@ -27,6 +26,7 @@ import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import com.google.android.filament.SwapChain;
/**
@@ -58,7 +58,7 @@ import com.google.android.filament.SwapChain;
* mUiHelper = new UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK);
*
* // Attach the SurfaceView to the helper, you could do the same with a TextureView
* mUiHelper.attachTo(surfaceView)
* mUiHelper.attachTo(mSurfaceView);
*
* // Set a rendering callback that we will use to invoke Filament
* mUiHelper.setRenderCallback(new UiHelper.RendererCallback() {
@@ -95,15 +95,11 @@ import com.google.android.filament.SwapChain;
* }
*
* public void onDestroy() {
* super.onDestroy()
* super.onDestroy();
* // Always detach the surface before destroying the engine
* mUiHelper.detach()
* 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()
* mEngine.destroy();
* }
*
* // This is an example of a render function. You will most likely invoke this from
@@ -113,8 +109,8 @@ import com.google.android.filament.SwapChain;
* // If beginFrame() returns false you should skip the frame
* // This means you are sending frames too quickly to the GPU
* if (mRenderer.beginFrame(swapChain)) {
* mRenderer.render(mView)
* mRenderer.endFrame()
* mRenderer.render(mView);
* mRenderer.endFrame();
* }
* }
* }

View File

@@ -0,0 +1,45 @@
/*
* 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.proguard;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/**
* Annotation used for marking methods and fields that are called from native
* code. Useful for keeping components that would otherwise be removed by
* Proguard. Use the value parameter to mention a file that calls this method.
*
* 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. Usage example:
* <pre>
*
* &commat;UsedByNative("NativeCrashHandler.cpp")
* public static void reportCrash(int signal, int code, int address) {
* ...
* }
* </pre>
*/
@Target({
ElementType.METHOD,
ElementType.FIELD,
ElementType.TYPE,
ElementType.CONSTRUCTOR})
public @interface UsedByNative {
String value();
}

View File

@@ -0,0 +1,45 @@
/*
* 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.proguard;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/**
* Annotation used for marking methods and fields that are called by reflection. Useful for keeping
* components that would otherwise be removed by Proguard. Use the value parameter to mention a file
* that calls this method.
*
* 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. Usage example:
* <pre>
*
* &commat;UsedByReflection("PeopleListItemView.java")
* public PeopleListItemViewV11(Context context) {
* super(context);
* }
* </pre>
*/
@Target({
ElementType.METHOD,
ElementType.FIELD,
ElementType.TYPE,
ElementType.CONSTRUCTOR})
public @interface UsedByReflection {
String value();
}

12
android/gltfio-android/.gitignore vendored Normal file
View File

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

View File

@@ -0,0 +1,101 @@
cmake_minimum_required(VERSION 3.6)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
set(DISABLE_FILAMENT_JNI TRUE)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../filament-android ${CMAKE_CURRENT_BINARY_DIR}/filament-android)
add_library(filament STATIC IMPORTED)
set_target_properties(filament PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament.a)
add_library(backend STATIC IMPORTED)
set_target_properties(backend PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbackend.a)
add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
add_library(filaflat STATIC IMPORTED)
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
add_library(image STATIC IMPORTED)
set_target_properties(image PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
add_library(ibl STATIC IMPORTED)
set_target_properties(ibl PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libibl.a)
add_library(geometry STATIC IMPORTED)
set_target_properties(geometry PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgeometry.a)
add_library(filabridge STATIC IMPORTED)
set_target_properties(filabridge PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilabridge.a)
add_library(gltfio STATIC IMPORTED)
set_target_properties(gltfio PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_core.a)
add_library(gltfio_resources STATIC IMPORTED)
set_target_properties(gltfio_resources PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgltfio_resources.a)
add_library(bluevk STATIC IMPORTED)
set_target_properties(bluevk PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbluevk.a)
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
..
../../libs/utils/include)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libgltfio-jni.map")
add_library(gltfio-jni SHARED
src/main/cpp/Animator.cpp
src/main/cpp/AssetLoader.cpp
src/main/cpp/FilamentAsset.cpp
src/main/cpp/KtxLoader.cpp
src/main/cpp/MaterialProvider.cpp
src/main/cpp/ResourceLoader.cpp
../common/CallbackUtils.cpp
../common/NioUtils.cpp
$<TARGET_OBJECTS:filament-jni-obj>
)
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols)
# The ordering in the following list is important because CMake does not have dependency information.
target_link_libraries(gltfio-jni
gltfio
filament
backend
filaflat
filabridge
geometry
image
ibl
utils
log
GLESv3
EGL
android
jnigraphics
gltfio_resources
m
)
if (FILAMENT_SUPPORTS_VULKAN)
target_link_libraries(gltfio-jni bluevk smol-v)
endif()

View File

@@ -0,0 +1,90 @@
// 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 = "1.3"
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 29
defaultConfig {
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
arguments.add("-DANDROID_PLATFORM=android-19")
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)
}
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
sourceSets {
main {
jni.srcDirs "src/main/cpp"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.google.android.filament:filament-android'
}

Binary file not shown.

View File

@@ -0,0 +1,5 @@
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

172
android/gltfio-android/gradlew vendored Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-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" "$@"

84
android/gltfio-android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-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

@@ -0,0 +1,4 @@
LIBGLTFIO {
global: Java_com_google_android_filament_*; JNI*;
local: *;
};

View File

@@ -0,0 +1 @@
_Java_com_google_android_filament_*

View File

@@ -0,0 +1,12 @@
/*
* 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
*/
includeBuild '../filament-android'
rootProject.name = 'gltfio-android'

View File

@@ -0,0 +1,18 @@
<!--
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.filament.gltfio" />

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <gltfio/Animator.h>
using namespace filament;
using namespace filament::math;
using namespace gltfio;
using namespace utils;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_Animator_nApplyAnimation(JNIEnv*, jclass, jlong nativeAnimator,
jint index, jfloat time) {
Animator* animator = (Animator*) nativeAnimator;
animator->applyAnimation(index, time);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_Animator_nUpdateBoneMatrices(JNIEnv*, jclass, jlong nativeAnimator) {
Animator* animator = (Animator*) nativeAnimator;
animator->updateBoneMatrices();
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_Animator_nGetAnimationCount(JNIEnv*, jclass, jlong nativeAnimator) {
Animator* animator = (Animator*) nativeAnimator;
return animator->getAnimationCount();
}
extern "C" JNIEXPORT float JNICALL
Java_com_google_android_filament_gltfio_Animator_nGetAnimationDuration(JNIEnv*, jclass,
jlong nativeAnimator, jint index) {
Animator* animator = (Animator*) nativeAnimator;
return animator->getAnimationDuration(index);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_google_android_filament_gltfio_Animator_nGetAnimationName(JNIEnv* env, jclass,
jlong nativeAnimator, jint index) {
Animator* animator = (Animator*) nativeAnimator;
const char* val = animator->getAnimationName(index);
return val ? env->NewStringUTF(val) : nullptr;
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <filament/Engine.h>
#include <utils/EntityManager.h>
#include <gltfio/AssetLoader.h>
#include <gltfio/MaterialProvider.h>
#include "common/NioUtils.h"
using namespace filament;
using namespace gltfio;
using namespace utils;
extern void registerCallbackUtils(JNIEnv*);
extern void registerNioUtils(JNIEnv*);
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
registerCallbackUtils(env);
registerNioUtils(env);
return JNI_VERSION_1_6;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetLoader(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeProvider, jlong nativeEntities) {
Engine* engine = (Engine*) nativeEngine;
MaterialProvider* materials = (MaterialProvider*) nativeProvider;
EntityManager* entities = (EntityManager*) nativeEntities;
return (jlong) AssetLoader::create({engine, materials, nullptr, entities});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAssetLoader(JNIEnv*, jclass,
jlong nativeLoader) {
AssetLoader* loader = (AssetLoader*) nativeLoader;
AssetLoader::destroy(&loader);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetFromBinary(JNIEnv* env, jclass,
jlong nativeLoader, jobject javaBuffer, jint remaining) {
AssetLoader* loader = (AssetLoader*) nativeLoader;
AutoBuffer buffer(env, javaBuffer, remaining);
return (jlong) loader->createAssetFromBinary((const uint8_t *) buffer.getData(),
buffer.getSize());
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_AssetLoader_nEnableDiagnostics(JNIEnv*, jclass,
jlong nativeLoader, jboolean enable) {
AssetLoader* loader = (AssetLoader*) nativeLoader;
loader->enableDiagnostics(enable);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAsset(JNIEnv*, jclass,
jlong nativeLoader, jlong nativeAsset) {
AssetLoader* loader = (AssetLoader*) nativeLoader;
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
loader->destroyAsset(asset);
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <gltfio/FilamentAsset.h>
using namespace filament;
using namespace filament::math;
using namespace gltfio;
using namespace utils;
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetRoot(JNIEnv*, jclass, jlong nativeAsset) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
return asset->getRoot().getId();
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetEntityCount(JNIEnv*, jclass,
jlong nativeAsset) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
return asset->getEntityCount();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetEntities(JNIEnv* env, jclass,
jlong nativeAsset, jintArray result) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
std::copy_n(asset->getEntities(), asset->getEntityCount(), entities);
env->ReleaseIntArrayElements(result, (jint*) entities, 0);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetBoundingBox(JNIEnv* env, jclass,
jlong nativeAsset, jfloatArray result) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
float* values = (float*) env->GetFloatArrayElements(result, nullptr);
const filament::Aabb box = asset->getBoundingBox();
const float3 center = box.center();
const float3 extent = box.extent();
values[0] = center.x;
values[1] = center.y;
values[2] = center.z;
values[3] = extent.x;
values[4] = extent.y;
values[5] = extent.z;
env->ReleaseFloatArrayElements(result, (jfloat*) values, 0);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetName(JNIEnv* env, jclass,
jlong nativeAsset, jint entityId) {
uint32_t id = entityId;
Entity* entity = (Entity*) &id;
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
const char* val = asset->getName(*entity);
return val ? env->NewStringUTF(val) : nullptr;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetAnimator(JNIEnv* env, jclass,
jlong nativeAsset) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
return (jlong) asset->getAnimator();
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <filament/Engine.h>
#include <filament/IndirectLight.h>
#include <filament/Skybox.h>
#include <image/KtxUtility.h>
#include "common/NioUtils.h"
using namespace filament;
using namespace filament::math;
using namespace image;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_KtxLoader_nCreateTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
return (jlong) ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
delete bundle;
}, bundle);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_KtxLoader_nCreateIndirectLight(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
delete bundle;
}, bundle);
float3 harmonics[9];
bundle->getSphericalHarmonics(harmonics);
IndirectLight* indirectLight = IndirectLight::Builder()
.reflections(cubemap)
.irradiance(3, harmonics)
.intensity(30000)
.build(*engine);
return (jlong) indirectLight;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_KtxLoader_nCreateSkybox(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
delete bundle;
}, bundle);
return (jlong) Skybox::Builder().environment(cubemap).showSun(true).build(*engine);
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <gltfio/MaterialProvider.h>
using namespace filament;
using namespace gltfio;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_MaterialProvider_nCreateMaterialProvider(JNIEnv*, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) createUbershaderLoader(engine);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_MaterialProvider_nDestroyMaterialProvider(JNIEnv*, jclass,
jlong nativeProvider) {
auto provider = (MaterialProvider*) nativeProvider;
delete provider;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <filament/Engine.h>
#include <gltfio/ResourceLoader.h>
#include <utils/Log.h>
#include "common/NioUtils.h"
using namespace filament;
using namespace gltfio;
using namespace utils;
static void destroy(void* data, size_t size, void *userData) {
AutoBuffer* buffer = (AutoBuffer*) userData;
delete buffer;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateResourceLoader(JNIEnv*, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) new ResourceLoader({ engine, utils::Path(), true, true });
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nDestroyResourceLoader(JNIEnv*, jclass,
jlong nativeLoader) {
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
delete loader;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nAddResourceData(JNIEnv* env, jclass,
jlong nativeLoader, jstring url, jobject javaBuffer, jint remaining) {
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
AutoBuffer* buffer = new AutoBuffer(env, javaBuffer, remaining);
const char* curl = env->GetStringUTFChars(url, nullptr);
loader->addResourceData(curl,
ResourceLoader::BufferDescriptor(buffer->getData(), buffer->getSize(), &destroy,
buffer));
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nLoadResources(JNIEnv*, jclass,
jlong nativeLoader, jlong nativeAsset) {
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
loader->loadResources(asset);
}

View File

@@ -0,0 +1,103 @@
/*
* 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.gltfio;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
* Updates matrices according to glTF <code>animation</code> and <code>skin</code> definitions.
*
* <p>Animator can be used for two things:
* <ul>
* <li>Updating matrices in <code>TransformManager</code> components according to glTF <code>animation</code> definitions.</li>
* <li>Updating bone matrices in <code>RenderableManager</code> components according to glTF <code>skin</code> definitions.</li>
* </ul>
* </p>
*
* @see AssetLoader
* @see FilamentAsset
* @see ResourceLoader
*/
public class Animator {
private long mNativeObject;
Animator(long nativeObject) {
mNativeObject = nativeObject;
}
/**
* Applies rotation, translation, and scale to entities that have been targeted by the given
* animation definition. Uses <code>TransformManager</code>.
*
* @param animationIndex Zero-based index for the <code>animation</code> of interest.
* @param time Elapsed time of interest in seconds.
*
* @see #getAnimationCount
*/
public void applyAnimation(@IntRange(from = 0) int animationIndex, float time) {
nApplyAnimation(mNativeObject, animationIndex, time);
}
/**
* Computes root-to-node transforms for all bone nodes, then passes
* the results into {@see RenderableManager#setBones}.
* Uses <code>TransformManager</code> and <code>RenderableManager</code>.
*
* <p>NOTE: this operation is independent of <code>animation</code>.</p>
*/
public void updateBoneMatrices() {
nUpdateBoneMatrices(mNativeObject);
}
/**
* Returns the number of <code>animation</code> definitions in the glTF asset.
*/
public int getAnimationCount() {
return nGetAnimationCount(mNativeObject);
}
/**
* Returns the duration of the specified glTF <code>animation</code> in seconds.
*
* @param animationIndex Zero-based index for the <code>animation</code> of interest.
*
* @see #getAnimationCount
* */
public float getAnimationDuration(@IntRange(from = 0) int animationIndex) {
return nGetAnimationDuration(mNativeObject, animationIndex);
}
/**
* Returns a weak reference to the string name of the specified <code>animation</code>, or an
* empty string if none was specified.
*
* @param animationIndex Zero-based index for the <code>animation</code> of interest.
*
* @see #getAnimationCount
*/
public String getAnimationName(@IntRange(from = 0) int animationIndex) {
return nGetAnimationName(mNativeObject, animationIndex);
}
private static native void nApplyAnimation(long nativeAnimator, int index, float time);
private static native void nUpdateBoneMatrices(long nativeAnimator);
private static native int nGetAnimationCount(long nativeAnimator);
private static native float nGetAnimationDuration(long nativeAnimator, int index);
private static native String nGetAnimationName(long nativeAnimator, int index);
}

View File

@@ -0,0 +1,137 @@
/*
* 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.gltfio;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.filament.Engine;
import com.google.android.filament.EntityManager;
import java.nio.Buffer;
/**
* Consumes a blob of glTF 2.0 content (either JSON or GLB) and produces {@link FilamentAsset}
* objects, which are bundles of Filament entities, material instances, textures, vertex buffers,
* and index buffers.
*
* <p>AssetLoader does not fetch external buffer data or create textures on its own. Clients can use
* the provided {@link ResourceLoader} class for this, which obtains the URI list from the asset.
* This is demonstrated in the Kotlin snippet below.</p>
*
* <pre>
*
* companion object {
* init {
* Filament.init()
* AssetLoader.init()
* }
* }
*
* override fun onCreate(savedInstanceState: Bundle?) {
*
* ...
*
* assetLoader = AssetLoader(engine, MaterialProvider(engine), EntityManager.get())
*
* filamentAsset = assets.open("models/lucy.glb").use { input ->
* val bytes = ByteArray(input.available())
* input.read(bytes)
* assetLoader.createAssetFromBinary(ByteBuffer.wrap(bytes))!!
* }
*
* ResourceLoader(engine).loadResources(filamentAsset).destroy()
* animator = asset.getAnimator()
*
* scene.addEntities(filamentAsset.entities)
* }
* </pre>
*
* @see Animator
* @see FilamentAsset
* @see ResourceLoader
*/
public class AssetLoader {
private long mNativeObject;
/**
* Initializes the gltfio JNI layer. Must be called before using any gltfio functionality.
*/
public static void init() {
System.loadLibrary("gltfio-jni");
}
/**
* Constructs an <code>AssetLoader </code>that can be used to create and destroy instances of
* {@link FilamentAsset}.
*
* @param engine the engine that the loader should pass to builder objects
* @param generator specifies if materials should be generated or loaded from a pre-built set
* @param entities the EntityManager that should be used to create entities
*/
public AssetLoader(@NonNull Engine engine, @NonNull MaterialProvider generator,
@NonNull EntityManager entities) {
long nativeEngine = engine.getNativeObject();
long nativeMaterials = generator.getNativeObject();
long nativeEntities = entities.getNativeObject();
mNativeObject = nCreateAssetLoader(nativeEngine, nativeMaterials, nativeEntities);
if (mNativeObject == 0) {
throw new IllegalStateException("Unable to parse glTF asset.");
}
}
/**
* Frees all memory consumed by the native <code>AssetLoader</code> and its material cache.
*/
public void destroy() {
nDestroyAssetLoader(mNativeObject);
mNativeObject = 0;
}
/**
* Creates a {@link FilamentAsset} from the contents of a GLB file.
*/
@Nullable
public FilamentAsset createAssetFromBinary(@NonNull Buffer buffer) {
long nativeAsset = nCreateAssetFromBinary(mNativeObject, buffer, buffer.remaining());
return new FilamentAsset(nativeAsset);
}
/**
* Allows clients to enable diagnostic shading on newly-loaded assets.
*/
public void enableDiagnostics(boolean enable) {
nEnableDiagnostics(mNativeObject, enable);
}
/**
* Frees all memory associated with the given {@link FilamentAsset}.
*/
public void destroyAsset(@Nullable FilamentAsset asset) {
nDestroyAsset(mNativeObject, asset.getNativeObject());
asset.clearNativeObject();
}
private static native long nCreateAssetLoader(long nativeEngine, long nativeGenerator,
long nativeEntities);
private static native void nDestroyAssetLoader(long nativeLoader);
private static native long nCreateAssetFromBinary(long nativeLoader, Buffer buffer, int remaining);
private static native void nEnableDiagnostics(long nativeLoader, boolean enable);
private static native void nDestroyAsset(long nativeLoader, long nativeAsset);
}

View File

@@ -0,0 +1,116 @@
/*
* 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.gltfio;
import android.support.annotation.NonNull;
import com.google.android.filament.Box;
import com.google.android.filament.Entity;
/**
* Owns a bundle of Filament objects that have been created by <code>AssetLoader</code>.
*
* <p>For usage instructions, see the documentation for {@link AssetLoader}.</p>
*
* <p>This class owns a hierarchy of entities that have been loaded from a glTF asset. Every entity has
* a <code>TransformManager</code> component, and some entities also have
* <code>NameComponentManager</code> and/or <code>RenderableManager</code> components.</p>
*
* <p>In addition to the aforementioned entities, an asset has strong ownership over a list of
* <code>VertexBuffer</code>, <code>IndexBuffer</code>, <code>MaterialInstance</code>, and
* <code>Texture</code>.</p>
*
* <p>Clients can use {@link ResourceLoader} to create textures, compute tangent quaternions, and
* upload data into vertex buffers and index buffers.</p>
*
* @see ResourceLoader
* @see Animator
* @see AssetLoader
*/
public class FilamentAsset {
private long mNativeObject;
private Animator mAnimator;
FilamentAsset(long nativeObject) {
mNativeObject = nativeObject;
mAnimator = null;
}
long getNativeObject() {
return mNativeObject;
}
/**
* Gets the transform root for the asset, which has no matching glTF node.
*/
public @Entity int getRoot() {
return nGetRoot(mNativeObject);
}
/**
* Gets the list of entities, one for each glTF node.
*
* <p>All of these have a transform component. Some of the returned entities may also have a
* renderable component.</p>
*/
public @Entity int[] getEntities() {
int[] result = new int[nGetEntityCount(mNativeObject)];
nGetEntities(mNativeObject, result);
return result;
}
/**
* Gets the bounding box computed from the supplied min / max values in glTF accessors.
*/
public @NonNull Box getBoundingBox() {
float[] box = new float[6];
nGetBoundingBox(mNativeObject, box);
return new Box(box[0], box[1], box[2], box[3], box[4], box[5]);
}
/**
* Gets the <code>NameComponentManager</code> label for the given entity, if it exists.
*/
public String getName(@Entity int entity) {
return nGetName(getNativeObject(), entity);
}
/**
* Creates or retrieves the <code>Animator</code> for this asset.
*
* <p>When calling this for the first time, this must be called after
* {@see ResourceLoader#loadResources}.</p>
*/
public Animator getAnimator() {
if (mAnimator != null) {
return mAnimator;
}
mAnimator = new Animator(nGetAnimator(getNativeObject()));
return mAnimator;
}
void clearNativeObject() {
mNativeObject = 0;
}
private static native int nGetRoot(long nativeAsset);
private static native int nGetEntityCount(long nativeAsset);
private static native void nGetEntities(long nativeAsset, int[] result);
private static native void nGetBoundingBox(long nativeAsset, float[] box);
private static native String nGetName(long nativeAsset, int entity);
private static native long nGetAnimator(long nativeAsset);
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.gltfio;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.filament.Engine;
import com.google.android.filament.IndirectLight;
import com.google.android.filament.Skybox;
import com.google.android.filament.Texture;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.Buffer;
/**
* Utilities for consuming KTX files and producing Filament textures, IBLs, and sky boxes.
*
* <p>KTX is a simple container format that makes it easy to bundle miplevels and cubemap faces
* into a single file.</p>
*/
public class KtxLoader {
private static Constructor<Texture> sTextureConstructor;
private static Constructor<IndirectLight> sIndirectLightConstructor;
private static Constructor<Skybox> sSkyboxConstructor;
static {
try {
sTextureConstructor = Texture.class.getDeclaredConstructor(long.class);
sTextureConstructor.setAccessible(true);
sIndirectLightConstructor = IndirectLight.class.getDeclaredConstructor(long.class);
sIndirectLightConstructor.setAccessible(true);
sSkyboxConstructor = Skybox.class.getDeclaredConstructor(long.class);
sSkyboxConstructor.setAccessible(true);
} catch (NoSuchMethodException e) {
// Cannot happen
}
}
public static class Options {
public boolean srgb;
}
/**
* Consumes the content of a KTX file and produces a {@link Texture} object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the KTX File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
@Nullable
public static Texture createTexture(@NonNull Engine engine, @NonNull Buffer buffer, @NonNull Options options) {
try {
long nativeEngine = engine.getNativeObject();
long nativeTexture = nCreateTexture(nativeEngine, buffer, buffer.remaining(), options.srgb);
return sTextureConstructor.newInstance(nativeTexture);
} catch (Exception e) {
return null;
}
}
/**
* Consumes the content of a KTX file and produces an {@link IndirectLight} object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the KTX File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
@Nullable
public static IndirectLight createIndirectLight(@NonNull Engine engine, @NonNull Buffer buffer, @NonNull Options options) {
try {
long nativeEngine = engine.getNativeObject();
long nativeIndirectLight = nCreateIndirectLight(nativeEngine, buffer, buffer.remaining(), options.srgb);
return sIndirectLightConstructor.newInstance(nativeIndirectLight);
} catch (Exception e) {
return null;
}
}
/**
* Consumes the content of a KTX file and produces a {@link Skybox} object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the KTX File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
@Nullable
public static Skybox createSkybox(@NonNull Engine engine, @NonNull Buffer buffer, @NonNull Options options) {
try {
long nativeEngine = engine.getNativeObject();
long nativeSkybox = nCreateSkybox(nativeEngine, buffer, buffer.remaining(), options.srgb);
return sSkyboxConstructor.newInstance(nativeSkybox);
} catch (Exception e) {
return null;
}
}
private static native long nCreateTexture(long nativeEngine, Buffer buffer, int remaining, boolean srgb);
private static native long nCreateIndirectLight(long nativeEngine, Buffer buffer, int remaining, boolean srgb);
private static native long nCreateSkybox(long nativeEngine, Buffer buffer, int remaining, boolean srgb);
}

View File

@@ -0,0 +1,56 @@
/*
* 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.gltfio;
import com.google.android.filament.Engine;
import java.lang.reflect.Method;
/**
* Loads pre-generated ubershader materials that fulfill glTF requirements.
*
* <p>This class is used by {@link AssetLoader} to create Filament materials.
* Client applications do not need to call methods on it.</p>
*/
public class MaterialProvider {
private long mNativeObject;
/**
* Constructs an ubershader loader using the supplied {@link Engine}.
*
* @param engine the engine used to create materials
*/
public MaterialProvider(Engine engine) {
long nativeEngine = engine.getNativeObject();
mNativeObject = nCreateMaterialProvider(nativeEngine);
}
/**
* Frees memory associated with the native material provider.
* */
public void destroy() {
nDestroyMaterialProvider(mNativeObject);
mNativeObject = 0;
}
long getNativeObject() {
return mNativeObject;
}
private static native long nCreateMaterialProvider(long nativeEngine);
private static native void nDestroyMaterialProvider(long nativeProvider);
}

View File

@@ -0,0 +1,99 @@
/*
* 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.gltfio;
import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.filament.Engine;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.Buffer;
/**
* Uploads vertex buffers and textures to the GPU and computes tangents.
*
* <p>For a usage example, see the documentation for {@link AssetLoader}.</p>
*
* @see AssetLoader
* @see FilamentAsset
*/
public class ResourceLoader {
private final long mNativeObject;
/**
* Constructs a resource loader tied to the given Filament engine.
*
* @param engine the engine that gets passed to all builder methods
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public ResourceLoader(@NonNull Engine engine) {
long nativeEngine = engine.getNativeObject();
mNativeObject = nCreateResourceLoader(nativeEngine);
}
/**
* Frees all memory associated with the native resource loader.
*/
public void destroy() {
nDestroyResourceLoader(mNativeObject);
}
/**
* Feeds the binary content of an external resource into the loader's URI cache.
*
* <p><code>ResourceLoader</code> does not know how to download external resources on its own
* (for example, external resources might come from a filesystem, a database, or the internet)
* so this method allows clients to download external resources and push them to the loader.</p>
*
* <p>When loading GLB files (as opposed to JSON-based glTF files), clients typically do not
* need to call this method.</p>
*
* @param uri the string path that matches an image URI or buffer URI in the glTF
* @param buffer the binary blob corresponding to the given URI
* @return self (for daisy chaining)
*/
@NonNull
public ResourceLoader addResourceData(@NonNull String uri, @NonNull Buffer buffer) {
nAddResourceData(mNativeObject, uri, buffer, buffer.remaining());
return this;
}
/**
* Iterates through all external buffers and images and creates corresponding Filament objects
* (vertex buffers, textures, etc), which become owned by the asset.
*
* <p>This is the main entry point for <code>ResourceLoader</code>, and only needs to be called
* once.</p>
*
* @param asset the Filament asset that contains URI-based resources
* @return self (for daisy chaining)
*/
@NonNull
public ResourceLoader loadResources(@NonNull FilamentAsset asset) {
nLoadResources(mNativeObject, asset.getNativeObject());
return this;
}
private static native long nCreateResourceLoader(long nativeEngine);
private static native void nDestroyResourceLoader(long nativeLoader);
private static native void nAddResourceData(long nativeLoader, String url, Buffer buffer,
int remaining);
private static native void nLoadResources(long nativeLoader, long nativeAsset);
}

View File

@@ -46,6 +46,18 @@ host machine:
![Material Builder](../../docs/images/samples/sample_image_based_lighting.jpg)
### `gltf-bloom`
Demonstrates how to load glTF models and render to an offscreen buffer:
![glTF Bloom](../../docs/images/samples/sample_gltf_bloom.jpg)
### `hello-camera`
Demonstrates how to use `Stream` with Android's Camera2 API:
![Hello Camera](../../docs/images/samples/sample_hello_camera.jpg)
## Prerequisites
Before you start, make sure to read [Filament's README](../../README.md). You need to be able to

12
android/samples/gltf-bloom/.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/caches
/.idea/gradle.xml
.DS_Store
/build
/captures
/app/src/main/assets
.externalNativeBuild

View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,68 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply from: '../../../build/filament-tasks.gradle'
compileMaterials {
group 'Filament'
description 'Compile materials'
inputDir = file("src/main/materials")
outputDir = file("src/main/assets/materials")
}
task copyMesh(type: Copy) {
from file("../../../../third_party/models/lucy/lucy.glb")
into file("src/main/assets/models")
}
generateIbl {
group 'Filament'
description 'Generate IBL'
cmgenArgs = "--format=ktx --size=256 --extract-blur=0.1 --deploy=src/main/assets/envs"
inputFile = file("../../../../third_party/environments/venetian_crossroads_2k.hdr")
outputDir = file("src/main/assets/envs")
}
preBuild.dependsOn compileMaterials
preBuild.dependsOn copyMesh
preBuild.dependsOn generateIbl
clean.doFirst {
delete "src/main/assets"
}
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.gltf"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// We use the .filamat extension for materials compiled with matc
// Telling aapt to not compress them allows to load them efficiently
aaptOptions {
noCompress 'filamat', 'ktx'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Depend on Filament
implementation 'com.google.android.filament:filament-android'
implementation 'com.google.android.filament:gltfio-android'
}

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

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