Compare commits

..

526 Commits

Author SHA1 Message Date
Benjamin Doherty
7bc65421a9 Merge branch 'rc/1.10.5' into release 2021-06-28 12:04:31 -07:00
Benjamin Doherty
736514cf37 Update RELEASE_NOTES for 1.10.5 2021-06-28 12:04:27 -07:00
Mathias Agopian
db0158dae8 fix webgl build
we need to select opengl on webgl.
2021-06-28 08:27:46 -07:00
Benjamin Doherty
e706695ed1 Bump version to 1.10.5 2021-06-21 11:18:26 -07:00
Benjamin Doherty
e8877ffe2d Merge branch 'rc/1.10.4' into release 2021-06-21 11:16:10 -07:00
Benjamin Doherty
300e853646 Update RELEASE_NOTES for 1.10.4 2021-06-21 11:15:44 -07:00
Benjamin Doherty
a403279fa6 Release Filament 1.10.4 2021-06-21 11:14:58 -07:00
Benjamin Doherty
1fd5d9dae6 Update RELEASE_NOTES for 1.10.4 2021-06-21 11:14:35 -07:00
Philip Rideout
8f6f831d5b Add missing #include. 2021-06-21 09:11:04 -07:00
Philip Rideout
599077b54c Use FixedCapacityVector in backend::Program. 2021-06-18 13:31:01 -07:00
Ben Doherty
9b7414b60c Fix, set mBackend to resolved backend in FilamentApp.cpp (#4160) 2021-06-17 18:00:40 -06:00
Philip Rideout
78430858fe gltfio: do not set clear coat in GLTFIO_LITE config.
This avoids an assertion in debug builds. We will document this behavior
much more thoroughly in a subsequent PR.

Fixes #4143.
2021-06-17 14:44:05 -07:00
Mathias Agopian
fe8528a963 Backend::DEFAULT now selects a backend most suited for the platform (#4155)
- OpenGL ES on Android
- Metal on MacOS/iOS
- Vulkan everywhere else (Linux/Windows)

The main change here is that OpenGL is no longer the default on
desktop.

Most of our samples have a `-a` option that can be use to specify the
desired backend.
2021-06-17 14:42:29 -07:00
Mathias Agopian
f365cb965b fix a potential memory corruption when using more than 4 render targets
The array size in the GL structure didn't match the number of supported
render targets.
2021-06-17 14:40:48 -07:00
Romain Guy
2b38cf4c65 Include ProGuard rules in our AARs (#4158) 2021-06-17 14:29:55 -07:00
Philip Rideout
2e9080a179 Fix issues in test_FeedbackLoops and VulkanDriver.
1) Add a missing destroyTexture to the test, which I believe fixed
the Metal assert that I was seeing, as well as some Vulkan validation
warnings.

2) Add a flushAndWait() utility to BackendTest, which is useful for
diagnostics.

3) Fix a layout validation issue in VulkanSwapChain for empty render
passes.
2021-06-17 11:29:39 -07:00
Mathias Agopian
0a50ee989e fix a possible crash when bloom is enabled
This reworks how we compute the bloom buffer size. The main changes are:

- The BloomOptions.resolution is changed to height instead of minor axis.
  This keeps a consistant look of the bloom regardless of the viewport.

- The anamorphism setting now dilates the bloom rather than to compress
  it (in the other direction), which maintains the same amount of bloom.
  However, the resolution decreases meaning that the user might need to
  adjust resolution and/or levels.

- limit the resolution do 2048 which is gles minspec.
2021-06-17 10:17:31 -07:00
Mathias Agopian
c9c9103ede disable skybox/clear optimization
We were disabling the color pass render target clear when a skybox
was present. This optimization doesn't work when the viewport is not
full. Currently there is no way to know that, so we disable this 
optimization for now. Performance loss is not expected to be significant
if present at all.
2021-06-16 16:20:15 -07:00
Mathias Agopian
1ce9e96490 fix automatic clearing of rendertargets
We were automatically clearing the color pass render target when
the view was translucent -- the idea was that when it gets blended at
the end it wouldn't override the content of the render target.

Unfortunately, this doesn't work when the rendertarget is imported,
because in that case, it's not actually blended, we're just rendering
into it directly. The clear would then erase the previous content.

This is fixed by moving the clearing decision in the execute closure and
piggy-backing on the computed discard flag. Discard means clear.
The discard flag will be set for newly created buffers and not for an
imported target that needs to keep its content.
2021-06-16 16:20:15 -07:00
Mathias Agopian
1f9c802e10 Fix imported target discard and clear flags
An imported target shouldn't specify the discardStart flags, those
are calculated from the graph. However, it needs to specify "keep" flags,
to take into account constaints that the graph cannot see (due to the fact
that it's imported into the graph). i.e. the imported target may have
content that needs to be preserved.

An imported target can specify a clear color and clear flags that will
override the flags from the logical Descriptor -- this is a way to
delay the swapchain clear to when we're actually rendering into it
(which usually happens in the very last pass).
2021-06-16 16:20:15 -07:00
Mathias Agopian
c6fda8385a fix opaque blit with imported render targets
When the source of a blit refers to an imported render target,
we can't create a HwRenderTarget from it because the resource
is not a real texture and doesn't have a HwTexture.
However, it can be converted back to the HwRenderTarget it
represents, using the FrameGraph's declareRenderPass API.
It's a slightly strange usage of this API, but not technically
wrong.

This is the main fix for bug #4085
2021-06-16 16:20:15 -07:00
Mathias Agopian
d0664bc119 add post-processing option to gltf-viewer 2021-06-16 16:20:15 -07:00
Philip Rideout
e7ed85ec94 Update WebGL tutorials. 2021-06-16 14:24:47 -07:00
Philip Rideout
5d1d4ff4d6 Update web site with latest WebGL artifacts. 2021-06-16 14:17:12 -07:00
Philip Rideout
57040ebb22 Fix and refactor support for S3TC + SRGB. 2021-06-16 14:08:51 -07:00
Philip Rideout
03b018e7f3 Repair FeedbackLoops test. 2021-06-16 14:07:49 -07:00
Romain Guy
04ada346b0 Materials can now provide custom lighting/shading (#4142)
* Materials can now provide custom lighting/shading

When a material uses the "lit" shading model, customSurfaceShading can
be enabled to replace Filament's lighting implementation. When this
feature is enabled, the material *must* provide the following function
in the fragment shader block:

    vec3 surfaceShading(
            const MaterialInputs materialInputs,
            const ShadingData shadingData,
            const LightData lightData
    ) {
        return vec3(1.0); // custom lighting here
    }

Please refer to the docs in Materials.html for more information about
this feature and the different values provided by the data structures
passed to the function.

* Update docs

* Update docs/Materials.md.html

Co-authored-by: Philip Rideout <philiprideout@gmail.com>

Co-authored-by: Philip Rideout <philiprideout@gmail.com>
2021-06-16 09:53:58 -07:00
Philip Rideout
f53c7723fb Vulkan: fix ReadPixels regression, refactor VMA inclusion. 2021-06-15 18:07:01 -07:00
Ben Doherty
cd48089318 filament-utils-android: fix string literal conversions (#4137) 2021-06-15 16:19:32 -06:00
Ben Doherty
0a6a74c78c filament-utils-android: fix string literal conversions (#4137) 2021-06-15 11:00:31 -06:00
Philip Rideout
b40982d579 Vulkan: repair headless swap chains.
I broke this when migrating to FixedCapacityVector.
2021-06-15 08:23:04 -07:00
Philip Rideout
2605633e1e Upgrade vkmemalloc. 2021-06-14 12:58:14 -07:00
Benjamin Doherty
6379ab22c9 Bump version to 1.10.4 2021-06-14 11:06:42 -06:00
Benjamin Doherty
0bf02b75d5 Merge branch 'rc/1.10.3' into release 2021-06-14 11:04:25 -06:00
Benjamin Doherty
2f7e873137 Update RELEASE_NOTES for 1.10.3 2021-06-14 11:03:54 -06:00
Benjamin Doherty
bb9e23519d Release Filament 1.10.3 2021-06-14 11:03:11 -06:00
Benjamin Doherty
c4259b5598 Update RELEASE_NOTES for 1.10.3 2021-06-14 11:02:45 -06:00
Philip Rideout
acfae2882d Vulkan: Use custom VMA pools to speed up Mali.
This makes the car load in 3 seconds instead of 30 seconds on Mali.

On devices that have bufferImageGranularity set to 1 in the
VkPhysicalDeviceLimits caps structure, we observe that vmaCreateBuffer
can be two orders of magnitude faster than with devices that have a
higher value for their bufferImageGranularity.

According to the Vulkan spec, the bufferImageGranularity aligment
constraint needs to be honored only when linear and non-linear resources
live next to each other in memory.  Since all VkBuffer objects are
linear, we can allocate them all from the same pool and ignore the
alignment constraint.
2021-06-11 14:48:29 -07:00
Philip Rideout
180eb61620 Vulkan: Fix uninitialized vector contents. 2021-06-11 10:40:04 -07:00
Philip Rideout
a92bb87cd8 Vulkan refactoring. 2021-06-11 09:18:18 -07:00
Philip Rideout
2c967b821b Minor Vulkan cleanup. 2021-06-11 08:48:07 -07:00
Philip Rideout
abe9a9731d Vulkan: use FixedCapacityVector in one more spot. 2021-06-11 08:24:54 -07:00
Philip Rideout
2837a48001 Vulkan: Use FixedCapacityVector in lots of places. 2021-06-10 14:41:03 -07:00
Philip Rideout
4aef84342d gltfio: Cache the dummy buffer to optimize load time.
This greatly improves the load time on some Mali devices. On one device,
loading the car model went from 85 seconds to 35 seconds.
2021-06-10 14:40:47 -07:00
Philip Rideout
9be6153875 Refactoring: simplify VulkanDisposer. 2021-06-10 13:49:37 -07:00
Philip Rideout
444640afb7 Refactoring: decouple VulkanBuffer and VulkanDisposer. 2021-06-10 13:49:37 -07:00
Philip Rideout
122908587b Fix build break. 2021-06-10 09:53:54 -07:00
Philip Rideout
c1654537e2 Vulkan: use debug_utils for custom labels.
VK debug markers do not show up in an AGI system trace, but we can sneak
them in by using debug_utils to assign labels to VkFramebuffer.

Note that the debug_utils extension is enabled only when launching your
app from AGI.
2021-06-10 09:32:10 -07:00
Philip Rideout
984a172cec Enable EXT_debug_utils on Android. 2021-06-10 09:32:10 -07:00
Mathias Agopian
ee2767875c Fix FixedCapacityVector::reserve()
We were initializing the new data with the default
Actor by accident.
2021-06-09 17:07:34 -07:00
Philip Rideout
fa0a41e62e sample-gltf-viewer: log the load time (useful for large models)
More precisely, this logs the time that the Filament backend takes
to process all the commands that were issued in the gltfio synchronous
loading phase, which mostly consists of creating and populating vertex
buffers.

This can be quite slow for vertex-heavy (CAD-style) models, and seems to
vary by several orders of magnitude from device to device on Vulkan.
2021-06-09 13:40:16 -07:00
Philip Rideout
edaf718281 Vulkan: fix storeOp for depth attachment.
This gets rid of the "GMEM Store Depth / Stencil" bars seen with AGI.
2021-06-08 14:34:31 -07:00
Philip Rideout
7cd5963d3a Adjust VK_MAX_COMMAND_BUFFERS to prevent a 5 ms stall.
This constant was previously set to 3 because of triple buffering, which
does not account for the fact that Filament may issue multiple commit()
calls during a single frame.

This new number was determined via experimentation.

On a Pixel 4, this reduces a 4.5 ms gap in "GPU Queue 0" to 420 us.
2021-06-08 14:34:23 -07:00
Philip Rideout
60f5512c5f JS bindings: remove bogus stride argument.
Fixes #4106.
2021-06-08 14:23:41 -07:00
Ben Doherty
6b3c1179bc Include sample-gltf-viewer with Android releases (#4099) 2021-06-08 10:41:48 -07:00
Ben Doherty
d1b9a1b996 Include sample-gltf-viewer with Android releases (#4099) 2021-06-08 10:32:49 -07:00
Mathias Agopian
1bd91e7e94 JobSystem: simplify callback code
we can use the lambda syntax instead of a static method.
2021-06-08 09:47:16 -07:00
Mathias Agopian
5e2f73c74e JobSystem: reduce parallel_for overhead
We reuse the current job for the right side instead of spawning a new
job, which has overhead. This also cuts in half the number of times we
need to copy the user functor.
2021-06-08 09:47:16 -07:00
Mathias Agopian
4a269e37c5 Don't use very small jobs when using parallel_for
The overhead of the jobsystem / job is about 50-100us, so we should
try to use jobs about an order of magnitude bigger -- which is actually
quite rare.

In particular the culling is so efficient that we'd need to process
10000 or more primitives for the jobsystem to be of any help, so for
now we never use the jobsystem for culling.
2021-06-08 09:47:16 -07:00
Mathias Agopian
3eceaf20a2 JobSystem: set thread pool count to ncores - 2
We need to reserve at least a code for the user and another one for the
backend thread.
2021-06-08 09:47:16 -07:00
Mathias Agopian
bbc4f4f21d JobSystem: remove the DONT_SIGNAL flag
A side effect of this flag was that we had to always use notify_all
when starting a job, instead of notify_one -- in practice, we found
experimentally that more calls to notify_one is cheaper than fewer
calls to notify_all.
2021-06-08 09:47:16 -07:00
Mathias Agopian
c5ef1d6252 JobSystem: signal condition with lock held
This seems to improve parallelism on multicores and at least on
Android, doesn't seem to impact performance.
2021-06-08 09:47:16 -07:00
Philip Rideout
a4280881d5 Fix BindingType in TypeScript definitions.
Fixes #4102.
2021-06-08 09:14:22 -07:00
Philip Rideout
8ef4c54712 Upgrade emsdk to 2.0.23 2021-06-08 08:36:32 -07:00
Philip Rideout
5ebc8c3e1a Ensure FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB is available.
If your build system does not provide a definition for this macro, then
you cannot compile CommandBufferQueue.cpp.

Since Allocators.h provides a backup value, it needs to be included.
2021-06-08 08:09:51 -07:00
Philip Rideout
c1a0e61e8e Fix FixedCapacityVector destructor.
std::allocator::deallocate() expects the same value that was given
during allocate().

Interestingly, this bug did not manifest any issues (even with ASAN) on
some platforms.
2021-06-07 15:56:33 -07:00
Philip Rideout
cbcb3e95c6 Fix FixedCapacityVector destructor.
std::allocator::deallocate() expects the same value that was given
during allocate().

Interestingly, this bug did not manifest any issues (even with ASAN) on
some platforms.
2021-06-07 15:56:02 -07:00
Benjamin Doherty
fc06298ed4 Bump version to 1.10.3 2021-06-07 11:22:04 -07:00
Benjamin Doherty
4ca87b188c Merge branch 'rc/1.10.2' into release 2021-06-07 11:19:51 -07:00
Benjamin Doherty
f1f60c3e0d Turn off warnings as errors for spirv-tools 2021-06-07 11:18:56 -07:00
Benjamin Doherty
76d21b56af Update RELEASE_NOTES for 1.10.2 2021-06-07 11:18:09 -07:00
Benjamin Doherty
02a8cffb18 Update RELEASE_NOTES for 1.10.2 2021-06-07 11:15:22 -07:00
Benjamin Doherty
d53f7ecd6a Release Filament 1.10.2 2021-06-07 11:14:43 -07:00
Philip Rideout
e297f65d8c getLight() should initialize all fields.
Fixes #4014.
2021-06-03 18:29:05 -07:00
Mathias Agopian
5356f65040 use "debug" namespace for system properties
"filament.perfcounters" is renamed to "debug.filament.perfcounters", 
because otherwise it can't be set by users on recent Android 
versions.
2021-06-03 17:13:52 -07:00
Mathias Agopian
5056abc357 Systrace now uses the official ATrace API
Use the official systrace API when available.
2021-06-02 18:28:39 -07:00
Philip Rideout
46029acd14 VulkanPipelineCache: fix padding with MSVC. 2021-06-02 17:51:54 -07:00
Philip Rideout
28e414c9a5 VulkanPipelineCache: stop using Vk structs for state tracking. 2021-06-02 17:51:54 -07:00
Philip Rideout
29c036d826 VulkanPipelineCache: do not hash uninitialized data.
This fixes an issue caught by a memory sanitizer, whereby padding in the
cache key structure was being consumed by a hashing function. In
practice this oversight was fairly harmless, but this change makes the
code more safe and predictable.
2021-06-02 17:51:54 -07:00
Philip Rideout
831a6d9480 gltfio: fix crash with non-triangles.
Fixes the "triangle count is zero" assertion with the big car model.

We do have nominal support for points and lines, but we should not
attempt to compute tangents for these.

As a reminder, glTF also supports loops, strips, and fans; this is the
only way in which Filament is non-conformant.
2021-06-02 16:47:14 -07:00
Mathias Agopian
fb2a95470a bring some improvements to logging from a reverted change
- cleanup Log header file
- lazy initialization of the log buffer
- aggressively resize down the log buffer
2021-06-02 16:40:58 -07:00
Mathias Agopian
4d73583f86 Better systrace logging and small improvements to JobSystem
Tweak how we signal/wakeup threads so we get better parallelism 
on Android.
2021-06-02 16:40:40 -07:00
Mathias Agopian
9a24c4001f Flush the CommandStream in a few strategic places
The CommandStream hold backend commands, but it has a limited size.
With some large models, we can run out of space especially during
initialization.

We can combat this by flushing the command stream regularly. With this
change, we do this every 128 renderable creation.

We also flush the CommandStream just before generating the draw
commands for the frame.

If the buffer is not sized correctly (currently at compile time), this
could cause stalls, which will be logged in DEBUG builds.
2021-06-02 12:16:45 -07:00
Mathias Agopian
4c9ae9dd91 use c++ thread_local now that it's supported on Android
there are cases where thread_local still doesn't work well, but
we're not using those cases.
2021-06-02 12:12:09 -07:00
Mathias Agopian
384d6921f6 add system property to override the backend selection
On Android, set `debug.filament.backend` to the desired backend:
0: default
1: gl/gles
2: vulkan
3: metal
4: noop

example:
   `adb shell setprop debug.filament.backend 2`

This will affect all filament apps on the device.

This sets the backed as if it was set from the public API.
2021-06-02 12:11:51 -07:00
Benjamin Doherty
0ab0e50a4f Turn off warnings as errors for spirv-tools 2021-06-02 11:16:42 -07:00
Benjamin Doherty
e0a8284fcf Update filament-specific-changes.patch 2021-06-02 10:58:44 -07:00
Benjamin Doherty
eafbf699a2 Turn off warnings as errors for spirv-tools 2021-06-02 10:58:44 -07:00
James Walker
4d3f10477a fix macOS main thread checker warnings with OpenGL (#4011)
* fix runtime warnings about certain NSView methods being called off the main thread

* address code style issues

* fix code style and threading concerns

* Remove unneeded __strong qualifiers, put __weak after the star as recommended by Apple, convert weak to strong before testing for nil to avoid a race

* convert tabs to spaces
2021-06-01 16:35:23 -07:00
Mathias Agopian
9a83805f19 build.sh -C option entirely cleans the android/ directory
All (and only) git-ignored files under android/ are deleted.

This is to prevent a recurring problem where "clean" builds were not
actually clean in some cases.
2021-06-01 14:10:08 -07:00
Mathias Agopian
6fcc2b579d fix LightManager::getFalloff
fixes #4043
2021-06-01 14:09:08 -07:00
Mathias Agopian
e04a3d7d3a AttachmentPoint in java and c++ mismatch
fixes #4055
2021-06-01 14:08:51 -07:00
Benjamin Doherty
34f4c06a5c Bump version to 1.10.2 2021-06-01 11:17:32 -07:00
Benjamin Doherty
6de36f1e53 Merge branch 'rc/1.10.1' into release 2021-06-01 11:15:49 -07:00
Benjamin Doherty
be61ea2dc8 Update RELEASE_NOTES for 1.10.1 2021-06-01 11:14:29 -07:00
Benjamin Doherty
c594d6a07e Release Filament 1.10.1 2021-06-01 11:13:41 -07:00
Benjamin Doherty
2a9a3b1ac2 Update RELEASE_NOTES for 1.10.1 2021-06-01 11:13:04 -07:00
Mathias Agopian
ee7feff9cc Revert "improve logs and tls support"
This reverts commit cc6201b0db.

On Android the loggers are not always initialized when several .so are
used, leading to crashes. It's not completely clear what is exactly 
happening.
2021-06-01 10:21:10 -07:00
Philip Rideout
02ce911405 Vk: Fix some synchronization validation warnings.
This fixes most of the warnings that are emitted by the relatively new
SYNCHRONIZATION_VALIDATION feature that LunarG provides.

This commit does not fix a warning that is emitted when SSAO is enabled,
when we sample from the currently bound depth attachment. This one is
tricky to fix.
2021-06-01 08:01:55 -07:00
Mathias Agopian
f12ee8f54c unit test for FixedCapacityVector 2021-05-28 09:16:18 -07:00
Mathias Agopian
81a98c6769 panic in release builds when command stream is corrupted
the CommandStream is limited in size and can get corrupted if
that size (default 1 MiB) is exceeded. We used to catch this
only on Debug builds, but this is too serious and unrecoverable, so
it must be caught in Release builds too.

At the point of detection the stream is corrupted, which can cause
the backend to get in an unknown state. But worse, program execution
could end up anywhere because the stream contains function pointers.
2021-05-28 09:16:02 -07:00
Mathias Agopian
e3f626934f fix sstream::c_str() when the buffer is first created (#4050) 2021-05-27 22:04:42 -07:00
Romain Guy
94ff2ea6b1 Add support for KHR_materials_specular to glTF (#4046)
* Add support for KHR_materials_specular to glTF

* Add support for IOR to ubershaders

* Update release notes

* Remove unused variable, fix comment
2021-05-27 17:33:24 -07:00
Mathias Agopian
cc6201b0db improve logs and tls support
- libutil's slog, cout, cerr, cwarn and cinfo were not thread safe
  at all.

- they are now thread_local

- for that reason the log buffer (which now exists per thread) is not
  allocated until it's needed and is aggressively shrunk.

- removed our thread_local emulation which was incomplete.

- don't expose LogStream publicly.
2021-05-27 15:54:19 -07:00
Mathias Agopian
d079df9ce5 make use of FixedCapacityVector in various places 2021-05-27 15:53:53 -07:00
Mathias Agopian
6a2c944bbd A fixed capacity vector.
This is (almost) drop-in replacement for std::vector, the main
difference is that FixedCapacityVector has a fixed (at runtime)
capacity, which makes it a lot more efficient and small for operations
like push_back();

The capacity can be set (and re-set) as usual with reserve(),
but exceeding the capacity when adding items will throw.
The capacity is also set when creating the vector with a size.

In addition a FixedCapacityVector<> instance is only 16 bytes instead
of 24 for std::vector<>.

The aim here is to reduce code bloat.
2021-05-27 15:53:53 -07:00
Mathias Agopian
266fea5e6c replace all size_t with uint32_t in the backend API
this helps save a lot of space in the CommandStream, it especially
matters with scenes with a lot of draw calls.
2021-05-27 15:53:31 -07:00
Mathias Agopian
6da3f85362 RenderPass.cpp got mistakenly renamed, fix that. 2021-05-27 15:53:09 -07:00
Philip Rideout
1d58892fed Vk: repair validation on Android. 2021-05-27 15:18:28 -07:00
Philip Rideout
ff1b6d28a8 Vk: fix handling of instance extensions. 2021-05-27 11:27:01 -07:00
Ben Doherty
ff935e05f2 image: Respect sRGB option for compressed formats (#4039) 2021-05-26 20:37:58 -07:00
Mathias Agopian
d378f5e4bb repair CommandStream logging 2021-05-26 20:33:47 -07:00
Philip Rideout
44eee6550c Vk: emit best practices warnings when validation is enabled. 2021-05-26 15:48:33 -07:00
Philip Rideout
260b8fb672 VulkanCommands: add diagnostics. 2021-05-26 15:48:33 -07:00
Mathias Agopian
2f240acc43 increase max job count to 16384 from 4096
the cost is only 2 bytes per job.
2021-05-26 12:18:05 -07:00
Mathias Agopian
189b528b3d improve handle creation in opengl backend
- we issue better logs when the allocation fails
- the pool selection is now performed at compile time
2021-05-26 12:17:50 -07:00
Philip Rideout
2b265d54a1 VulkanSwapChain: simplify and repair swap chain resizing.
Newer versions of MoltenVK seem to behave similarly to Android,
so there's no need to separate codepaths. I tested this by not only
resizing the window, but also dragging between displays with different
pixel ratios, and rotating on Android with & without `orientation` in
`configChanges`. I also tried our headless unit tests.
2021-05-26 10:34:39 -07:00
Philip Rideout
c61d67301f sample-gltf-viewer: fix lifetime cycle for RemoteServer.
The sample would crash when removing `orientation` from `configChanges`
and rotating the device, because the old RemoteServer would still be
alive when creating the second one, so the WebSocket port would be
unavailable.
2021-05-26 09:22:08 -07:00
Philip Rideout
5f3d8096f3 Vulkan: big refactor of VulkanSwapChain.
This has no behavioral changes, it's mostly just moving code around,
except that VulkanDriver::createSwapChain() is simpler now, and some
of the logic in beginRenderPass() makes more sense too.

This removes the useless `VulkanSurfaceContext` structure by moving
its data directly into `VulkanSwapChain`. Also created a new cpp file
just for the swap chain wrapper, which makes `VulkanContext` much less
unwieldy.
2021-05-25 20:04:08 -07:00
Alexey Pelykh
6e5b05d0b5 KTXLoader.getSphericalHarmonics
Co-authored-by: Fabian Rueckert <fabi.rueckert@gmail.com>
2021-05-25 20:02:19 -07:00
Benjamin Doherty
6bbae681ef Fix HelloCocoaPods iOS sample 2021-05-25 17:19:52 -07:00
Philip Rideout
097fac4cca Add support for drag-and-drop HDR.
This adds Java bindings for IBLPrefilterContext and uses them
in `sample-gltf-viewer`.
2021-05-25 12:46:52 -07:00
Philip Rideout
97515b0d7d Vulkan: minimize calls to vkCmdSetScissor. 2021-05-25 12:28:52 -07:00
Philip Rideout
3500101816 Repair live WebGL demos.
Fixes #4027.
2021-05-25 12:22:05 -07:00
Romain Guy
1cebf51672 Update README.md 2021-05-24 16:08:42 -07:00
Mathias Agopian
3b59dff577 fix some build warnings 2021-05-24 13:25:11 -07:00
Mathias Agopian
cd01ad06fd update SPIRV-CROSS to latest
SHA: ff61890722a91e97c44940494be5b6eed0d5ff5b
2021-05-24 13:24:54 -07:00
Benjamin Doherty
84b73a3770 Bump version to 1.10.1 2021-05-24 10:52:02 -07:00
Benjamin Doherty
662a10e273 Merge branch 'rc/1.10.0' into release 2021-05-24 10:49:10 -07:00
Benjamin Doherty
331332fab0 Update RELEASE_NOTES for 1.10.0 2021-05-24 10:48:45 -07:00
Benjamin Doherty
f3572876a1 Release Filament 1.10.0 2021-05-24 10:48:03 -07:00
Benjamin Doherty
ecce02502e Update RELEASE_NOTES for 1.10.0 2021-05-24 10:47:39 -07:00
Ben Doherty
c827004821 Add getPlatform API to Engine, move functionality into MetalPlatform (#4007)
This change allows access to the Engine's underlying Platform object. This is useful for Metal clients to access a new method on MetalPlatform, createAndEnqueueCommandBuffer.
2021-05-24 10:36:56 -07:00
Mathias Agopian
786eee4eb9 Fix a crash when using custom rendertargets
This was introduced recently.

Fix #3962
2021-05-24 09:53:54 -07:00
Mathias Agopian
92d2de5279 fix MRTs >= COLOR4 in the GL backend
These would be ignored.
2021-05-24 09:53:05 -07:00
Ben Doherty
f4070f3fb5 Fix Automation test_settings (#4009) 2021-05-24 09:10:25 -07:00
Alexey Pelykh
856a6567a1 LightManager: cone angles API (#3979) 2021-05-22 22:04:50 -07:00
Mathias Agopian
363edb1427 added MaterialInstance::duplicate(...)
It's now possible to duplicate a MaterialInstance.
2021-05-21 22:57:28 -07:00
Mathias Agopian
c209232950 a way to keep the content of custom RenderTarget attachments (#4008)
* a way to keep the content of custom RenderTarget attachments

Until now, all attachments of RenderTarget beyond COLOR0 were discarded
after rendering.

With this change, attachment whose texture has the SAMPLEABLE usage
bit set will be kept.

Fixes #3962
2021-05-21 22:54:52 -07:00
Ben Doherty
3f9120b129 Fix focusDistance warning in gltf_viewer (#4005) 2021-05-21 15:31:46 -07:00
Philip Rideout
d17875aea1 ImGuiHelper: fix support for custom images.
The texture binding in the material instance needs to be restored to the
glyph atlas when a custom image is not in use.
2021-05-21 12:49:37 -07:00
Philip Rideout
b1f0f905e5 HDRLoader: use HDRDecoder, not stb. 2021-05-21 12:36:43 -07:00
Philip Rideout
c71c7c70d4 imageio: split HDRDecoder into its own file 2021-05-21 12:36:43 -07:00
Philip Rideout
613ae56cc1 Add HDRLoader for JVM clients.
This adds support for decoding HDR files, dropping them into the remote
web page, and sending them over the wire.  However the decoded results
are not yet passed into IBLPrefilterContext, that will be subsequent
PR.

Rename KtxLoader to KTXLoader.

The remote UI has been tweaked a bit, so that it shows a more helpful
message when disconnected.
2021-05-21 12:36:43 -07:00
Philip Rideout
6607002939 ImGuiHelper: fix support for custom images.
The texture binding in the material instance needs to be restored to the
glyph atlas when a custom image is not in use.
2021-05-21 11:49:14 -07:00
Philip Rideout
2e40bb46e7 Fix minor typos. 2021-05-21 11:34:08 -07:00
Philip Rideout
b8897a68f9 matc: detect missing end brace.
matc was failing to report certain kinds of syntax errors and would
read out-of-bounds memory.

This change casuses the flare material to fail.
2021-05-21 09:20:33 -07:00
Philip Rideout
720288c420 JNI Cleanup: Remove useless constructors, publicize RenderTarget.
(1)
The C++ RenderTarget API might be used by an external Android library
such as filament-utils-android and therefore needs to be in the map
file.

(2)
Texture, Skybox, and IndirectLight each had two "nativeObject"
constructors which exist for the benefit of filament-utils-android,
but each of these classes only need one nativeObject constructor.
2021-05-20 15:18:34 -07:00
Romain Guy
97651a0ff4 Use CIE 2006 10-deg CMFs instead of CIE 1931 2021-05-19 12:42:41 -07:00
Ben Doherty
84efd4871e API CHANGE: remove some Camera, Engine, and View deprecated APIs (#3965) 2021-05-19 12:02:13 -07:00
Philip Rideout
3125c44ce1 Vulkan: change depth layout to permit feedback loops.
Vulkan does not permit the GENERAL layout when the depth buffer that is
currently being used for depth testing is also sampled from.

This (finally) fixes the last validation error that we were silencing,
which would occur only when SSAO was enabled.
2021-05-18 16:38:42 -07:00
Philip Rideout
d909b38d57 Vulkan: enable the maintenance extensions if available.
This prevents potentially bogus validation messages from arising.
2021-05-18 16:36:12 -07:00
Ben Doherty
5572ef8574 API CHANGE: remove some Camera, Engine, and View deprecated APIs (#3965) 2021-05-18 16:02:49 -07:00
Philip Rideout
3c4192bd0e matc: detect missing end brace.
matc was failing to report certain kinds of syntax errors and would
read out-of-bounds memory.

This change casuses the flare material to fail.
2021-05-18 10:58:15 -07:00
Philip Rideout
3fc9dc3684 Repair build when FILAMENT_VULKAN_VERBOSE is enabled. 2021-05-17 18:13:51 -07:00
Benjamin Doherty
85ea5a6b70 Bump version to 1.10.0 2021-05-17 11:00:42 -07:00
Benjamin Doherty
77891acb92 Merge branch 'rc/1.9.25' into release 2021-05-17 10:57:30 -07:00
Benjamin Doherty
a06e01a196 Update RELEASE_NOTES for 1.9.25 2021-05-17 10:57:02 -07:00
Benjamin Doherty
034b6892f4 Release Filament 1.9.25 2021-05-17 10:55:58 -07:00
Benjamin Doherty
74fe102035 Update RELEASE_NOTES for 1.9.25 2021-05-17 10:54:38 -07:00
Philip Rideout
25cc554925 WASM: fix "Missing field" error for lensFlare. 2021-05-17 10:06:56 -07:00
Ben Doherty
bd8ea711fd Add a FILAMENT_SUPPORTS_OPENGL CMake option (#3966) 2021-05-15 14:40:06 -07:00
Mathias Agopian
c1347e55cb add java API for Texture::Builder::import()
deprecate Stream::stream(intptr_t).

This method was needed for ARCore back in the days, but there is now a
zero-copy way to achieve the same thing. This API shouldn't be used anymore.
2021-05-14 17:26:30 -07:00
Philip Rideout
afbd6e6606 gltfio: fix morphing bugs uncovered by MorphStressTest.
The code that determined the "base slot" (i.e. the buffer object index
for the first morphed attribute) was very fragile and buggy.
MorphHelper now simply looks up the slot index in a stored mapping,
rather than trying to mimic the AssetLoader to determine the base slot.

Until now, most of the models we tested against only morphed the
position attribute, and never had a large set of target weights that
could be non-zero in a given time slice.
2021-05-14 17:05:27 -07:00
Mathias Agopian
d6c5cb7778 workaround a shader compiler bug on qualcomm h/w 2021-05-14 16:58:40 -07:00
Mathias Agopian
43d47745dd API CHANGE: remove deprecated populateTangentQuaternions 2021-05-14 13:35:25 -07:00
Mathias Agopian
f0d99070e4 Use a UBO instead of a texture for froxels data structure
MATERIAL BREAKAGE: this change breaks materials

In order to use one less sampler, we now use a UBO instead of a texture
to store the "froxel records". Currently this UBO is limited to 16KiB
vs. 64KiB before with the texture.

We also handle running out of record space better, by using a predefined
record that has all the lights in the scene. This way the scene will be
rendered properly, albeit at a potentially large performance cost.
2021-05-14 11:20:24 -07:00
Alexey Pelykh
6a49d67c6c Allow using specific NDK version, for CI don't use latest but required (#3950)
* Allow using specific NDK version, for CI don't use latest but required

* Default to highest available NDK version within same major release sequence

* Refactor NDK version selection
2021-05-14 11:06:31 -07:00
Philip Rideout
6b7c1b21cb VulkanPipelineCache: fix unbound pipeline error. 2021-05-13 23:33:06 -07:00
Philip Rideout
b7d1b4ca1a VulkanPipelineCache: create dummy sampler. 2021-05-13 23:13:49 -07:00
Philip Rideout
8a04d5761b Fix validation on Windows. 2021-05-13 18:25:47 -07:00
Benjamin Doherty
8d8729be8e Remote UI: update viewer with new URL input 2021-05-13 16:46:26 -07:00
Ben Doherty
d4325de47d Add URL input to Filament Remote Viewer (#3955) 2021-05-13 16:27:46 -07:00
Philip Rideout
e29c76465b Minor improvement to Vulkan robustness. 2021-05-13 13:16:57 -07:00
Philip Rideout
a220407aef Vulkan: Fix bistro, implement descriptor pool growth. 2021-05-13 12:28:12 -07:00
Philip Rideout
4df214003e Revert accidental Vulkan diagnostic commit.
This reverts commit 59a6758fce.
2021-05-13 08:56:48 -07:00
Philip Rideout
182250b9c0 VulkanPipelineCache: minor cleanup. 2021-05-13 08:34:02 -07:00
Philip Rideout
59a6758fce DO NOT COMMIT 2021-05-13 08:33:57 -07:00
Philip Rideout
73aa996444 VulkanPipelineCache: add a descriptor set arena.
This fixes the "descriptor set fragmentation" error that we would see on
Mali.

The pipeline cache now maintains an arena of descriptors that can be
re-used. We call this an "arena" to avoid confusion with
VkDescriptorPool.

Descriptors are returned to the arena only when they are not in use
by any pending command buffer. This allows them to be mutated safely
without worrying about synchronization.
2021-05-12 16:48:59 -07:00
Ben Doherty
d787a521b5 Fix DIST_DIR setting for Windows builds (#3945) 2021-05-12 11:16:30 -07:00
Ben Doherty
46e52c71e1 Fix DIST_DIR setting for Windows builds (#3945) 2021-05-12 11:15:49 -07:00
Ben Doherty
08769ec35e Fix DIST_DIR setting for Windows builds (#3945) 2021-05-12 11:15:10 -07:00
Philip Rideout
3aa18eafb3 VulkanPipelineCache: refactor and simplify.
The API of the pipeline cache is now easier to use. Internally, it now
maintains separate pipeline and descriptor bindings for each command
buffer, since that's how Vulkan works.
2021-05-11 12:46:48 -07:00
Philip Rideout
8d4a0e5aa9 Vulkan: fix uninitialized cmd buffer handle. 2021-05-11 11:03:17 -07:00
Ben Doherty
e8183d09c2 Fix MissingRequiredAttributes backend test with Metal (#3943) 2021-05-11 10:49:47 -07:00
Philip Rideout
5f1da1dfc0 VulkanDriver: Misc cleanup.
This cleanup is being done in preperation for a new descriptor set
strategy.
2021-05-10 18:26:12 -07:00
Philip Rideout
1dad27a172 Repair WebGL and fix potential INVALID_OPERATION.
We should take care not to call glVertexAttribPointer when there is
no bound ARRAY_BUFFER (i.e. when its binding is zero).

This fixes the black screen seen with some WebGL samples after
the recent memory leak fix related to the new BufferObject API.
2021-05-10 13:38:56 -07:00
Philip Rideout
c1c5776439 Serialization: enforce correctness for bool.
If expecting a bool and receiving anything other than true or false,
this is invalid and should fail. This change triggered a unit test
failure which uncovered several actual problems.
2021-05-10 13:27:41 -07:00
Mathias Agopian
da418fc7f2 fix another serialization bug 2021-05-10 12:15:52 -07:00
Philip Rideout
fcaae825b7 Repair WebGL and fix potential INVALID_OPERATION.
We should take care not to call glVertexAttribPointer when there is
no bound ARRAY_BUFFER (i.e. when its binding is zero).

This fixes the black screen seen with some WebGL samples after
the recent memory leak fix related to the new BufferObject API.
2021-05-10 12:13:00 -07:00
Philip Rideout
f5ee074674 Remote UI: fix lensFlare serialization. 2021-05-10 12:11:25 -07:00
Mathias Agopian
0c787b94b8 update remote ui 2021-05-10 11:22:55 -07:00
Philip Rideout
02f5f07db0 WASM: fix "Missing field" error for lensFlare. 2021-05-10 09:28:48 -07:00
Philip Rideout
a97591a193 Fix minor logic warning. 2021-05-10 08:36:34 -07:00
Benjamin Doherty
60d230b380 Bump version to 1.9.25 2021-05-07 21:42:48 -07:00
Benjamin Doherty
d7cb38e706 Merge branch 'rc/1.9.24' into release 2021-05-07 21:39:17 -07:00
Benjamin Doherty
80485bf520 Update RELEASE_NOTES for 1.9.24 2021-05-07 21:38:43 -07:00
Benjamin Doherty
ce00cca6ee Update RELEASE_NOTES for 1.9.24 2021-05-07 21:36:49 -07:00
Benjamin Doherty
401bd8ce73 Bump version to 1.9.24 2021-05-07 21:35:30 -07:00
Mathias Agopian
c23a7343d4 update remote ui 2021-05-07 16:57:05 -07:00
Romain Guy
75a24ee41f Update RELEASE_NOTES.md 2021-05-07 16:51:17 -07:00
Mathias Agopian
7e9a69df64 fix lens flare Settings writer 2021-05-07 16:18:52 -07:00
Mathias Agopian
12bf8d9659 DoF: don't use hole filling for the background
It did improve the look of the blur on far way geometry in some case,
but overall it hurts a lot more.
The case that falls appart is when everything is in the background layer
but there is a large depth difference anyways.
This creates a halo around edges.

Fixes #3221
2021-05-07 16:18:34 -07:00
Mathias Agopian
d1c8d42bd2 update remote ui 2021-05-07 15:19:15 -07:00
Mathias Agopian
c0fe2d1c09 new screen space lens flare effect
- this PR also improves bloom slightly


Note: for now this is not available on WebGL due to complications
in the bloom pass.
2021-05-07 13:20:16 -07:00
Philip Rideout
812f0d577b VulkanTexture: support format conversion via vkCmdBlitImage. 2021-05-07 12:46:37 -07:00
Philip Rideout
4a25ba1111 Minor VulkanTexture simplification. 2021-05-07 12:46:37 -07:00
Philip Rideout
0b4f3f76fc Vulkan: enable the mutableComparisonSamplers feature. 2021-05-07 11:09:17 -07:00
Philip Rideout
e7e19a88e6 Add missing files to BlueVK. 2021-05-07 09:22:23 -07:00
Philip Rideout
4295eaa311 Vulkan refactor 2 of 2 (Binder => PipelineCache) 2021-05-06 18:47:19 -07:00
Philip Rideout
43e78f7a93 Vulkan refactor 1 of 2 (VulkanTexture and VulkanConstants) 2021-05-06 18:47:19 -07:00
Philip Rideout
d627d57bad Second memory leak fix. (#3906)
Fixes #3888.
2021-05-06 14:25:46 -07:00
Philip Rideout
0a305a710a VulkanCommands now stalls when absolutely necessary. 2021-05-06 14:24:42 -07:00
Ben Doherty
ef45d695d0 metal: Query max color render targets (#3895) 2021-05-06 11:33:49 -07:00
Philip Rideout
ac50cb69f7 Vulkan: fix blit and readPixels for cubemaps. (#3903) 2021-05-06 11:16:28 -07:00
Philip Rideout
9fc6e398c6 BackendTest: add blit cubemap test. (#3901)
* BackendTest: add blit cubemap test.

This test is similar to manual mipmap generation for cubemaps and
can uncover issues that are provked by libiblprefilter. It simply
dumps out a PNG that can be manually inspected.

Also, this test does not do makeCurrent / commit and is therefore
similar to renderStandaloneView.

* Update filament/backend/test/test_Blit.cpp

Co-authored-by: Ben Doherty <bendoherty@google.com>

Co-authored-by: Ben Doherty <bendoherty@google.com>
2021-05-06 10:38:55 -07:00
Ben Doherty
e06b948343 Use 16 bit format for VSM (#3899) 2021-05-06 10:33:11 -07:00
Philip Rideout
28ca9df5a0 Second memory leak fix. (#3906)
Fixes #3888.
2021-05-06 10:15:20 -07:00
Romain Guy
c66915209e Update our build to the latest and greatest (#3902)
The new requirements are as follow:
- CMake 3.19
- Ninja 1.10
- Android Studio 4.2
- Android NDK 22.1
- Gradle 7.0
- Kotlin 1.5
2021-05-06 10:13:10 -07:00
Philip Rideout
cb4ffe39f4 Fix build break. 2021-05-05 15:00:59 -07:00
Philip Rideout
e07f91ce8b Vulkan: use more aggressive barriers (Mali). 2021-05-05 14:22:29 -07:00
Philip Rideout
03fcbfea62 Regenerate BlueVK and update MoltenVK binaries. (#3897)
LunarG just released a new SDK so we're updating everything.
2021-05-05 14:15:52 -07:00
Philip Rideout
f9d05a879a Vulkan: add a barrier after each render pass. (#3898)
The need for this barrier is fairly obvious, so it is surprising that
its absence has not caused problems on any platform except Mali.
2021-05-05 14:11:36 -07:00
Philip Rideout
8ffc776f1c Fix horrible memory leak in the GL driver. (#3894)
This leak was introduced in the following PR on April 7.
https://github.com/google/filament/pull/3775

The guilty party has been contacted and properly admonished for his
transgression.

This was tested by adding the following code after applyAnimation in
gltf_viewer.cpp

        static int nframes = 0;
        if (!gpath.empty() && nframes++ > 100) {
            static int count = 0;
            printf("reloading %d\n", count++);
            nframes = 0;
            app.resourceLoader->asyncCancelLoad();
            app.resourceLoader->evictResourceData();
            app.viewer->removeAsset();
            app.assetLoader->destroyAsset(app.asset);
            loadAsset(gpath, app);
            loadResources(gpath, app);
        }
2021-05-04 18:22:08 -07:00
Philip Rideout
7a8dd52c4c Fix horrible memory leak in the GL driver. (#3894)
This leak was introduced in the following PR on April 7.
https://github.com/google/filament/pull/3775

The guilty party has been contacted and properly admonished for his
transgression.

This was tested by adding the following code after applyAnimation in
gltf_viewer.cpp

        static int nframes = 0;
        if (!gpath.empty() && nframes++ > 100) {
            static int count = 0;
            printf("reloading %d\n", count++);
            nframes = 0;
            app.resourceLoader->asyncCancelLoad();
            app.resourceLoader->evictResourceData();
            app.viewer->removeAsset();
            app.assetLoader->destroyAsset(app.asset);
            loadAsset(gpath, app);
            loadResources(gpath, app);
        }
2021-05-04 17:50:46 -07:00
Mathias Agopian
ef48cad322 cleanup bloom
- remove areFeedbackLoopsSupported from backend API, since this is only
  a problem on WebGL

- binary only include either the regular or webgl version of the bloom
  code, never both, which should save some binary size

- bloom pass is now called outside of the colorGrading pass, which is
  cleaner and makes it available for other pass, should they need it
  (not the case right now).

- always pass ColorGradingConfig to all color grading related methods,
  instead of individual parameters

- very minor optimization in bloom shader
2021-05-04 17:25:45 -07:00
Ben Doherty
c39d692757 ios: Don't evict gltfio materials between asset loads (#3893) 2021-05-04 16:33:10 -07:00
Ben Doherty
4c1d8f310a Fix Filament remote file upload (#3891) 2021-05-04 14:52:42 -07:00
Mathias Agopian
1e1542fe16 ipbprefilter: simplify cpu side
- move kernel weight computation to the gpu side as a small cost, in
order to simplify the CPU side and reduce the binary size.

- skip samples with a weight of 0, which is a completely coherent 
check.

- fix a typo in move ctor
2021-05-04 13:12:39 -07:00
Mathias Agopian
647ac34c8c improve Texture::generateMipmap fallback
We now handle SAMPLER_2D_ARRAY, but SAMPLER_3D is still unsupported.
2021-05-04 10:53:27 -07:00
Mathias Agopian
ea34691625 Support a maximum of 8 render buffers (from 4)
We chose 8 renderbuffer because it seems to be commonly supported
on mobile gpu and is more than 6 which is needed for generating
cubemaps. 4 was the minimum guaranteed by ES3.0.

The main changes here are:
- TargetBufferFlags is now a uint32_t instead of uint8_t
- The number of render buffer supported by filament and supported by
  the hardware can now be different. Applications/users now must
  query this value if more than 4 is needed.
- added a backend query (used gl terminology)


This is a redo of a previous attempt. There was an issue in the GL
backend that caused MRT to fail on some devices.
2021-05-04 10:53:07 -07:00
Philip Rideout
4557255ce1 Vulkan: fix initial image layout for cubemaps. (#3885) 2021-05-04 09:45:15 -07:00
Philip Rideout
4cb951461b Vulkan: enable anisotropic filtering if supported. (#3884) 2021-05-04 09:43:52 -07:00
Philip Rideout
750dcbb9d8 Vulkan: fix image view type for render target attachments. (#3883)
When rendering into a single cubemap face, we should use
VK_IMAGE_VIEW_TYPE_2D rather than VK_IMAGE_VIEW_TYPE_CUBE.
2021-05-04 09:41:54 -07:00
Romain Guy
459f70f7b4 Update docs 2021-05-03 17:55:32 -07:00
Mathias Agopian
61748fa7dc improve opengl backend program failure logs 2021-05-03 15:10:14 -07:00
Benjamin Doherty
be032b52c1 Bump version to 1.9.24 2021-05-03 10:42:19 -07:00
Benjamin Doherty
4388e81e5f Merge branch 'rc/1.9.23' into release 2021-05-03 10:40:49 -07:00
Benjamin Doherty
a36d432b88 Update RELEASE_NOTES for 1.9.23 2021-05-03 10:40:15 -07:00
Benjamin Doherty
b3f43eea13 Release Filament 1.9.23 2021-05-03 10:39:26 -07:00
Benjamin Doherty
71a185d139 Update RELEASE_NOTES for 1.9.23 2021-05-03 10:38:59 -07:00
James Walker
df3c7e2c1c Improve documentation formatting
* Improve doxygen formatting of docs for Renderer::readPixels

* slight tweaks
2021-05-03 09:28:27 -07:00
Philip Rideout
cbc4c75a7e Vulkan: fix logic in Disposer, simplify StagePool. 2021-05-01 19:55:17 -07:00
Mathias Agopian
e068d8b698 ssao: fix a typo in the accurate normal reconstruction 2021-04-30 17:15:27 -07:00
Mathias Agopian
06e9a3d31f ssao: high quality upsampling didn't work when low pass was disabled 2021-04-30 17:15:27 -07:00
Philip Rideout
e5ac49f86d Vulkan: big refactor for command buffer management. (#3875)
This removes a lot of caveats that we had in the Vulkan backend. Many
driver API calls were unsupported due to a lack of command buffer, but
in the new scheme, a command buffer can *always* be made available,
and there's no weird separate "work and swap chain command buffers".

Here's how various driver API entry points now map into Vulkan actions:

```
makeCurrent => Acquire Swap Chain.
beginFrame => Do nothing.
endFrame => Submit command buffer and create a new one.
commit => Submit commit buffer again if necessary, Present Swap Chain.
```

This handles both copyFrame (which does not do beginFrame / endFrame)
and renderStandaloneView (which does not do makeCurrent / commit).
2021-04-30 15:31:24 -07:00
Ben Doherty
7fdc63b6ae Fix incorrect units documented for getIntensity (#3870) 2021-04-30 10:09:52 -07:00
Ben Doherty
808abdb6d7 Fix memory leak inside utils::details::SafeString (#3871) 2021-04-29 14:42:07 -07:00
Ben Doherty
037982a0ef Add gltf-viewer iOS sample (#3873) 2021-04-29 12:13:34 -07:00
Philip Rideout
5f86233218 Enable Vulkan in our Android Release package. (#3864)
This makes release builds consistent with continuous builds and default
local builds. It also makes it easier to test the Vulkan backend.
Clients who need a smaller APK size can always make their own build.

This also makes filament-android-release.aar go from 1.8M to 2.3M.
Note that we are now including bluevk, vkshaders (for the blit shader),
smol-v (for SPIRV decompression) and vk_mem_alloc (for mem allocation).
2021-04-27 23:00:57 -07:00
Mathias Agopian
8bd73a44c9 Revert "Support a maximum of 8 render buffers (from 4)" (#3868)
This reverts commit 6f948c101f.

This is breaking rendering on Android when certain postprocessing
effects are disabled (e.g. bloom/msaa/dof).
2021-04-27 22:56:10 -07:00
Mathias Agopian
f1984b19cc lightbulb: clear background
Fixes #3849
2021-04-27 20:50:48 -07:00
Mathias Agopian
c2330fe55a ssao: improve LOW and HIGH quality levels
Simply tweak the "spiralTurns" parameter, empirically to improve the
noise pattern produced by the gradient noise. In turn, this helps the
gaussian filter.
2021-04-27 20:50:03 -07:00
Mathias Agopian
dc56408d5f ssao: implement accurate normal reconstruction
This removes "false AO" effect on geometry edges.
Currently this is enabled on desktop only (quality == high).
2021-04-27 20:50:03 -07:00
Romain Guy
f5adbbddb8 Fix typo 2021-04-27 20:33:58 -07:00
Mathias Agopian
036bfa9b20 Materials now have a quality property.
We used to have that before, but it was hardcoded and depended on
mobile vs. desktop.
With this change, users can set the quality on the material itself.
The default match the current settings. There are 3 quality levels:

low: enables optimization that might not be 100% correct 
     (e.g. abs(x) instead of sqrt(x*x))

normal: like low, but doesn't sacrifices correctness.

high: could be improved upsampling, etc...
2021-04-27 14:20:50 -07:00
Mathias Agopian
2d9064d2bf Cleanup some shader #defines
- create a new FILAMENT_HAS_FEATURE_TEXTURE_GATHER, which can be used
  in the shaders to use textureGather.

- A new TARGET_GLES_ENVIRONMENT and TARGET_GL_ENVIRONMENT in addition
  to TARGET_METAL_ and TARGET_VULKAN_, for completeness.

- Rename TARGET_LANGUAGE_SPIRV to FILAMENT_VULKAN_SEMANTICS and add
  FILAMENT_OPENGL_SEMANTICS for completeness.

- expose the shader model to shaders as: FILAMENT_SHADER_MODEL_ES30 and
  FILAMENT_SHADER_MODEL_GL41

Use these new #define where appropriate.

The main change here is that TARGET_MOBILE is now only used for dealing
with the `mediump` default on mobile.

This change also enables textureGather on Metal.
2021-04-27 14:20:50 -07:00
Mathias Agopian
6f948c101f Support a maximum of 8 render buffers (from 4)
We chose 8 renderbuffer because it seems to be commonly supported
on mobile gpu and is more than 6 which is needed for generating
cubemaps. 4 was the minimum guaranteed by ES3.0.

The main changes here are:
- TargetBufferFlags is now a uint32_t instead of uint8_t
- The number of render buffer supported by filament and supported by
  the hardware can now be different. Applications/users now must
  query this value if more than 4 is needed.
- added a backend query (used gl terminology)
2021-04-27 12:15:22 -07:00
Romain Guy
9c123a59ab New experimental tone mapper (#3850)
* New experimental tone mapper

The new tone mapper proposed in this change replaces Uchimura (see
below) and is composed of two distinct algorithms:

- The first is the customizable compression curve from Timothy Lotte
  (from GDC 2015). The curve's default parameters were chosen to
  match the overall appearance (contrast) of the ACES curves used
  as our current default tone mapper. This was done to provide a
  good migration path to making this new solution the default in
  a future version of Filament.
  The compression curve can be customized via its contrast, shoulder,
  input middle gray, output middle gray, and maximum "HDR value"
  (scene referred).
  It is important to note that the compression is only applied to
  the luminance of the input scene referred value.
- The second is a novel approach by Troy Sobotka called Exposure
  Value Invariant Luminance Scaling (or EVILS). This solution works
  on the largest chromatic channel of the input value as opposed
  to mapping all RGB channels as we do in our other tone mappers.
  The algorithm effectively scales all channel by a ratio that
  depends on both the compressed luminance from the first stage
  and the luminance of input value normalized by the largest
  channel.

This new solution offers important benefits as it manages to
preserve chromaticity for high input values. It is also designed
to provide a desirable rolloff to white on overexposure. This
means that even without gamut mapping, this solution avoids many
hue skews (red to orange, blue to purple, etc.). The results
provided by this solution are much more natural and make using
other color grading tools much easier.

* Use std::pow instead of pow

* Fix Web builds
2021-04-26 18:09:37 -07:00
Philip Rideout
4006018907 Fix Java warnings. (#3856) 2021-04-26 13:49:49 -07:00
Mathias Agopian
02c1e1dc60 Improve libiblprefilter
- move public headers from filament/foo to filament-foo/
  to avoid confusion with libfilament's headers
- add support for equirectangular to cubemap conversion
- add support for using an .hdr file directly in all our samples
2021-04-26 12:17:42 -07:00
Ben Doherty
03d74f1313 Update web docs, add note about shadowMultiplier (#3855) 2021-04-26 12:05:25 -07:00
Benjamin Doherty
d2cf5985ac Bump version to 1.9.23 2021-04-26 10:55:10 -07:00
Benjamin Doherty
debcbb8e5c Merge branch 'rc/1.9.22' into release 2021-04-26 10:52:43 -07:00
Benjamin Doherty
4f2460a23c Update RELEASE_NOTES for 1.9.22 2021-04-26 10:52:37 -07:00
Benjamin Doherty
f68dbe1902 Release Filament 1.9.22 2021-04-26 10:52:37 -07:00
Benjamin Doherty
b9dd62c7d3 Update RELEASE_NOTES for 1.9.22 2021-04-26 10:47:11 -07:00
Mathias Agopian
d589634968 don't set sun parameters if we didn't have SH
The parameters would turn out as NaN.
We might need a better API for this, but it's
never okay to set NaN values.
2021-04-26 10:44:12 -07:00
Benjamin Doherty
dc2b430f34 Bump version to 1.9.22 2021-04-26 10:39:16 -07:00
Mathias Agopian
9914eb84a4 Fix documentation for getNormalizedViewportCoord
Fixes #3821
2021-04-23 22:39:01 -07:00
Mathias Agopian
0a6886e43b improve the importance sampling code
- fix a lod selection bug
- add interleaved gradient noise when sampling the brdf
- compute the diffuse using importance sampling too
2021-04-23 15:21:07 -07:00
Mathias Agopian
bcd4b65f7d fix a memory corruption introduced recently
fixes #3844
2021-04-23 15:20:51 -07:00
Philip Rideout
820717df0e gltfio: Use the new Transcoder API in some cases. (#3840)
Fixes issue seen with Vulkan + the quantized version of Avocado.

We already support the quantized glTF extension, which is when this
comes up. Technically this is only needed for Vulkan but gltfio does
not (and should not) know which backend is being used, so we simply
apply these transformations assuming the worst.

In practice this code usually won't be activated, and if even when it
is, it won't hurt loading time as much as other things like large
textures.
2021-04-22 16:11:34 -07:00
Philip Rideout
6178ba4a6b Add Transcoder API for C++ clients. (#3837)
* Add Transcoder API for C++ clients.

We will add JavaScript and Java support in a later PR.

* Transcoder: use fixed inner loop in some cases.

This lets clang produce better ARM code for common cases.

* Transcoder: stronger typing in Config, etc.

* Transcoder: add UTILS_RESTRICT and noexcept.
2021-04-22 13:29:52 -07:00
Mathias Agopian
6f14c1fa91 don't hardcode drawbuffer to 4
This is the first step at trying to un-hardcode the number of drawbuffer
we support. The ultimate goal is to go from currently 4 to 8.

Until now the maximum render buffer supported was the same than the actual
number of render buffer supported. At some point in the future this will
change, it this will have to be dynamic.

This change is to allow rendering a cubemap in a single pass on h/w that
support it. Many mobile GPU support 8 draw buffers.
2021-04-22 11:59:10 -07:00
Philip Rideout
6a94c77b1e Vulkan: fix VK_FORMAT to correctly handle non-integer types.
The SCALED formats are useful when the shader consumes a float, but
you want to give it an integer.
2021-04-22 11:18:49 -07:00
Philip Rideout
c3d6c853ab gltfio: robustness improvements for Draco meshes.
These changes are motivated by #3815.

See also:
    https://github.com/KhronosGroup/glTF-Blender-IO/issues/1326
    https://github.com/KhronosGroup/glTF-Blender-IO/issues/1345
2021-04-21 18:09:45 -07:00
Mathias Agopian
9575a7453e add an option to control the strength of the importance sampling
This is very useful either with a low sample count, or with a very
HDR image.
2021-04-21 15:41:43 -07:00
Mathias Agopian
cfd9689444 fix several bugs in the gpu prefilter code
- the miplevel wasn't computed correctly
- the random rotation was incorrect
- the default HDR compression was too aggressive
- better validation of the input cubemap
2021-04-21 15:41:43 -07:00
Mathias Agopian
c819265597 Add README.md file and fix some comments 2021-04-21 15:41:43 -07:00
Mathias Agopian
0427787cb7 Generate the kernel texture on the GPU
This avoids having to upload data from the cpu.
2021-04-21 15:41:43 -07:00
Mathias Agopian
e372cc25f2 more fixes from review comments
- get rid of createREflectionsTextures public api
- use default material instance
2021-04-21 15:41:43 -07:00
Mathias Agopian
b98d9dcff3 clarify requirements 2021-04-21 15:41:43 -07:00
Mathias Agopian
91b08705da rename library to filament-iblprefilter 2021-04-21 15:41:43 -07:00
Mathias Agopian
503abb3c94 rename a few things 2021-04-21 15:41:43 -07:00
Mathias Agopian
4b8d98af8c compute all lod kernel at once
we now store the kernel for each lod in a texture, this has several
advantages:
- the texture can be reused, so we can amortize that cost a bit
- we could generate the texture with a shader, so that we don't
  have to do any texture uplaod (TBD).
2021-04-21 15:41:43 -07:00
Mathias Agopian
ced6c3de1f GPU based IBL prefiltering library 2021-04-21 15:41:43 -07:00
Mathias Agopian
f8ced1170e fix typo that broke java apps 2021-04-21 15:15:01 -07:00
Ben Doherty
a166fcdcdf Specific sampler precision only on GLES (#3829) 2021-04-21 10:11:55 -07:00
Ben Doherty
faac96730a Disable VSM MSAA on Adreno devices (#3816) 2021-04-21 10:06:03 -07:00
Mathias Agopian
4929f11793 attempt to fix web build 2021-04-20 22:16:01 -07:00
Mathias Agopian
b1d877e7db Add Engine::getEntityManager() 2021-04-20 16:12:40 -07:00
Romain Guy
3f09e62f23 Fix docs 2021-04-20 14:40:04 -07:00
Ben Doherty
03bc9926dd Check that drawSwapChain exists inside endFrame (#3828) 2021-04-20 14:07:43 -07:00
Mathias Agopian
e64e8927ce don't use TARGET_MOBILE for quality settings
Until now we were using TARGET_MOBILE in our shaders for both 
quality setting and correctness.

With this PR we introduce a new define FILAMENT_QUALITY which currently
can take two value FILAMENT_QUALITY_LOW and FILAMENT_QUALITY_HIGH and
we use that instead of TARGET_MOBILE for quality settings.

Currently, FILAMENT_QUALITY_LOW is selected when TARGET_MOBILE is set.
2021-04-20 13:39:16 -07:00
Philip Rideout
0643b9e7dd Specify a version range for Pygments. 2021-04-20 12:30:11 -07:00
Benjamin Doherty
e5ef4e8868 Update RELEASE_NOTES for 1.9.21 2021-04-19 11:36:37 -07:00
Benjamin Doherty
032ce5ff83 Update RELEASE_NOTES for 1.9.21 2021-04-19 11:36:08 -07:00
Benjamin Doherty
c0d6cd3ac3 Merge branch 'rc/1.9.21' into release 2021-04-19 11:34:23 -07:00
Benjamin Doherty
b63ab2dc19 Update RELEASE_NOTES for 1.9.21 2021-04-19 11:32:31 -07:00
Benjamin Doherty
623833a5d6 Release Filament 1.9.21 2021-04-19 11:19:05 -07:00
Mathias Agopian
f7eb55f2f5 NEW API: Renderer can process standalone View
New Api:

- Renderer::renderStandaloneView() is a new method that can be used
  outside of beginFrame/endFrame on Views that have a RenderTarget
  associated. This can be used as a poor man's compute API.

Improvements to Renderer:

- more aggressively skip lighting/shadowing code that won't be
  needed by the current view

- Allow up to 64 KiB to be allocated from the render stream, up from
  1 KiB
2021-04-19 11:17:38 -07:00
Philip Rideout
b095e65e28 VulkanUtility: mark illegal formats with comments. 2021-04-16 15:26:04 -07:00
Benjamin Doherty
98fd95440f Minor updates to release script / guide 2021-04-16 12:11:43 -07:00
Philip Rideout
5f00e715ea Vulkan: another fix to the UBO barrier. (#3814)
Even though the vertex shader comes before the fragment shader,
both bits needs to be present in the barrier, since a Vulkan
implementation might partition its uniform cache between stages.

Thanks to Chris Forbes for pointing this out.
2021-04-16 10:17:51 -07:00
Mathias Agopian
64187ebe8a fix uninitialized state in rendertarget sample 2021-04-15 12:06:21 -07:00
Philip Rideout
1ab127ff03 Fix unused private field warning. 2021-04-15 11:37:08 -07:00
Philip Rideout
3c09d8784a Minor fixups for drag-and-drop viewer page. 2021-04-15 10:11:05 -07:00
Ben Doherty
31ec6550ec Fix Windows build error in filament_framegraph_test.cpp (#3809) 2021-04-15 10:04:34 -07:00
Philip Rideout
24b88219fa VulkanDriver: clean up pipeline barrier for UBO. (#3810)
After eyeballing this barrier I realized it was configured incorrectly,
but it did not seem to manifest as an actual error anywhere.

Basically, it needs to ensure that the UBO is fully updated before it
is read by the vertex shader associated with the next draw call.
2021-04-14 17:54:57 -07:00
Philip Rideout
5c437d9163 matdbg robustness improvements / cleanup. (#3799)
* matdbg robustness improvements / cleanup.

* matdbg code review feedback
2021-04-14 11:39:42 -07:00
Philip Rideout
09bda8a1dc Add glTF viewer to public website.
This will allow folks to drop a GLB into the following page to get a
WebGL preview. It always uses the latest version of Filament via unpkg.

https://google.github.io/filament/viewer

After the next release we can also use the `<filament-viewer>` component
itself from unpkg and remove the local copy.
2021-04-14 10:42:38 -07:00
Philip Rideout
f76084213c Update emscripten to 2.0.17
The latest version of emscripten includes major updates to LLVM and
Binaryen.
2021-04-14 10:13:24 -07:00
Philip Rideout
b8ed546555 Fix minor warnings. 2021-04-13 13:59:02 -07:00
Philip Rideout
9553786cd5 <filament-viewer> now supports optional drag-and-drop. 2021-04-13 13:41:34 -07:00
Benjamin Doherty
7ef79ad626 Update RELEASE_NOTES for 1.9.20 2021-04-13 11:49:19 -07:00
Benjamin Doherty
0ac2fe02dc Release Filament 1.9.20 2021-04-13 11:49:19 -07:00
Philip Rideout
c994ab9f60 sample-gltf-viewer: more improvements for zip files.
- If a resource file is missing, show toast instead of crashing.
- Allow glb files in zip files.
- Run blocking calls like createTempFile() on IO thread.
2021-04-13 11:20:08 -07:00
Mathias Agopian
600600b9af allow the public RenderTarget API to use MRT 2021-04-13 11:02:37 -07:00
Mathias Agopian
1b870a55e2 silently clamp MSAA sample count to maximum allowed
It's an error to ask for a higher MSAA sample count than supported by
the gl driver, and results in corrupted rendering.
We now always clamp the requested sample count to the maximum allowed 
but the gl driver.

includes some minor refactoring.
2021-04-12 16:05:43 -07:00
Philip Rideout
965e845133 sample-gltf-viewer: Delete zip file when done reading. 2021-04-12 16:03:30 -07:00
Philip Rideout
7107afbf0f sample-gltf-viewer: Prevent OOM for large models like Bistro. 2021-04-12 16:03:30 -07:00
Mathias Agopian
cbb809e535 enable contact-shadows functionality in mobile gltf-viewer
contact-shadows needs to be enabled per object.
2021-04-12 15:11:18 -07:00
Philip Rideout
c5169a431b Fix warning. 2021-04-12 12:46:07 -07:00
Mathias Agopian
6b798ec274 add README to benchmark folder 2021-04-12 12:15:41 -07:00
Ben Doherty
1cde9b326c Fix bad Javadoc in Texture.java 2021-04-12 11:57:18 -07:00
Benjamin Doherty
5d8dad561c Bump version to 1.9.21 2021-04-12 11:38:27 -07:00
Benjamin Doherty
8933be1ae2 Merge branch 'rc/1.9.20' into release 2021-04-12 11:36:17 -07:00
Benjamin Doherty
6b66b48b1d Update RELEASE_NOTES for 1.9.20 2021-04-12 11:35:45 -07:00
Benjamin Doherty
9c23eb6e33 Release Filament 1.9.20 2021-04-12 11:34:39 -07:00
Benjamin Doherty
baea54a3fc Update RELEASE_NOTES for 1.9.20 2021-04-12 09:20:31 -07:00
Philip Rideout
4b9ab66ce7 JavaScript: add missing TextureSampler bindings. 2021-04-09 13:00:50 -07:00
Mathias Agopian
ba7ebf5ea6 better handle anisotropic filtering with various drivers
Some drivers claim to support anisotropic filtering but don't allow
setting it via glSamplerParameter. Until now we were disabling 
anisotropic filtering entirely on these drivers at compile time.

With this change, we should detect at runtime which drivers have this
issue and use a workaround -- instead of disabling anisotropic 
filtering entirely.
2021-04-09 12:53:21 -07:00
Ben Doherty
afdc3d068c Add default precision qualifiers for special sampler types (#3786) 2021-04-09 10:12:03 -07:00
Mathias Agopian
941e81b3aa rework the "debugCommand" feature of backend
- it was called on the main thread side, which didn't allow to,
  for instance, systrace commands on the backend thread side.

- moved to a begin/end callback model

- implemented basic logging/systracing for all backends in Driver.cpp
  (and removed this functionality for the metal driver).

note: refactored CommandStream class attributes only to work around
a clang bug we running into in CI.
2021-04-08 16:35:07 -07:00
Mathias Agopian
de7075ff8f enable timer queries on Mali-G series 2021-04-08 16:34:48 -07:00
Philip Rideout
5deed8dc5a Vulkan: fix image layout validation error on Android. 2021-04-08 15:17:24 -07:00
Philip Rideout
93f0d0576d Improve error reporting for vkAllocateDescriptorSets. 2021-04-08 13:06:22 -07:00
Ben Doherty
ec339b0282 Fix texture swizzling crash with older Nvidia GPUs (#3779) 2021-04-08 10:38:59 -07:00
Philip Rideout
a67505bbe2 VertexBuffer cleanup and simplification.
This includes changes to OpenGL, Metal, and Vulkan backends.

At the backend level, vertex buffers are now always composed of buffer
objects. This lets us simplify the Driver API and some bookkeeping in
the backends.

This change also splits MAX_VERTEX_ATTRIBUTE_COUNT into two constants
because the maximum number of bound buffers is a separate concept from
the maximum number of attribute semantics (e.g. consider interleaving).
For now these two constants are set to the same value.

We also now store a byte count in HwBufferObject, which allows us to
remove the byte count from the Metal-specific handle, and to add some
asserts to debug builds to prevent size overflow.
2021-04-08 09:56:51 -07:00
Philip Rideout
8fd1cefcdf sample-gltf-viewer: keep screen turned on 2021-04-07 16:39:29 -07:00
Ben Doherty
03f7ac6ef4 Fix Material and MaterialInstance Javadocs (#3778) 2021-04-07 14:21:32 -07:00
Mathias Agopian
274e227f49 Fix some mediump related issues
- DoF: don't convert gl_FragCoord to mediump when generating noise
- SSAO: add a bunch of missing highp qualifiers
- all matrices and UV should be highp
- Also fix some typo in comments.
2021-04-07 11:39:36 -07:00
Mathias Agopian
9302a2e711 update remote controler 2021-04-06 21:18:18 -07:00
Mathias Agopian
ee9d87b543 use more reasonable near/far for gltf viewer 2021-04-06 17:55:51 -07:00
Mathias Agopian
391cf2487a add missing parameters in ssao serialization 2021-04-06 17:52:01 -07:00
Philip Rideout
914503a30e gltfio: honor stride in normalizeSkinningWeights.
This fixes the issue seen with RecursiveSkeletons.gltf, which is a model
that might soon be added to the Khronos sample models repo.

Fixes #3765.
2021-04-06 15:42:21 -07:00
Philip Rideout
17b8717557 Fix unit test regression. 2021-04-06 15:04:10 -07:00
Philip Rideout
4f49cdbd1e Update remote control web page. 2021-04-06 14:17:07 -07:00
Philip Rideout
24c5cbac68 ModelViewer and Remote UI now support focal length.
The focal length slider now works over a remote connection. Also, the
slider for focus distance now controls the value in `ViewerSettings`
(which gets applied to Camera) rather than the value in
`DepthOfFieldOptions` (which is deprecated).
2021-04-06 14:17:07 -07:00
Mathias Agopian
befc1de389 improve a bit GLES error logging code.
no functionality changes, just easier to use when debugging.
2021-04-06 14:00:32 -07:00
Mathias Agopian
45522f24c9 fix MSAA w/ multisampled_render_to_texture on Mali
according to the gl spec, we can't mix the EXT versions of
glRenderbufferStorageMultisample/glFramebufferMultisample with
the regular versions. Other drivers are more permissive.

When allocating a renderbuffer and the extention is supported, we always
use it.
2021-04-06 14:00:16 -07:00
Mathias Agopian
1bd0bb9b81 fix output location in fragment shaders
It looks like the layout(location) is needed for output parameters of
the fragment shader in GLES. Adreno dirver didn't seem to care, but
Mali drivers do. 

This fixes shaders that use multiple out buffers in debug mode.
2021-04-06 13:59:56 -07:00
Philip Rideout
4229610f05 Update emscripten in Google Actions.
This now matches what is already specified in BUILDING.md
2021-04-06 07:58:26 -07:00
Mathias Agopian
c062cd9914 gl backend minor code cleanup
- be more consistant with extension naming
- sort extension queries alphabetically
2021-04-05 22:51:56 -07:00
Mathias Agopian
449a5907d1 Better handle GL_GOOGLE_cpp_style_line_directive
We now alwyas scrap this extension usage if the driver doesn't support
it, regardless of being in debug or release mode.
2021-04-05 15:28:40 -07:00
Ben Doherty
9130ef5451 Check environment variable to force integrated Metal device (#3757) 2021-04-05 14:43:38 -07:00
Philip Rideout
82fcb656d9 gltfio: Use BufferObject API, simplify MorphHelper. (#3737)
* gltfio: Use BufferObject API, simplify MorphHelper.

* Repair Android build.
2021-04-05 13:00:39 -07:00
Philip Rideout
a139d7fc01 Fix Java warnings.
This adds the 565 enum to a switch block (which is an actual bug),
and it fixes a JavaDoc warning about missing summary fragments (which
is just a silly warning).
2021-04-05 13:00:15 -07:00
Ben Doherty
3242fbaf20 Implement Metal BufferObjects (#3749) 2021-04-05 12:45:07 -07:00
Philip Rideout
037a783e07 Add web component demo.
Just for fun, this is an example of a web component that allows you to
embed a Filament viewer with a single HTML element. It does not have
many features, but is much easier to use than our raw JavaScript API.
2021-04-05 11:42:27 -07:00
Benjamin Doherty
8c714d5a1f Update RELEASE_NOTES for 1.9.19 2021-04-05 11:14:52 -07:00
Benjamin Doherty
3fbc4f2915 Release Filament 1.9.19 2021-04-05 11:14:51 -07:00
Benjamin Doherty
d9f800454c Bump version to 1.9.20 2021-04-05 11:14:17 -07:00
Benjamin Doherty
f9ee0de07a Merge branch 'rc/1.9.19' into release 2021-04-05 11:11:13 -07:00
Benjamin Doherty
2786d0a9f7 Update RELEASE_NOTES for 1.9.19 2021-04-05 11:10:50 -07:00
Benjamin Doherty
491e8032e6 Release Filament 1.9.19 2021-04-05 11:10:20 -07:00
Benjamin Doherty
ef3f13f5d3 Update RELEASE_NOTES for 1.9.19 2021-04-05 11:09:38 -07:00
Benjamin Doherty
bcb5b2d790 Implement Metal BufferObjects 2021-04-05 11:01:36 -07:00
Adrian Perez
e29bfc2c86 ImGuiHelper can construct with a context (#3753)
* ImGuiHelper supports client-provided context

this lets impress load >1 embedded  font into the font table

* ImGuiHelper supports client-provided context

this lets impress load >1 embedded  font into the font table

Co-authored-by: Philip Rideout <philiprideout@gmail.com>
2021-04-05 10:42:57 -07:00
Mathias Agopian
8a34f3c289 revive somewhat the importance sampling mode 2021-04-04 23:36:17 -07:00
Mathias Agopian
951802dd73 SSAO: fix high-quality upsampling
Another mediump issue.
2021-04-04 22:20:03 -07:00
Philip Rideout
b95d91a65e WebGL: expose fitIntoUnitCube to JS. 2021-04-04 21:38:08 -07:00
Thomas Gorisse
fe94f935f1 Expose TransformManager.getParent(int) (#3751)
It will be nice to have access to TransformManager EntityInstance parent.
2021-04-03 15:45:46 -07:00
Romain Guy
6b529bb231 Fix typo 2021-04-02 15:16:00 -07:00
Philip Rideout
c2fabbf9d9 WebGL: support for multiple <canvas> elements.
We now annotate the JS wrapper for Engine with a GL context handle.

This is fairly hacky because emscripten hides its internal GL object
from JavaScript, and it does not provide a mechanism to pass JS objects
into inline assembly.
2021-04-02 14:29:48 -07:00
Philip Rideout
7d604cd05b Add script that updates remote UI.
This script makes it easy to update the web page at
https://google.github.io/filament/remote/ even if you do not have the
emscripten SDK. It works by downloadinug the latest continuous web
build, then placing the wasm file in the right place.

After running the script, the user must make a git commit to finish the
operation.
2021-04-02 12:34:16 -07:00
Philip Rideout
57f1932744 Vulkan: add swizzle support. 2021-04-02 12:34:00 -07:00
Mathias Agopian
891fb65daa added a slider to debug dynamic scaling issues
This is a big hackish, but is intended to help us debug scaling issues,
this adds a couple of sliders under [Debug] to control dynamic
scaling manually.
2021-04-02 11:01:53 -07:00
Mathias Agopian
f35be05e76 DoF: fix anamorphism of the Bokeh when dynamic scaling is used 2021-04-02 11:01:29 -07:00
Romain Guy
bd4a207b37 Switch specular-color to CIE 1931 10 degree observer 2021-04-02 09:55:11 -07:00
Philip Rideout
e19dff18c3 Add JSON unit test, fix ring count output.
Shockingly there were no unit tests that did a simple write-then-read.
This is important because it's easy to forget details such as trailing
commas and the fact that uint8_t is a char.
2021-04-01 21:06:44 -07:00
Philip Rideout
deee5d2815 Update the remote web page. 2021-04-01 18:00:49 -07:00
Philip Rideout
53f5fd91b7 Add print operator for BufferObjectBinding. 2021-04-01 14:52:06 -07:00
Philip Rideout
0969cec45d BufferObject API: add Vulkan support. 2021-04-01 14:52:06 -07:00
Philip Rideout
ded542a543 Introduce BufferObject API.
NOTE: after Metal and Vulkan support lands, we can potentially simplify
the Driver API by removing some of the old VertexBuffer entry points.

This introduces a new API-level object called `BufferObject`, and a new
backend-level object called `HwBufferObject`. This encapsulates a single
VBO. It's especially useful when clients need to share data between
multiple VertexBuffer objects. (e.g. for morphing).

In the future, buffer objects could perhaps be used for non-vertex data
(e.g. for compute).

The existing `VertexBuffer` class can now be configured to use buffer
objects by calling `enableBufferObjects` on the builder. By default its
API is unchanged. If buffer objects are enabled, then clients should use
`setBufferObjectAt` (which takes a buffer object) rather than
`setBufferAt` (which takes CPU data).

OpenGL is the trickiest backend for this, due to existence of VAOs.
The implementation in this PR uses a version-tracking scheme to
figure out when to update the VAO.
2021-04-01 14:52:06 -07:00
Mathias Agopian
385a17b8a5 DoF: add many user settings
- native/half resolution
- gather kernel ring counts
- circle-of-confusion radius clamps
2021-04-01 14:42:10 -07:00
Ben Doherty
0a0588aec8 Add Metal and Vulkan backend support to Suzanne sample (#3736) 2021-04-01 12:22:15 -07:00
Ben Doherty
9af62251b6 Fix Metal texture swizzling (#3732) 2021-04-01 10:19:50 -07:00
Mathias Agopian
819878a1da DoF: implement "background hole filling"
We use the technique used by Jimenez for the foreground applied to the
background, where we "guess" the missing background information from
neighboring pixels. In several papers it's not deemed useful for the
background, however, it does improve the blur quality a lot very shallow
DoF, i.e. when a moderately blurred background sits over a strongly 
blured one.
2021-03-31 17:49:41 -07:00
Mathias Agopian
e7364cdcb3 DoF: don't rely on texture swizzle being supported 2021-03-31 12:17:34 -07:00
Mathias Agopian
e5bfe81d0c DoF: use only a single low res source for both fg and bg
Before we were keeping a foreground and background version of the
low resolution source, but in practice it really doesn't make a big
difference and we save a fair amount of bandwidth this way.

The bulk of the change is to remove a texture/target which mostly
affects the downsample and mipmap passes.
Also renamed some variables to be less confusing (MaxMin to MinMax for e.g.)
and fixed a few typos.
2021-03-31 12:17:34 -07:00
Mathias Agopian
c4eb790065 Add support for texture swizzling in framegraph 2021-03-31 12:17:34 -07:00
Romain Guy
ac56efcd95 Revert misguided attempt to fix bloom with glTF (#3728)
* Revert misguided attempt to fix bloom with glTF

* Put back line removed by mistake
2021-03-31 10:08:36 -07:00
Mathias Agopian
9fcb8ccb9e DoF: document a typo
there has been a typo in the DoF code a while, but fixing it looks
much worse. we need to understand why. so for now we at least
document the typo in the code.
2021-03-30 21:34:59 -07:00
Mathias Agopian
67a936d845 fix a linker warning 2021-03-30 15:58:17 -07:00
Ben Doherty
d11f3f7d5a Implement Metal texture swizzling (#3720) 2021-03-30 15:38:55 -07:00
Mathias Agopian
625c4d8968 implement query for texture swizzle
unfortunately metal does support texture swizzle on all versions of
macos we support.
2021-03-30 14:24:17 -07:00
Ben Doherty
239b933d5e Fix VSM on Android (#3719) 2021-03-30 14:05:53 -07:00
Philip Rideout
3161f6a8f1 Remote UI now handles keyboard input. 2021-03-30 08:15:01 -07:00
Philip Rideout
d2bff95c90 Easy build: add matdbg option and help message. 2021-03-30 08:14:23 -07:00
Philip Rideout
a0e7c26a63 Remote pip lockfile from web docs generator. 2021-03-29 14:49:12 -07:00
Ben Doherty
02de3f2e2a Fix, regression with Metal buffers (#3715) 2021-03-29 14:21:34 -07:00
Ben Doherty
5bfa9633d2 Fix, regression with Metal buffers (#3715) 2021-03-29 14:20:40 -07:00
Benjamin Doherty
0e7bb53c07 Bump version to 1.9.19 2021-03-29 11:09:32 -07:00
Benjamin Doherty
759109d478 Merge branch 'rc/1.9.18' into release 2021-03-29 11:06:55 -07:00
Benjamin Doherty
ff5ecb17ea Update RELEASE_NOTES for 1.9.18 2021-03-29 11:06:35 -07:00
Benjamin Doherty
83ba56d3e7 Release Filament 1.9.18 2021-03-29 11:05:44 -07:00
Benjamin Doherty
54d5af6edf Update RELEASE_NOTES for 1.9.18 2021-03-29 11:04:57 -07:00
Mathias Agopian
2d398c2398 DoF: fix noise radius calculation (#3709)
This small bug was introduced recently with the dynamic kernel size
changes, the noise radius depends on the number of rings in the kernel.
2021-03-29 10:46:34 -07:00
Philip Rideout
38fbe47ced RenderTarget: fix NPE when depth is not present.
This fixes a recent regression that would occur when a RenderTarget
does not have a depth attachment.
2021-03-29 10:32:22 -07:00
Philip Rideout
cf070c6bc7 RenderTarget: fix NPE when depth is not present.
This fixes a recent regression that would occur when a RenderTarget
does not have a depth attachment.
2021-03-29 10:31:04 -07:00
Mathias Agopian
3c577b6191 DoF: fix several mediump-related bugs
The gist of it is that we can't always accumulate samples naively, and
we have to use different strategies with different tile types.

For the fast tiles it seems enough to reorder the sum, accumulating each
ring first, and then accumulating that into the output, because all
samples have the same weight.

For the foreground tiles, for some reason I couldn't find any major
issue and I'm not sure why.

For the background tiles, we need to use highp intermediates because
every sample has different magnitudes (weights)
2021-03-29 09:48:51 -07:00
Mathias Agopian
acb2da7759 Improvements to Camera APIs (#3701)
* move the focus distance from DofOptions to Camera

The DofOption parameter is now deprecated, but will still work if the
focus distance is not set on Camera.

* A few new helper APIs on Camera

- getFocalLength() which returns the focal length used internally for
  DoF computations.

- computeEffectiveFov() and computeEffectiveFocalLength() which can be
used to better simulate a real camera's FOV changes with the
focus distance.

Modified gltf_viewer so it uses the effective fov/focallendth when
DoF is active.

* simplify setLensProjection

We can call setProjection directly instead of converting to a fov
first, which ends up performing atan(tan(x)).

Also improve parameters names.
2021-03-25 15:22:19 -07:00
Mathias Agopian
a0c2edd1a2 DoF: dynamically and conservatively adjust the kernel density per tile
This adjustment is conservative, i.e. we limit the number of rings in
the kernel based on the kernel size in a way that it won't impact the
result. For instance, if the kernel size is 2 or lower, we don't need 4
rings.

This improves performance significantly, especially with large maximum
right counts.
2021-03-25 15:19:57 -07:00
Ben Doherty
ad555d897d Expose MaterialInstance APIs that should have been public (#3703) 2021-03-25 11:29:39 -07:00
Mathias Agopian
4a6e62070b DoF: slightly better opacity for the background
We now use the same calculation than for the foreground, this seems
to produce slightly smoother transitions
2021-03-24 22:10:40 -07:00
Mathias Agopian
0c081d4295 DoF: implement fix for foreground opacity
This fixes an issue where objects in-focus show through the blurred
foreground.
2021-03-24 16:22:22 -07:00
Mathias Agopian
04ff2fb806 DoF: shader code refactoring
here we just move the fast/foreground and background tiles processing
into their own function. this is just to make the code more readable.
2021-03-24 16:22:22 -07:00
Philip Rideout
4fb9ee4470 Remove old emscripten workaround from GL backend.
This was put in as a workaround for #2856. I made a fix to emscripten
itself (yay open source) in July. So, this workaround is no longer
necessary.

Verified with the rigged figure model.

https://github.com/emscripten-core/emscripten/pull/11742
2021-03-24 14:58:53 -07:00
Philip Rideout
3d2734b163 Minor Driver API simplification.
As far as I can tell, there is no need for the `enabledAttributes`
argument in `setRenderPrimitiveBuffer`. This helps pave the way for
the upcoming BufferObject API.
2021-03-24 14:31:18 -07:00
Philip Rideout
c4a12fe48a Update cgltf to v1.10 2021-03-24 14:31:09 -07:00
Ben Doherty
40b8667aef Fix Metal bug when setGeometryAt is called multiple times (#3693) 2021-03-24 12:42:55 -07:00
Mathias Agopian
cb9578327b attempt to improve doxygen formating
fixes: #3692
2021-03-24 12:24:12 -07:00
Mathias Agopian
7b0a8cf2c2 fix JNI setImage and friends buffer size calculation
- setImage() used the width of the texture for calculating the required
  user buffer size, but this was too large when only updating a
  portion of the texture. It would result in a BufferOverFlowException.

- setImage3D() had the opposite problem where it didn't take into
  account the depth of the texture.

- the offset in the user buffer was called "bottom" on the C++ JNI side,
  but it is called "top" on the java and filament side.

Fixes #3685
2021-03-24 12:20:16 -07:00
Philip Rideout
4197afba49 Web site: update Filament in /remote. 2021-03-24 08:24:00 -07:00
Philip Rideout
495fb14b9c Move Camera settings from gltf_viewer to SimpleViewer. 2021-03-24 08:24:00 -07:00
Mathias Agopian
4de1b0de2d DoF: add a "filter" parameter to the DoF settings
Currently the only NONE and MEDIAN are available options, at some 
point we may add a "MAX" option which is cheaper.

There is no real practical uses for this option with these only two
choices, other than for debugging.
2021-03-23 17:27:31 -07:00
Mathias Agopian
abcf4010dd DoF: support full-resolution DoF
This is mostly used for debugging and having somewhat of a reference.
Change to the shader are minimal because all CoC values were always
treated as full-resolution. We just need to replace the downsampling
shader by one that just calculates the CoC. And we need to introduce
a CoC scale factor to compute the LOD to use (this was hardcoded
before).

On the C++ side, it's mostly a matter of replacing hardcoded buffer size
scales by a runtime or compile time variable.
2021-03-23 16:12:03 -07:00
Philip Rideout
65928612b1 Add vkshaders to README. 2021-03-23 12:38:50 -07:00
Adrian Perez
a33c85bdd4 CString can construct from a string_view (#3677)
* CString can construct from a string_view

(string_views lack a null terminator)

* Update libs/utils/src/CString.cpp

Co-authored-by: Mathias Agopian <pixelflinger@gmail.com>
2021-03-23 00:46:18 -07:00
Mathias Agopian
3ec3f222c5 Dof: improve significantly foreground layer
We're implementing the two-layer technique described in
Jimenez DoF paper, where the foreground field is split in two layers, front
and back. In addition we compute accurately the foreground field alpha.

From a performance standpoint, most of the extra work is increased
register pressure and a bit of ALU.
2021-03-22 16:55:40 -07:00
Mathias Agopian
e9a43e7344 DoF: code cleanup
- mostly rename variables
2021-03-22 16:55:40 -07:00
Mathias Agopian
fc835aebc6 DoF: fix a few small bugs
- foreground in-layer feather was off
- sample weights was off my 2x
2021-03-22 16:55:40 -07:00
Mathias Agopian
a3504bd9b6 DoF: make code a bit less confusing
Always store min CoC in the red channel and max Coc in the green
channel for both the CoC and Tiles textures.
(The tiles texture was doing the opposite).
2021-03-22 16:55:40 -07:00
Mathias Agopian
7c604623e6 DoF: code cleanup
Remove the RING_DENSITY variable because it
can't be changed.
2021-03-22 16:55:40 -07:00
Ben Doherty
3d3f19aa71 Enable VSM shadows with shadow multiplier (#3678) 2021-03-22 12:37:07 -07:00
Benjamin Doherty
f066c925ba Bump version to 1.9.18 2021-03-22 10:16:34 -07:00
Benjamin Doherty
00f4b45df6 Update RELEASE_NOTES for 1.9.17 2021-03-22 10:16:20 -07:00
Benjamin Doherty
07140cf2fa Release Filament 1.9.17 2021-03-22 10:16:02 -07:00
Benjamin Doherty
994fdf4e1d Merge branch 'rc/1.9.17' into release 2021-03-22 10:12:20 -07:00
Benjamin Doherty
50b50d65e3 Update RELEASE_NOTES for 1.9.17 2021-03-22 10:11:02 -07:00
Romain Guy
28acd0fa6a Update build scripts to match latest AGP and Kotlin 2021-03-19 12:44:25 -07:00
Philip Rideout
0b91f3d785 Add deprecation annotation to Camera. 2021-03-19 11:04:30 -07:00
Mathias Agopian
1bb18f5f0a DoF: fix a bug that caused black dots around the fast tiles
this would happen only when a fast tile had a CoC < 2, because it
would then have an opacity, but we were ignoring it. It's color then
didn't match the color of the surrounding layer and the median filter
would spread a pixel from the surrounding layer into the fast tile.

we simply fix this by (1) generating the alpha/color for fast tiles,
which is easy to do and on the combine pass, skip the fast tile 
combine when the tile has a an opacity.
2021-03-18 14:57:46 -07:00
Mathias Agopian
2e1d88caae DoF: always apply the correct sample weight
before we were not doing that because it caused some aliasing
artifacts with mipmapping, however it turns out that there are artifacts
anyways, and using the proper weights actually reduces the most severe
ones.

the artifacts are due -- it seems -- to the low density of the kernel.
2021-03-18 14:57:46 -07:00
Mathias Agopian
a59f4dd3fc DoF: minor optimizations
we can refactor the code to get rid off the call to mergeRings() for 
the first ring, and we don't need to initialize the current bucket
either.
2021-03-18 14:57:46 -07:00
Mathias Agopian
0aaa985649 Fix a hang in JobSystem
The hang was caused by a subtle race. When a job is completed, its 
thread must signal all the threads that might be waiting on this job.
The signaling code was attempting to signal only the minimum number
of threads -- this was important especially in the case where no threads
were waiting, then the call to notify() could be avoided.

Unfortunately, for performance reasons we're not calling notify() with
the condition lock held, this meant that between the time the number of 
waiting threads was latched and the time of the notify() call, more
threads could enter their condition variable wait(), and it would
then be possible for these threads to wake up, instead of the thread
we were trying to wake up (the one waiting on the job).

It would then get stuck forever.

This bug was introduced in 2df639133b


Also add some debugging code for this kind of failure (disabled)
2021-03-18 09:57:25 -07:00
prewettg
46b356cb2c Fix blanking windows not being drawn into on macOS (#3616)
* Fix blanking windows not being drawn into on macOS

* Refactored to create swap chain info object; added fixes for resizing; added sample.

* CocoaGLSwapChain should inherit from Platform::SwapChain

* Link to SDL directly for multiple_windows example

* SDL apparently redefines main to SDL_main and requires C++ linkage

* Fix main to have SDL-approved signature
2021-03-18 09:49:20 -07:00
Philip Rideout
a20ae75d11 gltfio: Add support for data:// in image URI's. (#3662) 2021-03-17 17:57:41 -07:00
Philip Rideout
8d78b1f2e1 gltfio: Add internal MorphHelper, enable up to 255 targets. (#3661)
* gltfio: Add internal MorphHelper, enable up to 255 targets.

Previously, gltfio could not animate models with more than 4 morph
targets. Now we can handle up to 255 targets, as long as no more than
4 targets are ever used simultaneously. This allows us to handle
many more models, such as those exported by Modo, and the horse model
in #1852.

We do this by picking the highest 4 weights. The indices for these
weights are called the "primary indices", and we construct a new
VertexBuffer for each unique set of primary indices.

In the near future this will be made more efficient by adding a new
VertexBuffer API to the Filament core.

Fixes #1487.

* Code review fixups.
2021-03-17 15:52:24 -07:00
Ben Doherty
9030abaa89 Fix RenderTarget slice bug (#3656) 2021-03-17 15:47:31 -07:00
Mathias Agopian
e8b16d600e Fix a hang in JobSystem
The hang was caused by a subtle race. When a job is completed, its 
thread must signal all the threads that might be waiting on this job.
The signaling code was attempting to signal only the minimum number
of threads -- this was important especially in the case where no threads
were waiting, then the call to notify() could be avoided.

Unfortunately, for performance reasons we're not calling notify() with
the condition lock held, this meant that between the time the number of 
waiting threads was latched and the time of the notify() call, more
threads could enter their condition variable wait(), and it would
then be possible for these threads to wake up, instead of the thread
we were trying to wake up (the one waiting on the job).

It would then get stuck forever.

This bug was introduced in 2df639133b


Also add some debugging code for this kind of failure (disabled)
2021-03-17 13:44:30 -07:00
Benjamin Doherty
24121a4734 Fix typo with Metal createRenderTarget 2021-03-17 10:29:07 -07:00
Philip Rideout
6eabe0491c gltfio: Refactor Animator.
This does not change any behavior, it just prepares for the upcoming
MorphHelper class.
2021-03-17 07:38:00 -07:00
Philip Rideout
20b0972130 gltfio: Refactor the tangents job.
This cleans up the glTF tangents generator and allows it to be used
in other parts of the library.
2021-03-16 16:43:02 -07:00
Mathias Agopian
98da09b247 fix rendertarget sample app
we can't use a projection with infinite far as a custom
projection matrix, because this is not suited for culling.

recently a new version of setCustomProjection was added which allows
to specify both the rendering and culling projections.
2021-03-16 16:09:14 -07:00
Mathias Agopian
cc13420e31 add missing includes
Should fix #3633
2021-03-15 22:45:31 -07:00
Benjamin Doherty
29564f8eae Bump version to 1.9.17 2021-03-15 10:15:25 -07:00
Benjamin Doherty
c15db68a5b Merge branch 'rc/1.9.16' into release 2021-03-15 10:12:56 -07:00
Benjamin Doherty
fd55da0319 Update RELEASE_NOTES for 1.9.16 2021-03-15 10:12:24 -07:00
Benjamin Doherty
240d9d0919 Release Filament 1.9.16 2021-03-15 10:11:11 -07:00
Benjamin Doherty
3452fb3e56 Update RELEASE_NOTES for 1.9.16 2021-03-15 10:10:40 -07:00
Mathias Agopian
41634a301e demangle callstacks in debug builds (unixes only)
This requires dladdr() and __cxa_demangle().
2021-03-13 23:22:01 -08:00
Philip Rideout
cf75b11cba Add missing deprecated annotations. 2021-03-12 13:33:14 -08:00
Philip Rideout
81bba4644a Remove unused imports. 2021-03-12 13:07:29 -08:00
Mathias Agopian
35eb8e7be1 Revert GL backend handle tracking
This wasn't very useful in the first place because we're recycling
handles very quickly. Additionally there was a race condition
which cause false positives.

This reverts commit bc6acd5c5a.
This reverts commit 3a15756c78.
2021-03-12 13:02:55 -08:00
Mathias Agopian
f7e92b0ee3 Revert GL backend handle tracking
This wasn't very useful in the first place because we're recycling
handles very quickly. Additionally there was a race condition
which cause false positives.

This reverts commit bc6acd5c5a.
This reverts commit 3a15756c78.
2021-03-12 12:57:03 -08:00
Mathias Agopian
1e58fd4842 minor jobsystem fixes
- one version of run() ignored the flags parameter
- don't immediately signal created jobs in froxelizer
  to avoid redundant calls to signal()
2021-03-12 11:47:28 -08:00
Ben Doherty
fa7ad8d867 Fix dominant light shadows in Metal and Vulkan (#3631) 2021-03-12 10:08:33 -08:00
Mathias Agopian
834b774128 Fixes some issues with imported rendertargets
We were not declaring the attachments it was using.

Fixes #3628
2021-03-12 08:26:16 -08:00
Philip Rideout
eb40fa753f gltfio: Fix tangents when morphing is enabled.
The vertex data for glTF morph targets are deltas rather than final
values, so we were passing incorrect data into the SurfaceOrientation
helper.

This has been a long-standing bug that affected models with morphing,
including Buster Drone. However in practice we have observed visual
issues only with AnimatedMorphCube.

Tested against AnimatedMorphCube, Buster Drone, Cesium Man, Fox, and
Littlest Tokyo.

Fixes #1609
2021-03-11 14:09:52 -08:00
Mathias Agopian
dc36b228d6 Fixes some issues with imported rendertargets
We were not declaring the attachments it was using.

Fixes #3628
2021-03-11 14:06:26 -08:00
Philip Rideout
11e3eff009 Update TypeScript bindings. 2021-03-11 10:28:44 -08:00
Philip Rideout
52abe75cfd RemoteServer code cleanup and logcat cleanup.
This fixes two different logcat messages that would occur when scrubbing
a slider in the UI:

- "Discarding message, message queue overflow."
- "Downloading model..." would repeat itself needlessly
2021-03-11 07:52:32 -08:00
Romain Guy
8065d18f54 Update release notes 2021-03-10 16:15:18 -08:00
Philip Rideout
1b3684933d Repair WebGL build. 2021-03-10 16:01:29 -08:00
Mathias Agopian
e657921b5a Camera API improvements
- Add a "shift" parameter to Camera. This has the effect of translating
  the viewport, without changing its size. 
  This is an effect similar to using a shift lens.

- Camera::setScaling() now takes a double2 instead of double4, this is
  because scaling the result of the projection in the Z direction 
  can lead to very confusing problems -- it will essentially move the
  near/far planes, and we don't want to expose that as a public API.

- setCustomProjection() now allows to set a different projection for
  rendering and culling (useful for e.g. for using an infinite far 
  rendering projection matrix).
2021-03-10 16:01:29 -08:00
Seth Vargo
91ce5c785b Improve Actions hygiene (#3630)
Only run GitHub Actions for pushes and PRs against the main branch of the repository.
2021-03-10 15:02:16 -08:00
Philip Rideout
676b0542c4 sample-gltf-viewer: fix ColorGrading JNI assert 2021-03-10 11:14:31 -08:00
Philip Rideout
dced766999 Update Remote Control page. 2021-03-10 10:51:19 -08:00
Philip Rideout
eb0b5d16bf Migrate ColorGrading to SimpleViewer. 2021-03-10 09:27:51 -08:00
Mathias Agopian
2845f37ac7 improve CoC computation comment 2021-03-09 22:21:28 -08:00
Mathias Agopian
922ce83f48 add the --split-view option to gltf_viewer
useful for debugging shadows problems
2021-03-09 10:48:23 -08:00
Mathias Agopian
7445d80202 Improve circle-of-confusion computation
- generously document the CoC computation

- rewrite the code so that the computation will work for any
  perspective projection matrix, instead of assuming
  an "infinite-far" projection.
2021-03-09 10:48:08 -08:00
Philip Rideout
4d6f3ad392 JsonSerializer: do not repeatedly re-construct ostringstream. 2021-03-08 15:13:01 -08:00
Philip Rideout
c4ac8a9f06 AutomationEngine can now be used as a remote control. 2021-03-08 10:32:06 -08:00
Philip Rideout
b554a68186 Remote page now has UI and pushes settings. 2021-03-08 10:32:06 -08:00
Philip Rideout
b7ad20249d Improve the Settings serialization API, expose to JS.
This not only makes it easier to expose to JavaScript, it also paves the
way for a much more efficient implementation.
2021-03-08 10:32:06 -08:00
Philip Rideout
65f4b600bc Polish up the Remote Control page. 2021-03-08 10:32:06 -08:00
Philip Rideout
03945b88c8 ImGuiHelper now manages the UI camera. 2021-03-08 10:32:06 -08:00
Philip Rideout
24583332a2 Add filagui and SimpleViewer to the WASM build. 2021-03-08 10:32:06 -08:00
Benjamin Doherty
5aa0eb9f9d Bump version to 1.9.16 2021-03-08 10:09:14 -08:00
Benjamin Doherty
d9a6e2e649 Merge branch 'rc/1.9.15' into release 2021-03-08 10:07:00 -08:00
Benjamin Doherty
ce26801a91 Update RELEASE_NOTES for 1.9.15 2021-03-08 10:06:30 -08:00
Benjamin Doherty
7fd5b65f3b Release Filament 1.9.15 2021-03-08 10:05:56 -08:00
Benjamin Doherty
cb823b16a1 Update RELEASE_NOTES for 1.9.15 2021-03-08 10:05:19 -08:00
Philip Rideout
61b1542468 Add new remote page to site. 2021-03-08 08:57:57 -08:00
Mathias Agopian
d740378277 More code size optimizations and bvecn fixes
MaterialInstance: generate versions of setParameter() methods that
are templated on the parameter sizeof(), which allows us to
coalesce implementations, e.g. vec4<float> and vec4<int> are now
the same. We make the compiler generate non-inline version of all
these methods, the typed version just call through, taking
advantage of the tail-call optimization in clang.


MaterialParser: improve code to avoid calling multiple methods that
all did more or less the same thing and were inlined.

PostProcessManager: use a loop to initialize the materials

ToneMapping: de-dup ACES implementation

And other more minor optimizations.


Fix alignment issues with setting booleans in UBOs
2021-03-05 10:59:30 -08:00
Philip Rideout
0815adf722 PostProcessManager: fix setMinMaxLevels for StructureMipmap. 2021-03-05 08:15:04 -08:00
Philip Rideout
ef1eacf22e PostProcessManager: fix setMinMaxLevels for StructureMipmap. 2021-03-05 08:15:04 -08:00
Benjamin Doherty
fc896f81f0 Fix broken filamat lite build 2021-03-04 10:09:26 -08:00
Ben Doherty
884d5c1b87 Make material compilation deterministic (#3610)
With multithreaded variant compilation, compiled materials differ based on which variants finish first. This change ensures that compiled materials are always bit-for-bit identical.

This is helpful when comparing two compiled materials. Hashing the material files can be used to check for equality. It's also convenient for variants to occupy the same index when using matinfo's --print-glsl flag, for example.
2021-03-03 16:55:35 -08:00
Romain Guy
627186abc8 Update incorrect documentation (#3608) 2021-03-03 14:42:47 -08:00
Philip Rideout
30b0f39a36 sample-gltf-viewer: add polish to the drag-and-drop feature. 2021-03-03 14:41:22 -08:00
Philip Rideout
c3c2a732cd gltfio: Add ResourceLoader evict API. 2021-03-03 14:41:22 -08:00
Philip Rideout
5cc8ebd3e1 gltfio: fix ResourceLoader cache bug. 2021-03-03 14:41:22 -08:00
Philip Rideout
9ceb3b016c sample-gltf-viewer: add drag-and-drop feature.
This adds a WebSockets server to filament-utils-android.

Unlike my first attempt (#3599), this does not use a piping server and
is therefore much faster to use over a LAN. It also has lower user
friction because there is no need to touch a button in the app or
scan a QR code.
2021-03-03 14:41:22 -08:00
Philip Rideout
76e18475d3 gltf_viewer: avoid writeJson when automation is off. 2021-03-03 12:10:42 -08:00
Philip Rideout
2964e99175 sample-gltf-viewer: add URL hint. 2021-03-03 12:10:42 -08:00
Mathias Agopian
1189c9e294 FrameGraph rewrite from the ground up
The main goal of this rewrite was to make the code
simpler and easier to maintain.

The API is mostly unchanged, however there are some differences.
- we now have the concept of subresources, e.g. for Textures, as
  subresource is a mip level or layer.
- RenderTargets are no longer resources, instead they are transiant
  objects associated to a pass and are now called RenderPasses.
- RenderPasses take subresources for attachments.
- We have better validation of graph building.

We should also compute discard flags more accurately.
2021-03-02 22:25:56 -08:00
Philip Rideout
50799f3760 Replace QR code page with something better. 2021-03-02 18:36:38 -08:00
Philip Rideout
4b580b6eb1 Add automation to Android build, change PNG to PPM.
This adds libs/viewer to filament-utils-android and provides JNI
bindings for AutomationEngine.

This commit also changes the AutomationEngine to use PPM for screenshots
rather than PNG. The reasoning is that it is wasteful to include stb and
our two image-related libraries just to dump screenshots, especially for
a feature we might not use on Android.
2021-03-02 10:41:06 -08:00
Ben Doherty
8d6e794486 Remove exceptions on iOS (#3600) 2021-03-02 10:38:19 -08:00
Benjamin Doherty
ecc3e73967 Bump version to 1.9.15 2021-03-01 11:13:44 -08:00
Benjamin Doherty
7fa2053c55 Update RELEASE_NOTES for 1.9.14 2021-03-01 11:11:15 -08:00
Benjamin Doherty
cb7f81ccd6 Release Filament 1.9.14 2021-03-01 11:10:46 -08:00
Philip Rideout
6227496478 Update MoltenVK to 1.1.2 2021-03-01 09:42:23 -08:00
Philip Rideout
74aa7d3c87 Add QRCode page for glTF files. 2021-02-28 17:59:53 -08:00
Ben Doherty
bc107e7def Downgrade Linux GitHub Actions environment to fix error (#3588) 2021-02-26 17:00:56 -08:00
Ben Doherty
09e05ae00d Label Metal render encoders with group markers (#3583) 2021-02-26 10:37:34 -08:00
Philip Rideout
1921536f90 filamat: Fix data race with SPIRV error registrations. 2021-02-24 10:17:51 -08:00
Philip Rideout
1a9334e818 Modernize Python print syntax. 2021-02-23 14:43:30 -08:00
Mathias Agopian
bc6acd5c5a GL backend: fix race condition when asserting a handle exists 2021-02-22 23:25:43 -08:00
Mathias Agopian
3a15756c78 GL backend: track handles lifetime in debug builds 2021-02-22 17:22:18 -08:00
Mathias Agopian
f1fd96983b assert_invariant() now terminates the program in failure
rename logAndPanic to panicLog, since it doesn't actually panics.
2021-02-22 14:57:41 -08:00
1233 changed files with 84958 additions and 16949 deletions

View File

@@ -1,6 +1,12 @@
name: Presubmit
on: [pull_request]
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build-desktop:

View File

@@ -96,6 +96,20 @@ jobs:
- name: Run build script
run: |
cd build/android && printf "y" | ./build.sh release
- name: Sign sample-gltf-viewer
run: |
echo "${APK_KEYSTORE_BASE64}" > filament.jks.base64
base64 --decode filament.jks.base64 > filament.jks
BUILD_TOOLS_VERSION=$(ls ${ANDROID_HOME}/build-tools | sort -V | tail -n 1)
APKSIGNER=${ANDROID_HOME}/build-tools/${BUILD_TOOLS_VERSION}/apksigner
IN_FILE="out/sample-gltf-viewer-release.apk"
OUT_FILE="out/filament-gltf-viewer-${TAG}-android.apk"
${APKSIGNER} sign --ks filament.jks --key-pass=pass:${APK_KEYSTORE_PASS} --ks-pass=pass:${APK_KEYSTORE_PASS} --in ${IN_FILE} --out ${OUT_FILE}
rm "${IN_FILE}"
env:
TAG: ${{ steps.git_ref.outputs.tag }}
APK_KEYSTORE_BASE64: ${{ secrets.APK_KEYSTORE_BASE64 }}
APK_KEYSTORE_PASS: ${{ secrets.APK_KEYSTORE_PASS }}
- name: Upload release assets
run: |
pip3 install setuptools
@@ -107,7 +121,7 @@ jobs:
mv out/gltfio-android-lite-release.aar out/gltfio-${TAG}-lite-android.aar
mv out/filament-utils-android-release.aar out/filament-utils-${TAG}-android.aar
mv out/filament-utils-android-lite-release.aar out/filament-utils-${TAG}-lite-android.aar
python3 build/common/upload-assets.py ${TAG} out/*.aar
python3 build/common/upload-assets.py ${TAG} out/*.aar out/*.apk
env:
TAG: ${{ steps.git_ref.outputs.tag }}
GITHUB_API_KEY: ${{ secrets.GITHUB_API_KEY }}

View File

@@ -4,9 +4,9 @@
To build Filament, you must first install the following tools:
- CMake 3.10 (or more recent)
- CMake 3.19 (or more recent)
- clang 7.0 (or more recent)
- [ninja 1.8](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) (or more recent)
- [ninja 1.10](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) (or more recent)
To build the Java based components of the project you can optionally install (recommended):
@@ -17,9 +17,9 @@ section below.
To build Filament for Android you must also install the following:
- Android Studio 4.1.0 or more recent
- Android Studio 4.2.0 or more recent
- Android SDK
- Android NDK "side-by-side" 22.0 or higher
- Android NDK "side-by-side" 22.1 or higher
### Environment variables
@@ -84,6 +84,7 @@ The following CMake options are boolean options specific to Filament:
- `FILAMENT_ENABLE_JAVA`: Compile Java projects: requires a JDK and the JAVA_HOME env var
- `FILAMENT_ENABLE_LTO`: Enable link-time optimizations if supported by the compiler
- `FILAMENT_BUILD_FILAMAT`: Build filamat and JNI buildings
- `FILAMENT_SUPPORTS_OPENGL`: Include the OpenGL backend
- `FILAMENT_SUPPORTS_METAL`: Include the Metal backend
- `FILAMENT_SUPPORTS_VULKAN`: Include the Vulkan backend
- `FILAMENT_INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
@@ -375,7 +376,7 @@ same version that our continuous builds use.
```
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/2.0.12.zip > emsdk.zip
curl -L https://github.com/emscripten-core/emsdk/archive/2.0.23.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
python ./emsdk.py install latest
python ./emsdk.py activate latest

View File

@@ -1,7 +1,7 @@
# ==================================================================================================
# CMake
# ==================================================================================================
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.19)
# ==================================================================================================
# Project declaration
@@ -25,6 +25,10 @@ option(FILAMENT_SUPPORTS_XCB "Include XCB support in Linux builds" ON)
option(FILAMENT_SUPPORTS_XLIB "Include XLIB support in Linux builds" ON)
set(FILAMENT_NDK_VERSION "" CACHE STRING
"Android NDK version or version prefix to be used when building for Android."
)
set(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB "2" CACHE STRING
"Per render pass arena size. Must be roughly 1 MB larger than FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, default 2."
)
@@ -299,7 +303,7 @@ endif()
# On Android RELEASE builds, we disable exceptions and RTTI to save some space (about 75 KiB
# saved by -fno-exception and 10 KiB saved by -fno-rtti).
if (ANDROID OR WEBGL)
if (ANDROID OR IOS OR WEBGL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
endif()
@@ -365,6 +369,12 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebIn
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTNT_DEV")
endif()
# By default, build with support for OpenGL on all platforms.
option(FILAMENT_SUPPORTS_OPENGL "Include the OpenGL backend" ON)
if (FILAMENT_SUPPORTS_OPENGL)
add_definitions(-DFILAMENT_SUPPORTS_OPENGL)
endif()
# By default, build with Vulkan support on desktop platforms, although clients must request to use
# it at run time.
if (WIN32 OR WEBGL OR IOS)
@@ -400,6 +410,13 @@ else()
option(FILAMENT_ENABLE_MATDBG "Enable the material debugger" OFF)
endif()
# Only optimize materials in Release mode (so error message lines match the source code)
if (CMAKE_BUILD_TYPE MATCHES Release)
option(FILAMENT_DISABLE_MATOPT "Disable material optimizations" OFF)
else()
option(FILAMENT_DISABLE_MATOPT "Disable material optimizations" ON)
endif()
# ==================================================================================================
# Material compilation flags
# ==================================================================================================
@@ -413,9 +430,9 @@ 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_OPENGL)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a opengl)
endif()
if (FILAMENT_SUPPORTS_VULKAN)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a vulkan)
endif()
@@ -423,8 +440,7 @@ 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)
if (FILAMENT_DISABLE_MATOPT)
set(MATC_OPT_FLAGS -g)
endif()
@@ -443,11 +459,15 @@ if (NOT DIST_ARCH)
if (CMAKE_OSX_ARCHITECTURES MATCHES ".*;.*")
set(DIST_ARCH "universal")
else()
if (NOT CMAKE_OSX_ARCHITECTURES STREQUAL "")
if (NOT "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
set(DIST_ARCH "${CMAKE_OSX_ARCHITECTURES}")
endif()
endif()
endif()
# On Windows machines, the host processor is set to 'AMD64', which we'll interpret as x86_64.
string(TOLOWER "${DIST_ARCH}" DIST_ARCH)
string(REPLACE "amd64" "x86_64" DIST_ARCH "${DIST_ARCH}")
if (NOT DIST_DIR)
set(DIST_DIR "${DIST_ARCH}")
endif()
@@ -572,23 +592,29 @@ add_subdirectory(${EXTERNAL}/libgtest/tnt)
add_subdirectory(${LIBRARIES}/camutils)
add_subdirectory(${LIBRARIES}/filabridge)
add_subdirectory(${LIBRARIES}/filaflat)
add_subdirectory(${LIBRARIES}/filagui)
add_subdirectory(${LIBRARIES}/filameshio)
add_subdirectory(${LIBRARIES}/geometry)
add_subdirectory(${LIBRARIES}/gltfio)
add_subdirectory(${LIBRARIES}/ibl)
add_subdirectory(${LIBRARIES}/iblprefilter)
add_subdirectory(${LIBRARIES}/image)
add_subdirectory(${LIBRARIES}/math)
add_subdirectory(${LIBRARIES}/mathio)
add_subdirectory(${LIBRARIES}/utils)
add_subdirectory(${LIBRARIES}/viewer)
add_subdirectory(${FILAMENT}/filament)
add_subdirectory(${FILAMENT}/shaders)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/hat-trie/tnt)
add_subdirectory(${EXTERNAL}/imgui/tnt)
add_subdirectory(${EXTERNAL}/robin-map/tnt)
add_subdirectory(${EXTERNAL}/smol-v/tnt)
add_subdirectory(${EXTERNAL}/benchmark/tnt)
add_subdirectory(${EXTERNAL}/meshoptimizer)
add_subdirectory(${EXTERNAL}/cgltf/tnt)
add_subdirectory(${EXTERNAL}/draco/tnt)
add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
@@ -602,7 +628,6 @@ if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
# the material debugger requires filamat
if (FILAMENT_ENABLE_MATDBG OR IS_HOST_PLATFORM)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${LIBRARIES}/matdbg)
endif()
endif()
@@ -624,11 +649,11 @@ if (WEBGL)
endif()
if (IS_HOST_PLATFORM)
add_subdirectory(${LIBRARIES}/bluegl)
if (FILAMENT_SUPPORTS_OPENGL)
add_subdirectory(${LIBRARIES}/bluegl)
endif()
add_subdirectory(${LIBRARIES}/filamentapp)
add_subdirectory(${LIBRARIES}/filagui)
add_subdirectory(${LIBRARIES}/imageio)
add_subdirectory(${LIBRARIES}/viewer)
add_subdirectory(${FILAMENT}/java/filamat)
add_subdirectory(${FILAMENT}/java/filament)
@@ -638,8 +663,6 @@ if (IS_HOST_PLATFORM)
add_subdirectory(${EXTERNAL}/astcenc/tnt)
add_subdirectory(${EXTERNAL}/etc2comp)
add_subdirectory(${EXTERNAL}/imgui/tnt)
add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/libassimp/tnt)
add_subdirectory(${EXTERNAL}/libpng/tnt)
add_subdirectory(${EXTERNAL}/libsdl2/tnt)

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.9.14'
implementation 'com.google.android.filament:filament-android:1.10.5'
}
```
@@ -63,7 +63,7 @@ A much smaller alternative to `filamat-android` that can only generate OpenGL sh
iOS projects can use CocoaPods to install the latest release:
```
pod 'Filament', '~> 1.9.14'
pod 'Filament', '~> 1.10.5'
```
### Snapshots
@@ -131,6 +131,7 @@ Here are a few screenshots of applications that use Filament in production:
- Clustered forward renderer
- Cook-Torrance microfacet specular BRDF
- Lambertian diffuse BRDF
- Custom lighting/surface shading
- HDR/linear lighting
- Metallic workflow
- Clear coat
@@ -142,6 +143,7 @@ Here are a few screenshots of applications that use Filament in production:
- Physically-based camera (shutter speed, sensitivity and aperture)
- Physical light units
- Point lights, spot lights and directional light
- Specular anti-aliasing
- Spot and directional light shadows
- Cascaded shadows
- VSM or PCF shadows
@@ -149,13 +151,17 @@ Here are a few screenshots of applications that use Filament in production:
- Screen-space ambient occlusion
- Screen-space refraction
- Global fog
- Dynamic resolution
### Post processing
- HDR bloom
- Depth of field bokeh
- Multiple tone mappers: ACES, filmic, etc.
- Color grading: white balance, channel mixer, shadows/mid-tones/highlights, ASC CDL,
contrast, saturation, etc.
- TAA, FXAA, MSAA and specular anti-aliasing
- Dynamic resolution
- TAA, FXAA, MSAA
- Screen-space lens flares
### glTF 2.0

View File

@@ -39,7 +39,7 @@ build/common/bump-version.sh $RELEASE
Commit changes to main with the title:
```
Bump version to $RELEASE
Release Filament $RELEASE
```
Do not push to origin yet.
@@ -106,7 +106,9 @@ git push origin release
Use the GitHub UI to create a GitHub release corresponding to $RELEASE version.
Make sure the target is set to the release branch.
## 7. Delete the old rc branch.
## 7. Delete the old rc branch (optional).
This step is optional. The old rc branch may be left alive for a few weeks for posterity.
```
git push origin --delete rc/$RELEASE
@@ -134,5 +136,5 @@ git push origin main
## 10. Push the new rc branch.
```
git push origin rc/$NEXT_RELEASE
git push origin -u rc/$NEXT_RELEASE
```

View File

@@ -3,7 +3,186 @@
This file contains one line summaries of commits that are worthy of mentioning in release notes.
A new header is inserted each time a *tag* is created.
## Next release (main branch)
## v1.10.6 (currently main branch)
## v1.10.5
- android: AAR libraries now properly include their ProGuard rules.
- engine: User materials can now provide custom lighting/surface shading, please consult
the [materials documentation](https://google.github.io/filament/Materials.html) for details.
- engine: `Backend::DEFAULT` now selects the most appropriate backend for the platform, rather than
always `OPENGL`. On Android the default is `OPENGL`, on Apple platforms the default is `METAL` and
on all other platforms that default is `VULKAN`.
- engine: Fix a potential memory corruption when using more than 4 render targets.
- engine: Fix a possible crash when bloom is enabled.
- engine: Fix and refactor support for S3TC + SRGB with OpenGL.
- engine: Fix automatic clearing of rendertargets.
- engine: Fix imported render target discard and clear flags.
- engine: Fix opaque blit with imported render targets.
## v1.10.4
- engine: improvements to internal job system.
- Vulkan: performance improvements on Mali.
- gltfio: improvements to load time for large models.
- WebGL: remove bogus stride argument, fix `BindingType` TypeScript definition.
## v1.10.3
- android: use `debug.filament.backend` system property to select the desired backend.
- engine: fix `LightManager::getFalloff`.
- gltfio: fix crash with non-triangles.
- macOS: fix main thread checker warnings with OpenGL.
- vulkan: fix crash on Windows machines with NVIDIA GPUs.
## v1.10.2
- Vulkan: validation and diagnostic improvements
- engine: improvements for scenes with many renderables.
- gltfio: added support for `KHR_materials_ior`.
- java: Add bindings for `IBLPrefilterContext`.
- java: add `KTXLoader.getSphericalHarmonics` JNI binding
- libimage: fix, respect sRGB option for compressed formats.
- sample-gltf-viewer: fix lifetime cycle for RemoteServer.
## v1.10.1
- engine: Add `getPlatform` API to Engine.
- engine: Add a new cone angles API to `LightManager`.
- engine: Attachments of custom RendereTargets are not systematically discarded.
- engine: Fix a crash when using custom rendertargets.
- engine: New API to duplicate a `MaterialInstance`.
- filagui: fix support for custom images in ImGuiHelper.
- java: Add bindings for HDRLoader.
## v1.10.0
- engine: User materials can now use 9 samplers instead of 8 [⚠️ **Material breakage**].
- engine: Remove `populateTangentQuaternions` [⚠️ **API change**].
- engine: Deprecate `Stream::Builder::stream(intptr_t)` [⚠️ **API Change**].
- engine: Remove deprecated APIs: `Camera::setScaling`, `Engine::destroy(Camera*)`,
`Engine::createCamera`, `Renderer::beginFrame(SwapChain*, uint64_t,
backend::FrameScheduledCallback, void*)`, and `View::setShadowsEnabled` [⚠️ **API Change**].
- engine: Remove `focusDistance` from `View::BloomOptions` [⚠️ **API Change**].
- engine: Add a `FILAMENT_SUPPORTS_OPENGL` CMake option to enable/disable OpenGL support.
- Vulkan: fixes and improvements for large scenes.
- gltfio: fix morphing bugs uncovered by MorphStressTest.
- Java: add API for `Texture::Builder::import()`.
- WebGL: Fix a potential INVALID_OPERATION.
## v1.9.25
- NEW API: Screen-space lens flare effect.
- engine: Fix several memory leaks in the GL backend.
- Vulkan: General bug fixes and improvements.
- Vulkan: Fix some problems seen on Mali devices.
- ios: Fix VSM shadows not working.
- webgl: Fix black screen seen with some samples.
## v1.9.24
- engine: Fix memory leaks in OpenGL driver.
- engine: new experimental tone mapper, `EVILS` (name will most likely change).
- engine: Improvements to Vulkan backend.
- engine: Fix incorrect units documented for `LightManager.getIntensity`.
- engine: fix high quality upsampling for SSAO.
- engine: implement accurate normal reconstruction for SSAO.
- engine: improve LOW and HIGH quality levels for SSAO.
- libs: improvements to `libiblprefilter`.
- materials: New `quality` property.
- samples: Add new gltf-viewer iOS sample.
- samples: clear the background in lightbulb sample.
## v1.9.23
- Vulkan: various fixes.
- android: fix crash seen using VSM with MSAA on Adreno devices.
- engine: Add `Engine::getEntityManager()`.
- engine: Fix desktop crash seen with some GPU drivers.
- engine: improve importance sampling.
- gltfio: robustness improvements for Draco meshes.
- libs: Add new Transcoder API for C++ clients (part of `libgeometry`).
- libs: New `iblprefilter` library to compute IBL pre-integration on the GPU using filament.
- materials: Fix documentation for `getNormalizedViewportCoord`.
- samples: fix rendertarget sample crash on launch.
## v1.9.22
- NEW API: `Renderer::renderStandaloneView()` is a new method that can be used outside of
beginFrame/endFrame on Views that have a RenderTarget associated. This can be used as a
pseudo-compute API.
- Vulkan: bug fixes and improvements.
- engine: RenderTarget API can now use MRT.
- sample-gltf-viewer: improvements for reading zip files.
- sample-gltf-viewer: enable contact-shadows functionality in mobile gltf-viewer.
- windows: fix build error in filament_framegraph_test.
## v1.9.21
- JavaScript: add missing TextureSampler bindings.
- Metal: Fix texture swizzling crash with older Nvidia GPUs.
- Vulkan: fix image layout validation error on Android.
- android: fix MSAA w/ multisampled_render_to_texture on Mali.
- engine: better anisotropic filtering with various drivers.
- gltfio: Use BufferObject API, simplify MorphHelper.
- gltfio: honor stride in normalizeSkinningWeights.
- samples: Add web component demo.
## v1.9.20
- Android: Fix VSM.
- engine: Introduce BufferObject API.
- engine: Add new isTextureSwizzleSupported API on Texture.
- engine: Add support to Metal and Vulkan backends for texture swizzling.
- engine: Add new DoF settings (native/half res, gather kernel ring counts, CoC radius clamp).
- engine: DoF quality and performance improvements.
- engine: Fix high-quality upsampling issue with SSAO.
- Java: Expose `TransformManager.getParent(int)`.
- samples: Add Metal and Vulkan backend support to Suzanne sample.
- WebGL: expose fitIntoUnitCube to JS.
- WebGL: support for multiple `<canvas>` elements.
## v1.9.19
- engine: Fix Metal bug when setGeometryAt is called multiple times.
- engine: Improvements to DoF.
- engine: Fix RenderTarget NPE when depth is not present.
- engine: Improvements to Camera APIs. Move focus distance from DofOptions to Camera.
- engine: VSM shadows now support `shadowMultiplier`.
- java: Expose severla MaterialInstance APIs (setColorWrite, setDepthWrite, setDepthCulling) that
should have been public.
- java: fix bug with Texture::setImage buffer size calculation.
## v1.9.18
- engine: Fix a DoF bug that caused black dots around the fast tiles.
- engine: Minor DoF optimizations.
- engine: Fix blanking windows not being drawn into on macOS.
- gltfio: Add support for data:// in image URI's.
- gltfio: Add internal MorphHelper, enable up to 255 targets.
- engine: Fix a hang in JobSystem.
- samples: Fix rendertarget sample app.
## v1.9.17
- engine: New shift parameter on `Camera` to translate the viewport and emulate a tilt/shift lens.
- engine: `Camera::setCustomProjection()` now allows to set a different projection for culling and rendering.
- engine: Fixed depth of field rendering with custom projection matrices.
- engine: Fix a rare indefinite hang.
- gltfio: `SimpleViewer` now exposes more rendering parameters, including `ColorGrading`.
- gltfio: Fix tangents when morphing is enabled.
- Metal/Vulkan: fix incorrect dominant light shadows rendering.
- Fixe some issues with imported rendertargets.
## v1.9.16
gltfio: Add ResourceLoader evict API.
gltfio: Fix ResourceLoader cache bug.
iOS: Disable exceptions to reduce binary size.
## v1.9.15
- filamat/matc: fix sporadic crash.
## v1.9.14

View File

@@ -64,9 +64,9 @@ buildscript {
'minSdk': 19,
'targetSdk': 30,
'compileSdk': 30,
'kotlin': '1.4.30',
'kotlin': '1.5.0',
'buildTools': '30.0.3',
'ndk': '22.0.7026061'
'ndk': '22.1.7171670'
]
ext.deps = [
@@ -78,7 +78,7 @@ buildscript {
]
dependencies {
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'com.android.tools.build:gradle:4.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}
@@ -116,7 +116,6 @@ buildscript {
repositories {
mavenCentral()
google()
jcenter()
}
}
@@ -138,7 +137,6 @@ subprojects {
repositories {
mavenCentral()
google()
jcenter()
}
if (!name.startsWith("sample")) {
@@ -163,11 +161,13 @@ subprojects {
ndk {
abiFilters(*rootProject.ext.abis)
}
}
consumerProguardFiles '../proguard-rules.pro'
}
externalNativeBuild {
cmake {
version "3.19.0+"
path "CMakeLists.txt"
}
}

View File

@@ -19,8 +19,11 @@ import org.gradle.api.file.FileType
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.logging.LogLevel
import org.gradle.api.logging.Logger
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.incremental.InputFileDetails
@@ -33,24 +36,23 @@ import java.nio.file.Paths
class TaskWithBinary extends DefaultTask {
private final String binaryName
private File binaryPath = null
private Property<String> binaryPath = null
TaskWithBinary(String name) {
binaryName = name
}
String getBinaryName() {
return binaryName
}
File getBinary() {
@Input
Property<String> getBinary() {
if (binaryPath == null) {
def tool = ["/bin/${binaryName}.exe", "/bin/${binaryName}"]
def fullPath = tool.collect { path ->
Paths.get(project.ext.filamentToolsPath.absolutePath, path).toFile()
}
binaryPath = OperatingSystem.current().isWindows() ? fullPath[0] : fullPath[1]
binaryPath = project.objects.property(String.class)
binaryPath.set(
(OperatingSystem.current().isWindows() ? fullPath[0] : fullPath[1]).toString())
}
return binaryPath
}
@@ -65,14 +67,6 @@ class LogOutputStream extends ByteArrayOutputStream {
this.level = level
}
Logger getLogger() {
return logger
}
LogLevel getLevel() {
return level
}
@Override
void flush() {
logger.log(level, toString())
@@ -85,10 +79,10 @@ class LogOutputStream extends ByteArrayOutputStream {
abstract class MaterialCompiler extends TaskWithBinary {
@Incremental
@InputDirectory
final DirectoryProperty inputDir = project.objects.directoryProperty()
abstract DirectoryProperty getInputDir()
@OutputDirectory
final DirectoryProperty outputDir = project.objects.directoryProperty()
abstract DirectoryProperty getOutputDir()
MaterialCompiler() {
super("matc")
@@ -115,8 +109,8 @@ abstract class MaterialCompiler extends TaskWithBinary {
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
if (!new File(binary.get()).exists()) {
throw new GradleException("Could not find ${binary.get()}." +
" Ensure Filament has been built/installed before building this app.")
}
@@ -129,7 +123,7 @@ abstract class MaterialCompiler extends TaskWithBinary {
project.exec {
standardOutput out
errorOutput err
executable "${getBinary()}"
executable "${binary.get()}"
args matcArgs
}
}
@@ -143,15 +137,17 @@ abstract class MaterialCompiler extends TaskWithBinary {
// Custom task to process IBLs using cmgen
// This task handles incremental builds
class IblGenerator extends TaskWithBinary {
String cmgenArgs = null
abstract class IblGenerator extends TaskWithBinary {
@Input
@Optional
abstract Property<String> getCmgenArgs()
@Incremental
@InputFile
final RegularFileProperty inputFile = project.objects.fileProperty()
abstract RegularFileProperty getInputFile()
@OutputDirectory
final DirectoryProperty outputDir = project.objects.directoryProperty()
abstract DirectoryProperty getOutputDir()
IblGenerator() {
super("cmgen")
@@ -178,23 +174,25 @@ class IblGenerator extends TaskWithBinary {
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
if (!new File(binary.get()).exists()) {
throw new GradleException("Could not find ${binary.get()}." +
" Ensure Filament has been built/installed before building this app.")
}
def outputPath = outputDir.get().asFile
def commandArgs = cmgenArgs.getOrNull()
if (commandArgs == null) {
commandArgs =
'-q -x ' + outputPath + ' --format=rgb32f ' +
'--extract-blur=0.08 --extract=' + outputPath.absolutePath
}
commandArgs = commandArgs + " " + file
project.exec {
standardOutput out
if (!cmgenArgs) {
cmgenArgs =
'-q -x ' + outputPath + ' --format=rgb32f ' +
'--extract-blur=0.08 --extract=' + outputPath.absolutePath
}
cmgenArgs = cmgenArgs + " " + file
errorOutput err
executable "${getBinary()}"
args(cmgenArgs.split())
executable "${binary.get()}"
args(commandArgs.split())
}
}
}
@@ -207,13 +205,13 @@ class IblGenerator extends TaskWithBinary {
// Custom task to compile mesh files using filamesh
// This task handles incremental builds
class MeshCompiler extends TaskWithBinary {
abstract class MeshCompiler extends TaskWithBinary {
@Incremental
@InputFile
final RegularFileProperty inputFile = project.objects.fileProperty()
abstract RegularFileProperty getInputFile()
@OutputDirectory
final DirectoryProperty outputDir = project.objects.directoryProperty()
abstract DirectoryProperty getOutputDir()
MeshCompiler() {
super("filamesh")
@@ -240,15 +238,15 @@ class MeshCompiler extends TaskWithBinary {
out.write(header)
out.flush()
if (!getBinary().exists()) {
throw new GradleException("Could not find ${getBinary()}." +
if (!new File(binary.get()).exists()) {
throw new GradleException("Could not find ${binary.get()}." +
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
standardOutput out
errorOutput err
executable "${getBinary()}"
executable "${binary.get()}"
args(file, getOutputFile(file))
}
}
@@ -291,8 +289,8 @@ class FilamentToolsPlugin implements Plugin<Project> {
enabled =
extension.materialInputDir.isPresent() &&
extension.materialOutputDir.isPresent()
inputDir = extension.materialInputDir.getOrNull()
outputDir = extension.materialOutputDir.getOrNull()
inputDir.set(extension.materialInputDir.getOrNull())
outputDir.set(extension.materialOutputDir.getOrNull())
}
project.preBuild.dependsOn "filamentCompileMaterials"

View File

@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.19)
project(filamat-android)
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)

View File

@@ -291,6 +291,13 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderFlipUV(
builder->flipUV(flipUV);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderCustomSurfaceShading(JNIEnv*,
jclass, jlong nativeBuilder, jboolean customSurfaceShading) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->customSurfaceShading(customSurfaceShading);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderMultiBounceAmbientOcclusion(
JNIEnv*, jclass, jlong nativeBuilder, jboolean multiBounceAO) {

View File

@@ -391,6 +391,12 @@ public class MaterialBuilder {
return this;
}
@NonNull
public MaterialBuilder customSurfaceShading(boolean customSurfaceShading) {
nMaterialBuilderCustomSurfaceShading(mNativeObject, customSurfaceShading);
return this;
}
@NonNull
public MaterialBuilder multiBounceAmbientOcclusion(boolean multiBounceAO) {
nMaterialBuilderMultiBounceAmbientOcclusion(mNativeObject, multiBounceAO);
@@ -556,6 +562,8 @@ public class MaterialBuilder {
private static native void nMaterialBuilderClearCoatIorChange(long mNativeObject,
boolean clearCoatIorChange);
private static native void nMaterialBuilderFlipUV(long nativeBuilder, boolean flipUV);
private static native void nMaterialBuilderCustomSurfaceShading(long nativeBuilder,
boolean customSurfaceShading);
private static native void nMaterialBuilderMultiBounceAmbientOcclusion(long nativeBuilder,
boolean multiBounceAO);
private static native void nMaterialBuilderSpecularAmbientOcclusion(long nativeBuilder,

View File

@@ -1,7 +1,9 @@
cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.19)
project(filament-android)
option(FILAMENT_SUPPORTS_VULKAN "Enables Vulkan on Android" OFF)
option(FILAMENT_ENABLE_MATDBG "Enables Material debugger" OFF)
option(FILAMENT_DISABLE_MATOPT "Disables material optimizations" OFF)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
@@ -55,6 +57,7 @@ set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libfilament-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
add_library(filament-jni SHARED
src/main/cpp/BufferObject.cpp
src/main/cpp/Camera.cpp
src/main/cpp/Colors.cpp
src/main/cpp/ColorGrading.cpp
@@ -95,7 +98,6 @@ target_link_libraries(filament-jni
PRIVATE backend
PRIVATE filaflat
PRIVATE filabridge
PRIVATE geometry
PRIVATE ibl-lite
PRIVATE log
PRIVATE GLESv3
@@ -103,6 +105,10 @@ target_link_libraries(filament-jni
PRIVATE android
PRIVATE jnigraphics
PRIVATE utils
# libgeometry is PUBLIC because gltfio uses it.
PUBLIC geometry
$<$<STREQUAL:${FILAMENT_ENABLE_MATDBG},ON>:matdbg>
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:bluevk>
$<$<STREQUAL:${FILAMENT_SUPPORTS_VULKAN},ON>:vkshaders>

View File

@@ -2,7 +2,9 @@ LIBFILAMENT {
global:
Java_com_google_android_filament_*;
JNI*;
*filament*BufferObject*;
*filament*Camera*;
*filament*Color*;
*filament*Exposure*;
*filament*Skybox*;
*filament*Engine*;
@@ -10,10 +12,14 @@ LIBFILAMENT {
*filament*Aabb*;
*filament*IndirectLight*;
*filament*LightManager*;
*filament*Renderer*;
*filament*RenderTarget*;
*filament*Scene*;
*filament*Transform*;
*filament*Material*;
*filament*IndexBuffer*;
*filament*VertexBuffer*;
*filament*View*;
*filament*Texture*;
*filament*geometry*;

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2021 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/BufferObject.h>
#include <backend/BufferDescriptor.h>
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace backend;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_BufferObject_nCreateBuilder(JNIEnv *env, jclass type) {
return (jlong) new BufferObject::Builder();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_BufferObject_nDestroyBuilder(JNIEnv *env, jclass type,
jlong nativeBuilder) {
BufferObject::Builder* builder = (BufferObject::Builder *) nativeBuilder;
delete builder;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_BufferObject_nBuilderSize(JNIEnv *env, jclass type,
jlong nativeBuilder, jint byteCount) {
BufferObject::Builder* builder = (BufferObject::Builder *) nativeBuilder;
builder->size((uint32_t) byteCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_BufferObject_nBuilderBindingType(JNIEnv *env, jclass type,
jlong nativeBuilder, jint bindingType) {
using BindingType = BufferObject::BindingType;
BufferObject::Builder* builder = (BufferObject::Builder *) nativeBuilder;
BindingType types[] = {BindingType::VERTEX};
builder->bindingType(types[bindingType]);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_BufferObject_nBuilderBuild(JNIEnv *env, jclass type,
jlong nativeBuilder, jlong nativeEngine) {
BufferObject::Builder* builder = (BufferObject::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_BufferObject_nGetByteCount(JNIEnv *env, jclass type,
jlong nativeBufferObject) {
BufferObject *bufferObject = (BufferObject *) nativeBufferObject;
return (jint) bufferObject->getByteCount();
}
extern "C" JNIEXPORT int JNICALL
Java_com_google_android_filament_BufferObject_nSetBuffer(JNIEnv *env, jclass type,
jlong nativeBufferObject, jlong nativeEngine, jobject buffer, int remaining,
jint destOffsetInBytes, jint count,
jobject handler, jobject runnable) {
BufferObject *bufferObject = (BufferObject *) nativeBufferObject;
Engine *engine = (Engine *) nativeEngine;
AutoBuffer nioBuffer(env, buffer, count);
void* data = nioBuffer.getData();
size_t sizeInBytes = nioBuffer.getSize();
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
bufferObject->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
return 0;
}

View File

@@ -18,6 +18,8 @@
#include <filament/Camera.h>
#include <utils/Entity.h>
#include <math/mat4.h>
using namespace filament;
@@ -47,20 +49,31 @@ Java_com_google_android_filament_Camera_nSetLensProjection(JNIEnv*, jclass,
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetCustomProjection(JNIEnv *env, jclass,
jlong nativeCamera, jdoubleArray inMatrix_, jdouble near, jdouble far) {
jlong nativeCamera, jdoubleArray inProjection_, jdoubleArray inProjectionForCulling_,
jdouble near, jdouble far) {
Camera *camera = (Camera *) nativeCamera;
jdouble *inMatrix = env->GetDoubleArrayElements(inMatrix_, NULL);
camera->setCustomProjection(*reinterpret_cast<const filament::math::mat4 *>(inMatrix), near, far);
env->ReleaseDoubleArrayElements(inMatrix_, inMatrix, JNI_ABORT);
jdouble *inProjection = env->GetDoubleArrayElements(inProjection_, NULL);
jdouble *inProjectionForCulling = env->GetDoubleArrayElements(inProjectionForCulling_, NULL);
camera->setCustomProjection(
*reinterpret_cast<const filament::math::mat4 *>(inProjection),
*reinterpret_cast<const filament::math::mat4 *>(inProjectionForCulling),
near, far);
env->ReleaseDoubleArrayElements(inProjection_, inProjection, JNI_ABORT);
env->ReleaseDoubleArrayElements(inProjectionForCulling_, inProjectionForCulling, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetScaling(JNIEnv* env, jclass,
jlong nativeCamera, jdoubleArray inScaling_) {
jlong nativeCamera, jdouble x, jdouble y) {
Camera *camera = (Camera *) nativeCamera;
jdouble *inScaling = env->GetDoubleArrayElements(inScaling_, NULL);
camera->setScaling(*reinterpret_cast<const filament::math::double4*>(inScaling));
env->ReleaseDoubleArrayElements(inScaling_, inScaling, JNI_ABORT);
camera->setScaling({(double)x, (double)y});
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetShift(JNIEnv* env, jclass,
jlong nativeCamera, jdouble x, jdouble y) {
Camera *camera = (Camera *) nativeCamera;
camera->setShift({(double)x, (double)y});
}
extern "C" JNIEXPORT void JNICALL
@@ -205,3 +218,36 @@ Java_com_google_android_filament_Camera_nGetSensitivity(JNIEnv*, jclass,
Camera *camera = (Camera *) nativeCamera;
return camera->getSensitivity();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Camera_nSetFocusDistance(JNIEnv*, jclass,
jlong nativeCamera, jfloat focusDistance) {
Camera *camera = (Camera *) nativeCamera;
camera->setFocusDistance(focusDistance);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_Camera_nGetFocusDistance(JNIEnv*, jclass,
jlong nativeCamera) {
Camera *camera = (Camera *) nativeCamera;
return camera->getFocusDistance();
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_Camera_nGetFocalLength(JNIEnv*, jclass,
jlong nativeCamera) {
Camera *camera = (Camera *) nativeCamera;
return camera->getFocalLength();
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_Camera_nComputeEffectiveFocalLength(JNIEnv*, jclass,
jdouble focalLength, jdouble focusDistance) {
return Camera::computeEffectiveFocalLength(focalLength, focusDistance);
}
extern "C" JNIEXPORT jdouble JNICALL
Java_com_google_android_filament_Camera_nComputeEffectiveFov(JNIEnv*, jclass,
jdouble fovInDegrees, jdouble focusDistance) {
return Camera::computeEffectiveFov(fovInDegrees, focusDistance);
}

View File

@@ -16,6 +16,7 @@
#include <jni.h>
#include <filament/Camera.h>
#include <filament/Engine.h>
#include <utils/Entity.h>
@@ -120,15 +121,8 @@ Java_com_google_android_filament_Engine_nDestroyRenderer(JNIEnv*, jclass,
// Camera
extern "C" [[deprecated]] JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateCamera(JNIEnv*, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) engine->createCamera();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nCreateCameraWithEntity(JNIEnv*, jclass,
Java_com_google_android_filament_Engine_nCreateCamera(JNIEnv*, jclass,
jlong nativeEngine, jint entity_) {
Engine* engine = (Engine*) nativeEngine;
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
@@ -143,12 +137,12 @@ Java_com_google_android_filament_Engine_nGetCameraComponent(JNIEnv*, jclass,
return (jlong) engine->getCameraComponent(entity);
}
extern "C" [[deprecated]] JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyCamera(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeCamera) {
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nDestroyCameraComponent(JNIEnv*, jclass,
jlong nativeEngine, jint entity_) {
Engine* engine = (Engine*) nativeEngine;
Camera *camera = (Camera *) nativeCamera;
engine->destroy(camera);
Entity& entity = *reinterpret_cast<Entity*>(&entity_);
engine->destroyCameraComponent(entity);
}
// Scene
@@ -312,3 +306,9 @@ Java_com_google_android_filament_Engine_nGetJobSystem(JNIEnv*, jclass, jlong nat
Engine* engine = (Engine*) nativeEngine;
return (jlong) &engine->getJobSystem();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nGetEntityManager(JNIEnv*, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) &engine->getEntityManager();
}

View File

@@ -379,3 +379,17 @@ Java_com_google_android_filament_LightManager_nIsShadowCaster(JNIEnv*, jclass,
LightManager *lm = (LightManager *) nativeLightManager;
return (jboolean)lm->isShadowCaster((LightManager::Instance) i);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetOuterConeAngle(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return (jfloat)lm->getSpotLightOuterCone((LightManager::Instance) i);
}
extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_LightManager_nGetInnerConeAngle(JNIEnv*, jclass,
jlong nativeLightManager, jint i) {
LightManager *lm = (LightManager *) nativeLightManager;
return (jfloat)lm->getSpotLightInnerCone((LightManager::Instance) i);
}

View File

@@ -364,3 +364,19 @@ Java_com_google_android_filament_MaterialInstance_nGetMaterial(JNIEnv* env, jcla
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
return (jlong) instance->getMaterial();
}
extern "C"
JNIEXPORT jlong JNICALL
Java_com_google_android_filament_MaterialInstance_nDuplicate(JNIEnv* env, jclass clazz,
jlong otherNativeMaterialInstance, jstring name) {
MaterialInstance* other = (MaterialInstance*) otherNativeMaterialInstance;
const char *cstr = nullptr;
if (name != nullptr) {
cstr = env->GetStringUTFChars(name, nullptr);
}
MaterialInstance* mi = MaterialInstance::duplicate(other, cstr);
if (name != nullptr) {
env->ReleaseStringUTFChars(name, cstr);
}
return (jlong)mi;
}

View File

@@ -50,6 +50,14 @@ Java_com_google_android_filament_Renderer_nRender(JNIEnv *, jclass, jlong native
renderer->render(view);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nRenderStandaloneView(JNIEnv *, jclass, jlong nativeRenderer,
jlong nativeView) {
Renderer *renderer = (Renderer *) nativeRenderer;
View *view = (View *) nativeView;
renderer->renderStandaloneView(view);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nCopyFrame(JNIEnv *, jclass, jlong nativeRenderer,
jlong nativeDstSwapChain,

View File

@@ -102,7 +102,10 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Stream_nBuilderStream(JNIEnv*, jclass,
jlong nativeStreamBuilder, jlong externalTextureId) {
StreamBuilder* builder = (StreamBuilder*) nativeStreamBuilder;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
builder->builder()->stream(externalTextureId);
#pragma clang diagnostic pop
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -34,12 +34,13 @@
using namespace filament;
using namespace backend;
static size_t getTextureDataSize(const Texture *texture, size_t level,
Texture::Format format, Texture::Type type, size_t stride, size_t alignment) {
static size_t getTextureDataSize(const Texture *texture,
size_t level, Texture::Format format, Texture::Type type,
size_t stride, size_t height, size_t alignment) {
// Zero stride implies tight row-to-row packing.
stride = stride == 0 ? texture->getWidth(level) : std::max(size_t(1), stride >> level);
return Texture::computeTextureDataSize(format, type,
stride, texture->getHeight(level), alignment);
stride = stride == 0 ? texture->getWidth(level) : std::max(size_t(1), stride >> level);
height = height == 0 ? texture->getHeight(level) : std::max(size_t(1), height >> level);
return Texture::computeTextureDataSize(format, type, stride, height, alignment);
}
extern "C" JNIEXPORT jboolean JNICALL
@@ -50,6 +51,13 @@ Java_com_google_android_filament_Texture_nIsTextureFormatSupported(JNIEnv*, jcla
(Texture::InternalFormat) internalFormat);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Texture_nIsTextureSwizzleSupported(JNIEnv*, jclass,
jlong nativeEngine) {
Engine *engine = (Engine *) nativeEngine;
return (jboolean) Texture::isTextureSwizzleSupported(*engine);
}
// Texture::Builder...
extern "C" JNIEXPORT jlong JNICALL
@@ -121,6 +129,13 @@ Java_com_google_android_filament_Texture_nBuilderSwizzle(JNIEnv *, jclass ,
(Texture::Swizzle)r, (Texture::Swizzle)g, (Texture::Swizzle)b, (Texture::Swizzle)a);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_Texture_nBuilderImportTexture(JNIEnv*, jclass, jlong nativeBuilder, jlong id) {
Texture::Builder *builder = (Texture::Builder *) nativeBuilder;
builder->import((intptr_t)id);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Texture_nBuilderBuild(JNIEnv*, jclass,
jlong nativeBuilder, jlong nativeEngine) {
@@ -175,14 +190,14 @@ 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,
jobject storage, jint remaining,
jint left, jint bottom, jint type, jint alignment,
jint left, jint top, jint type, jint alignment,
jint stride, jint format,
jobject handler, jobject runnable) {
Texture* texture = (Texture*) nativeTexture;
Engine* engine = (Engine*) nativeEngine;
size_t sizeInBytes = getTextureDataSize(texture, (size_t) level, (Texture::Format) format,
(Texture::Type) type, (size_t) stride, (size_t) alignment);
(Texture::Type) type, (size_t) stride, (size_t) height, (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
@@ -194,7 +209,7 @@ Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong na
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) bottom,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
texture->setImage(*engine, (size_t) level, (uint32_t) xoffset, (uint32_t) yoffset,
@@ -239,14 +254,14 @@ Java_com_google_android_filament_Texture_nSetImage3D(JNIEnv* env, jclass, jlong
jint xoffset, jint yoffset, jint zoffset,
jint width, jint height, jint depth,
jobject storage, jint remaining,
jint left, jint bottom, jint type, jint alignment,
jint left, jint top, jint type, jint alignment,
jint stride, jint format,
jobject handler, jobject runnable) {
Texture* texture = (Texture*) nativeTexture;
Engine* engine = (Engine*) nativeEngine;
size_t sizeInBytes = getTextureDataSize(texture, (size_t) level, (Texture::Format) format,
(Texture::Type) type, (size_t) stride, (size_t) alignment);
(Texture::Type) type, (size_t) stride, (size_t) height, (size_t) alignment) * depth;
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
@@ -258,7 +273,7 @@ Java_com_google_android_filament_Texture_nSetImage3D(JNIEnv* env, jclass, jlong
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) bottom,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
texture->setImage(*engine, (size_t) level,
@@ -306,7 +321,7 @@ Java_com_google_android_filament_Texture_nSetImage3DCompressed(JNIEnv *env, jcla
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
jlong nativeTexture, jlong nativeEngine, jint level, jobject storage, jint remaining,
jint left, jint bottom, jint type, jint alignment, jint stride, jint format,
jint left, jint top, jint type, jint alignment, jint stride, jint format,
jintArray faceOffsetsInBytes_,
jobject handler, jobject runnable) {
Texture *texture = (Texture *) nativeTexture;
@@ -318,7 +333,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
env->ReleaseIntArrayElements(faceOffsetsInBytes_, faceOffsetsInBytes, JNI_ABORT);
size_t sizeInBytes = 6 * getTextureDataSize(texture, (size_t) level, (Texture::Format) format,
(Texture::Type) type, (size_t) stride, (size_t) alignment);
(Texture::Type) type, (size_t) stride, 0, (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
@@ -330,7 +345,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
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) bottom,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
@@ -341,7 +356,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env, jclass,
jlong nativeTexture, jlong nativeEngine, jint level, jobject storage, jint remaining,
jint left, jint bottom, jint type, jint alignment,
jint left, jint top, jint type, jint alignment,
jint compressedSizeInBytes, jint compressedFormat, jintArray faceOffsetsInBytes_,
jobject handler, jobject runnable) {

View File

@@ -86,6 +86,13 @@ Java_com_google_android_filament_TransformManager_nSetParent(JNIEnv*, jclass,
(TransformManager::Instance) newParent);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TransformManager_nGetParent(JNIEnv*, jclass,
jlong nativeTransformManager, jint i) {
TransformManager* tm = (TransformManager*) nativeTransformManager;
return tm->getParent((TransformManager::Instance) i).getId();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_TransformManager_nSetTransform(JNIEnv* env,
jclass, jlong nativeTransformManager, jint i,

View File

@@ -50,6 +50,13 @@ Java_com_google_android_filament_VertexBuffer_nBuilderVertexCount(JNIEnv *env, j
builder->vertexCount((uint32_t) vertexCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderEnableBufferObjects(JNIEnv *env, jclass type,
jlong nativeBuilder, jboolean enabled) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
builder->enableBufferObjects(enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderBufferCount(JNIEnv *env, jclass type,
jlong nativeBuilder, jint bufferCount) {
@@ -115,42 +122,11 @@ Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass t
return 0;
}
extern "C" [[deprecated]] JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nPopulateTangentQuaternions(JNIEnv *env,
jclass type, jint quatType, jint quatCount, jobject outBuffer, jint outRemaining,
jint outStride, jobject normals, jint normalsRemaining, jint normalsStride,
jobject tangents, jint tangentsRemaining, jint tangentsStride) {
AutoBuffer outNioBuffer(env, outBuffer, outRemaining, true);
void* outData = outNioBuffer.getData();
AutoBuffer normalsNioBuffer(env, normals, normalsRemaining);
auto normalsData = (const float3*) normalsNioBuffer.getData();
if (tangents) {
AutoBuffer tangentsNioBuffer(env, tangents, tangentsRemaining);
auto tangentsData = (const float4*) tangentsNioBuffer.getData();
VertexBuffer::populateTangentQuaternions({
.quatType = (VertexBuffer::QuatType) quatType,
.quatCount = (size_t) quatCount,
.outBuffer = outData,
.outStride = (size_t) outStride,
.normals = normalsData,
.normalsStride = (size_t) normalsStride,
.tangents = tangentsData,
.tangentsStride = (size_t) tangentsStride
});
return;
}
VertexBuffer::populateTangentQuaternions({
.quatType = (VertexBuffer::QuatType) quatType,
.quatCount = (size_t) quatCount,
.outBuffer = outData,
.outStride = (size_t) outStride,
.normals = normalsData,
.normalsStride = (size_t) normalsStride,
.tangents = nullptr,
.tangentsStride = 0
});
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv *env, jclass type,
jlong nativeVertexBuffer, jlong nativeEngine, jint bufferIndex, jlong nativeBufferObject) {
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
Engine *engine = (Engine *) nativeEngine;
BufferObject *bufferObject = (BufferObject *) nativeBufferObject;
vertexBuffer->setBufferObjectAt(*engine, (uint8_t) bufferIndex, bufferObject);
}

View File

@@ -253,7 +253,10 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetBloomOptions(JNIEnv*, jclass,
jlong nativeView, jlong nativeTexture,
jfloat dirtStrength, jfloat strength, jint resolution, jfloat anamorphism, jint levels,
jint blendMode, jboolean threshold, jboolean enabled, jfloat highlight) {
jint blendMode, jboolean threshold, jboolean enabled, jfloat highlight,
jboolean lensFlare, jboolean starburst, jfloat chromaticAberration, jint ghostCount,
jfloat ghostSpacing, jfloat ghostThreshold, jfloat haloThickness, jfloat haloRadius,
jfloat haloThreshold) {
View* view = (View*) nativeView;
Texture* dirt = (Texture*) nativeTexture;
View::BloomOptions options = {
@@ -266,7 +269,16 @@ Java_com_google_android_filament_View_nSetBloomOptions(JNIEnv*, jclass,
.blendMode = (View::BloomOptions::BlendMode)blendMode,
.threshold = (bool)threshold,
.enabled = (bool)enabled,
.highlight = highlight
.highlight = highlight,
.lensFlare = (bool)lensFlare,
.starburst = (bool)starburst,
.chromaticAberration = chromaticAberration,
.ghostCount = (uint8_t)ghostCount,
.ghostSpacing = ghostSpacing,
.ghostThreshold = ghostThreshold,
.haloThickness = haloThickness,
.haloRadius = haloRadius,
.haloThreshold = haloThreshold
};
view->setBloomOptions(options);
}
@@ -300,10 +312,24 @@ Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nat
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass ,
jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled) {
jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter,
jboolean nativeResolution, jint foregroundRingCount, jint backgroundRingCount, jint fastGatherRingCount,
jint maxForegroundCOC, jint maxBackgroundCOC) {
View* view = (View*) nativeView;
view->setDepthOfFieldOptions({.focusDistance = focusDistance, .cocScale = cocScale,
.maxApertureDiameter = maxApertureDiameter, .enabled = (bool)enabled});
View::DepthOfFieldOptions::Filter eFilter{};
if (filter == 1) {
// View::DepthOfFieldOptions::Filter::MEDIAN value is actually 2
eFilter = View::DepthOfFieldOptions::Filter::MEDIAN;
}
view->setDepthOfFieldOptions({.cocScale = cocScale,
.maxApertureDiameter = maxApertureDiameter, .enabled = (bool)enabled, .filter = eFilter,
.nativeResolution = (bool)nativeResolution,
.foregroundRingCount = (uint8_t)foregroundRingCount,
.backgroundRingCount = (uint8_t)backgroundRingCount,
.fastGatherRingCount = (uint8_t)fastGatherRingCount,
.maxForegroundCOC = (uint8_t)maxForegroundCOC,
.maxBackgroundCOC = (uint8_t)maxBackgroundCOC,
});
}
extern "C"

View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
/**
* A generic GPU buffer containing data.
*
* Usage of this BufferObject is optional. For simple use cases it is not necessary. It is useful
* only when you need to share data between multiple VertexBuffer instances. It also allows you to
* efficiently swap-out the buffers in VertexBuffer.
*
* NOTE: For now this is only used for vertex data, but in the future we may use it for other things
* (e.g. compute).
*
* @see VertexBuffer
*/
public class BufferObject {
private long mNativeObject;
private BufferObject(long nativeBufferObject) {
mNativeObject = nativeBufferObject;
}
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
// Keep to finalize native resources
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
public enum BindingType {
VERTEX,
}
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new BuilderFinalizer(mNativeBuilder);
}
/**
* Size of the buffer in bytes.
*
* @param byteCount Maximum number of bytes the BufferObject can hold.
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder size(@IntRange(from = 1) int byteCount) {
nBuilderSize(mNativeBuilder, byteCount);
return this;
}
/**
* The binding type for this buffer object. (defaults to VERTEX)
*
* @param bindingType Distinguishes between SSBO, VBO, etc. For now this must be VERTEX.
* @return A reference to this Builder for chaining calls.
*/
@NonNull
public Builder bindingType(@NonNull BindingType bindingType) {
nBuilderBindingType(mNativeBuilder, bindingType.ordinal());
return this;
}
/**
* Creates and returns the <code>BufferObject</code> object. After creation, the buffer
* is uninitialized. Use {@link #setBuffer} to initialize the <code>BufferObject</code>.
*
* @param engine reference to the {@link Engine} to associate this <code>BufferObject</code>
* with
*
* @return the newly created <code>BufferObject</code> object
*
* @exception IllegalStateException if the BufferObject could not be created
*
* @see #setBuffer
*/
@NonNull
public BufferObject build(@NonNull Engine engine) {
long nativeBufferObject = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
if (nativeBufferObject == 0)
throw new IllegalStateException("Couldn't create BufferObject");
return new BufferObject(nativeBufferObject);
}
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);
}
}
}
}
/**
* Returns the size of this <code>BufferObject</code> in elements.
*
* @return the number of bytes the <code>BufferObject</code> holds
*/
@IntRange(from = 0)
public int getByteCount() {
return nGetByteCount(getNativeObject());
}
/**
* Asynchronously copy-initializes this <code>BufferObject</code> from the data provided.
*
* @param engine reference to the {@link Engine} to associate this
* <code>BufferObject</code> with
* @param buffer a CPU-side {@link Buffer} with the data used to initialize the
* <code>BufferObject</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>BufferObject</code> from the data
* provided.
*
* @param engine reference to the {@link Engine} to associate this
* <code>BufferObject</code> with
* @param buffer a CPU-side {@link Buffer} with the data used to initialize the
* <code>BufferObject</code>.
* @param destOffsetInBytes offset in <i>bytes</i> into the <code>BufferObject</code>
* @param count number of bytes 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);
}
/**
* Asynchronously copy-initializes a region of this <code>BufferObject</code> from the data
* provided.
*
* @param engine reference to the {@link Engine} to associate this
* <code>BufferObject</code> with
* @param buffer a CPU-side {@link Buffer} with the data used to initialize the
* <code>BufferObject</code>.
* @param destOffsetInBytes offset in <i>bytes</i> into the <code>BufferObject</code>
* @param count number of bytes 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,
@Nullable Object handler, @Nullable Runnable callback) {
int result = nSetBuffer(getNativeObject(), engine.getNativeObject(), buffer, buffer.remaining(),
destOffsetInBytes, count == 0 ? buffer.remaining() : count, handler, callback);
if (result < 0) {
throw new BufferOverflowException();
}
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed BufferObject");
}
return mNativeObject;
}
void clearNativeObject() {
mNativeObject = 0;
}
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderSize(long nativeBuilder, int byteCount);
private static native void nBuilderBindingType(long nativeBuilder, int bindingType);
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native int nGetByteCount(long nativeBufferObject);
private static native int nSetBuffer(long nativeBufferObject, long nativeEngine,
Buffer buffer, int remaining,
int destOffsetInBytes, int count, Object handler, Runnable callback);
}

View File

@@ -29,7 +29,7 @@ import androidx.annotation.Size;
*
* In Filament, Camera is a component that must be associated with an entity. To do so,
* use {@link Engine#createCamera(int)}. A Camera component is destroyed using
* {@link Engine#destroyCamera(Camera)}.
* {@link Engine#destroyCameraComponent(int Entity)} ()}.
*
* <pre>
* Camera myCamera = engine.createCamera(myCameraEntity);
@@ -37,7 +37,7 @@ import androidx.annotation.Size;
* myCamera.lookAt(0, 1.60, 1,
* 0, 0, 0,
* 0, 1, 0);
* engine.destroyCamera(myCamera);
* engine.destroyCameraComponent(myCameraEntity);
* </pre>
*
*
@@ -121,6 +121,9 @@ import androidx.annotation.Size;
public class Camera {
private long mNativeObject;
@Entity
private final int mEntity;
/**
* Denotes the projection type used by this camera.
* @see #setProjection
@@ -143,8 +146,9 @@ public class Camera {
HORIZONTAL
}
Camera(long nativeCamera) {
Camera(long nativeCamera, @Entity int entity) {
mNativeObject = nativeCamera;
mEntity = entity;
}
/**
@@ -248,9 +252,9 @@ public class Camera {
}
/**
* Sets the projection matrix.
* Sets a custom projection matrix.
*
* @param inMatrix custom projection matrix.
* @param inProjection custom projection matrix for rendering and culling
*
* @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>.
@@ -266,10 +270,71 @@ public class Camera {
* <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[] inProjection,
double near, double far) {
Asserts.assertMat4dIn(inMatrix);
nSetCustomProjection(getNativeObject(), inMatrix, near, far);
Asserts.assertMat4dIn(inProjection);
nSetCustomProjection(getNativeObject(), inProjection, inProjection, near, far);
}
/**
* Sets a custom projection matrix.
*
* @param inProjection custom projection matrix for rendering.
*
* @param inProjectionForCulling custom projection matrix for culling.
*
* @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[] inProjection,
@NonNull @Size(min = 16) double[] inProjectionForCulling,
double near, double far) {
Asserts.assertMat4dIn(inProjection);
Asserts.assertMat4dIn(inProjectionForCulling);
nSetCustomProjection(getNativeObject(), inProjection, inProjectionForCulling, near, far);
}
/**
* Sets an additional matrix that scales the projection matrix.
*
* <p>This is useful to adjust the aspect ratio of the camera independent from its projection.
* First, pass an aspect of 1.0 to setProjection. Then set the scaling with the desired aspect
* ratio:<br>
*
* <code>
* double aspect = width / height;
*
* // with Fov.HORIZONTAL passed to setProjection:
* camera.setScaling(1.0, aspect);
*
* // with Fov.VERTICAL passed to setProjection:
* camera.setScaling(1.0 / aspect, 1.0);
* </code>
*
* By default, this is an identity matrix.
* </p>
*
* @param xscaling horizontal scaling to be applied after the projection matrix.
* @param yscaling vertical scaling to be applied after the projection matrix.
*
* @see Camera#setProjection
* @see Camera#setLensProjection
* @see Camera#setCustomProjection
*/
public void setScaling(double xscaling, double yscaling) {
nSetScaling(getNativeObject(), xscaling, yscaling);
}
/**
@@ -299,10 +364,33 @@ public class Camera {
* @see Camera#setProjection
* @see Camera#setLensProjection
* @see Camera#setCustomProjection
*
* @deprecated use {@link #setScaling(double, double)}
*
*/
@Deprecated
public void setScaling(@NonNull @Size(min = 4) double[] inScaling) {
Asserts.assertDouble4In(inScaling);
nSetScaling(getNativeObject(), inScaling);
setScaling(inScaling[0], inScaling[1]);
}
/**
* Sets an additional matrix that shifts (translates) the projection matrix.
* <p>
* The shift parameters are specified in NDC coordinates, that is, if the translation must
* be specified in pixels, the xshift and yshift parameters be scaled by 1.0 / viewport.width
* and 1.0 / viewport.height respectively.
* </p>
*
* @param xshift horizontal shift in NDC coordinates applied after the projection
* @param yshift vertical shift in NDC coordinates applied after the projection
*
* @see Camera#setProjection
* @see Camera#setLensProjection
* @see Camera#setCustomProjection
*/
public void setShift(double xshift, double yshift) {
nSetShift(getNativeObject(), xshift, yshift);
}
/**
@@ -344,6 +432,7 @@ public class Camera {
}
/**
* Gets the distance to the near plane
* @return Distance to the near plane
*/
public float getNear() {
@@ -351,6 +440,7 @@ public class Camera {
}
/**
* Gets the distance to the far plane
* @return Distance to the far plane
*/
public float getCullingFar() {
@@ -547,6 +637,7 @@ public class Camera {
}
/**
* Gets the aperture in f-stops
* @return Aperture in f-stops
*/
public float getAperture() {
@@ -554,6 +645,7 @@ public class Camera {
}
/**
* Gets the shutter speed in seconds
* @return Shutter speed in seconds
*/
public float getShutterSpeed() {
@@ -561,12 +653,69 @@ public class Camera {
}
/**
* Gets the focal length in meters
* @return focal length in meters [m]
*/
public double getFocalLength() {
return nGetFocalLength(getNativeObject());
}
/**
* Set the camera focus distance in world units
* @param distance Distance from the camera to the focus plane in world units. Must be
* positive and larger than the camera's near clipping plane.
*/
public void setFocusDistance(float distance) {
nSetFocusDistance(getNativeObject(), distance);
}
/**
* Gets the distance from the camera to the focus plane in world units
* @return Distance from the camera to the focus plane in world units
*/
public float getFocusDistance() {
return nGetFocusDistance(getNativeObject());
}
/**
* Gets the sensitivity in ISO
* @return Sensitivity in ISO
*/
public float getSensitivity() {
return nGetSensitivity(getNativeObject());
}
/**
* Gets the entity representing this Camera
* @return the entity this Camera component is attached to
*/
@Entity
public int getEntity() {
return mEntity;
}
/**
* Helper to compute the effective focal length taking into account the focus distance
*
* @param focalLength focal length in any unit (e.g. [m] or [mm])
* @param focusDistance focus distance in same unit as focalLength
* @return the effective focal length in same unit as focalLength
*/
static double computeEffectiveFocalLength(double focalLength, double focusDistance) {
return nComputeEffectiveFocalLength(focalLength, focusDistance);
}
/**
* Helper to compute the effective field-of-view taking into account the focus distance
*
* @param fovInDegrees full field of view in degrees
* @param focusDistance focus distance in meters [m]
* @return effective full field of view in degrees
*/
static double computeEffectiveFov(double fovInDegrees, double focusDistance) {
return nComputeEffectiveFov(fovInDegrees, focusDistance);
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed Camera");
@@ -581,8 +730,9 @@ public class Camera {
private static native void nSetProjection(long nativeCamera, int projection, double left, double right, double bottom, double top, double near, double far);
private static native void nSetProjectionFov(long nativeCamera, double fovInDegrees, double aspect, double near, double far, int fov);
private static native void nSetLensProjection(long nativeCamera, double focalLength, double aspect, double near, double far);
private static native void nSetCustomProjection(long nativeCamera, double[] inMatrix, double near, double far);
private static native void nSetScaling(long nativeCamera, double[] inScaling);
private static native void nSetCustomProjection(long nativeCamera, double[] inProjection, double[] inProjectionForCulling, double near, double far);
private static native void nSetScaling(long nativeCamera, double x, double y);
private static native void nSetShift(long nativeCamera, double x, double y);
private static native void nSetModelMatrix(long nativeCamera, float[] in);
private static native void nLookAt(long nativeCamera, double eyeX, double eyeY, double eyeZ, double centerX, double centerY, double centerZ, double upX, double upY, double upZ);
private static native float nGetNear(long nativeCamera);
@@ -600,4 +750,9 @@ public class Camera {
private static native float nGetAperture(long nativeCamera);
private static native float nGetShutterSpeed(long nativeCamera);
private static native float nGetSensitivity(long nativeCamera);
private static native void nSetFocusDistance(long nativeCamera, float distance);
private static native float nGetFocusDistance(long nativeCamera);
private static native double nGetFocalLength(long nativeCamera);
private static native double nComputeEffectiveFocalLength(double focalLength, double focusDistance);
private static native double nComputeEffectiveFov(double fovInDegrees, double focusDistance);
}

View File

@@ -109,15 +109,16 @@ public class ColorGrading {
ACES,
/** Filmic tone mapping, modelled after ACES but applied in sRGB space. */
FILMIC,
/** Filmic tone mapping, with more contrast and saturation. */
UCHIMURA,
/** Exposure value invariant luminance scaling tone mapping, offers the best behaviors in high intensity areas. */
EVILS,
/** Reinhard luma-based tone mapping. */
REINHARD,
/** Tone mapping used to validate/debug scene exposure. */
DISPLAY_RANGE,
}
ColorGrading(long colorGrading) {
// NOTE: This constructor is public only so that filament-utils can use it.
public ColorGrading(long colorGrading) {
mNativeObject = colorGrading;
}

View File

@@ -110,6 +110,7 @@ public class Engine {
@NonNull private final TransformManager mTransformManager;
@NonNull private final LightManager mLightManager;
@NonNull private final RenderableManager mRenderableManager;
@NonNull private final EntityManager mEntityManager;
/**
* Denotes a backend
@@ -142,6 +143,7 @@ public class Engine {
mTransformManager = new TransformManager(nGetTransformManager(nativeEngine));
mLightManager = new LightManager(nGetLightManager(nativeEngine));
mRenderableManager = new RenderableManager(nGetRenderableManager(nativeEngine));
mEntityManager = new EntityManager(nGetEntityManager(nativeEngine));
}
/**
@@ -397,19 +399,6 @@ 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());
if (nativeCamera == 0) throw new IllegalStateException("Couldn't create Camera");
return new Camera(nativeCamera);
}
/**
* Creates and adds a {@link Camera} component to a given <code>entity</code>.
*
@@ -419,9 +408,9 @@ public class Engine {
*/
@NonNull
public Camera createCamera(@Entity int entity) {
long nativeCamera = nCreateCameraWithEntity(getNativeObject(), entity);
long nativeCamera = nCreateCamera(getNativeObject(), entity);
if (nativeCamera == 0) throw new IllegalStateException("Couldn't create Camera");
return new Camera(nativeCamera);
return new Camera(nativeCamera, entity);
}
/**
@@ -435,16 +424,16 @@ public class Engine {
public Camera getCameraComponent(@Entity int entity) {
long nativeCamera = nGetCameraComponent(getNativeObject(), entity);
if (nativeCamera == 0) return null;
return new Camera(nativeCamera);
return new Camera(nativeCamera, entity);
}
/**
* Destroys a {@link Camera} component and frees all its associated resources.
* @param camera the {@link Camera} to destroy
* Destroys the {@link Camera} component associated with the given entity.
*
* @param entity an entity
*/
public void destroyCamera(@NonNull Camera camera) {
nDestroyCamera(getNativeObject(), camera.getNativeObject());
camera.clearNativeObject();
public void destroyCameraComponent(@Entity int entity) {
nDestroyCameraComponent(getNativeObject(), entity);
}
// Scene
@@ -632,6 +621,14 @@ public class Engine {
return mRenderableManager;
}
/**
* @return the {@link EntityManager} used by this {@link Engine}
*/
@NonNull
public EntityManager getEntityManager() {
return mEntityManager;
}
/**
* 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
@@ -683,10 +680,9 @@ public class Engine {
private static native boolean nDestroyView(long nativeEngine, long nativeView);
private static native long nCreateRenderer(long nativeEngine);
private static native boolean nDestroyRenderer(long nativeEngine, long nativeRenderer);
private static native long nCreateCamera(long nativeEngine);
private static native long nCreateCameraWithEntity(long nativeEngine, int entity);
private static native long nCreateCamera(long nativeEngine, int entity);
private static native long nGetCameraComponent(long nativeEngine, int entity);
private static native void nDestroyCamera(long nativeEngine, long nativeCamera);
private static native void nDestroyCameraComponent(long nativeEngine, int entity);
private static native long nCreateScene(long nativeEngine);
private static native boolean nDestroyScene(long nativeEngine, long nativeScene);
private static native long nCreateFence(long nativeEngine);
@@ -707,4 +703,5 @@ public class Engine {
private static native long nGetLightManager(long nativeEngine);
private static native long nGetRenderableManager(long nativeEngine);
private static native long nGetJobSystem(long nativeEngine);
private static native long nGetEntityManager(long nativeEngine);
}

View File

@@ -31,6 +31,10 @@ public class EntityManager {
private EntityManager() {
}
EntityManager(long nativeEntityManager) {
mNativeObject = nativeEntityManager;
}
@NonNull
public static EntityManager get() {
return Holder.INSTANCE;

View File

@@ -21,8 +21,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import com.google.android.filament.proguard.UsedByReflection;
/**
* <code>IndirectLight</code> is used to simulate environment lighting, a form of global illumination.
*
@@ -86,11 +84,7 @@ import com.google.android.filament.proguard.UsedByReflection;
public class IndirectLight {
long mNativeObject;
public IndirectLight(Engine engine, long indirectLight) {
mNativeObject = indirectLight;
}
IndirectLight(long indirectLight) {
public IndirectLight(long indirectLight) {
mNativeObject = indirectLight;
}
@@ -288,7 +282,7 @@ public class IndirectLight {
* 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)
* the result is in <i>lux</i>, or <i>lumen/m^2</i> (default = 30000)
*
* @return This Builder, for chaining calls.
*/
@@ -354,14 +348,14 @@ public class IndirectLight {
* 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)
* the result is in <i>lux</i>, or <i>lumen/m^2</i> (default = 30000)
*/
public void setIntensity(float intensity) {
nSetIntensity(getNativeObject(), intensity);
}
/**
* Returns the environment's intensity in cd/m<sup>2</sup>.
* Returns the environment's intensity in <i>lux</i>, or <i>lumen/m^2</i>.
*/
public float getIntensity() {
return nGetIntensity(getNativeObject());
@@ -430,6 +424,7 @@ public class IndirectLight {
}
/** @deprecated */
@Deprecated
@NonNull @Size(min = 3)
public float[] getDirectionEstimate(@Nullable @Size(min = 3) float[] direction) {
direction = Asserts.assertFloat3(direction);
@@ -472,6 +467,7 @@ public class IndirectLight {
/** @deprecated */
@Deprecated
@NonNull @Size(min = 4)
public float[] getColorEstimate(@Nullable @Size(min = 4) float[] colorIntensity, float x, float y, float z) {
colorIntensity = Asserts.assertFloat4(colorIntensity);

View File

@@ -1065,6 +1065,14 @@ public class LightManager {
return nIsShadowCaster(mNativeObject, i);
}
public float getOuterConeAngle(@EntityInstance int i) {
return nGetOuterConeAngle(mNativeObject, i);
}
public float getInnerConeAngle(@EntityInstance int i) {
return nGetInnerConeAngle(mNativeObject, i);
}
public long getNativeObject() {
return mNativeObject;
}
@@ -1118,4 +1126,6 @@ public class LightManager {
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);
private static native float nGetOuterConeAngle(long nativeLightManager, int i);
private static native float nGetInnerConeAngle(long nativeLightManager, int i);
}

View File

@@ -760,7 +760,7 @@ public class Material {
* @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 offset the number of elements in <code>v</code> 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:
@@ -768,11 +768,6 @@ public class Material {
* 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()
@@ -789,7 +784,7 @@ public class Material {
* @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 offset the number of elements in <code>v</code> 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:
@@ -797,11 +792,6 @@ public class Material {
* 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()
@@ -818,7 +808,7 @@ public class Material {
* @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 offset the number of elements in <code>v</code> 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:
@@ -826,11 +816,6 @@ public class Material {
* 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()

View File

@@ -64,6 +64,22 @@ public class MaterialInstance {
mNativeMaterial = nGetMaterial(mNativeObject);
}
/**
* Creates a new {@link #MaterialInstance} using another {@link #MaterialInstance} as a template for initialization.
* The new {@link #MaterialInstance} is an instance of the same {@link Material} of the template instance and
* must be destroyed just like any other {@link #MaterialInstance}.
*
* @param other A {@link #MaterialInstance} to use as a template for initializing a new instance
* @param name A name for the new {@link #MaterialInstance} or nullptr to use the template's name
* @return A new {@link #MaterialInstance}
*/
@NonNull
public static MaterialInstance duplicate(@NonNull MaterialInstance other, String name) {
long nativeInstance = nDuplicate(other.mNativeObject, name);
if (nativeInstance == 0) throw new IllegalStateException("Couldn't duplicate MaterialInstance");
return new MaterialInstance(other.mMaterial, nativeInstance);
}
/** @return the {@link Material} associated with this instance */
@NonNull
public Material getMaterial() {
@@ -238,7 +254,7 @@ public class MaterialInstance {
* @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 offset the number of elements in <code>v</code> 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:
@@ -246,11 +262,6 @@ public class MaterialInstance {
* 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,
@@ -265,7 +276,7 @@ public class MaterialInstance {
* @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 offset the number of elements in <code>v</code> 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:
@@ -273,11 +284,6 @@ public class MaterialInstance {
* 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,
@@ -292,7 +298,7 @@ public class MaterialInstance {
* @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 offset the number of elements in <code>v</code> 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:
@@ -300,11 +306,6 @@ public class MaterialInstance {
* 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,
@@ -452,7 +453,7 @@ public class MaterialInstance {
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:colorWrite">
* Rasterization: colorWrite</a>
*/
void setColorWrite(boolean enable) {
public void setColorWrite(boolean enable) {
nSetColorWrite(getNativeObject(), enable);
}
@@ -463,7 +464,7 @@ public class MaterialInstance {
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:depthWrite">
* Rasterization: depthWrite</a>
*/
void setDepthWrite(boolean enable) {
public void setDepthWrite(boolean enable) {
nSetDepthWrite(getNativeObject(), enable);
}
@@ -474,7 +475,7 @@ public class MaterialInstance {
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:depthCulling">
* Rasterization: depthCulling</a>
*/
void setDepthCulling(boolean enable) {
public void setDepthCulling(boolean enable) {
nSetDepthCulling(getNativeObject(), enable);
}
@@ -554,4 +555,6 @@ public class MaterialInstance {
private static native String nGetName(long nativeMaterialInstance);
private static native long nGetMaterial(long nativeMaterialInstance);
private static native long nDuplicate(long otherNativeMaterialInstance, String name);
}

View File

@@ -32,12 +32,12 @@ import androidx.annotation.Nullable;
*/
public class RenderTarget {
private long mNativeObject;
private final Texture[] mTextures = new Texture[2];
private static final int ATTACHMENT_COUNT = 5;
private final Texture[] mTextures = new Texture[ATTACHMENT_COUNT];
private RenderTarget(long nativeRenderTarget, Builder builder) {
mNativeObject = nativeRenderTarget;
mTextures[0] = builder.mTextures[0];
mTextures[1] = builder.mTextures[1];
System.arraycopy(builder.mTextures, 0, mTextures, 0, ATTACHMENT_COUNT);
}
public long getNativeObject() {
@@ -52,7 +52,14 @@ public class RenderTarget {
*/
public enum AttachmentPoint {
COLOR,
DEPTH,
COLOR1,
COLOR2,
COLOR3,
COLOR4,
COLOR5,
COLOR6,
COLOR7,
DEPTH
}
/**
@@ -62,7 +69,7 @@ public class RenderTarget {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
private final BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
private final Texture[] mTextures = new Texture[2];
private final Texture[] mTextures = new Texture[ATTACHMENT_COUNT];
public Builder() {
mNativeBuilder = nCreateBuilder();

View File

@@ -315,7 +315,7 @@ public class Renderer {
* <li>Color pass</li>
* <li>Post-processing pass</li>
* </ul>
*
* <p>
* A typical render loop looks like this:
*
* <pre>
@@ -331,31 +331,58 @@ public class Renderer {
* </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 <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> 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> 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>
* <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());
}
/**
* Renders a standalone {@link View} into its associated <code>RenderTarget</code>.
*
* <p>
* This call is mostly equivalent to calling {@link #render(View)} inside a
* {@link #beginFrame} / {@link #endFrame} block, but incurs less overhead. It can be used
* as a poor man's compute API.
* </p>
*
* <ul>
* <li><code>renderStandaloneView()</code> must be called <b>outside</b> of
* {@link #beginFrame} / {@link #endFrame}.</li>
*
* <li><code>renderStandaloneView()</code> must be called from the {@link Engine}'s main thread
* (or external synchronization must be provided). In particular, calls to
* <code>renderStandaloneView()</code> on different <code>Renderer</code> instances <b>must</b>
* be synchronized.</li>
*
* <li><code>renderStandaloneView()</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>
*
* @param view the {@link View} to render. This View must have an associated {@link RenderTarget}
* @see View
*/
public void renderStandaloneView(@NonNull View view) {
nRenderStandaloneView(getNativeObject(), view.getNativeObject());
}
/**
* Copies the currently rendered {@link View} to the indicated {@link SwapChain}, using the
* indicated source and destination rectangle.
@@ -635,6 +662,7 @@ public class Renderer {
private static native boolean nBeginFrame(long nativeRenderer, long nativeSwapChain, long frameTimeNanos);
private static native void nEndFrame(long nativeRenderer);
private static native void nRender(long nativeRenderer, long nativeView);
private static native void nRenderStandaloneView(long nativeRenderer, long nativeView);
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,

View File

@@ -128,6 +128,7 @@ public class Scene {
/**
* @deprecated See {@link #removeEntity(int)}
*/
@Deprecated
public void remove(@Entity int entity) {
removeEntity(entity);
}

View File

@@ -23,8 +23,6 @@ import androidx.annotation.Size;
import static com.google.android.filament.Colors.LinearColor;
import com.google.android.filament.proguard.UsedByReflection;
/**
* Skybox
* <p>When added to a {@link Scene}, the <code>Skybox</code> fills all untouched pixels.</p>
@@ -53,11 +51,7 @@ import com.google.android.filament.proguard.UsedByReflection;
public class Skybox {
private long mNativeObject;
public Skybox(Engine engine, long nativeSkybox) {
mNativeObject = nativeSkybox;
}
Skybox(long nativeSkybox) {
public Skybox(long nativeSkybox) {
mNativeObject = nativeSkybox;
}
@@ -115,13 +109,14 @@ public class Skybox {
}
/**
* Sets the <code>Skybox</code> intensity when no {@link IndirectLight} is set
* Sets the <code>Skybox</code> intensity when no {@link IndirectLight} is set on the
* {@link Scene}.
*
* <p>This call is ignored when an {@link IndirectLight} is set, otherwise it is used in
* its place.</p>
* <p>This call is ignored when an {@link IndirectLight} is set on the {@link Scene}, and
* the intensity of the {@link IndirectLight} is used instead.</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)
* the result is in <i>lux</i>, or <i>lumen/m^2</i> (default = 30000)
*
* @return This Builder, for chaining calls.
*
@@ -237,7 +232,7 @@ public class Skybox {
}
/**
* Returns the <code>Skybox</code>'s intensity in cd/m<sup>2</sup>.
* Returns the <code>Skybox</code>'s intensity in <i>lux</i>, or <i>lumen/m^2</i>.
*/
public float getIntensity() { return nGetIntensity(getNativeObject()); }

View File

@@ -166,7 +166,9 @@ public class Stream {
* <code>GL_TEXTURE_EXTERNAL_OES.</code>
* @return This Builder, for chaining calls.
* @see Texture#setExternalStream
* @deprecated this method existed only for ARCore which doesn't need this anymore, use {@link Texture.Builder#importTexture(long)} instead.
*/
@Deprecated
@NonNull
public Builder stream(long externalTextureId) {
nBuilderStream(mNativeBuilder, externalTextureId);

View File

@@ -73,11 +73,7 @@ import static com.google.android.filament.Texture.Type.COMPRESSED;
public class Texture {
private long mNativeObject;
Texture(long nativeTexture) {
mNativeObject = nativeTexture;
}
public Texture(Engine engine, long nativeTexture) {
public Texture(long nativeTexture) {
mNativeObject = nativeTexture;
}
@@ -509,12 +505,15 @@ public class Texture {
case RGBA_INTEGER:
n = 4;
break;
default: throw new IllegalStateException("unsupported format enum");
}
int bpp = n;
switch (type) {
case UBYTE:
case BYTE:
case COMPRESSED:
// nothing to do
break;
case USHORT:
@@ -531,6 +530,9 @@ public class Texture {
// Special case, format must be RGB and uses 4 bytes
bpp = 4;
break;
case USHORT_565:
bpp = 2;
break;
}
int bpr = bpp * stride;
@@ -562,6 +564,17 @@ public class Texture {
return nIsTextureFormatSupported(engine.getNativeObject(), format.ordinal());
}
/**
* Checks whether texture swizzling is supported in this {@link Engine}.
* This depends on the selected backend.
*
* @param engine {@link Engine}
* @return <code>true</code> if texture swizzling.
*/
public static boolean isTextureSwizzleSupported(@NonNull Engine engine) {
return nIsTextureSwizzleSupported(engine.getNativeObject());
}
/**
* Use <code>Builder</code> to construct a <code>Texture</code> object instance.
*/
@@ -678,6 +691,26 @@ public class Texture {
return this;
}
/**
* Specify a native texture to import as a Filament texture.
* <p>
* The texture id is backend-specific:
* <ul>
* <li> OpenGL: GLuint texture ID </li>
* </ul>
* </p>
*
*
* @param id a backend specific texture identifier
*
* @return This Builder, for chaining calls.
*/
@NonNull
public Builder importTexture(long id) {
nBuilderImportTexture(mNativeBuilder, id);
return this;
}
/**
* Creates a new <code>Texture</code> instance.
* @param engine The {@link Engine} to associate this <code>Texture</code> with.
@@ -882,7 +915,7 @@ public class Texture {
* @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 yoffset z-offset in texel of the region to modify
* @param zoffset z-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 depth depth in texel or index of the region to modify
@@ -1137,6 +1170,7 @@ public class Texture {
}
private static native boolean nIsTextureFormatSupported(long nativeEngine, int internalFormat);
private static native boolean nIsTextureSwizzleSupported(long nativeEngine);
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeBuilder);
@@ -1149,6 +1183,7 @@ public class Texture {
private static native void nBuilderFormat(long nativeBuilder, int format);
private static native void nBuilderUsage(long nativeBuilder, int flags);
private static native void nBuilderSwizzle(long nativeBuilder, int r, int g, int b, int a);
private static native void nBuilderImportTexture(long nativeBuilder, long id);
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native int nGetWidth(long nativeTexture, int level);
@@ -1160,35 +1195,35 @@ public class Texture {
private static native int nSetImage(long nativeTexture, long nativeEngine,
int level, int xoffset, int yoffset, int width, int height,
Buffer storage, int remaining, int left, int bottom, int type, int alignment,
Buffer storage, int remaining, int left, int top, int type, int alignment,
int stride, int format,
Object handler, Runnable callback);
private static native int nSetImageCompressed(long nativeTexture, long nativeEngine,
int level, int xoffset, int yoffset, int width, int height,
Buffer storage, int remaining, int left, int bottom, int type, int alignment,
Buffer storage, int remaining, int left, int top, int type, int alignment,
int compressedSizeInBytes, int compressedFormat,
Object handler, Runnable callback);
private static native int nSetImage3D(long nativeTexture, long nativeEngine,
int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth,
Buffer storage, int remaining, int left, int bottom, int type, int alignment,
Buffer storage, int remaining, int left, int top, int type, int alignment,
int stride, int format,
Object handler, Runnable callback);
private static native int nSetImage3DCompressed(long nativeTexture, long nativeEngine,
int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth,
Buffer storage, int remaining, int left, int bottom, int type, int alignment,
Buffer storage, int remaining, int left, int top, int type, int alignment,
int compressedSizeInBytes, int compressedFormat,
Object handler, Runnable callback);
private static native int nSetImageCubemap(long nativeTexture, long nativeEngine,
int level, Buffer storage, int remaining, int left, int bottom, int type,
int level, Buffer storage, int remaining, int left, int top, int type,
int alignment, int stride, int format,
int[] faceOffsetsInBytes, Object handler, Runnable callback);
private static native int nSetImageCubemapCompressed(long nativeTexture, long nativeEngine,
int level, Buffer storage, int remaining, int left, int bottom, int type,
int level, Buffer storage, int remaining, int left, int top, int type,
int alignment, int compressedSizeInBytes, int compressedFormat,
int[] faceOffsetsInBytes, Object handler, Runnable callback);

View File

@@ -140,6 +140,19 @@ import androidx.annotation.Size;
nSetParent(mNativeObject, i, newParent);
}
/**
* Returns the actual parent entity of an {@link EntityInstance} originally defined
* by {@link #setParent(int, int)}.
*
* @param i the {@link EntityInstance} of the transform component to get the parent from.
* @return the parent {@link Entity}.
* @see #getInstance
*/
@Entity
public int getParent(@EntityInstance int i) {
return nGetParent(mNativeObject, i);
}
/**
* Sets a local transform of a transform component.
* <p>This operation can be slow if the hierarchy of transform is too deep, and this
@@ -241,6 +254,7 @@ import androidx.annotation.Size;
private static native int nCreateArray(long mNativeObject, int entity, int parent, float[] localTransform);
private static native void nDestroy(long nativeTransformManager, int entity);
private static native void nSetParent(long nativeTransformManager, int i, int newParent);
private static native int nGetParent(long nativeTransformManager, int i);
private static native void nSetTransform(long nativeTransformManager, int i, float[] localTransform);
private static native void nGetTransform(long nativeTransformManager, int i, float[] outLocalTransform);
private static native void nGetWorldTransform(long nativeTransformManager, int i, float[] outWorldTransform);

View File

@@ -104,48 +104,6 @@ public class VertexBuffer {
HALF3,
HALF4,
}
/**
* Specifies the quaternion type for the {@link #populateTangentQuaternions} utility.
*/
public enum QuatType {
/** 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 {
/** 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 {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
@@ -170,6 +128,21 @@ public class VertexBuffer {
return this;
}
/**
* Allows buffers to be swapped out and shared using BufferObject.
*
* If buffer objects mode is enabled, clients must call setBufferObjectAt rather than
* setBufferAt. This allows sharing of data between VertexBuffer objects, but it may
* slightly increase the memory footprint of Filament's internal bookkeeping.
*
* @param enabled If true, enables buffer object mode. False by default.
*/
@NonNull
public Builder enableBufferObjects(boolean enabled) {
nBuilderEnableBufferObjects(mNativeBuilder, enabled);
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.
@@ -397,36 +370,21 @@ 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.
* Swaps in the given buffer object.
*
* <p>
* The given output buffer must be preallocated with at least quatCount * outStride bytes.
* <p>
* To use this, you must first call enableBufferObjects() on the Builder.
*
* <p>
* Normals are required but tangents are optional, in which case this function tries to generate
* reasonable tangents. The given normals should be unit length.
* </p>
*
* <p>
* If supplied, the tangent vectors should be unit length and should be orthogonal to the
* normals. The w component of the tangent is a sign (-1 or +1) indicating handedness of the
* basis.
* </p>
*
* @deprecated Instead please use SurfaceOrientation since it has additional capabilities and a
* builder-style API.
*
* @param context an initialized QuatTangentContext object
* @param engine Reference to the filament::Engine to associate this VertexBuffer with.
* @param bufferIndex Index of the buffer to initialize. Must be between 0
* and Builder::bufferCount() - 1.
* @param bufferObject The handle to the GPU data that will be used in this buffer slot.
*/
public static void populateTangentQuaternions(@NonNull QuatTangentContext context) {
nPopulateTangentQuaternions(context.quatType.ordinal(), context.quatCount,
context.outBuffer, context.outBuffer.remaining(), context.outStride,
context.normals, context.normals.remaining(), context.normalsStride,
context.tangents, context.tangents != null ? context.tangents.remaining() : 0,
context.tangentsStride);
public void setBufferObjectAt(@NonNull Engine engine, int bufferIndex,
@NonNull BufferObject bufferObject) {
nSetBufferObjectAt(getNativeObject(), engine.getNativeObject(), bufferIndex,
bufferObject.getNativeObject());
}
public long getNativeObject() {
@@ -443,6 +401,7 @@ public class VertexBuffer {
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderVertexCount(long nativeBuilder, int vertexCount);
private static native void nBuilderEnableBufferObjects(long nativeBuilder, boolean enabled);
private static native void nBuilderBufferCount(long nativeBuilder, int bufferCount);
private static native void nBuilderAttribute(long nativeBuilder, int attribute,
int bufferIndex, int attributeType, int byteOffset, int byteStride);
@@ -455,7 +414,6 @@ public class VertexBuffer {
int bufferIndex, Buffer buffer, int remaining, int destOffsetInBytes, int count,
Object handler, Runnable callback);
private static native void nPopulateTangentQuaternions(int quatType, int quatCount,
Buffer outBuffer, int outRemaining, int outStride, Buffer normals, int normalsRemaining,
int normalsStride, Buffer tangents, int tangentsRemaining, int tangentsStride);
private static native void nSetBufferObjectAt(long nativeVertexBuffer, long nativeEngine,
int bufferIndex, long nativeBufferObject);
}

View File

@@ -266,7 +266,7 @@ public class View {
/**
* Options for Temporal Anti-aliasing (TAA)
* @see View#setTemporalAntiAliasingOptions()
* @see View#setTemporalAntiAliasingOptions
*/
public static class TemporalAntiAliasingOptions {
/** reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother) */
@@ -284,11 +284,11 @@ public class View {
*
* enabled: Enable or disable the bloom post-processing effect. Disabled by default.
* levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
* maximum is 12. This value together with resolution influences the spread of the
* maximum is 11. This value together with resolution influences the spread of the
* blur effect. This value can be silently reduced to accommodate the original
* image size.
* resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
* the maximum is lower of the original resolution and 4096. This parameter is
* resolution: Resolution of bloom's vertical axis. The minimum value is 2^levels and the
* the maximum is lower of the original resolution and 2048. This parameter is
* silently clamped to the minimum and maximum.
* It is highly recommended that this value be smaller than the target resolution
* after dynamic resolution is applied (horizontally and vertically).
@@ -329,7 +329,7 @@ public class View {
public float strength = 0.10f;
/**
* Resolution of minor axis (2^levels to 4096)
* Resolution of minor axis (2^levels to 2048)
*/
public int resolution = 360;
@@ -339,7 +339,7 @@ public class View {
public float anamorphism = 1.0f;
/**
* Number of blur levels (3 to 12)
* Number of blur levels (3 to 11)
*/
public int levels = 6;
@@ -363,6 +363,52 @@ public class View {
* minimum value is 10.0.
*/
public float highlight = 1000.0f;
/**
* enable screen-space lens flare
*/
public boolean lensFlare = false;
/**
* enable starburst effect on lens flare
*/
public boolean starburst = true;
/**
* amount of chromatic aberration
*/
public float chromaticAberration = 0.005f;
/**
* number of flare "ghosts"
*/
public int ghostCount = 4;
/**
* spacing of the ghost in screen units [0, 1[
*/
public float ghostSpacing = 0.6f;
/**
* hdr threshold for the ghosts
*/
public float ghostThreshold = 10.0f;
/**
* thickness of halo in vertical screen units, 0 to disable
*/
public float haloThickness = 0.1f;
/**
* radius of halo in vertical screen units [0, 0.5]
*/
public float haloRadius = 0.4f;
/**
* hdr threshold for the halo
*/
public float haloThreshold = 10.0f;
}
/**
@@ -431,8 +477,10 @@ public class View {
*/
public static class DepthOfFieldOptions {
/** focus distance in world units */
public float focusDistance = 10.0f;
public enum Filter {
NONE,
MEDIAN
}
/**
* circle of confusion scale factor (amount of blur)
@@ -451,6 +499,59 @@ public class View {
/** enable or disable Depth of field effect */
public boolean enabled = false;
/** filter to use for filling gaps in the kernel */
@NonNull
public Filter filter = Filter.MEDIAN;
/** perform DoF processing at native resolution */
public boolean nativeResolution = false;
/**
* <p>Number of of rings used by the foreground kernel. The number of rings affects quality
* and performance. The actual number of sample per pixel is defined
* as (ringCount * 2 - 1)^2. Here are a few commonly used values:</p>
* 3 rings : 25 ( 5x 5 grid)
* 4 rings : 49 ( 7x 7 grid)
* 5 rings : 81 ( 9x 9 grid)
* 17 rings : 1089 (33x33 grid)
*
* <p>With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings.</p>
*
* <p>Usually all three settings below are set to the same value, however, it is often
* acceptable to use a lower ring count for the "fast tiles", which improves performance.
* Fast tiles are regions of the screen where every pixels have a similar
* circle-of-confusion radius.</p>
*
* <p>A value of 0 means default, which is 5 on desktop and 3 on mobile.</p>
*/
public int foregroundRingCount = 0;
/**
* Number of of rings used by the background kernel. The number of rings affects quality
* and performance.
* @see #foregroundRingCount
*/
public int backgroundRingCount = 0;
/**
* Number of of rings used by the fast gather kernel. The number of rings affects quality
* and performance.
* @see #foregroundRingCount
*/
public int fastGatherRingCount = 0;
/**
* maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range.
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
*/
public int maxForegroundCOC = 0;
/**
* maximum circle-of-confusion in pixels for the background, must be in [0, 32] range.
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
*/
public int maxBackgroundCOC = 0;
};
/**
@@ -830,16 +931,6 @@ public class View {
nSetShadowingEnabled(getNativeObject(), enabled);
}
/**
* Enables or disables shadow mapping. Enabled by default.
*
* @deprecated Use {@link #setShadowingEnabled}
*/
@Deprecated
public void setShadowsEnabled(boolean enabled) {
setShadowingEnabled(enabled);
}
/**
* @return whether shadowing is enabled
*/
@@ -1294,7 +1385,10 @@ public class View {
nSetBloomOptions(getNativeObject(), options.dirt != null ? options.dirt.getNativeObject() : 0,
options.dirtStrength, options.strength, options.resolution,
options.anamorphism, options.levels, options.blendingMode.ordinal(),
options.threshold, options.enabled, options.highlight);
options.threshold, options.enabled, options.highlight,
options.lensFlare, options.starburst, options.chromaticAberration,
options.ghostCount, options.ghostSpacing, options.ghostThreshold,
options.haloThickness, options.haloRadius, options.haloThreshold);
}
/**
@@ -1379,7 +1473,10 @@ public class View {
*/
public void setDepthOfFieldOptions(@NonNull DepthOfFieldOptions options) {
mDepthOfFieldOptions = options;
nSetDepthOfFieldOptions(getNativeObject(), options.focusDistance, options.cocScale, options.maxApertureDiameter, options.enabled);
nSetDepthOfFieldOptions(getNativeObject(), options.cocScale,
options.maxApertureDiameter, options.enabled, options.filter.ordinal(),
options.nativeResolution, options.foregroundRingCount, options.backgroundRingCount,
options.fastGatherRingCount, options.maxForegroundCOC, options.maxBackgroundCOC);
}
/**
@@ -1435,10 +1532,12 @@ public class View {
private static native int nGetAmbientOcclusion(long nativeView);
private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution, float intensity, int quality, int lowPassFilter, int upsampling, boolean enabled, float minHorizonAngleRad);
private static native void nSetSSCTOptions(long nativeView, float ssctLightConeRad, float ssctStartTraceDistance, float ssctContactDistanceMax, float ssctIntensity, float v, float v1, float v2, float ssctDepthBias, float ssctDepthSlopeBias, int ssctSampleCount, int ssctRayCount, boolean ssctEnabled);
private static native void nSetBloomOptions(long nativeView, long dirtNativeObject, float dirtStrength, float strength, int resolution, float anamorphism, int levels, int blendMode, boolean threshold, boolean enabled, float highlight);
private static native void nSetBloomOptions(long nativeView, long dirtNativeObject, float dirtStrength, float strength, int resolution, float anamorphism, int levels, int blendMode, boolean threshold, boolean enabled, float highlight,
boolean lensFlare, boolean starburst, float chromaticAberration, int ghostCount, float ghostSpacing, float ghostThreshold, float haloThickness, float haloRadius, float haloThreshold);
private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, boolean enabled);
private static native void nSetBlendMode(long nativeView, int blendMode);
private static native void nSetDepthOfFieldOptions(long nativeView, float focusDistance, float cocScale, float maxApertureDiameter, boolean enabled);
private static native void nSetDepthOfFieldOptions(long nativeView, float cocScale, float maxApertureDiameter, boolean enabled, int filter,
boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
private static native void nSetVignetteOptions(long nativeView, float midPoint, float roundness, float feather, float r, float g, float b, float a, boolean enabled);
private static native void nSetTemporalAntiAliasingOptions(long nativeView, float feedback, float filterWidth, boolean enabled);
private static native boolean nIsShadowingEnabled(long nativeView);

View File

@@ -23,8 +23,6 @@ import androidx.annotation.NonNull;
import com.google.android.filament.Engine;
import com.google.android.filament.Texture;
import java.lang.reflect.Method;
public final class TextureHelper {
// Keep in sync with Texture.cpp
private static final int BITMAP_CONFIG_ALPHA_8 = 0;

View File

@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.19)
project(filament-utils-android)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
set(IMAGEIO_DIR ../../libs/imageio)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../gltfio-android ${CMAKE_CURRENT_BINARY_DIR}/gltfio-android)
@@ -12,27 +14,54 @@ add_library(image STATIC IMPORTED)
set_target_properties(image PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
include_directories(${FILAMENT_DIR}/include
..
../../libs/utils/include)
add_library(viewer STATIC IMPORTED)
set_target_properties(viewer PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libviewer.a)
add_library(civetweb STATIC IMPORTED)
set_target_properties(civetweb PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libcivetweb.a)
add_library(iblprefilter STATIC IMPORTED)
set_target_properties(iblprefilter PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament-iblprefilter.a)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
add_library(filament-utils-jni SHARED
src/main/cpp/AutomationEngine.cpp
src/main/cpp/Bookmark.cpp
src/main/cpp/HDRLoader.cpp
src/main/cpp/IBLPrefilterContext.cpp
src/main/cpp/Utils.cpp
src/main/cpp/Manipulator.cpp
src/main/cpp/RemoteServer.cpp
${IMAGEIO_DIR}/include/imageio/ImageDecoder.h
${IMAGEIO_DIR}/include/imageio/HDRDecoder.h
${IMAGEIO_DIR}/src/HDRDecoder.cpp
../common/CallbackUtils.cpp
../common/NioUtils.cpp
)
target_compile_definitions(filament-utils-jni PUBLIC IMAGEIO_LITE=1)
target_include_directories(filament-utils-jni PRIVATE
${FILAMENT_DIR}/include
..
${IMAGEIO_DIR}/include
../../libs/utils/include)
set_target_properties(filament-utils-jni PROPERTIES LINK_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.symbols)
# The ordering in the following list is important because CMake does not have dependency information.
target_link_libraries(filament-utils-jni
gltfio-jni
civetweb
camutils
iblprefilter
image
viewer
)

View File

@@ -45,7 +45,7 @@ dependencies {
implementation deps.androidx.annotations
implementation project(':filament-android')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
fullImplementation module("com.google.android.filament:gltfio-android:${VERSION_NAME}")

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2021 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 <viewer/AutomationEngine.h>
using namespace filament;
using namespace filament::viewer;
using namespace utils;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nCreateAutomationEngine(JNIEnv* env, jclass,
jstring spec_) {
const char* spec = env->GetStringUTFChars(spec_, 0);
jlong result = (jlong) AutomationEngine::createFromJSON(spec, strlen(spec));
env->ReleaseStringUTFChars(spec_, spec);
return result;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nCreateDefaultAutomationEngine(JNIEnv* env,
jclass klass) {
return (jlong) AutomationEngine::createDefault();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nSetOptions(JNIEnv* env, jclass klass,
jlong nativeAutomation, jfloat sleepDuration, jint minFrameCount, jboolean verbose) {
AutomationEngine* automation = (AutomationEngine*) nativeAutomation;
AutomationEngine::Options options = {
.sleepDuration = sleepDuration,
.minFrameCount = minFrameCount,
.verbose = (bool) verbose,
// Since they write to the filesystem, we do not currently support exporting screenshots
// and JSON files on Android.
.exportScreenshots = false,
.exportSettings = false,
};
automation->setOptions(options);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nStartRunning(JNIEnv* env, jclass klass,
jlong nativeAutomation) {
AutomationEngine* automation = (AutomationEngine*) nativeAutomation;
automation->startRunning();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nStartBatchMode(JNIEnv* env, jclass klass,
jlong nativeAutomation) {
AutomationEngine* automation = (AutomationEngine*) nativeAutomation;
automation->startBatchMode();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nTick(JNIEnv* env, jclass klass,
jlong nativeAutomation, jlong view, jlongArray materials, jlong renderer, jfloat deltaTime) {
using MaterialPointer = MaterialInstance*;
jsize materialCount = 0;
jlong* longMaterials = nullptr;
MaterialPointer* ptrMaterials = nullptr;
if (materials) {
materialCount = env->GetArrayLength(materials);
ptrMaterials = new MaterialPointer[materialCount];
longMaterials = env->GetLongArrayElements(materials, nullptr);
for (jsize i = 0; i < materialCount; i++) {
ptrMaterials[i] = (MaterialPointer) longMaterials[i];
}
}
AutomationEngine* automation = (AutomationEngine*) nativeAutomation;
automation->tick((View*) view, ptrMaterials, materialCount, (Renderer*) renderer, deltaTime);
if (longMaterials) {
env->ReleaseLongArrayElements(materials, longMaterials, 0);
delete[] ptrMaterials;
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nApplySettings(JNIEnv* env, jclass klass,
jlong nativeAutomation, jstring json, jlong view, jlongArray materials, jlong nativeIbl,
jint lightEntity, jlong nativeLm, jlong scene, jlong renderer) {
using MaterialPointer = MaterialInstance*;
jsize materialCount = 0;
jlong* longMaterials = nullptr;
MaterialPointer* ptrMaterials = nullptr;
if (materials) {
materialCount = env->GetArrayLength(materials);
ptrMaterials = new MaterialPointer[materialCount];
longMaterials = env->GetLongArrayElements(materials, nullptr);
for (jsize i = 0; i < materialCount; i++) {
ptrMaterials[i] = (MaterialPointer) longMaterials[i];
}
}
AutomationEngine* automation = (AutomationEngine*) nativeAutomation;
const char* nativeJson = env->GetStringUTFChars(json, 0);
size_t jsonLength = env->GetStringUTFLength(json);
automation->applySettings(nativeJson, jsonLength, (View*) view, ptrMaterials, materialCount,
(IndirectLight*) nativeIbl, (Entity&) lightEntity, (LightManager*) nativeLm,
(Scene*) scene, (Renderer*) renderer);
env->ReleaseStringUTFChars(json, nativeJson);
if (longMaterials) {
env->ReleaseLongArrayElements(materials, longMaterials, 0);
delete[] ptrMaterials;
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nGetViewerOptions(JNIEnv* env, jclass,
jlong nativeObject, jobject result) {
AutomationEngine* automation = (AutomationEngine*) nativeObject;
auto options = automation->getViewerOptions();
const jclass klass = env->GetObjectClass(result);
const jfieldID cameraAperture = env->GetFieldID(klass, "cameraAperture", "F");
const jfieldID cameraSpeed = env->GetFieldID(klass, "cameraSpeed", "F");
const jfieldID cameraISO = env->GetFieldID(klass, "cameraISO", "F");
const jfieldID groundShadowStrength = env->GetFieldID(klass, "groundShadowStrength", "F");
const jfieldID groundPlaneEnabled = env->GetFieldID(klass, "groundPlaneEnabled", "Z");
const jfieldID skyboxEnabled = env->GetFieldID(klass, "skyboxEnabled", "Z");
const jfieldID cameraFocalLength = env->GetFieldID(klass, "cameraFocalLength", "F");
const jfieldID cameraFocusDistance = env->GetFieldID(klass, "cameraFocusDistance", "F");
env->SetFloatField(result, cameraAperture, options.cameraAperture);
env->SetFloatField(result, cameraSpeed, options.cameraSpeed);
env->SetFloatField(result, cameraISO, options.cameraISO);
env->SetFloatField(result, groundShadowStrength, options.groundShadowStrength);
env->SetBooleanField(result, groundPlaneEnabled, options.groundPlaneEnabled);
env->SetBooleanField(result, skyboxEnabled, options.skyboxEnabled);
env->SetFloatField(result, cameraFocalLength, options.cameraFocalLength);
env->SetFloatField(result, cameraFocusDistance, options.cameraFocusDistance);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nGetColorGrading(JNIEnv*, jclass,
jlong nativeObject, jlong nativeEngine) {
AutomationEngine* automation = (AutomationEngine*) nativeObject;
return (jlong) automation->getColorGrading((Engine*) nativeEngine);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nSignalBatchMode(JNIEnv*, jclass, jlong native) {
AutomationEngine* automation = (AutomationEngine*) native;
automation->signalBatchMode();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nStopRunning(JNIEnv*, jclass, jlong native) {
AutomationEngine* automation = (AutomationEngine*) native;
automation->stopRunning();
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nShouldClose(JNIEnv*, jclass, jlong native) {
AutomationEngine* automation = (AutomationEngine*) native;
return automation->shouldClose();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_AutomationEngine_nDestroy(JNIEnv*, jclass, jlong native) {
AutomationEngine* automation = (AutomationEngine*) native;
delete automation;
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2021 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/Texture.h>
#include <imageio/HDRDecoder.h>
#include <utils/Log.h>
#include <sstream>
#include "common/NioUtils.h"
using namespace filament;
using namespace image;
using namespace utils;
using PixelBufferDescriptor = Texture::PixelBufferDescriptor;
jlong nCreateHDRTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jint internalFormat) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
Texture::InternalFormat textureFormat = (Texture::InternalFormat) internalFormat;
auto dataPtr = (char const*) buffer.getData();
const size_t byteCount = buffer.getSize();
// This creates a copy but it's the easest way to create a memory stream.
std::string ins(dataPtr, byteCount);
std::istringstream in(ins);
LinearImage* image = new LinearImage(ImageDecoder::decode(in, "memory.hdr"));
// This can happen if a decoding error occurs.
if (image->getChannels() != 3) {
delete image;
return 0;
}
Texture* texture = Texture::Builder()
.width(image->getWidth())
.height(image->getHeight())
.levels(0xff)
.sampler(Texture::Sampler::SAMPLER_2D)
.format(textureFormat)
.build(*engine);
if (texture == nullptr) {
slog.e << "Unable to create Filament Texture from HDR image." << io::endl;
delete image;
return 0;
}
PixelBufferDescriptor::Callback freeCallback = [](void* buf, size_t, void* userdata) {
delete (LinearImage*) userdata;
};
PixelBufferDescriptor pbd(
(void const* ) image->getPixelRef(),
image->getWidth() * image->getHeight() * 3 * sizeof(float),
PixelBufferDescriptor::PixelDataFormat::RGB,
PixelBufferDescriptor::PixelDataType::FLOAT,
freeCallback,
image);
// Note that the setImage call could fail (e.g. due to an invalid combination of internal format
// and PixelDataFormat) but there is no way of detecting such a failure.
texture->setImage(*engine, 0, std::move(pbd));
texture->generateMipmaps(*engine);
return (jlong) texture;
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2021 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-iblprefilter/IBLPrefilterContext.h>
#include <filament/Engine.h>
#include <filament/Texture.h>
using namespace filament;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nCreate(JNIEnv* env, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) new IBLPrefilterContext(*engine);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nDestroy(JNIEnv*, jclass, jlong native) {
IBLPrefilterContext* context = (IBLPrefilterContext*) native;
delete context;
}
extern "C" JNIEXPORT long JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nCreateEquirectHelper(JNIEnv* env, jclass, jlong nativeContext) {
IBLPrefilterContext* context = (IBLPrefilterContext*) nativeContext;
return (long) new IBLPrefilterContext::EquirectangularToCubemap(*context);
}
extern "C" JNIEXPORT long JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nEquirectHelperRun(JNIEnv* env, jclass, jlong nativeHelper, long nativeEquirect) {
auto helper = (IBLPrefilterContext::EquirectangularToCubemap*) nativeHelper;
auto texture = (filament::Texture*) nativeEquirect;
auto result = (*helper)(texture);
return (long) result;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nDestroyEquirectHelper(JNIEnv* env, jclass, jlong nativeObject) {
delete (IBLPrefilterContext::EquirectangularToCubemap*) nativeObject;
}
extern "C" JNIEXPORT long JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nCreateSpecularFilter(JNIEnv* env, jclass, jlong nativeContext) {
IBLPrefilterContext* context = (IBLPrefilterContext*) nativeContext;
return (long) new IBLPrefilterContext::SpecularFilter(*context);
}
extern "C" JNIEXPORT long JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nSpecularFilterRun(JNIEnv* env, jclass, jlong nativeHelper, long nativeSkybox) {
auto helper = (IBLPrefilterContext::SpecularFilter*) nativeHelper;
auto texture = (filament::Texture*) nativeSkybox;
auto result = (*helper)(texture);
return (long) result;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_IBLPrefilterContext_nDestroySpecularFilter(JNIEnv* env, jclass, jlong nativeObject) {
delete (IBLPrefilterContext::SpecularFilter*) nativeObject;
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2021 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 <viewer/RemoteServer.h>
using namespace filament::viewer;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_utils_RemoteServer_nCreate(JNIEnv* env, jclass, jint port) {
RemoteServer* server = new RemoteServer(port);
if (!server->isValid()) {
delete server;
return 0;
}
return (jlong) server;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_RemoteServer_nDestroy(JNIEnv*, jclass, jlong native) {
RemoteServer* server = (RemoteServer*) native;
delete server;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_google_android_filament_utils_RemoteServer_nPeekIncomingLabel(JNIEnv* env, jclass, jlong native) {
RemoteServer* server = (RemoteServer*) native;
char const* label = server->peekIncomingLabel();
return label ? env->NewStringUTF(label) : nullptr;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_google_android_filament_utils_RemoteServer_nPeekReceivedLabel(JNIEnv* env, jclass, jlong native) {
RemoteServer* server = (RemoteServer*) native;
ReceivedMessage const* msg = server->peekReceivedMessage();
return msg ? env->NewStringUTF(msg->label) : nullptr;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_utils_RemoteServer_nPeekReceivedBufferLength(JNIEnv* env, jclass, jlong native) {
RemoteServer* server = (RemoteServer*) native;
ReceivedMessage const* msg = server->peekReceivedMessage();
return msg ? msg->bufferByteCount : 0;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_utils_RemoteServer_nAcquireReceivedMessage(JNIEnv* env, jclass, jlong native, jobject buffer, jint length) {
RemoteServer* server = (RemoteServer*) native;
ReceivedMessage const* msg = server->acquireReceivedMessage();
if (msg == nullptr) {
return;
}
void* address = env->GetDirectBufferAddress(buffer);
if (address == nullptr) {
// This should never happen because the Java layer does allocateDirect.
return;
}
memcpy(address, msg->buffer, length);
server->releaseReceivedMessage(msg);
}

View File

@@ -28,7 +28,10 @@ using namespace filament;
using namespace filament::math;
using namespace image;
static jlong nCreateTexture(JNIEnv* env, jclass,
jlong nCreateHDRTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jint internalFormat);
static jlong nCreateKTXTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
@@ -73,6 +76,19 @@ static jlong nCreateSkybox(JNIEnv* env, jclass,
return (jlong) Skybox::Builder().environment(cubemap).showSun(true).build(*engine);
}
static jboolean nGetSphericalHarmonics(JNIEnv* env, jclass, jobject javaBuffer, jint remaining,
jfloatArray outSphericalHarmonics_) {
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle bundle((const uint8_t*) buffer.getData(), buffer.getSize());
jfloat* outSphericalHarmonics = env->GetFloatArrayElements(outSphericalHarmonics_, nullptr);
const auto success = bundle.getSphericalHarmonics(
reinterpret_cast<filament::math::float3*>(outSphericalHarmonics)
);
env->ReleaseFloatArrayElements(outSphericalHarmonics_, outSphericalHarmonics, JNI_ABORT);
return success ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv* env;
@@ -80,15 +96,27 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
return -1;
}
jclass c = env->FindClass("com/google/android/filament/utils/KtxLoader");
if (c == nullptr) return JNI_ERR;
int rc;
static const JNINativeMethod methods[] = {
{"nCreateTexture", "(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateTexture)},
{"nCreateIndirectLight", "(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateIndirectLight)},
{"nCreateSkybox", "(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateSkybox)},
// KTXLoader
jclass ktxloaderClass = env->FindClass("com/google/android/filament/utils/KTXLoader");
if (ktxloaderClass == nullptr) return JNI_ERR;
static const JNINativeMethod ktxMethods[] = {
{(char*)"nCreateKTXTexture", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateKTXTexture)},
{(char*)"nCreateIndirectLight", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateIndirectLight)},
{(char*)"nCreateSkybox", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateSkybox)},
{(char*)"nGetSphericalHarmonics", (char*)"(Ljava/nio/Buffer;I[F)Z", reinterpret_cast<void*>(nGetSphericalHarmonics)},
};
int rc = env->RegisterNatives(c, methods, sizeof(methods) / sizeof(JNINativeMethod));
rc = env->RegisterNatives(ktxloaderClass, ktxMethods, sizeof(ktxMethods) / sizeof(JNINativeMethod));
if (rc != JNI_OK) return rc;
// HDRLoader
jclass hdrloaderClass = env->FindClass("com/google/android/filament/utils/HDRLoader");
if (hdrloaderClass == nullptr) return JNI_ERR;
static const JNINativeMethod hdrMethods[] = {
{(char*)"nCreateHDRTexture", (char*)"(JLjava/nio/Buffer;II)J", reinterpret_cast<void*>(nCreateHDRTexture)},
};
rc = env->RegisterNatives(hdrloaderClass, hdrMethods, sizeof(hdrMethods) / sizeof(JNINativeMethod));
if (rc != JNI_OK) return rc;
return JNI_VERSION_1_6;

View File

@@ -0,0 +1,256 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.filament.ColorGrading;
import com.google.android.filament.Engine;
import com.google.android.filament.Entity;
import com.google.android.filament.IndirectLight;
import com.google.android.filament.LightManager;
import com.google.android.filament.Scene;
import com.google.android.filament.View;
import com.google.android.filament.MaterialInstance;
import com.google.android.filament.Renderer;
/**
* The AutomationEngine makes it easy to push a bag of settings values to Filament.
* It can also be used to iterate through settings permutations for testing purposes.
*
* When creating an automation engine for testing purposes, clients give it a JSON string that
* tells it how to generate permutations of settings. Automation is always in one of two states:
* running or idle. The running state can be entered immediately (startRunning) or by requesting
* batch mode (startBatchMode).
*
* When executing a test, clients should call tick() after each frame is rendered, which provides an
* opportunity to push settings to Filament, increment the current test index (if enough time has
* elapsed), and request an asychronous screenshot.
*
* The time to sleep between tests is configurable and can be set to zero. Automation also waits a
* specified minimum number of frames between tests.
*
* Batch mode is meant for non-interactive applications. In batch mode, automation defers applying
* the first test case until the client unblocks it via signalBatchMode(). This is useful when
* waiting for a large model file to become fully loaded. Batch mode also offers a query
* (shouldClose) that is triggered after the last test has been invoked.
*/
public class AutomationEngine {
private long mNativeObject;
private ColorGrading mColorGrading;
/**
* Allows users to toggle screenshots, change the sleep duration between tests, etc.
*/
public static class Options {
/**
* Minimum time that automation waits between applying a settings object and advancing
* to the next test case. Specified in seconds.
*/
public float sleepDuration = 0.2f;
/**
* Similar to sleepDuration, but expressed as a frame count. Both the minimum sleep time
* and the minimum frame count must be elapsed before automation advances to the next test.
*/
public int minFrameCount = 2;
/**
* If true, test progress is dumped to the utils Log (info priority).
*/
public boolean verbose = true;
}
/**
* Allows remote control for the viewer.
*/
public static class ViewerOptions {
public float cameraAperture = 16.0f;
public float cameraSpeed = 125.0f;
public float cameraISO = 100.0f;
public float groundShadowStrength = 0.75f;
public boolean groundPlaneEnabled = false;
public boolean skyboxEnabled = true;
public float cameraFocalLength = 28.0f;
public float cameraFocusDistance = 0.0f;
}
/**
* Creates an automation engine from a JSON specification.
*
* An example of a JSON spec can be found by searching the repo for DEFAULT_AUTOMATION.
* This is documented using a JSON schema (look for viewer/schemas/automation.json).
*
* @param jsonSpec Valid JSON string that conforms to the automation schema.
*/
public AutomationEngine(@NonNull String jsonSpec) {
mNativeObject = nCreateAutomationEngine(jsonSpec);
if (mNativeObject == 0) throw new IllegalStateException("Couldn't create AutomationEngine");
}
/**
* Creates an automation engine for the sole purpose of pushing settings, or for executing
* the default test sequence.
*
* To see how the default test sequence is generated, search for DEFAULT_AUTOMATION.
*/
public AutomationEngine() {
mNativeObject = nCreateDefaultAutomationEngine();
if (mNativeObject == 0) throw new IllegalStateException("Couldn't create AutomationEngine");
}
/**
* Configures the automation engine for users who wish to set up a custom sleep time
* between tests, etc.
*/
public void setOptions(@NonNull Options options) {
nSetOptions(mNativeObject, options.sleepDuration, options.minFrameCount, options.verbose);
}
/**
* Activates the automation test. During the subsequent call to tick(), the first test is
* applied and automation enters the running state.
*/
public void startRunning() { nStartRunning(mNativeObject); }
/**
* Activates the automation test, but enters a paused state until the user calls
* signalBatchMode().
*/
public void startBatchMode() { nStartBatchMode(mNativeObject); }
/**
* Notifies the automation engine that time has passed and a new frame has been rendered.
*
* This is when settings get applied, screenshots are (optionally) exported, and the internal
* test counter is potentially incremented.
*
* @param view The Filament View that automation pushes changes to.
* @param materials Optional set of of materials that can receive parameter tweaks.
* @param renderer The Filament Renderer that can be used to take screenshots.
* @param deltaTime The amount of time that has passed since the previous tick in seconds.
*/
public void tick(@NonNull View view, @Nullable MaterialInstance[] materials,
@NonNull Renderer renderer, float deltaTime) {
long[] nativeMaterialInstances = null;
if (materials != null) {
nativeMaterialInstances = new long[materials.length];
for (int i = 0; i < nativeMaterialInstances.length; i++) {
nativeMaterialInstances[i] = materials[i].getNativeObject();
}
}
long nativeView = view.getNativeObject();
long nativeRenderer = renderer.getNativeObject();
nTick(mNativeObject, nativeView, nativeMaterialInstances, nativeRenderer, deltaTime);
}
/**
* Mutates a set of client-owned Filament objects according to a JSON string.
*
* This method is an alternative to tick(). It allows clients to use the automation engine as a
* remote control, as opposed to iterating through a predetermined test sequence.
*
* This updates the stashed Settings object, then pushes those settings to the given
* Filament objects. Clients can optionally call getColorGrading() after calling this method.
*/
public void applySettings(@NonNull String settingsJson, @NonNull View view,
@Nullable MaterialInstance[] materials, @Nullable IndirectLight ibl, @Entity int light,
@NonNull LightManager lm, @NonNull Scene scene, @NonNull Renderer renderer) {
long[] nativeMaterialInstances = null;
if (materials != null) {
nativeMaterialInstances = new long[materials.length];
for (int i = 0; i < nativeMaterialInstances.length; i++) {
nativeMaterialInstances[i] = materials[i].getNativeObject();
}
}
long nativeView = view.getNativeObject();
long nativeIbl = ibl == null ? 0 : ibl.getNativeObject();
long nativeLm = lm.getNativeObject();
long nativeScene = scene.getNativeObject();
long nativeRenderer = renderer.getNativeObject();
nApplySettings(mNativeObject, settingsJson, nativeView, nativeMaterialInstances,
nativeIbl, light, nativeLm, nativeScene, nativeRenderer);
}
/**
* Gets the current viewer options.
*
* NOTE: Focal length here might be different from the user-specified value, due to DoF options.
*/
@NonNull
public ViewerOptions getViewerOptions() {
ViewerOptions result = new ViewerOptions();
nGetViewerOptions(mNativeObject, result);
return result;
}
/**
* Gets a color grading object that corresponds to the latest settings.
*
* This method either returns a cached instance, or it destroys the cached instance and creates
* a new one.
*/
@NonNull
public ColorGrading getColorGrading(@NonNull Engine engine) {
// The native layer automatically destroys the old color grading instance,
// so there is no need to call Engine#destroyColorGrading here.
long nativeCg = nGetColorGrading(mNativeObject, engine.getNativeObject());
if (mColorGrading == null || mColorGrading.getNativeObject() != nativeCg) {
mColorGrading = nativeCg == 0 ? null : new ColorGrading(nativeCg);
}
return mColorGrading;
}
/**
* Signals that batch mode can begin. Call this after all meshes and textures finish loading.
*/
public void signalBatchMode() { nSignalBatchMode(mNativeObject); }
/**
* Cancels an in-progress automation session.
*/
public void stopRunning() { nStopRunning(mNativeObject); }
/**
* Returns true if automation is in batch mode and all tests have finished.
*/
public boolean shouldClose() { return nShouldClose(mNativeObject); }
@Override
protected void finalize() throws Throwable {
nDestroy(mNativeObject);
super.finalize();
}
private static native long nCreateAutomationEngine(String jsonSpec);
private static native long nCreateDefaultAutomationEngine();
private static native void nSetOptions(long nativeObject, float sleepDuration,
int minFrameCount, boolean verbose);
private static native void nStartRunning(long nativeObject);
private static native void nStartBatchMode(long nativeObject);
private static native void nTick(long nativeObject, long view, long[] materials, long renderer,
float deltaTime);
private static native void nApplySettings(long nativeObject, String jsonSettings, long view,
long[] materials, long ibl, int light, long lightManager, long scene, long renderer);
private static native void nGetViewerOptions(long nativeObject, Object result);
private static native long nGetColorGrading(long nativeObject, long nativeEngine);
private static native void nSignalBatchMode(long nativeObject);
private static native void nStopRunning(long nativeObject);
private static native boolean nShouldClose(long nativeObject);
private static native void nDestroy(long nativeObject);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils
import com.google.android.filament.Engine
import com.google.android.filament.Texture
import java.nio.Buffer
/**
* Utility for decoding an HDR file and producing a Filament texture.
*/
object HDRLoader {
class Options {
var desiredFormat = Texture.InternalFormat.RGB16F
}
/**
* Consumes the content of an HDR file and produces a [Texture] object.
*
* @param engine Gets passed to the builder.
* @param buffer The content of the HDR File.
* @param options Loader options.
* @return The resulting Filament texture, or null on failure.
*/
fun createTexture(engine: Engine, buffer: Buffer, options: Options = Options()): Texture? {
val nativeEngine = engine.nativeObject
val nativeTexture = nCreateHDRTexture(nativeEngine, buffer, buffer.remaining(), options.desiredFormat.ordinal)
if (nativeTexture == 0L) {
return null;
}
return Texture(nativeTexture)
}
private external fun nCreateHDRTexture(nativeEngine: Long, buffer: Buffer, remaining: Int, format: Int): Long
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils;
import com.google.android.filament.Engine;
import com.google.android.filament.Texture;
/**
* IBLPrefilterContext creates and initializes GPU state common to all environment map filters
* supported. Typically, only one instance per filament Engine of this object needs to exist.
*
* Java usage example:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* context = new IBLPrefilterContext(engine);
* equirectangularToCubemap = new IBLPrefilterContext.EquirectangularToCubemap(context);
*
* Texture equirect = HDRLoader.createTexture("foo.hdr");
* Texture skyboxTexture = equirectangularToCubemap.run(equirect);
* engine.destroy(equirect);
*
* specularFilter = new IBLPrefilterContext.SpecularFilter(context);
* Texture reflections = specularFilter.run(skyboxTexture);
*
* IndirectLight ibl = IndirectLight.Builder()
* .reflections(reflections)
* .intensity(30000.0f)
* .build(engine);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
public class IBLPrefilterContext {
private final long mNativeObject;
public IBLPrefilterContext(Engine engine) {
mNativeObject = nCreate(engine.getNativeObject());
if (mNativeObject == 0) throw new IllegalStateException("Couldn't create IBLPrefilterContext");
}
@Override
protected void finalize() throws Throwable {
nDestroy(mNativeObject);
super.finalize();
}
public static class EquirectangularToCubemap {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final HelperFinalizer mFinalizer;
private final long mNativeHelper;
public EquirectangularToCubemap(IBLPrefilterContext context) {
mNativeHelper = nCreateEquirectHelper(context.mNativeObject);
mFinalizer = new HelperFinalizer(mNativeHelper);
}
public Texture run(Texture equirect) {
long nativeTexture = nEquirectHelperRun(mNativeHelper, equirect.getNativeObject());
return new Texture(nativeTexture);
}
private static class HelperFinalizer {
private final long mNativeObject;
HelperFinalizer(long nativeObject) { mNativeObject = nativeObject; }
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) { // Ignore
} finally {
nDestroyEquirectHelper(mNativeObject);
}
}
}
}
public static class SpecularFilter {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final HelperFinalizer mFinalizer;
private final long mNativeHelper;
public SpecularFilter(IBLPrefilterContext context) {
mNativeHelper = nCreateSpecularFilter(context.mNativeObject);
mFinalizer = new HelperFinalizer(mNativeHelper);
}
public Texture run(Texture skybox) {
long nativeTexture = nSpecularFilterRun(mNativeHelper, skybox.getNativeObject());
return new Texture(nativeTexture);
}
private static class HelperFinalizer {
private final long mNativeObject;
HelperFinalizer(long nativeObject) { mNativeObject = nativeObject; }
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) { // Ignore
} finally {
nDestroySpecularFilter(mNativeObject);
}
}
}
}
private static native long nCreate(long nativeEngine);
private static native void nDestroy(long nativeObject);
private static native long nCreateEquirectHelper(long nativeContext);
private static native long nEquirectHelperRun(long nativeHelper, long nativeEquirect);
private static native void nDestroyEquirectHelper(long nativeObject);
private static native long nCreateSpecularFilter(long nativeContext);
private static native long nSpecularFilterRun(long nativeHelper, long nativeSkybox);
private static native void nDestroySpecularFilter(long nativeObject);
}

View File

@@ -29,7 +29,7 @@ import java.nio.Buffer
* KTX is a simple container format that makes it easy to bundle miplevels and cubemap faces
* into a single file.
*/
object KtxLoader {
object KTXLoader {
class Options {
var srgb = false
}
@@ -44,8 +44,8 @@ object KtxLoader {
*/
fun createTexture(engine: Engine, buffer: Buffer, options: Options = Options()): Texture {
val nativeEngine = engine.nativeObject
val nativeTexture = nCreateTexture(nativeEngine, buffer, buffer.remaining(), options.srgb)
return Texture(engine, nativeTexture)
val nativeTexture = nCreateKTXTexture(nativeEngine, buffer, buffer.remaining(), options.srgb)
return Texture(nativeTexture)
}
/**
@@ -59,7 +59,7 @@ object KtxLoader {
fun createIndirectLight(engine: Engine, buffer: Buffer, options: Options = Options()): IndirectLight {
val nativeEngine = engine.nativeObject
val nativeIndirectLight = nCreateIndirectLight(nativeEngine, buffer, buffer.remaining(), options.srgb)
return IndirectLight(engine, nativeIndirectLight)
return IndirectLight(nativeIndirectLight)
}
/**
@@ -73,10 +73,23 @@ object KtxLoader {
fun createSkybox(engine: Engine, buffer: Buffer, options: Options = Options()): Skybox {
val nativeEngine = engine.nativeObject
val nativeSkybox = nCreateSkybox(nativeEngine, buffer, buffer.remaining(), options.srgb)
return Skybox(engine, nativeSkybox)
return Skybox(nativeSkybox)
}
private external fun nCreateTexture(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
/**
* Retrieves spherical harmonics from the content of a KTX file.
*
* @param buffer The content of the KTX File.
* @return The resulting array of 9 * 3 floats, or null on failure.
*/
fun getSphericalHarmonics(buffer: Buffer): FloatArray? {
val sphericalHarmonics = FloatArray(9 * 3)
val success = nGetSphericalHarmonics(buffer, buffer.remaining(), sphericalHarmonics)
return if (success) sphericalHarmonics else null
}
private external fun nCreateKTXTexture(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
private external fun nCreateIndirectLight(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
private external fun nGetSphericalHarmonics(buffer: Buffer, remaining: Int, outSphericalHarmonics: FloatArray): Boolean
private external fun nCreateSkybox(nativeEngine: Long, buffer: Buffer, remaining: Int, srgb: Boolean): Long
}

View File

@@ -27,9 +27,8 @@ import com.google.android.filament.gltfio.*
import kotlinx.coroutines.*
import java.nio.Buffer
private const val kNearPlane = 0.5
private const val kFarPlane = 10000.0
private const val kFovDegrees = 45.0
private const val kNearPlane = 0.05 // 5 cm
private const val kFarPlane = 1000.0 // 1 km
private const val kAperture = 16f
private const val kShutterSpeed = 1f / 125f
private const val kSensitivity = 100f
@@ -73,9 +72,16 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
var normalizeSkinningWeights = true
var recomputeBoundingBoxes = false
var cameraFocalLength = 28f
set(value) {
field = value
updateCameraProjection()
}
val scene: Scene
val view: View
val camera: Camera
val renderer: Renderer
@Entity val light: Int
private val uiHelper: UiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK)
@@ -87,7 +93,6 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
private var fetchResourcesJob: Job? = null
private val renderer: Renderer
private var swapChain: SwapChain? = null
private var assetLoader: AssetLoader
private var resourceLoader: ResourceLoader
@@ -100,7 +105,7 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
init {
renderer = engine.createRenderer()
scene = engine.createScene()
camera = engine.createCamera().apply { setExposure(kAperture, kShutterSpeed, kSensitivity) }
camera = engine.createCamera(engine.entityManager.create()).apply { setExposure(kAperture, kShutterSpeed, kSensitivity) }
view = engine.createView()
view.scene = scene
view.camera = camera
@@ -171,12 +176,17 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
*
* The given callback is triggered for each requested resource.
*/
fun loadModelGltf(buffer: Buffer, callback: (String) -> Buffer) {
fun loadModelGltf(buffer: Buffer, callback: (String) -> Buffer?) {
destroyModel()
asset = assetLoader.createAssetFromJson(buffer)
asset?.let { asset ->
for (uri in asset.resourceUris) {
resourceLoader.addResourceData(uri, callback(uri))
val resourceBuffer = callback(uri)
if (resourceBuffer == null) {
this.asset = null
return
}
resourceLoader.addResourceData(uri, resourceBuffer)
}
resourceLoader.asyncBeginLoad(asset)
animator = asset.animator
@@ -221,6 +231,7 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
fun destroyModel() {
fetchResourcesJob?.cancel()
resourceLoader.asyncCancelLoad()
resourceLoader.evictResourceData()
asset?.let { asset ->
this.scene.removeEntities(asset.entities)
assetLoader.destroyAsset(asset)
@@ -261,9 +272,14 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
}
private fun populateScene(asset: FilamentAsset) {
val rcm = engine.renderableManager
var count = 0
val popRenderables = {count = asset.popRenderables(readyRenderables); count != 0}
while (popRenderables()) {
for (i in 0..count-1) {
val ri = rcm.getInstance(readyRenderables[i])
rcm.setScreenSpaceContactShadows(ri, true)
}
scene.addEntities(readyRenderables.take(count).toIntArray())
}
scene.addEntities(asset.lightEntities)
@@ -283,7 +299,8 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
engine.destroyRenderer(renderer)
engine.destroyView(this@ModelViewer.view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
EntityManager.get().destroy(camera.entity)
EntityManager.get().destroy(light)
@@ -322,6 +339,13 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
}
}
private fun updateCameraProjection() {
val width = view.viewport.width
val height = view.viewport.height
val aspect = width.toDouble() / height.toDouble()
camera.setLensProjection(cameraFocalLength.toDouble(), aspect, kNearPlane, kFarPlane)
}
inner class SurfaceCallback : UiHelper.RendererCallback {
override fun onNativeWindowChanged(surface: Surface) {
swapChain?.let { engine.destroySwapChain(it) }
@@ -341,9 +365,8 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener {
override fun onResized(width: Int, height: Int) {
view.viewport = Viewport(0, 0, width, height)
val aspect = width.toDouble() / height.toDouble()
camera.setProjection(kFovDegrees, aspect, kNearPlane, kFarPlane, Camera.Fov.VERTICAL)
cameraManipulator.setViewport(width, height)
updateCameraProjection()
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament.utils;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Manages a tiny WebSocket server that can receive model data and viewer settings.
*
* Client apps can call acquireReceivedMessage to check for new data and pop it off the small
* internal queue.
*/
public class RemoteServer {
private long mNativeObject;
/**
* Encapsulates a message sent from the web client.
*/
public static class ReceivedMessage {
public String label;
public ByteBuffer buffer;
}
public RemoteServer(int port) {
mNativeObject = nCreate(port);
if (mNativeObject == 0) throw new IllegalStateException("Couldn't create RemoteServer");
}
/**
* Checks if a download is currently in progress and returns its label.
* Returns null if nothing is being downloaded.
*/
public @Nullable String peekIncomingLabel() {
return nPeekIncomingLabel(mNativeObject);
}
/**
* Checks if a peeked message has JSON content.
*/
public static boolean isJson(@Nullable String label) {
return label != null && label.endsWith(".json");
}
/**
* Checks if a peeked message has binary content.
*/
public static boolean isBinary(@Nullable String label) {
return label != null && !label.endsWith(".json");
}
/**
* Pops a message off the incoming queue or returns null if there are no unread messages.
*/
public @Nullable ReceivedMessage acquireReceivedMessage() {
int length = nPeekReceivedBufferLength(mNativeObject);
if (length == 0) {
return null;
}
ReceivedMessage message = new ReceivedMessage();
message.label = nPeekReceivedLabel(mNativeObject);
message.buffer = ByteBuffer.allocateDirect(length);
message.buffer.order(ByteOrder.LITTLE_ENDIAN);
nAcquireReceivedMessage(mNativeObject, message.buffer, length);
return message;
}
/*
* Destroys the native WebSocket server and frees up the port.
*
* This might need to be done explicitly (as opposed to waiting for gc) to free up the port.
*/
public void close() {
nDestroy(mNativeObject);
mNativeObject = 0;
}
@Override
protected void finalize() throws Throwable {
nDestroy(mNativeObject);
super.finalize();
}
private static native long nCreate(int port);
private static native String nPeekIncomingLabel(long nativeObject);
private static native String nPeekReceivedLabel(long nativeObject);
private static native int nPeekReceivedBufferLength(long nativeObject);
private static native void nAcquireReceivedMessage(long nativeObject, ByteBuffer buffer, int length);
private static native void nDestroy(long nativeObject);
}

View File

@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.19)
project(gltfio-android)
set(FILAMENT_DIR ${FILAMENT_DIST_DIR})
set(GLTFIO_DIR ../../libs/gltfio)
@@ -44,7 +45,11 @@ set(GLTFIO_SRCS
${GLTFIO_DIR}/src/FilamentInstance.cpp
${GLTFIO_DIR}/src/GltfEnums.h
${GLTFIO_DIR}/src/MaterialProvider.cpp
${GLTFIO_DIR}/src/MorphHelper.h
${GLTFIO_DIR}/src/MorphHelper.cpp
${GLTFIO_DIR}/src/ResourceLoader.cpp
${GLTFIO_DIR}/src/TangentsJob.h
${GLTFIO_DIR}/src/TangentsJob.cpp
${GLTFIO_DIR}/src/UbershaderLoader.cpp
${GLTFIO_DIR}/src/Wireframe.cpp
${GLTFIO_DIR}/src/Wireframe.h

View File

@@ -70,6 +70,13 @@ Java_com_google_android_filament_gltfio_ResourceLoader_nHasResourceData(JNIEnv*
return status;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nEvictResourceData(JNIEnv*, jclass,
jlong nativeLoader) {
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
loader->evictResourceData();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nLoadResources(JNIEnv*, jclass,
jlong nativeLoader, jlong nativeAsset) {

View File

@@ -101,6 +101,15 @@ public class ResourceLoader {
return nHasResourceData(mNativeObject, uri);
}
/**
* Frees memory by evicting the URI cache that was populated via addResourceData.
*
* This can be called only after a model is fully loaded or after loading has been cancelled.
*/
public void evictResourceData() {
nEvictResourceData(mNativeObject);
}
/**
* Iterates through all external buffers and images and creates corresponding Filament objects
* (vertex buffers, textures, etc), which become owned by the asset.
@@ -161,6 +170,7 @@ public class ResourceLoader {
private static native void nDestroyResourceLoader(long nativeLoader);
private static native void nAddResourceData(long nativeLoader, String url, Buffer buffer,
int remaining);
private static native void nEvictResourceData(long nativeLoader);
private static native boolean nHasResourceData(long nativeLoader, String url);
private static native void nLoadResources(long nativeLoader, long nativeAsset);
private static native boolean nAsyncBeginLoad(long nativeLoader, long nativeAsset);

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.9.14
VERSION_NAME=1.10.5
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

Binary file not shown.

View File

@@ -1,6 +1,5 @@
#Thu Nov 05 09:33:02 PST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

53
android/gradlew vendored
View File

@@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ 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"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -66,6 +82,7 @@ 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
@@ -109,10 +126,11 @@ 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
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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
@@ -138,19 +156,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $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" ;;
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
@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
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" "$@"

43
android/gradlew.bat vendored
View File

@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@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"
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@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
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ 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%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

@@ -36,4 +36,5 @@ dependencies {
implementation project(':filament-android')
implementation project(':gltfio-android')
implementation project(':filament-utils-android')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
}

View File

@@ -10,7 +10,8 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:largeHeap="true"
android:theme="@android:style/Theme.NoTitleBar">
<activity android:name="com.google.android.filament.gltf.MainActivity"
android:screenOrientation="fullSensor"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">

View File

@@ -19,33 +19,58 @@ package com.google.android.filament.gltf
import android.annotation.SuppressLint
import android.app.Activity
import android.os.Bundle
import android.view.Choreographer
import android.util.Log
import android.view.*
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.SurfaceView
import com.google.android.filament.utils.KtxLoader
import com.google.android.filament.utils.ModelViewer
import com.google.android.filament.utils.Utils
import android.widget.TextView
import android.widget.Toast
import com.google.android.filament.Fence
import com.google.android.filament.IndirectLight
import com.google.android.filament.Skybox
import com.google.android.filament.utils.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileInputStream
import java.io.RandomAccessFile
import java.nio.Buffer
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
import java.util.zip.ZipInputStream
class MainActivity : Activity() {
companion object {
// Load the library for the utility layer, which in turn loads gltfio and the Filament core.
init { Utils.init() }
private const val TAG = "gltf-viewer"
}
private lateinit var surfaceView: SurfaceView
private lateinit var choreographer: Choreographer
private val frameScheduler = FrameCallback()
private lateinit var modelViewer: ModelViewer
private lateinit var titlebarHint: TextView
private val doubleTapListener = DoubleTapListener()
private lateinit var doubleTapDetector: GestureDetector
private var remoteServer: RemoteServer? = null
private var statusToast: Toast? = null
private var statusText: String? = null
private var latestDownload: String? = null
private val automation = AutomationEngine()
private var loadStartTime = 0L
private var loadStartFence: Fence? = null
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
surfaceView = SurfaceView(this).apply { setContentView(this) }
setContentView(R.layout.simple_layout)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
titlebarHint = findViewById(R.id.user_hint)
surfaceView = findViewById(R.id.main_sv)
choreographer = Choreographer.getInstance()
doubleTapDetector = GestureDetector(applicationContext, doubleTapListener)
@@ -58,23 +83,28 @@ class MainActivity : Activity() {
true
}
createRenderables()
createDefaultRenderables()
createIndirectLight()
val dynamicResolutionOptions = modelViewer.view.dynamicResolutionOptions
dynamicResolutionOptions.enabled = true
modelViewer.view.dynamicResolutionOptions = dynamicResolutionOptions
setStatusText("To load a new model, go to the above URL on your host machine.")
val ssaoOptions = modelViewer.view.ambientOcclusionOptions
ssaoOptions.enabled = true
modelViewer.view.ambientOcclusionOptions = ssaoOptions
val view = modelViewer.view
view.dynamicResolutionOptions = view.dynamicResolutionOptions.apply {
enabled = true
}
val bloomOptions = modelViewer.view.bloomOptions
bloomOptions.enabled = true
modelViewer.view.bloomOptions = bloomOptions
view.ambientOcclusionOptions = view.ambientOcclusionOptions.apply {
enabled = true
}
view.bloomOptions = view.bloomOptions.apply {
enabled = true
}
remoteServer = RemoteServer(8082)
}
private fun createRenderables() {
private fun createDefaultRenderables() {
val buffer = assets.open("models/scene.gltf").use { input ->
val bytes = ByteArray(input.available())
input.read(bytes)
@@ -90,11 +120,11 @@ class MainActivity : Activity() {
val scene = modelViewer.scene
val ibl = "default_env"
readCompressedAsset("envs/$ibl/${ibl}_ibl.ktx").let {
scene.indirectLight = KtxLoader.createIndirectLight(engine, it)
scene.indirectLight = KTXLoader.createIndirectLight(engine, it)
scene.indirectLight!!.intensity = 30_000.0f
}
readCompressedAsset("envs/$ibl/${ibl}_skybox.ktx").let {
scene.skybox = KtxLoader.createSkybox(engine, it)
scene.skybox = KTXLoader.createSkybox(engine, it)
}
}
@@ -105,6 +135,154 @@ class MainActivity : Activity() {
return ByteBuffer.wrap(bytes)
}
private fun clearStatusText() {
statusToast?.let {
it.cancel()
statusText = null
}
}
private fun setStatusText(text: String) {
runOnUiThread {
if (statusToast == null || statusText != text) {
statusText = text
statusToast = Toast.makeText(applicationContext, text, Toast.LENGTH_SHORT)
statusToast!!.show()
}
}
}
private suspend fun loadGlb(message: RemoteServer.ReceivedMessage) {
withContext(Dispatchers.Main) {
modelViewer.destroyModel()
modelViewer.loadModelGlb(message.buffer)
modelViewer.transformToUnitCube()
loadStartTime = System.nanoTime()
loadStartFence = modelViewer.engine.createFence()
}
}
private suspend fun loadHdr(message: RemoteServer.ReceivedMessage) {
withContext(Dispatchers.Main) {
val engine = modelViewer.engine
val equirect = HDRLoader.createTexture(engine, message.buffer)
if (equirect == null) {
setStatusText("Could not decode HDR file.")
} else {
setStatusText("Successfully decoded HDR file.")
val context = IBLPrefilterContext(engine)
val equirectToCubemap = IBLPrefilterContext.EquirectangularToCubemap(context)
val skyboxTexture = equirectToCubemap.run(equirect)!!
engine.destroyTexture(equirect)
val specularFilter = IBLPrefilterContext.SpecularFilter(context)
val reflections = specularFilter.run(skyboxTexture)
val ibl = IndirectLight.Builder()
.reflections(reflections)
.intensity(30000.0f)
.build(engine)
val sky = Skybox.Builder().environment(skyboxTexture).build(engine)
modelViewer.scene.skybox = sky
modelViewer.scene.indirectLight = ibl
}
}
}
private suspend fun loadZip(message: RemoteServer.ReceivedMessage) {
// To alleviate memory pressure, remove the old model before deflating the zip.
withContext(Dispatchers.Main) {
modelViewer.destroyModel()
}
// Large zip files should first be written to a file to prevent OOM.
// It is also crucial that we null out the message "buffer" field.
val (zipStream, zipFile) = withContext(Dispatchers.IO) {
val file = File.createTempFile("incoming", "zip", cacheDir)
val raf = RandomAccessFile(file, "rw")
raf.getChannel().write(message.buffer);
message.buffer = null
raf.seek(0)
Pair(FileInputStream(file), file)
}
// Deflate each resource using the IO dispatcher, one by one.
var gltfPath: String? = null
var outOfMemory: String? = null
val pathToBufferMapping = withContext(Dispatchers.IO) {
val deflater = ZipInputStream(zipStream)
val mapping = HashMap<String, Buffer>()
while (true) {
val entry = deflater.nextEntry ?: break
if (entry.isDirectory) continue
// This isn't strictly required, but as an optimization
// we ignore common junk that often pollutes ZIP files.
if (entry.name.startsWith("__MACOSX")) continue
if (entry.name.startsWith(".DS_Store")) continue
val uri = entry.name
val byteArray: ByteArray? = try {
deflater.readBytes()
}
catch (e: OutOfMemoryError) {
outOfMemory = uri
break
}
Log.i(TAG, "Deflated ${byteArray!!.size} bytes from $uri")
val buffer = ByteBuffer.wrap(byteArray)
mapping[uri] = buffer
if (uri.endsWith(".gltf") || uri.endsWith(".glb")) {
gltfPath = uri
}
}
mapping
}
zipFile.delete()
if (gltfPath == null) {
setStatusText("Could not find .gltf or .glb in the zip.")
return
}
if (outOfMemory != null) {
setStatusText("Out of memory while deflating $outOfMemory")
return
}
val gltfBuffer = pathToBufferMapping[gltfPath]!!
// The gltf is often not at the root level (e.g. if a folder is zipped) so
// we need to extract its path in order to resolve the embedded uri strings.
var gltfPrefix = gltfPath!!.substringBeforeLast('/', "")
if (gltfPrefix.isNotEmpty()) {
gltfPrefix += "/"
}
withContext(Dispatchers.Main) {
if (gltfPath!!.endsWith(".glb")) {
modelViewer.loadModelGlb(gltfBuffer)
} else {
modelViewer.loadModelGltf(gltfBuffer) { uri ->
val path = gltfPrefix + uri
if (!pathToBufferMapping.contains(path)) {
Log.e(TAG, "Could not find $path in the zip.")
setStatusText("Zip is missing $path")
}
pathToBufferMapping[path]
}
}
modelViewer.transformToUnitCube()
loadStartTime = System.nanoTime()
loadStartFence = modelViewer.engine.createFence()
}
}
override fun onResume() {
super.onResume()
choreographer.postFrameCallback(frameScheduler)
@@ -118,6 +296,31 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
choreographer.removeFrameCallback(frameScheduler)
remoteServer?.close()
}
fun loadModelData(message: RemoteServer.ReceivedMessage) {
Log.i(TAG, "Downloaded model ${message.label} (${message.buffer.capacity()} bytes)")
clearStatusText()
titlebarHint.text = message.label
CoroutineScope(Dispatchers.IO).launch {
if (message.label.endsWith(".zip")) {
loadZip(message)
} else if (message.label.endsWith(".hdr")) {
loadHdr(message)
} else {
loadGlb(message)
}
}
}
fun loadSettings(message: RemoteServer.ReceivedMessage) {
val json = StandardCharsets.UTF_8.decode(message.buffer).toString()
automation.applySettings(json, modelViewer.view, null,
modelViewer.scene.indirectLight, modelViewer.light, modelViewer.engine.lightManager,
modelViewer.scene, modelViewer.renderer)
modelViewer.view.colorGrading = automation.getColorGrading((modelViewer.engine))
modelViewer.cameraFocalLength = automation.viewerOptions.cameraFocalLength
}
inner class FrameCallback : Choreographer.FrameCallback {
@@ -125,6 +328,16 @@ class MainActivity : Activity() {
override fun doFrame(frameTimeNanos: Long) {
choreographer.postFrameCallback(this)
loadStartFence?.let {
if (it.wait(Fence.Mode.FLUSH, 0) == Fence.FenceStatus.CONDITION_SATISFIED) {
val end = System.nanoTime()
val total = (end - loadStartTime) / 1_000_000
Log.i(TAG, "The Filament backend took ${total} ms to load the model geometry.")
modelViewer.engine.destroyFence(it)
loadStartFence = null
}
}
modelViewer.animator?.apply {
if (animationCount > 0) {
val elapsedTimeSeconds = (frameTimeNanos - startTime).toDouble() / 1_000_000_000
@@ -134,14 +347,35 @@ class MainActivity : Activity() {
}
modelViewer.render(frameTimeNanos)
// Check if a new download is in progress. If so, let the user know with toast.
val currentDownload = remoteServer?.peekIncomingLabel()
if (RemoteServer.isBinary(currentDownload) && currentDownload != latestDownload) {
latestDownload = currentDownload
Log.i(TAG, "Downloading $currentDownload")
setStatusText("Downloading $currentDownload")
}
// Check if a new message has been fully received from the client.
val message = remoteServer?.acquireReceivedMessage()
if (message != null) {
if (message.label == latestDownload) {
latestDownload = null
}
if (RemoteServer.isJson(message.label)) {
loadSettings(message)
} else {
loadModelData(message)
}
}
}
}
// Just for testing purposes, this releases the model and reloads it.
// Just for testing purposes, this releases the current model and reloads the default model.
inner class DoubleTapListener : GestureDetector.SimpleOnGestureListener() {
override fun onDoubleTap(e: MotionEvent?): Boolean {
modelViewer.destroyModel()
createRenderables()
createDefaultRenderables()
return super.onDoubleTap(e)
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/simple_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/user_hint"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center|center_horizontal|center_vertical"
android:text="https://google.github.io/filament/remote"
android:textIsSelectable="true"
android:textSize="18sp"
android:textStyle="bold" />
<SurfaceView
android:id="@+id/main_sv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>

View File

@@ -109,7 +109,8 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -342,13 +343,14 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -113,7 +113,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -271,12 +271,13 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -113,7 +113,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -249,12 +249,13 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -114,7 +114,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -358,13 +358,14 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -101,7 +101,7 @@ class FilamentLiveWallpaper : WallpaperService() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -167,7 +167,8 @@ class FilamentLiveWallpaper : WallpaperService() {
engine.destroyRenderer(renderer)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
EntityManager.get().destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly
@@ -221,4 +222,4 @@ class FilamentLiveWallpaper : WallpaperService() {
}
}
}
}
}

View File

@@ -112,7 +112,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -289,12 +289,13 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -65,6 +65,7 @@ class MainActivity : Activity() {
private lateinit var view1: View
private lateinit var view2: View
private lateinit var view3: View
private lateinit var view4: View
// We need skybox to set the background color
private lateinit var skybox: Skybox
// Should be pretty obvious :)
@@ -119,16 +120,20 @@ class MainActivity : Activity() {
view1 = engine.createView()
view2 = engine.createView()
view3 = engine.createView()
view4 = engine.createView()
view0.setName("view0");
view1.setName("view1");
view2.setName("view2");
view3.setName("view3");
view4.setName("view4");
view4.blendMode = View.BlendMode.TRANSLUCENT;
skybox = Skybox.Builder().build(engine);
scene.skybox = skybox
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupViews() {
@@ -136,11 +141,13 @@ class MainActivity : Activity() {
view1.camera = camera
view2.camera = camera
view3.camera = camera
view4.camera = camera
view0.scene = scene
view1.scene = scene
view2.scene = scene
view3.scene = scene
view4.scene = scene
}
private fun setupScene() {
@@ -373,15 +380,17 @@ class MainActivity : Activity() {
engine.destroyView(view1)
engine.destroyView(view2)
engine.destroyView(view3)
engine.destroyView(view4)
engine.destroySkybox(skybox)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly
@@ -410,6 +419,9 @@ class MainActivity : Activity() {
skybox.setColor(0.0f, 0.0f, 1.0f, 1.0f);
renderer.render(view3)
skybox.setColor(0.0f, 0.0f, 0.0f, 0.0f);
renderer.render(view4)
renderer.endFrame()
}
}
@@ -442,6 +454,7 @@ class MainActivity : Activity() {
view1.viewport = Viewport(width / 2, 0, width / 2, height / 2)
view2.viewport = Viewport(0, height / 2, width / 2, height / 2)
view3.viewport = Viewport(width / 2, height / 2, width / 2, height / 2)
view4.viewport = Viewport(width / 4, height / 4, width / 2, height / 2)
}
}

View File

@@ -148,7 +148,7 @@ public class MainActivity extends Activity
mRenderer = mEngine.createRenderer();
mScene = mEngine.createScene();
mView = mEngine.createView();
mCamera = mEngine.createCamera();
mCamera = mEngine.createCamera(mEngine.getEntityManager().create());
mCamera.lookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
@@ -223,9 +223,10 @@ public class MainActivity extends Activity
mEngine.destroyView(mView);
mEngine.destroyScene(mScene);
mEngine.destroyCamera(mCamera);
mEngine.destroyCameraComponent(mCamera.getEntity());
EntityManager.get().destroy(mPage.renderable);
EntityManager.get().destroy(mCamera.getEntity());
mEngine.destroy();
}
@@ -298,4 +299,4 @@ public class MainActivity extends Activity
canvas.drawBitmap(bmp, borderSize, borderSize, null);
return modified;
}
}
}

View File

@@ -121,7 +121,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -328,13 +328,14 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -113,7 +113,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -271,12 +271,13 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -39,5 +39,5 @@ dependencies {
implementation deps.kotlin
implementation project(':filament-android')
implementation project(':gltfio-android')
implementation project(':filament-utils-android') // required for KtxLoader
implementation project(':filament-utils-android') // required for KTXLoader
}

View File

@@ -117,7 +117,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
}
private fun setupView() {
@@ -269,12 +269,13 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(light)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

View File

@@ -136,7 +136,7 @@ class MainActivity : Activity() {
renderer = engine.createRenderer()
scene = engine.createScene()
view = engine.createView()
camera = engine.createCamera()
camera = engine.createCamera(engine.entityManager.create())
// clear the swapchain with transparent pixels
val options = renderer.clearOptions
@@ -294,12 +294,13 @@ class MainActivity : Activity() {
engine.destroyMaterial(material)
engine.destroyView(view)
engine.destroyScene(scene)
engine.destroyCamera(camera)
engine.destroyCameraComponent(camera.entity)
// Engine.destroyEntity() destroys Filament related resources only
// (components), not the entity itself
val entityManager = EntityManager.get()
entityManager.destroy(renderable)
entityManager.destroy(camera.entity)
// Destroying the engine will free up any resource you may have forgotten
// to destroy, but it's recommended to do the cleanup properly

139
build.sh
View File

@@ -17,6 +17,12 @@ function print_help {
echo " Generate .tgz build archives, implies -i."
echo " -c"
echo " Clean build directories."
echo " -C"
echo " Clean build directories and revert android/ to a freshly sync'ed state."
echo " All (and only) git-ignored files under android/ are deleted."
echo " This is sometimes needed instead of -c (which still misses some clean steps)."
echo " -d"
echo " Enable matdbg and disable material optimization."
echo " -f"
echo " Always invoke CMake before incremental builds."
echo " -i"
@@ -46,6 +52,10 @@ function print_help {
echo " For macOS, this builds universal binaries for both Apple silicon and Intel-based Macs."
echo " -w"
echo " Build Web documents (compiles .md.html files to .html)."
echo " -k sample1,sample2,..."
echo " When building for Android, also build select sample APKs."
echo " sampleN is an Android sample, e.g., sample-gltf-viewer."
echo " This automatically performs a partial desktop build and install."
echo ""
echo "Build types:"
echo " release"
@@ -80,13 +90,37 @@ function print_help {
echo ""
}
function print_matdbg_help {
echo "matdbg is enabled in the build, but some extra steps are needed."
echo ""
echo "FOR DESKTOP BUILDS:"
echo ""
echo "Please set the port environment variable before launching. e.g., on macOS do:"
echo " export FILAMENT_MATDBG_PORT=8080"
echo ""
echo "FOR ANDROID BUILDS:"
echo ""
echo "1) The most reliable way to enable matdbg is to bypass Gradle and"
echo " directly modify the appropriate two lines in the following file:"
echo " ./android/filament-android/CMakeLists.txt"
echo ""
echo "2) The port number is hardcoded to 8081 so you will need to do:"
echo " adb forward tcp:8081 tcp:8081"
echo ""
echo "3) Be sure to enable INTERNET permission in your app's manifest file."
echo ""
}
# Unless explicitly specified, NDK version will be selected as highest available version within same major release chain
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/build/android/ndk.version | cut -f 1 -d ".")}
# Requirements
CMAKE_MAJOR=3
CMAKE_MINOR=10
ANDROID_NDK_VERSION=21
CMAKE_MINOR=19
# Internal variables
ISSUE_CLEAN=false
ISSUE_CLEAN_AGGRESSIVE=false
ISSUE_DEBUG_BUILD=false
ISSUE_RELEASE_BUILD=false
@@ -111,6 +145,9 @@ ISSUE_CMAKE_ALWAYS=false
ISSUE_WEB_DOCS=false
ANDROID_SAMPLES=()
BUILD_ANDROID_SAMPLES=false
RUN_TESTS=false
FILAMENT_ENABLE_JAVA=ON
@@ -122,6 +159,8 @@ VULKAN_ANDROID_GRADLE_OPTION=""
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=OFF"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
@@ -143,6 +182,12 @@ function build_clean {
rm -Rf android/filament-utils-android/build android/filament-utils-android/.externalNativeBuild android/filament-utils-android/.cxx
}
function build_clean_aggressive {
echo "Cleaning build directories..."
rm -Rf out
git clean -qfX android
}
function build_desktop_target {
local lc_target=$(echo "$1" | tr '[:upper:]' '[:lower:]')
local build_targets=$2
@@ -174,6 +219,7 @@ function build_desktop_target {
-DCMAKE_INSTALL_PREFIX="../${lc_target}/filament" \
-DFILAMENT_ENABLE_JAVA="${FILAMENT_ENABLE_JAVA}" \
${SWIFTSHADER_OPTION} \
${MATDBG_OPTION} \
${deployment_target} \
${architectures} \
../..
@@ -296,8 +342,10 @@ function build_android_target {
-G "${BUILD_GENERATOR}" \
-DIMPORT_EXECUTABLES_DIR=out \
-DCMAKE_BUILD_TYPE="$1" \
-DFILAMENT_NDK_VERSION="${FILAMENT_NDK_VERSION}" \
-DCMAKE_INSTALL_PREFIX="../android-${lc_target}/filament" \
-DCMAKE_TOOLCHAIN_FILE="../../build/toolchain-${arch}-linux-android.cmake" \
${MATDBG_OPTION} \
${VULKAN_ANDROID_OPTION} \
../..
fi
@@ -339,16 +387,9 @@ function ensure_android_build {
exit 1
fi
local ndk_side_by_side="${ANDROID_HOME}/ndk/"
if [[ -d ${ndk_side_by_side} ]]; then
# shellcheck disable=SC2012
local ndk_version=$(ls "${ndk_side_by_side}" | sort -V | tail -n 1 | cut -f 1 -d ".")
if [[ ${ndk_version} -lt ${ANDROID_NDK_VERSION} ]]; then
echo "Error: Android NDK side-by-side version ${ANDROID_NDK_VERSION} or higher must be installed, exiting"
exit 1
fi
else
echo "Error: Android NDK side-by-side version ${ANDROID_NDK_VERSION} or higher must be installed, exiting"
# shellcheck disable=SC2012
if [[ -z $(ls "${ANDROID_HOME}/ndk/" | sort -V | grep "^${FILAMENT_NDK_VERSION}") ]]; then
echo "Error: Android NDK side-by-side version ${FILAMENT_NDK_VERSION} or compatible must be installed, exiting"
exit 1
fi
@@ -372,6 +413,24 @@ function build_android {
build_desktop "${MOBILE_HOST_TOOLS}"
# When building the samples, we need to partially "install" the host tools so Gradle can see
# them.
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
mkdir -p out/debug/filament/bin
for tool in ${MOBILE_HOST_TOOLS}; do
cp out/cmake-debug/tools/${tool}/${tool} out/debug/filament/bin/
done
fi
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
mkdir -p out/release/filament/bin
for tool in ${MOBILE_HOST_TOOLS}; do
cp out/cmake-release/tools/${tool}/${tool} out/release/filament/bin/
done
fi
fi
INSTALL_COMMAND=${old_install_command}
if [[ "${ABI_ARM64_V8A}" == "true" ]]; then
@@ -411,6 +470,15 @@ function build_android {
-Pfilament_abis=${ABI_GRADLE_OPTION} \
:filamat-android:assembleDebug
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
./gradlew \
-Pfilament_dist_dir=../out/android-debug/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
:samples:${sample}:assembleDebug
done
fi
if [[ "${INSTALL_COMMAND}" ]]; then
echo "Installing out/filamat-android-debug.aar..."
cp filamat-android/build/outputs/aar/filamat-android-lite-debug.aar ../out/
@@ -426,6 +494,14 @@ function build_android {
echo "Installing out/filament-utils-android-debug.aar..."
cp filament-utils-android/build/outputs/aar/filament-utils-android-lite-debug.aar ../out/
cp filament-utils-android/build/outputs/aar/filament-utils-android-full-debug.aar ../out/filament-utils-android-debug.aar
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
echo "Installing out/${sample}-debug.apk"
cp samples/${sample}/build/outputs/apk/debug/${sample}-debug-unsigned.apk \
../out/${sample}-debug.apk
done
fi
fi
fi
@@ -443,6 +519,15 @@ function build_android {
-Pfilament_abis=${ABI_GRADLE_OPTION} \
:filamat-android:assembleRelease
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
./gradlew \
-Pfilament_dist_dir=../out/android-release/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
:samples:${sample}:assembleRelease
done
fi
if [[ "${INSTALL_COMMAND}" ]]; then
echo "Installing out/filamat-android-release.aar..."
cp filamat-android/build/outputs/aar/filamat-android-lite-release.aar ../out/
@@ -458,6 +543,14 @@ function build_android {
echo "Installing out/filament-utils-android-release.aar..."
cp filament-utils-android/build/outputs/aar/filament-utils-android-lite-release.aar ../out/
cp filament-utils-android/build/outputs/aar/filament-utils-android-full-release.aar ../out/filament-utils-android-release.aar
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
echo "Installing out/${sample}-release.apk"
cp samples/${sample}/build/outputs/apk/release/${sample}-release-unsigned.apk \
../out/${sample}-release.apk
done
fi
fi
fi
@@ -484,6 +577,7 @@ function build_ios_target {
-DPLATFORM_NAME="${platform}" \
-DIOS=1 \
-DCMAKE_TOOLCHAIN_FILE=../../third_party/clang/iOS.cmake \
${MATDBG_OPTION} \
../..
fi
@@ -654,7 +748,7 @@ function run_tests {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacfijmp:q:uvslwt" opt; do
while getopts ":hacCfijmp:q:uvslwtdk:" opt; do
case ${opt} in
h)
print_help
@@ -667,6 +761,13 @@ while getopts ":hacfijmp:q:uvslwt" opt; do
c)
ISSUE_CLEAN=true
;;
C)
ISSUE_CLEAN_AGGRESSIVE=true
;;
d)
PRINT_MATDBG_HELP=true
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_DISABLE_MATOPT=ON"
;;
f)
ISSUE_CMAKE_ALWAYS=true
;;
@@ -764,6 +865,10 @@ while getopts ":hacfijmp:q:uvslwt" opt; do
w)
ISSUE_WEB_DOCS=true
;;
k)
BUILD_ANDROID_SAMPLES=true
ANDROID_SAMPLES=$(echo "${OPTARG}" | tr ',' '\n')
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
echo ""
@@ -802,6 +907,10 @@ if [[ "${ISSUE_CLEAN}" == "true" ]]; then
build_clean
fi
if [[ "${ISSUE_CLEAN_AGGRESSIVE}" == "true" ]]; then
build_clean_aggressive
fi
if [[ "${ISSUE_DESKTOP_BUILD}" == "true" ]]; then
build_desktop
fi
@@ -825,3 +934,7 @@ fi
if [[ "${RUN_TESTS}" == "true" ]]; then
run_tests
fi
if [[ "${PRINT_MATDBG_HELP}" == "true" ]]; then
print_matdbg_help
fi

View File

@@ -8,12 +8,6 @@
#
# The default is release
NDK_VERSION="ndk;22.0.7026061"
ANDROID_NDK_VERSION=22
# Exclude Vulkan from CI builds for Android. (It is enabled for other platforms.)
EXCLUDE_VULKAN=-v
echo "This script is intended to run in a CI environment and may modify your current environment."
echo "Please refer to BUILDING.md for more information."
@@ -50,20 +44,12 @@ elif [[ "$LC_UNAME" == "darwin" ]]; then
fi
source `dirname $0`/../common/build-common.sh
# For continuous builds, do not exclude Vulkan.
if [[ "$TARGET" == "continuous" ]]; then
EXCLUDE_VULKAN=
fi
# Unless explicitly specified, NDK version will be set to match exactly the required one
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/ndk.version)}
# Only update and install the NDK if necessary, as this can be slow
ndk_side_by_side="${ANDROID_HOME}/ndk/"
if [[ -d $ndk_side_by_side ]]; then
ndk_version=`ls ${ndk_side_by_side} | sort -V | tail -n 1 | cut -f 1 -d "."`
if [[ ${ndk_version} -lt ${ANDROID_NDK_VERSION} ]]; then
${ANDROID_HOME}/tools/bin/sdkmanager "${NDK_VERSION}" > /dev/null
fi
else
${ANDROID_HOME}/tools/bin/sdkmanager "${NDK_VERSION}" > /dev/null
# Install the required NDK version specifically (if not present)
if [[ ! -d "${ANDROID_HOME}/ndk/$FILAMENT_NDK_VERSION" ]]; then
${ANDROID_HOME}/tools/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION" > /dev/null
fi
# Only build 1 32 bit and 1 64 bit target during presubmit to cut down build times
@@ -73,5 +59,11 @@ if [[ "$TARGET" == "presubmit" ]]; then
ANDROID_ABIS="-q arm64-v8a,x86"
fi
# Build the Android sample-gltf-viewer APK during release.
BUILD_SAMPLES=
if [[ "$TARGET" == "release" ]]; then
BUILD_SAMPLES="-k sample-gltf-viewer"
fi
pushd `dirname $0`/../.. > /dev/null
./build.sh -p android $EXCLUDE_VULKAN $ANDROID_ABIS -c $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION} ./build.sh -p android $ANDROID_ABIS -c $BUILD_SAMPLES $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE

View File

@@ -0,0 +1 @@
22.1.7171670

View File

@@ -134,7 +134,7 @@ git commit --amend -C HEAD
####################################################################################################
git checkout main
git branch --track "${NEW_RC_BRANCH}"
git branch "${NEW_RC_BRANCH}"
####################################################################################################
# Delete the old release candidate branch
@@ -154,7 +154,7 @@ if [[ "${PUSH_CHANGES}" == "true" ]]; then
git push origin --delete "${RC_BRANCH}"
# Push the new rc branch
git push origin "${NEW_RC_BRANCH}"
git push origin -u "${NEW_RC_BRANCH}"
else
echo ""
echo "Done."
@@ -164,7 +164,7 @@ else
echo "---------------------------------------------------------"
echo "git push origin release"
echo "git push origin --delete ${RC_BRANCH}"
echo "git push origin ${NEW_RC_BRANCH}"
echo "git push origin -u ${NEW_RC_BRANCH}"
echo "---------------------------------------------------------"
echo "Or, to undo everything:"
echo "---------------------------------------------------------"

View File

@@ -10,7 +10,7 @@ XCODEBUILD_FLAGS='CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_AL
# This sets the BUILD_DEBUG and BUILD_RELEASE variables based on the CI job.
pushd `dirname $0`/../../ios/samples
PROJECTS="hello-ar hello-gltf hello-pbr hello-triangle transparent-rendering"
PROJECTS="gltf-viewer hello-ar hello-gltf hello-pbr hello-triangle transparent-rendering"
function build_project {
local project="$1"

View File

@@ -1,6 +1,6 @@
#!/bin/bash
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-mac.zip
unzip -q ninja-mac.zip
chmod +x ninja
export PATH="$PWD:$PATH"

View File

@@ -3,9 +3,9 @@
# version of clang we want to use
GITHUB_CLANG_VERSION=8
# version of CMake to use instead of the default one
CMAKE_VERSION=3.13.4
CMAKE_VERSION=3.19.5
# version of ninja to use
NINJA_VERSION=1.8.2
NINJA_VERSION=1.10.2
# Steps for GitHub Workflows
if [[ "$GITHUB_WORKFLOW" ]]; then

View File

@@ -1,6 +1,6 @@
#!/bin/bash
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-mac.zip
unzip -q ninja-mac.zip
chmod +x ninja
export PATH="$PWD:$PATH"

View File

@@ -31,7 +31,11 @@ set(DIST_ARCH arm64-v8a)
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} HOST_NAME_L)
file(TO_CMAKE_PATH $ENV{ANDROID_HOME} ANDROID_HOME_UNIX)
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/*)
if (NOT FILAMENT_NDK_VERSION)
file(READ "${CMAKE_CURRENT_LIST_DIR}/android/ndk.version" FILAMENT_NDK_VERSION)
string(REGEX MATCH "^\\d+" FILAMENT_NDK_VERSION ${FILAMENT_NDK_VERSION})
endif()
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/${FILAMENT_NDK_VERSION}*)
list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)

View File

@@ -32,7 +32,11 @@ set(DIST_ARCH armeabi-v7a)
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} HOST_NAME_L)
file(TO_CMAKE_PATH $ENV{ANDROID_HOME} ANDROID_HOME_UNIX)
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/*)
if (NOT FILAMENT_NDK_VERSION)
file(READ "${CMAKE_CURRENT_LIST_DIR}/android/ndk.version" FILAMENT_NDK_VERSION)
string(REGEX MATCH "^\\d+" FILAMENT_NDK_VERSION ${FILAMENT_NDK_VERSION})
endif()
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/${FILAMENT_NDK_VERSION}*)
list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)

View File

@@ -31,7 +31,11 @@ set(DIST_ARCH x86)
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} HOST_NAME_L)
file(TO_CMAKE_PATH $ENV{ANDROID_HOME} ANDROID_HOME_UNIX)
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/*)
if (NOT FILAMENT_NDK_VERSION)
file(READ "${CMAKE_CURRENT_LIST_DIR}/android/ndk.version" FILAMENT_NDK_VERSION)
string(REGEX MATCH "^\\d+" FILAMENT_NDK_VERSION ${FILAMENT_NDK_VERSION})
endif()
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/${FILAMENT_NDK_VERSION}*)
list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)

View File

@@ -31,7 +31,11 @@ set(DIST_ARCH x86_64)
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} HOST_NAME_L)
file(TO_CMAKE_PATH $ENV{ANDROID_HOME} ANDROID_HOME_UNIX)
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/*)
if (NOT FILAMENT_NDK_VERSION)
file(READ "${CMAKE_CURRENT_LIST_DIR}/android/ndk.version" FILAMENT_NDK_VERSION)
string(REGEX MATCH "^\\d+" FILAMENT_NDK_VERSION ${FILAMENT_NDK_VERSION})
endif()
file(GLOB NDK_VERSIONS LIST_DIRECTORIES true ${ANDROID_HOME_UNIX}/ndk/${FILAMENT_NDK_VERSION}*)
list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)

View File

@@ -9,7 +9,7 @@ export PATH="$PWD:$PATH"
# npm install -g typescript
# Install emscripten.
curl -L https://github.com/emscripten-core/emsdk/archive/1.39.19.zip > emsdk.zip
curl -L https://github.com/emscripten-core/emsdk/archive/2.0.23.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
./emsdk install latest
./emsdk activate latest

View File

@@ -4366,7 +4366,7 @@ L_{max} &amp;= 2^{EV_{100}} \times 1.2
<span class="line"></span>
<span class="line"><span class="hljs-comment">// Computes the exposure normalization factor from</span></span>
<span class="line"><span class="hljs-comment">// the camera's EV100</span></span>
<span class="line"><span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">exposure</span><span class="hljs-params">(ev100)</span> </span>{</span>
<span class="line"><span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">exposure</span><span class="hljs-params">(<span class="hljs-keyword">float</span> ev100)</span> </span>{</span>
<span class="line"> <span class="hljs-keyword">return</span> <span class="hljs-number">1.0</span> / (<span class="hljs-built_in">pow</span>(<span class="hljs-number">2.0</span>, ev100) * <span class="hljs-number">1.2</span>);</span>
<span class="line">}</span>
<span class="line"></span>

View File

@@ -2877,7 +2877,7 @@ float exposureSettings(float aperture, float shutterSpeed, float sensitivity) {
// Computes the exposure normalization factor from
// the camera's EV100
float exposure(ev100) {
float exposure(float ev100) {
return 1.0 / (pow(2.0, ev100) * 1.2);
}

View File

@@ -77,33 +77,36 @@ counter-increment: h6;margin-right:10px}</style><style>.hljs{display:block;overf
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:parameters" class="level3"><span class="tocNumber">4.2.3&nbsp; </span>General: parameters</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:variantfilter" class="level3"><span class="tocNumber">4.2.4&nbsp; </span>General: variantFilter</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:flipuv" class="level3"><span class="tocNumber">4.2.5&nbsp; </span>General: flipUV</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:requires" class="level3"><span class="tocNumber">4.2.6&nbsp; </span>Vertex and attributes: requires</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:variables" class="level3"><span class="tocNumber">4.2.7&nbsp; </span>Vertex and attributes: variables</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:vertexdomain" class="level3"><span class="tocNumber">4.2.8&nbsp; </span>Vertex and attributes: vertexDomain</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:interpolation" class="level3"><span class="tocNumber">4.2.9&nbsp; </span>Vertex and attributes: interpolation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:blending" class="level3"><span class="tocNumber">4.2.10&nbsp; </span>Blending and transparency: blending</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:postlightingblending" class="level3"><span class="tocNumber">4.2.11&nbsp; </span>Blending and transparency: postLightingBlending</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:transparency" class="level3"><span class="tocNumber">4.2.12&nbsp; </span>Blending and transparency: transparency</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:maskthreshold" class="level3"><span class="tocNumber">4.2.13&nbsp; </span>Blending and transparency: maskThreshold</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractionmode" class="level3"><span class="tocNumber">4.2.14&nbsp; </span>Blending and transparency: refractionMode</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractiontype" class="level3"><span class="tocNumber">4.2.15&nbsp; </span>Blending and transparency: refractionType</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:culling" class="level3"><span class="tocNumber">4.2.16&nbsp; </span>Rasterization: culling</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:colorwrite" class="level3"><span class="tocNumber">4.2.17&nbsp; </span>Rasterization: colorWrite</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthwrite" class="level3"><span class="tocNumber">4.2.18&nbsp; </span>Rasterization: depthWrite</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthculling" class="level3"><span class="tocNumber">4.2.19&nbsp; </span>Rasterization: depthCulling</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:doublesided" class="level3"><span class="tocNumber">4.2.20&nbsp; </span>Rasterization: doubleSided</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" class="level3"><span class="tocNumber">4.2.21&nbsp; </span>Lighting: shadowMultiplier</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" class="level3"><span class="tocNumber">4.2.22&nbsp; </span>Lighting: clearCoatIorChange</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" class="level3"><span class="tocNumber">4.2.23&nbsp; </span>Lighting: multiBounceAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" class="level3"><span class="tocNumber">4.2.24&nbsp; </span>Lighting: specularAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" class="level3"><span class="tocNumber">4.2.25&nbsp; </span>Anti-aliasing: specularAntiAliasing</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" class="level3"><span class="tocNumber">4.2.26&nbsp; </span>Anti-aliasing: specularAntiAliasingVariance</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" class="level3"><span class="tocNumber">4.2.27&nbsp; </span>Anti-aliasing: specularAntiAliasingThreshold</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/general:quality" class="level3"><span class="tocNumber">4.2.6&nbsp; </span>General: quality</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:requires" class="level3"><span class="tocNumber">4.2.7&nbsp; </span>Vertex and attributes: requires</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:variables" class="level3"><span class="tocNumber">4.2.8&nbsp; </span>Vertex and attributes: variables</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:vertexdomain" class="level3"><span class="tocNumber">4.2.9&nbsp; </span>Vertex and attributes: vertexDomain</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/vertexandattributes:interpolation" class="level3"><span class="tocNumber">4.2.10&nbsp; </span>Vertex and attributes: interpolation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:blending" class="level3"><span class="tocNumber">4.2.11&nbsp; </span>Blending and transparency: blending</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:postlightingblending" class="level3"><span class="tocNumber">4.2.12&nbsp; </span>Blending and transparency: postLightingBlending</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:transparency" class="level3"><span class="tocNumber">4.2.13&nbsp; </span>Blending and transparency: transparency</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:maskthreshold" class="level3"><span class="tocNumber">4.2.14&nbsp; </span>Blending and transparency: maskThreshold</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractionmode" class="level3"><span class="tocNumber">4.2.15&nbsp; </span>Blending and transparency: refractionMode</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/blendingandtransparency:refractiontype" class="level3"><span class="tocNumber">4.2.16&nbsp; </span>Blending and transparency: refractionType</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:culling" class="level3"><span class="tocNumber">4.2.17&nbsp; </span>Rasterization: culling</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:colorwrite" class="level3"><span class="tocNumber">4.2.18&nbsp; </span>Rasterization: colorWrite</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthwrite" class="level3"><span class="tocNumber">4.2.19&nbsp; </span>Rasterization: depthWrite</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthculling" class="level3"><span class="tocNumber">4.2.20&nbsp; </span>Rasterization: depthCulling</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:doublesided" class="level3"><span class="tocNumber">4.2.21&nbsp; </span>Rasterization: doubleSided</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" class="level3"><span class="tocNumber">4.2.22&nbsp; </span>Lighting: shadowMultiplier</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" class="level3"><span class="tocNumber">4.2.23&nbsp; </span>Lighting: clearCoatIorChange</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" class="level3"><span class="tocNumber">4.2.24&nbsp; </span>Lighting: multiBounceAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" class="level3"><span class="tocNumber">4.2.25&nbsp; </span>Lighting: specularAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" class="level3"><span class="tocNumber">4.2.26&nbsp; </span>Anti-aliasing: specularAntiAliasing</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" class="level3"><span class="tocNumber">4.2.27&nbsp; </span>Anti-aliasing: specularAntiAliasingVariance</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" class="level3"><span class="tocNumber">4.2.28&nbsp; </span>Anti-aliasing: specularAntiAliasingThreshold</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" class="level3"><span class="tocNumber">4.2.29&nbsp; </span>Shading: customSurfaceShading</a><br>
&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock" class="level2"><span class="tocNumber">4.3&nbsp; </span>Vertex block</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock/materialvertexinputs" class="level3"><span class="tocNumber">4.3.1&nbsp; </span>Material vertex inputs</a><br>
&nbsp;&nbsp;<a href="#materialdefinitions/fragmentblock" class="level2"><span class="tocNumber">4.4&nbsp; </span>Fragment block</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/fragmentblock/preparematerialfunction" class="level3"><span class="tocNumber">4.4.1&nbsp; </span>prepareMaterial function</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/fragmentblock/materialfragmentinputs" class="level3"><span class="tocNumber">4.4.2&nbsp; </span>Material fragment inputs</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/fragmentblock/customsurfaceshading" class="level3"><span class="tocNumber">4.4.3&nbsp; </span>Custom surface shading</a><br>
&nbsp;&nbsp;<a href="#materialdefinitions/shaderpublicapis" class="level2"><span class="tocNumber">4.5&nbsp; </span>Shader public APIs</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/shaderpublicapis/types" class="level3"><span class="tocNumber">4.5.1&nbsp; </span>Types</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/shaderpublicapis/math" class="level3"><span class="tocNumber">4.5.2&nbsp; </span>Math</a><br>
@@ -217,7 +220,7 @@ designed after to offer good interoperability with other common tools and engine
</p><p>
This material model can be used to describe a large number of non-metallic surfaces (<em class="underscore">dielectrics</em>)
This material model can be used to describe many non-metallic surfaces (<em class="underscore">dielectrics</em>)
or metallic surfaces (<em class="underscore">conductors</em>).
</p><p>
@@ -245,7 +248,7 @@ in <a href="#table_standardproperties">table&nbsp;1</a>.
<tr><td style="text-align:right"> <strong class="asterisk">clearCoatNormal</strong> </td><td style="text-align:left"> A detail normal used to perturb the clear coat layer using <em class="underscore">bump mapping</em> (<em class="underscore">normal mapping</em>) </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">emissive</strong> </td><td style="text-align:left"> Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">postLightingColor</strong> </td><td style="text-align:left"> Additional color that can be blended with the result of the lighting computations. See <code>postLightingBlending</code> </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">ior</strong> </td><td style="text-align:left"> Index of refraction for refractive objects </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">ior</strong> </td><td style="text-align:left"> Index of refraction, either for refractive objects or as an alternative to reflectance </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">transmission</strong> </td><td style="text-align:left"> Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">absorption</strong> </td><td style="text-align:left"> Absorption factor for refractive objects </td></tr>
<tr><td style="text-align:right"> <strong class="asterisk">microThickness</strong> </td><td style="text-align:left"> Thickness of the thin layer of refractive objects </td></tr>
@@ -316,7 +319,7 @@ The type and range of each property is described in <a href="#table_standardprop
<p></p><p>
The index of refraction (IOR) and the reflectance represent the same physical attribute,
therefore they don't need to be both specified. Typically, only the reflectance is specified
therefore they don't need to be both specified. Typically, only the reflectance is specified,
and the IOR is deduced automatically. When only the IOR is specified, the reflectance is then
deduced automatically. It is possible to specify both, in which case their values are kept
as-is, which can lead to physically impossible materials, however, this might be desirable
@@ -755,7 +758,7 @@ and with (right)</div></div></center>
The <code>bentNormal</code> property defines the average unoccluded direction at a point on the surface. It is
used to improve the accuracy of indirect lighting. Bent normals can also improve the quality of
specular ambient occlusion (see section <a href="#toc4.2.24">4.2.24</a> about
specular ambient occlusion (see section <a href="#toc4.2.25">4.2.25</a> about
<code>specularAmbientOcclusion</code>).
</p><p>
@@ -843,7 +846,8 @@ this option for more information.
The <code>ior</code> property only affects non-metallic surfaces. This property can be used to control the
index of refraction and the specular intensity of materials. The <code>ior</code> property is intended to
be used with refractive (transmissive) materials, which are enabled when the <code>refractionMode</code> is
set to <code>cubemap</code> or <code>screenspace</code>.
set to <code>cubemap</code> or <code>screenspace</code>. It can also be used on non-refractive objects as an alternative
to setting the reflectance.
</p><p>
@@ -869,7 +873,7 @@ light to bend further away from the initial path.
<p></p><p>
The appearance of a refractive material will greatly depend on the <code>refractionType</code> and
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.15">4.2.15</a> and section <a href="#toc4.2.14">4.2.14</a>
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.16">4.2.16</a> and section <a href="#toc4.2.15">4.2.15</a>
for more information.
</p><p>
@@ -1565,7 +1569,23 @@ non-shader data.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> flipUV : false</span>
<span class="line">}</span></code></pre>
<a class="target" name="vertexandattributes:requires">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:requires">&nbsp;</a><a class="target" name="toc4.2.6">&nbsp;</a><h3>Vertex and attributes: requires</h3>
<a class="target" name="general:quality">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/general:quality">&nbsp;</a><a class="target" name="toc4.2.6">&nbsp;</a><h3>General: quality</h3>
<p>
</p><dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> Any of <code>low</code>, <code>normal</code>, <code>high</code>, <code>default</code>. Defaults to <code>default</code>.
</p></dd><dt>Description</dt><dd><p> Set some global quality parameters of the material. <code>low</code> enables optimizations that can
slightly affect correctness and is the default on mobile platforms. <code>normal</code> does not affect
correctness and is otherwise similar to <code>low</code>. <code>high</code> enables quality settings that can
adversely affect performance and is the default on desktop platforms.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> quality : default</span>
<span class="line">}</span></code></pre>
<a class="target" name="vertexandattributes:requires">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:requires">&nbsp;</a><a class="target" name="toc4.2.7">&nbsp;</a><h3>Vertex and attributes: requires</h3>
<p>
@@ -1597,7 +1617,7 @@ non-shader data.
<span class="line"> material.baseColor = texture(materialParams_texture, getUV0());</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
<a class="target" name="vertexandattributes:variables">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:variables">&nbsp;</a><a class="target" name="toc4.2.7">&nbsp;</a><h3>Vertex and attributes: variables</h3>
<a class="target" name="vertexandattributes:variables">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:variables">&nbsp;</a><a class="target" name="toc4.2.8">&nbsp;</a><h3>Vertex and attributes: variables</h3>
<p>
@@ -1644,7 +1664,7 @@ non-shader data.
<span class="line"> material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix(), u);</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
<a class="target" name="vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="toc4.2.8">&nbsp;</a><h3>Vertex and attributes: vertexDomain</h3>
<a class="target" name="vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:vertexdomain">&nbsp;</a><a class="target" name="toc4.2.9">&nbsp;</a><h3>Vertex and attributes: vertexDomain</h3>
<p>
@@ -1673,7 +1693,7 @@ non-shader data.
<p></p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> vertexDomain : device</span>
<span class="line">}</span></code></pre>
<a class="target" name="vertexandattributes:interpolation">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:interpolation">&nbsp;</a><a class="target" name="toc4.2.9">&nbsp;</a><h3>Vertex and attributes: interpolation</h3>
<a class="target" name="vertexandattributes:interpolation">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:interpolation">&nbsp;</a><a class="target" name="toc4.2.10">&nbsp;</a><h3>Vertex and attributes: interpolation</h3>
<p>
@@ -1689,7 +1709,7 @@ non-shader data.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> interpolation : flat</span>
<span class="line">}</span></code></pre>
<a class="target" name="blendingandtransparency:blending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blending">&nbsp;</a><a class="target" name="toc4.2.10">&nbsp;</a><h3>Blending and transparency: blending</h3>
<a class="target" name="blendingandtransparency:blending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blending">&nbsp;</a><a class="target" name="toc4.2.11">&nbsp;</a><h3>Blending and transparency: blending</h3>
<p>
@@ -1729,7 +1749,7 @@ non-shader data.
<p></p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> blending : transparent</span>
<span class="line">}</span></code></pre>
<a class="target" name="blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="toc4.2.11">&nbsp;</a><h3>Blending and transparency: postLightingBlending</h3>
<a class="target" name="blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:postlightingblending">&nbsp;</a><a class="target" name="toc4.2.12">&nbsp;</a><h3>Blending and transparency: postLightingBlending</h3>
<p>
@@ -1759,7 +1779,7 @@ non-shader data.
<p></p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> postLightingBlending : add</span>
<span class="line">}</span></code></pre>
<a class="target" name="blendingandtransparency:transparency">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:transparency">&nbsp;</a><a class="target" name="toc4.2.12">&nbsp;</a><h3>Blending and transparency: transparency</h3>
<a class="target" name="blendingandtransparency:transparency">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:transparency">&nbsp;</a><a class="target" name="toc4.2.13">&nbsp;</a><h3>Blending and transparency: transparency</h3>
<p>
@@ -1806,7 +1826,7 @@ and correctly sorted</div></div></center>
and sorting issues are minimized or eliminated</div></div></center>
<p></p>
<a class="target" name="blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="toc4.2.13">&nbsp;</a><h3>Blending and transparency: maskThreshold</h3>
<a class="target" name="blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:maskthreshold">&nbsp;</a><a class="target" name="toc4.2.14">&nbsp;</a><h3>Blending and transparency: maskThreshold</h3>
<p>
@@ -1822,7 +1842,7 @@ and sorting issues are minimized or eliminated</div></div></center>
<span class="line"> blending : masked,</span>
<span class="line"> maskThreshold : 0.5</span>
<span class="line">}</span></code></pre>
<a class="target" name="blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="toc4.2.14">&nbsp;</a><h3>Blending and transparency: refractionMode</h3>
<a class="target" name="blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractionmode">&nbsp;</a><a class="target" name="toc4.2.15">&nbsp;</a><h3>Blending and transparency: refractionMode</h3>
<p>
@@ -1843,7 +1863,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> refractionMode : cubemap,</span>
<span class="line">}</span></code></pre>
<a class="target" name="blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="toc4.2.15">&nbsp;</a><h3>Blending and transparency: refractionType</h3>
<a class="target" name="blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractiontype">&nbsp;</a><a class="target" name="toc4.2.16">&nbsp;</a><h3>Blending and transparency: refractionType</h3>
<p>
@@ -1862,7 +1882,7 @@ and sorting issues are minimized or eliminated</div></div></center>
<span class="line"> refractionMode : cubemap,</span>
<span class="line"> refractionType : thin,</span>
<span class="line">}</span></code></pre>
<a class="target" name="rasterization:culling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:culling">&nbsp;</a><a class="target" name="toc4.2.16">&nbsp;</a><h3>Rasterization: culling</h3>
<a class="target" name="rasterization:culling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:culling">&nbsp;</a><a class="target" name="toc4.2.17">&nbsp;</a><h3>Rasterization: culling</h3>
<p>
@@ -1876,7 +1896,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd></td></tr></tbody></table></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> culling : none</span>
<span class="line">}</span></code></pre>
<a class="target" name="rasterization:colorwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:colorwrite">&nbsp;</a><a class="target" name="toc4.2.17">&nbsp;</a><h3>Rasterization: colorWrite</h3>
<a class="target" name="rasterization:colorwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:colorwrite">&nbsp;</a><a class="target" name="toc4.2.18">&nbsp;</a><h3>Rasterization: colorWrite</h3>
<p>
@@ -1889,7 +1909,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd></td></tr></tbody></table></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> colorWrite : false</span>
<span class="line">}</span></code></pre>
<a class="target" name="rasterization:depthwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthwrite">&nbsp;</a><a class="target" name="toc4.2.18">&nbsp;</a><h3>Rasterization: depthWrite</h3>
<a class="target" name="rasterization:depthwrite">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthwrite">&nbsp;</a><a class="target" name="toc4.2.19">&nbsp;</a><h3>Rasterization: depthWrite</h3>
<p>
@@ -1902,7 +1922,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd></td></tr></tbody></table></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> depthWrite : false</span>
<span class="line">}</span></code></pre>
<a class="target" name="rasterization:depthculling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthculling">&nbsp;</a><a class="target" name="toc4.2.19">&nbsp;</a><h3>Rasterization: depthCulling</h3>
<a class="target" name="rasterization:depthculling">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:depthculling">&nbsp;</a><a class="target" name="toc4.2.20">&nbsp;</a><h3>Rasterization: depthCulling</h3>
<p>
@@ -1916,7 +1936,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> depthCulling : false</span>
<span class="line">}</span></code></pre>
<a class="target" name="rasterization:doublesided">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:doublesided">&nbsp;</a><a class="target" name="toc4.2.20">&nbsp;</a><h3>Rasterization: doubleSided</h3>
<a class="target" name="rasterization:doublesided">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/rasterization:doublesided">&nbsp;</a><a class="target" name="toc4.2.21">&nbsp;</a><h3>Rasterization: doubleSided</h3>
<p>
@@ -1932,7 +1952,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> doubleSided : true</span>
<span class="line">}</span></code></pre>
<a class="target" name="lighting:shadowmultiplier">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier">&nbsp;</a><a class="target" name="toc4.2.21">&nbsp;</a><h3>Lighting: shadowMultiplier</h3>
<a class="target" name="lighting:shadowmultiplier">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier">&nbsp;</a><a class="target" name="toc4.2.22">&nbsp;</a><h3>Lighting: shadowMultiplier</h3>
<p>
@@ -1943,6 +1963,7 @@ and sorting issues are minimized or eliminated</div></div></center>
</p></dd><dt>Description</dt><dd><p> Only available in the <code>unlit</code> shading model. If this property is enabled, the final color
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
This is only supported with shadows from directional lights.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> name : "Invisible shadow plane",</span>
@@ -1958,7 +1979,7 @@ and sorting issues are minimized or eliminated</div></div></center>
<span class="line"> material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
<a class="target" name="lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="toc4.2.22">&nbsp;</a><h3>Lighting: clearCoatIorChange</h3>
<a class="target" name="lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="toc4.2.23">&nbsp;</a><h3>Lighting: clearCoatIorChange</h3>
<p>
@@ -1980,7 +2001,7 @@ with <code>clearCoatIorChange</code> enabled (left) and disabled
(right).</div></div></center>
<p></p>
<a class="target" name="lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="toc4.2.23">&nbsp;</a><h3>Lighting: multiBounceAmbientOcclusion</h3>
<a class="target" name="lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="toc4.2.24">&nbsp;</a><h3>Lighting: multiBounceAmbientOcclusion</h3>
<p>
@@ -2009,7 +2030,7 @@ occclusion enabled (left) and disabled (right).</div></div></center>
occclusion enabled and disabled.</div></div></center>
<p></p>
<a class="target" name="lighting:specularambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion">&nbsp;</a><a class="target" name="toc4.2.24">&nbsp;</a><h3>Lighting: specularAmbientOcclusion</h3>
<a class="target" name="lighting:specularambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3>Lighting: specularAmbientOcclusion</h3>
<p>
@@ -2037,7 +2058,7 @@ occclusion enabled and disabled.</div></div></center>
particularly visible under the hose.</div></div></center>
<p></p>
<a class="target" name="anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasing</h3>
<a class="target" name="anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="toc4.2.26">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasing</h3>
<p>
@@ -2054,7 +2075,7 @@ particularly visible under the hose.</div></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> specularAntiAliasing : true</span>
<span class="line">}</span></code></pre>
<a class="target" name="anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="toc4.2.26">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingVariance</h3>
<a class="target" name="anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="toc4.2.27">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingVariance</h3>
<p>
@@ -2069,7 +2090,7 @@ particularly visible under the hose.</div></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> specularAntiAliasingVariance : 0.2</span>
<span class="line">}</span></code></pre>
<a class="target" name="anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="toc4.2.27">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingThreshold</h3>
<a class="target" name="anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="toc4.2.28">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingThreshold</h3>
<p>
@@ -2083,6 +2104,22 @@ particularly visible under the hose.</div></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> specularAntiAliasingThreshold : 0.1</span>
<span class="line">}</span></code></pre>
<a class="target" name="shading:customsurfaceshading">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading">&nbsp;</a><a class="target" name="toc4.2.29">&nbsp;</a><h3>Shading: customSurfaceShading</h3>
<p>
</p><dl><dt>Type</dt><dd><p> <code>bool</code>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
</p></dd><dt>Description</dt><dd><p> Enables custom surface shading when set to true. When surface shading is enabled, the fragment
shader must provide an extra function that will be invoked for every light in the scene that
may influence the current fragment. Please refer to the <a href="#customsurfaceshading">Custom surface shading</a> section below
for more information.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> customSurfaceShading : true</span>
<span class="line">}</span></code></pre>
<a class="target" name="vertexblock">&nbsp;</a><a class="target" name="materialdefinitions/vertexblock">&nbsp;</a><a class="target" name="toc4.3">&nbsp;</a><h2>Vertex block</h2>
<p>
@@ -2275,6 +2312,177 @@ plastic with bump mapping:
<span class="line"> <span class="hljs-type">float</span> ior; <span class="hljs-comment">// default: 1.5</span></span>
<span class="line"> <span class="hljs-type">float</span> microThickness; <span class="hljs-comment">// default: 0.0, not available with refractionType "solid"</span></span>
<span class="line">}</span></code></pre>
<a class="target" name="customsurfaceshading">&nbsp;</a><a class="target" name="materialdefinitions/fragmentblock/customsurfaceshading">&nbsp;</a><a class="target" name="toc4.4.3">&nbsp;</a><h3>Custom surface shading</h3>
<p>
When <code>customSurfaceShading</code> is set to <code>true</code> in the material block, the fragment block <strong class="asterisk">must</strong>
declare and implement the <code>surfaceShading</code> function:
</p><pre class="listing tilde"><code><span class="line">fragment {</span>
<span class="line"> <span class="hljs-type">void</span> material(<span class="hljs-keyword">inout</span> MaterialInputs material) {</span>
<span class="line"> prepareMaterial(material);</span>
<span class="line"> <span class="hljs-comment">// prepare material inputs</span></span>
<span class="line"> }</span>
<span class="line"></span>
<span class="line"> <span class="hljs-type">vec3</span> surfaceShading(</span>
<span class="line"> <span class="hljs-keyword">const</span> MaterialInputs materialInputs,</span>
<span class="line"> <span class="hljs-keyword">const</span> ShadingData shadingData,</span>
<span class="line"> <span class="hljs-keyword">const</span> LightData lightData</span>
<span class="line"> ) {</span>
<span class="line"> <span class="hljs-keyword">return</span> <span class="hljs-type">vec3</span>(<span class="hljs-number">1.0</span>); <span class="hljs-comment">// output of custom lighting</span></span>
<span class="line"> }</span>
<span class="line">}</span></code></pre><p>
This function will be invoked for every light (directional, spot or point) in the scene that may
influence the current fragment. The <code>surfaceShading</code> is invoked with 3 sets of data:
</p><p>
</p><ul>
<li class="minus"><code>MaterialInputs</code>, as described in the <a href="#materialfragmentinputs">Material fragment inputs</a> section and prepared in the
<code>material</code> function explained above
</li>
<li class="minus"><code>ShadingData</code>, a structure containing values derived from <code>MaterialInputs</code> (see below)
</li>
<li class="minus"><code>LightData</code>, a structure containing values specific to the light being currently
evaluated (see below)</li></ul>
<p></p><p>
The <code>surfaceShading</code> function must return an RGB color in linear sRGB. Alpha blending and alpha
masking are handled outside of this function and must therefore be ignored.
</p><p>
</p><div class="admonition note"><div class="admonition-title"> About shadowed fragments</div>
<p></p><p>
The <code>surfaceShading</code> function is invoked even when a fragment is known to be fully in the shadow
of the current light (<code>lightData.NdotL &lt;= 0.0</code> or <code>lightData.visibility &lt;= 0.0</code>). This gives
more flexibility to the <code>surfaceShading</code> function as it provides a simple way to handle constant
ambient lighting for instance.</p></div>
<p></p><p>
</p><div class="admonition warning"><div class="admonition-title"> Shading models</div>
<p></p><p>
Custom surface shading only works with the <code>lit</code> shading model. Attempting to use any other
model will result in an error.</p></div>
<p></p>
<a class="target" name="shadingdatastructure">&nbsp;</a><a class="target" name="materialdefinitions/fragmentblock/customsurfaceshading/shadingdatastructure">&nbsp;</a><a class="target" name="toc4.4.3.1">&nbsp;</a><h4>Shading data structure</h4>
<pre class="listing tilde"><code><span class="line">struct ShadingData {</span>
<span class="line"> <span class="hljs-comment">// The material's diffuse color, as derived from baseColor and metallic.</span></span>
<span class="line"> <span class="hljs-comment">// This color is pre-multiplied by alpha and in the linear sRGB color space.</span></span>
<span class="line"> <span class="hljs-type">vec3</span> diffuseColor;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// The material's specular color, as derived from baseColor and metallic.</span></span>
<span class="line"> <span class="hljs-comment">// This color is pre-multiplied by alpha and in the linear sRGB color space.</span></span>
<span class="line"> <span class="hljs-type">vec3</span> f0;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// The perceptual roughness it the roughness value set in MaterialInputs,</span></span>
<span class="line"> <span class="hljs-comment">// with extra processing:</span></span>
<span class="line"> <span class="hljs-comment">// - Clamped to safe values</span></span>
<span class="line"> <span class="hljs-comment">// - Filtered if specularAntiAliasing is enabled</span></span>
<span class="line"> <span class="hljs-comment">// This value is between 0.0 and 1.0.</span></span>
<span class="line"> <span class="hljs-type">float</span> perceptualRoughness;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// The roughness value expected by BRDFs. This value is the square of</span></span>
<span class="line"> <span class="hljs-comment">// perceptualRoughness. This value is between 0.0 and 1.0.</span></span>
<span class="line"> <span class="hljs-type">float</span> roughness;</span>
<span class="line">};</span></code></pre>
<a class="target" name="lightdatastructure">&nbsp;</a><a class="target" name="materialdefinitions/fragmentblock/customsurfaceshading/lightdatastructure">&nbsp;</a><a class="target" name="toc4.4.3.2">&nbsp;</a><h4>Light data structure</h4>
<pre class="listing tilde"><code><span class="line">struct LightData {</span>
<span class="line"> <span class="hljs-comment">// The color (.rgb) and pre-exposed intensity (.w) of the light.</span></span>
<span class="line"> <span class="hljs-comment">// The color is an RGB value in the linear sRGB color space.</span></span>
<span class="line"> <span class="hljs-comment">// The pre-exposed intensity is the intensity of the light multiplied by</span></span>
<span class="line"> <span class="hljs-comment">// the camera's exposure value.</span></span>
<span class="line"> <span class="hljs-type">vec4</span> colorIntensity;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// The normalized light vector, in world space (direction from the</span></span>
<span class="line"> <span class="hljs-comment">// current fragment's position to the light).</span></span>
<span class="line"> <span class="hljs-type">vec3</span> l;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// The dot product of the shading normal (with normal mapping applied)</span></span>
<span class="line"> <span class="hljs-comment">// and the light vector. This value is equal to the result of</span></span>
<span class="line"> <span class="hljs-comment">// saturate(dot(getWorldSpaceNormal(), lightData.l)).</span></span>
<span class="line"> <span class="hljs-comment">// This value is always between 0.0 and 1.0. When the value is &lt;= 0.0,</span></span>
<span class="line"> <span class="hljs-comment">// the current fragment is not visible from the light and lighting</span></span>
<span class="line"> <span class="hljs-comment">// computations can be skipped.</span></span>
<span class="line"> <span class="hljs-type">float</span> NdotL;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// The position of the light in world space.</span></span>
<span class="line"> <span class="hljs-type">vec3</span> worldPosition;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// Attenuation of the light based on the distance from the current</span></span>
<span class="line"> <span class="hljs-comment">// fragment to the light in world space. This value between 0.0 and 1.0</span></span>
<span class="line"> <span class="hljs-comment">// is computed differently for each type of light (it's always 1.0 for</span></span>
<span class="line"> <span class="hljs-comment">// directional lights).</span></span>
<span class="line"> <span class="hljs-type">float</span> attenuation;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// Visibility factor computed from shadow maps or other occlusion data</span></span>
<span class="line"> <span class="hljs-comment">// specific to the light being evaluated. This value is between 0.0 and</span></span>
<span class="line"> <span class="hljs-comment">// 1.0.</span></span>
<span class="line"> <span class="hljs-type">float</span> visibility;</span>
<span class="line">};</span></code></pre>
<a class="target" name="example">&nbsp;</a><a class="target" name="materialdefinitions/fragmentblock/customsurfaceshading/example">&nbsp;</a><a class="target" name="toc4.4.3.3">&nbsp;</a><h4>Example</h4>
<p>
The material below shows how to use custom surface shading to implement a simplified toon shader:
</p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> name : Toon,</span>
<span class="line"> shadingModel : lit,</span>
<span class="line"> parameters : [</span>
<span class="line"> {</span>
<span class="line"> type : float3,</span>
<span class="line"> name : baseColor</span>
<span class="line"> }</span>
<span class="line"> ],</span>
<span class="line"> customSurfaceShading : <span class="hljs-literal">true</span></span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">fragment {</span>
<span class="line"> <span class="hljs-type">void</span> material(<span class="hljs-keyword">inout</span> MaterialInputs material) {</span>
<span class="line"> prepareMaterial(material);</span>
<span class="line"> material.baseColor.rgb = materialParams.baseColor;</span>
<span class="line"> }</span>
<span class="line"></span>
<span class="line"> <span class="hljs-type">vec3</span> surfaceShading(</span>
<span class="line"> <span class="hljs-keyword">const</span> MaterialInputs materialInputs,</span>
<span class="line"> <span class="hljs-keyword">const</span> ShadingData shadingData,</span>
<span class="line"> <span class="hljs-keyword">const</span> LightData lightData</span>
<span class="line"> ) {</span>
<span class="line"> <span class="hljs-comment">// Number of visible shade transitions</span></span>
<span class="line"> <span class="hljs-keyword">const</span> <span class="hljs-type">float</span> shades = <span class="hljs-number">5.0</span>;</span>
<span class="line"> <span class="hljs-comment">// Ambient intensity</span></span>
<span class="line"> <span class="hljs-keyword">const</span> <span class="hljs-type">float</span> ambient = <span class="hljs-number">0.1</span>;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-type">float</span> toon = <span class="hljs-built_in">max</span>(<span class="hljs-built_in">ceil</span>(lightData.NdotL * shades) / shades, ambient);</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// Shadowing and attenuation</span></span>
<span class="line"> toon *= lightData.visibility * lightData.attenuation;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-comment">// Color and intensity</span></span>
<span class="line"> <span class="hljs-type">vec3</span> light = lightData.colorIntensity.rgb * lightData.colorIntensity.w;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-keyword">return</span> shadingData.diffuseColor * light * toon;</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre><p>
The result can be seen in <a href="#figure_toonshading">figure&nbsp;40</a>.
</p><p>
</p><center><div class="image" style=""><a href="images/screenshot_toon_shading.png" target="_blank"><img class="markdeep" src="images/screenshot_toon_shading.png"></a><div class="imagecaption"><a class="target" name="figure_toonshading">&nbsp;</a><b style="font-style:normal;">Figure&nbsp;40:</b> simple toon shading implemented with custom
surface shading</div></div></center>
<p></p>
<a class="target" name="shaderpublicapis">&nbsp;</a><a class="target" name="materialdefinitions/shaderpublicapis">&nbsp;</a><a class="target" name="toc4.5">&nbsp;</a><h2>Shader public APIs</h2>
<a class="target" name="types">&nbsp;</a><a class="target" name="materialdefinitions/shaderpublicapis/types">&nbsp;</a><a class="target" name="toc4.5.1">&nbsp;</a><h3>Types</h3>
@@ -2379,7 +2587,7 @@ The following APIs are only available from the fragment block:
<tr><td style="text-align:left"> <strong class="asterisk">getWorldNormalVector()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Normalized normal in world space, after bump mapping (must be used after <code>prepareMaterial()</code>) </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getWorldGeometricNormalVector()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Normalized normal in world space, before bump mapping (can be used before <code>prepareMaterial()</code>) </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getWorldReflectedVector()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Reflection of the view vector about the normal (must be used after <code>prepareMaterial()</code>) </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getNormalizedViewportCoord()</strong> </td><td style="text-align:center"> float2 </td><td style="text-align:left"> Normalized viewport position (i.e. clip-space position normalized to [0, 1], can be used before <code>prepareMaterial()</code>) </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getNormalizedViewportCoord()</strong> </td><td style="text-align:center"> float3 </td><td style="text-align:left"> Normalized viewport position (i.e. NDC coordinates normalized to [0, 1], can be used before <code>prepareMaterial()</code>) </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getNdotV()</strong> </td><td style="text-align:center"> float </td><td style="text-align:left"> The result of <code>dot(normal, view)</code>, always strictly greater than 0 (must be used after <code>prepareMaterial()</code>) </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getColor()</strong> </td><td style="text-align:center"> float4 </td><td style="text-align:left"> Interpolated color of the fragment, if the color attribute is required </td></tr>
<tr><td style="text-align:left"> <strong class="asterisk">getUV0()</strong> </td><td style="text-align:center"> float2 </td><td style="text-align:left"> First interpolated set of UV coordinates, only available if the uv0 attribute is required </td></tr>

View File

@@ -68,7 +68,7 @@ The lit model is Filament's standard material model. This physically-based shadi
designed after to offer good interoperability with other common tools and engines such as _Unity 5_,
_Unreal Engine 4_, _Substance Designer_ or _Marmoset Toolbag_.
This material model can be used to describe a large number of non-metallic surfaces (_dielectrics_)
This material model can be used to describe many non-metallic surfaces (_dielectrics_)
or metallic surfaces (_conductors_).
The appearance of a material using the standard model is controlled using the properties described
@@ -93,7 +93,7 @@ in table [standardProperties].
**clearCoatNormal** | A detail normal used to perturb the clear coat layer using _bump mapping_ (_normal mapping_)
**emissive** | Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass
**postLightingColor** | Additional color that can be blended with the result of the lighting computations. See `postLightingBlending`
**ior** | Index of refraction for refractive objects
**ior** | Index of refraction, either for refractive objects or as an alternative to reflectance
**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
**absorption** | Absorption factor for refractive objects
**microThickness** | Thickness of the thin layer of refractive objects
@@ -146,7 +146,7 @@ The type and range of each property is described in table [standardPropertiesTyp
!!! Note: About `ior` and `reflectance`
The index of refraction (IOR) and the reflectance represent the same physical attribute,
therefore they don't need to be both specified. Typically, only the reflectance is specified
therefore they don't need to be both specified. Typically, only the reflectance is specified,
and the IOR is deduced automatically. When only the IOR is specified, the reflectance is then
deduced automatically. It is possible to specify both, in which case their values are kept
as-is, which can lead to physically impossible materials, however, this might be desirable
@@ -507,7 +507,8 @@ this option for more information.
The `ior` property only affects non-metallic surfaces. This property can be used to control the
index of refraction and the specular intensity of materials. The `ior` property is intended to
be used with refractive (transmissive) materials, which are enabled when the `refractionMode` is
set to `cubemap` or `screenspace`.
set to `cubemap` or `screenspace`. It can also be used on non-refractive objects as an alternative
to setting the reflectance.
The index of refraction (or refractive index) of a material is a dimensionless number that describes
how fast light travels through that material. The higher the number, the slower light travels
@@ -1096,6 +1097,26 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: quality
Type
: `string`
Value
: Any of `low`, `normal`, `high`, `default`. Defaults to `default`.
Description
: Set some global quality parameters of the material. `low` enables optimizations that can
slightly affect correctness and is the default on mobile platforms. `normal` does not affect
correctness and is otherwise similar to `low`. `high` enables quality settings that can
adversely affect performance and is the default on desktop platforms.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
quality : default
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Vertex and attributes: requires
Type
@@ -1501,6 +1522,7 @@ Description
: Only available in the `unlit` shading model. If this property is enabled, the final color
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
This is only supported with shadows from directional lights.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
@@ -1660,6 +1682,26 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Shading: customSurfaceShading
Type
: `bool`
Value
: `true` or `false`. Defaults to `false`.
Description
: Enables custom surface shading when set to true. When surface shading is enabled, the fragment
shader must provide an extra function that will be invoked for every light in the scene that
may influence the current fragment. Please refer to the Custom surface shading section below
for more information.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
customSurfaceShading : true
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Vertex block
The vertex block is optional and can be used to control the vertex shading stage of the material.
@@ -1847,6 +1889,165 @@ struct MaterialInputs {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Custom surface shading
When `customSurfaceShading` is set to `true` in the material block, the fragment block **must**
declare and implement the `surfaceShading` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
// prepare material inputs
}
vec3 surfaceShading(
const MaterialInputs materialInputs,
const ShadingData shadingData,
const LightData lightData
) {
return vec3(1.0); // output of custom lighting
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This function will be invoked for every light (directional, spot or point) in the scene that may
influence the current fragment. The `surfaceShading` is invoked with 3 sets of data:
- `MaterialInputs`, as described in the Material fragment inputs section and prepared in the
`material` function explained above
- `ShadingData`, a structure containing values derived from `MaterialInputs` (see below)
- `LightData`, a structure containing values specific to the light being currently
evaluated (see below)
The `surfaceShading` function must return an RGB color in linear sRGB. Alpha blending and alpha
masking are handled outside of this function and must therefore be ignored.
!!! Note: About shadowed fragments
The `surfaceShading` function is invoked even when a fragment is known to be fully in the shadow
of the current light (`lightData.NdotL <= 0.0` or `lightData.visibility <= 0.0`). This gives
more flexibility to the `surfaceShading` function as it provides a simple way to handle constant
ambient lighting for instance.
!!! Warning: Shading models
Custom surface shading only works with the `lit` shading model. Attempting to use any other
model will result in an error.
#### Shading data structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
struct ShadingData {
// The material's diffuse color, as derived from baseColor and metallic.
// This color is pre-multiplied by alpha and in the linear sRGB color space.
vec3 diffuseColor;
// The material's specular color, as derived from baseColor and metallic.
// This color is pre-multiplied by alpha and in the linear sRGB color space.
vec3 f0;
// The perceptual roughness is the roughness value set in MaterialInputs,
// with extra processing:
// - Clamped to safe values
// - Filtered if specularAntiAliasing is enabled
// This value is between 0.0 and 1.0.
float perceptualRoughness;
// The roughness value expected by BRDFs. This value is the square of
// perceptualRoughness. This value is between 0.0 and 1.0.
float roughness;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#### Light data structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
struct LightData {
// The color (.rgb) and pre-exposed intensity (.w) of the light.
// The color is an RGB value in the linear sRGB color space.
// The pre-exposed intensity is the intensity of the light multiplied by
// the camera's exposure value.
vec4 colorIntensity;
// The normalized light vector, in world space (direction from the
// current fragment's position to the light).
vec3 l;
// The dot product of the shading normal (with normal mapping applied)
// and the light vector. This value is equal to the result of
// saturate(dot(getWorldSpaceNormal(), lightData.l)).
// This value is always between 0.0 and 1.0. When the value is <= 0.0,
// the current fragment is not visible from the light and lighting
// computations can be skipped.
float NdotL;
// The position of the light in world space.
vec3 worldPosition;
// Attenuation of the light based on the distance from the current
// fragment to the light in world space. This value between 0.0 and 1.0
// is computed differently for each type of light (it's always 1.0 for
// directional lights).
float attenuation;
// Visibility factor computed from shadow maps or other occlusion data
// specific to the light being evaluated. This value is between 0.0 and
// 1.0.
float visibility;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#### Example
The material below shows how to use custom surface shading to implement a simplified toon shader:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
material {
name : Toon,
shadingModel : lit,
parameters : [
{
type : float3,
name : baseColor
}
],
customSurfaceShading : true
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor.rgb = materialParams.baseColor;
}
vec3 surfaceShading(
const MaterialInputs materialInputs,
const ShadingData shadingData,
const LightData lightData
) {
// Number of visible shade transitions
const float shades = 5.0;
// Ambient intensity
const float ambient = 0.1;
float toon = max(ceil(lightData.NdotL * shades) / shades, ambient);
// Shadowing and attenuation
toon *= lightData.visibility * lightData.attenuation;
// Color and intensity
vec3 light = lightData.colorIntensity.rgb * lightData.colorIntensity.w;
return shadingData.diffuseColor * light * toon;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The result can be seen in figure [toonShading].
![Figure [toonShading]: simple toon shading implemented with custom
surface shading](images/screenshot_toon_shading.png)
## Shader public APIs
### Types
@@ -1936,7 +2137,7 @@ The following APIs are only available from the fragment block:
**getWorldNormalVector()** | float3 | Normalized normal in world space, after bump mapping (must be used after `prepareMaterial()`)
**getWorldGeometricNormalVector()** | float3 | Normalized normal in world space, before bump mapping (can be used before `prepareMaterial()`)
**getWorldReflectedVector()** | float3 | Reflection of the view vector about the normal (must be used after `prepareMaterial()`)
**getNormalizedViewportCoord()** | float2 | Normalized viewport position (i.e. clip-space position normalized to [0, 1], can be used before `prepareMaterial()`)
**getNormalizedViewportCoord()** | float3 | Normalized viewport position (i.e. NDC coordinates normalized to [0, 1], can be used before `prepareMaterial()`)
**getNdotV()** | float | The result of `dot(normal, view)`, always strictly greater than 0 (must be used after `prepareMaterial()`)
**getColor()** | float4 | Interpolated color of the fragment, if the color attribute is required
**getUV0()** | float2 | First interpolated set of UV coordinates, only available if the uv0 attribute is required

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 KiB

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